ec6123aacf7981022faf85fcb758f0b69cf149c2
[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     (* Run the test only if 'string' is available in the daemon. *)
313   | IfAvailable of string
314
315 (* Some initial scenarios for testing. *)
316 and test_init =
317     (* Do nothing, block devices could contain random stuff including
318      * LVM PVs, and some filesystems might be mounted.  This is usually
319      * a bad idea.
320      *)
321   | InitNone
322
323     (* Block devices are empty and no filesystems are mounted. *)
324   | InitEmpty
325
326     (* /dev/sda contains a single partition /dev/sda1, with random
327      * content.  /dev/sdb and /dev/sdc may have random content.
328      * No LVM.
329      *)
330   | InitPartition
331
332     (* /dev/sda contains a single partition /dev/sda1, which is formatted
333      * as ext2, empty [except for lost+found] and mounted on /.
334      * /dev/sdb and /dev/sdc may have random content.
335      * No LVM.
336      *)
337   | InitBasicFS
338
339     (* /dev/sda:
340      *   /dev/sda1 (is a PV):
341      *     /dev/VG/LV (size 8MB):
342      *       formatted as ext2, empty [except for lost+found], mounted on /
343      * /dev/sdb and /dev/sdc may have random content.
344      *)
345   | InitBasicFSonLVM
346
347     (* /dev/sdd (the ISO, see images/ directory in source)
348      * is mounted on /
349      *)
350   | InitISOFS
351
352 (* Sequence of commands for testing. *)
353 and seq = cmd list
354 and cmd = string list
355
356 (* Note about long descriptions: When referring to another
357  * action, use the format C<guestfs_other> (ie. the full name of
358  * the C function).  This will be replaced as appropriate in other
359  * language bindings.
360  *
361  * Apart from that, long descriptions are just perldoc paragraphs.
362  *)
363
364 (* Generate a random UUID (used in tests). *)
365 let uuidgen () =
366   let chan = open_process_in "uuidgen" in
367   let uuid = input_line chan in
368   (match close_process_in chan with
369    | WEXITED 0 -> ()
370    | WEXITED _ ->
371        failwith "uuidgen: process exited with non-zero status"
372    | WSIGNALED _ | WSTOPPED _ ->
373        failwith "uuidgen: process signalled or stopped by signal"
374   );
375   uuid
376
377 (* These test functions are used in the language binding tests. *)
378
379 let test_all_args = [
380   String "str";
381   OptString "optstr";
382   StringList "strlist";
383   Bool "b";
384   Int "integer";
385   Int64 "integer64";
386   FileIn "filein";
387   FileOut "fileout";
388   BufferIn "bufferin";
389 ]
390
391 let test_all_rets = [
392   (* except for RErr, which is tested thoroughly elsewhere *)
393   "test0rint",         RInt "valout";
394   "test0rint64",       RInt64 "valout";
395   "test0rbool",        RBool "valout";
396   "test0rconststring", RConstString "valout";
397   "test0rconstoptstring", RConstOptString "valout";
398   "test0rstring",      RString "valout";
399   "test0rstringlist",  RStringList "valout";
400   "test0rstruct",      RStruct ("valout", "lvm_pv");
401   "test0rstructlist",  RStructList ("valout", "lvm_pv");
402   "test0rhashtable",   RHashtable "valout";
403 ]
404
405 let test_functions = [
406   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
407    [],
408    "internal test function - do not use",
409    "\
410 This is an internal test function which is used to test whether
411 the automatically generated bindings can handle every possible
412 parameter type correctly.
413
414 It echos the contents of each parameter to stdout.
415
416 You probably don't want to call this function.");
417 ] @ List.flatten (
418   List.map (
419     fun (name, ret) ->
420       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
421         [],
422         "internal test function - do not use",
423         "\
424 This is an internal test function which is used to test whether
425 the automatically generated bindings can handle every possible
426 return type correctly.
427
428 It converts string C<val> to the return type.
429
430 You probably don't want to call this function.");
431        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
432         [],
433         "internal test function - do not use",
434         "\
435 This is an internal test function which is used to test whether
436 the automatically generated bindings can handle every possible
437 return type correctly.
438
439 This function always returns an error.
440
441 You probably don't want to call this function.")]
442   ) test_all_rets
443 )
444
445 (* non_daemon_functions are any functions which don't get processed
446  * in the daemon, eg. functions for setting and getting local
447  * configuration values.
448  *)
449
450 let non_daemon_functions = test_functions @ [
451   ("launch", (RErr, []), -1, [FishAlias "run"],
452    [],
453    "launch the qemu subprocess",
454    "\
455 Internally libguestfs is implemented by running a virtual machine
456 using L<qemu(1)>.
457
458 You should call this after configuring the handle
459 (eg. adding drives) but before performing any actions.");
460
461   ("wait_ready", (RErr, []), -1, [NotInFish],
462    [],
463    "wait until the qemu subprocess launches (no op)",
464    "\
465 This function is a no op.
466
467 In versions of the API E<lt> 1.0.71 you had to call this function
468 just after calling C<guestfs_launch> to wait for the launch
469 to complete.  However this is no longer necessary because
470 C<guestfs_launch> now does the waiting.
471
472 If you see any calls to this function in code then you can just
473 remove them, unless you want to retain compatibility with older
474 versions of the API.");
475
476   ("kill_subprocess", (RErr, []), -1, [],
477    [],
478    "kill the qemu subprocess",
479    "\
480 This kills the qemu subprocess.  You should never need to call this.");
481
482   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
483    [],
484    "add an image to examine or modify",
485    "\
486 This function adds a virtual machine disk image C<filename> to the
487 guest.  The first time you call this function, the disk appears as IDE
488 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
489 so on.
490
491 You don't necessarily need to be root when using libguestfs.  However
492 you obviously do need sufficient permissions to access the filename
493 for whatever operations you want to perform (ie. read access if you
494 just want to read the image or write access if you want to modify the
495 image).
496
497 This is equivalent to the qemu parameter
498 C<-drive file=filename,cache=off,if=...>.
499
500 C<cache=off> is omitted in cases where it is not supported by
501 the underlying filesystem.
502
503 C<if=...> is set at compile time by the configuration option
504 C<./configure --with-drive-if=...>.  In the rare case where you
505 might need to change this at run time, use C<guestfs_add_drive_with_if>
506 or C<guestfs_add_drive_ro_with_if>.
507
508 Note that this call checks for the existence of C<filename>.  This
509 stops you from specifying other types of drive which are supported
510 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
511 the general C<guestfs_config> call instead.");
512
513   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
514    [],
515    "add a CD-ROM disk image to examine",
516    "\
517 This function adds a virtual CD-ROM disk image to the guest.
518
519 This is equivalent to the qemu parameter C<-cdrom filename>.
520
521 Notes:
522
523 =over 4
524
525 =item *
526
527 This call checks for the existence of C<filename>.  This
528 stops you from specifying other types of drive which are supported
529 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
530 the general C<guestfs_config> call instead.
531
532 =item *
533
534 If you just want to add an ISO file (often you use this as an
535 efficient way to transfer large files into the guest), then you
536 should probably use C<guestfs_add_drive_ro> instead.
537
538 =back");
539
540   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
541    [],
542    "add a drive in snapshot mode (read-only)",
543    "\
544 This adds a drive in snapshot mode, making it effectively
545 read-only.
546
547 Note that writes to the device are allowed, and will be seen for
548 the duration of the guestfs handle, but they are written
549 to a temporary file which is discarded as soon as the guestfs
550 handle is closed.  We don't currently have any method to enable
551 changes to be committed, although qemu can support this.
552
553 This is equivalent to the qemu parameter
554 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
555
556 C<if=...> is set at compile time by the configuration option
557 C<./configure --with-drive-if=...>.  In the rare case where you
558 might need to change this at run time, use C<guestfs_add_drive_with_if>
559 or C<guestfs_add_drive_ro_with_if>.
560
561 C<readonly=on> is only added where qemu supports this option.
562
563 Note that this call checks for the existence of C<filename>.  This
564 stops you from specifying other types of drive which are supported
565 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
566 the general C<guestfs_config> call instead.");
567
568   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
569    [],
570    "add qemu parameters",
571    "\
572 This can be used to add arbitrary qemu command line parameters
573 of the form C<-param value>.  Actually it's not quite arbitrary - we
574 prevent you from setting some parameters which would interfere with
575 parameters that we use.
576
577 The first character of C<param> string must be a C<-> (dash).
578
579 C<value> can be NULL.");
580
581   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
582    [],
583    "set the qemu binary",
584    "\
585 Set the qemu binary that we will use.
586
587 The default is chosen when the library was compiled by the
588 configure script.
589
590 You can also override this by setting the C<LIBGUESTFS_QEMU>
591 environment variable.
592
593 Setting C<qemu> to C<NULL> restores the default qemu binary.
594
595 Note that you should call this function as early as possible
596 after creating the handle.  This is because some pre-launch
597 operations depend on testing qemu features (by running C<qemu -help>).
598 If the qemu binary changes, we don't retest features, and
599 so you might see inconsistent results.  Using the environment
600 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
601 the qemu binary at the same time as the handle is created.");
602
603   ("get_qemu", (RConstString "qemu", []), -1, [],
604    [InitNone, Always, TestRun (
605       [["get_qemu"]])],
606    "get the qemu binary",
607    "\
608 Return the current qemu binary.
609
610 This is always non-NULL.  If it wasn't set already, then this will
611 return the default qemu binary name.");
612
613   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
614    [],
615    "set the search path",
616    "\
617 Set the path that libguestfs searches for kernel and initrd.img.
618
619 The default is C<$libdir/guestfs> unless overridden by setting
620 C<LIBGUESTFS_PATH> environment variable.
621
622 Setting C<path> to C<NULL> restores the default path.");
623
624   ("get_path", (RConstString "path", []), -1, [],
625    [InitNone, Always, TestRun (
626       [["get_path"]])],
627    "get the search path",
628    "\
629 Return the current search path.
630
631 This is always non-NULL.  If it wasn't set already, then this will
632 return the default path.");
633
634   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
635    [],
636    "add options to kernel command line",
637    "\
638 This function is used to add additional options to the
639 guest kernel command line.
640
641 The default is C<NULL> unless overridden by setting
642 C<LIBGUESTFS_APPEND> environment variable.
643
644 Setting C<append> to C<NULL> means I<no> additional options
645 are passed (libguestfs always adds a few of its own).");
646
647   ("get_append", (RConstOptString "append", []), -1, [],
648    (* This cannot be tested with the current framework.  The
649     * function can return NULL in normal operations, which the
650     * test framework interprets as an error.
651     *)
652    [],
653    "get the additional kernel options",
654    "\
655 Return the additional kernel options which are added to the
656 guest kernel command line.
657
658 If C<NULL> then no options are added.");
659
660   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
661    [],
662    "set autosync mode",
663    "\
664 If C<autosync> is true, this enables autosync.  Libguestfs will make a
665 best effort attempt to run C<guestfs_umount_all> followed by
666 C<guestfs_sync> when the handle is closed
667 (also if the program exits without closing handles).
668
669 This is disabled by default (except in guestfish where it is
670 enabled by default).");
671
672   ("get_autosync", (RBool "autosync", []), -1, [],
673    [InitNone, Always, TestRun (
674       [["get_autosync"]])],
675    "get autosync mode",
676    "\
677 Get the autosync flag.");
678
679   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
680    [],
681    "set verbose mode",
682    "\
683 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
684
685 Verbose messages are disabled unless the environment variable
686 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
687
688   ("get_verbose", (RBool "verbose", []), -1, [],
689    [],
690    "get verbose mode",
691    "\
692 This returns the verbose messages flag.");
693
694   ("is_ready", (RBool "ready", []), -1, [],
695    [InitNone, Always, TestOutputTrue (
696       [["is_ready"]])],
697    "is ready to accept commands",
698    "\
699 This returns true iff this handle is ready to accept commands
700 (in the C<READY> state).
701
702 For more information on states, see L<guestfs(3)>.");
703
704   ("is_config", (RBool "config", []), -1, [],
705    [InitNone, Always, TestOutputFalse (
706       [["is_config"]])],
707    "is in configuration state",
708    "\
709 This returns true iff this handle is being configured
710 (in the C<CONFIG> state).
711
712 For more information on states, see L<guestfs(3)>.");
713
714   ("is_launching", (RBool "launching", []), -1, [],
715    [InitNone, Always, TestOutputFalse (
716       [["is_launching"]])],
717    "is launching subprocess",
718    "\
719 This returns true iff this handle is launching the subprocess
720 (in the C<LAUNCHING> state).
721
722 For more information on states, see L<guestfs(3)>.");
723
724   ("is_busy", (RBool "busy", []), -1, [],
725    [InitNone, Always, TestOutputFalse (
726       [["is_busy"]])],
727    "is busy processing a command",
728    "\
729 This returns true iff this handle is busy processing a command
730 (in the C<BUSY> state).
731
732 For more information on states, see L<guestfs(3)>.");
733
734   ("get_state", (RInt "state", []), -1, [],
735    [],
736    "get the current state",
737    "\
738 This returns the current state as an opaque integer.  This is
739 only useful for printing debug and internal error messages.
740
741 For more information on states, see L<guestfs(3)>.");
742
743   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
744    [InitNone, Always, TestOutputInt (
745       [["set_memsize"; "500"];
746        ["get_memsize"]], 500)],
747    "set memory allocated to the qemu subprocess",
748    "\
749 This sets the memory size in megabytes allocated to the
750 qemu subprocess.  This only has any effect if called before
751 C<guestfs_launch>.
752
753 You can also change this by setting the environment
754 variable C<LIBGUESTFS_MEMSIZE> before the handle is
755 created.
756
757 For more information on the architecture of libguestfs,
758 see L<guestfs(3)>.");
759
760   ("get_memsize", (RInt "memsize", []), -1, [],
761    [InitNone, Always, TestOutputIntOp (
762       [["get_memsize"]], ">=", 256)],
763    "get memory allocated to the qemu subprocess",
764    "\
765 This gets the memory size in megabytes allocated to the
766 qemu subprocess.
767
768 If C<guestfs_set_memsize> was not called
769 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
770 then this returns the compiled-in default value for memsize.
771
772 For more information on the architecture of libguestfs,
773 see L<guestfs(3)>.");
774
775   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
776    [InitNone, Always, TestOutputIntOp (
777       [["get_pid"]], ">=", 1)],
778    "get PID of qemu subprocess",
779    "\
780 Return the process ID of the qemu subprocess.  If there is no
781 qemu subprocess, then this will return an error.
782
783 This is an internal call used for debugging and testing.");
784
785   ("version", (RStruct ("version", "version"), []), -1, [],
786    [InitNone, Always, TestOutputStruct (
787       [["version"]], [CompareWithInt ("major", 1)])],
788    "get the library version number",
789    "\
790 Return the libguestfs version number that the program is linked
791 against.
792
793 Note that because of dynamic linking this is not necessarily
794 the version of libguestfs that you compiled against.  You can
795 compile the program, and then at runtime dynamically link
796 against a completely different C<libguestfs.so> library.
797
798 This call was added in version C<1.0.58>.  In previous
799 versions of libguestfs there was no way to get the version
800 number.  From C code you can use dynamic linker functions
801 to find out if this symbol exists (if it doesn't, then
802 it's an earlier version).
803
804 The call returns a structure with four elements.  The first
805 three (C<major>, C<minor> and C<release>) are numbers and
806 correspond to the usual version triplet.  The fourth element
807 (C<extra>) is a string and is normally empty, but may be
808 used for distro-specific information.
809
810 To construct the original version string:
811 C<$major.$minor.$release$extra>
812
813 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
814
815 I<Note:> Don't use this call to test for availability
816 of features.  In enterprise distributions we backport
817 features from later versions into earlier versions,
818 making this an unreliable way to test for features.
819 Use C<guestfs_available> instead.");
820
821   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
822    [InitNone, Always, TestOutputTrue (
823       [["set_selinux"; "true"];
824        ["get_selinux"]])],
825    "set SELinux enabled or disabled at appliance boot",
826    "\
827 This sets the selinux flag that is passed to the appliance
828 at boot time.  The default is C<selinux=0> (disabled).
829
830 Note that if SELinux is enabled, it is always in
831 Permissive mode (C<enforcing=0>).
832
833 For more information on the architecture of libguestfs,
834 see L<guestfs(3)>.");
835
836   ("get_selinux", (RBool "selinux", []), -1, [],
837    [],
838    "get SELinux enabled flag",
839    "\
840 This returns the current setting of the selinux flag which
841 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
842
843 For more information on the architecture of libguestfs,
844 see L<guestfs(3)>.");
845
846   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
847    [InitNone, Always, TestOutputFalse (
848       [["set_trace"; "false"];
849        ["get_trace"]])],
850    "enable or disable command traces",
851    "\
852 If the command trace flag is set to 1, then commands are
853 printed on stdout before they are executed in a format
854 which is very similar to the one used by guestfish.  In
855 other words, you can run a program with this enabled, and
856 you will get out a script which you can feed to guestfish
857 to perform the same set of actions.
858
859 If you want to trace C API calls into libguestfs (and
860 other libraries) then possibly a better way is to use
861 the external ltrace(1) command.
862
863 Command traces are disabled unless the environment variable
864 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
865
866   ("get_trace", (RBool "trace", []), -1, [],
867    [],
868    "get command trace enabled flag",
869    "\
870 Return the command trace flag.");
871
872   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
873    [InitNone, Always, TestOutputFalse (
874       [["set_direct"; "false"];
875        ["get_direct"]])],
876    "enable or disable direct appliance mode",
877    "\
878 If the direct appliance mode flag is enabled, then stdin and
879 stdout are passed directly through to the appliance once it
880 is launched.
881
882 One consequence of this is that log messages aren't caught
883 by the library and handled by C<guestfs_set_log_message_callback>,
884 but go straight to stdout.
885
886 You probably don't want to use this unless you know what you
887 are doing.
888
889 The default is disabled.");
890
891   ("get_direct", (RBool "direct", []), -1, [],
892    [],
893    "get direct appliance mode flag",
894    "\
895 Return the direct appliance mode flag.");
896
897   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
898    [InitNone, Always, TestOutputTrue (
899       [["set_recovery_proc"; "true"];
900        ["get_recovery_proc"]])],
901    "enable or disable the recovery process",
902    "\
903 If this is called with the parameter C<false> then
904 C<guestfs_launch> does not create a recovery process.  The
905 purpose of the recovery process is to stop runaway qemu
906 processes in the case where the main program aborts abruptly.
907
908 This only has any effect if called before C<guestfs_launch>,
909 and the default is true.
910
911 About the only time when you would want to disable this is
912 if the main process will fork itself into the background
913 (\"daemonize\" itself).  In this case the recovery process
914 thinks that the main program has disappeared and so kills
915 qemu, which is not very helpful.");
916
917   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
918    [],
919    "get recovery process enabled flag",
920    "\
921 Return the recovery process enabled flag.");
922
923   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
924    [],
925    "add a drive specifying the QEMU block emulation to use",
926    "\
927 This is the same as C<guestfs_add_drive> but it allows you
928 to specify the QEMU interface emulation to use at run time.");
929
930   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
931    [],
932    "add a drive read-only specifying the QEMU block emulation to use",
933    "\
934 This is the same as C<guestfs_add_drive_ro> but it allows you
935 to specify the QEMU interface emulation to use at run time.");
936
937 ]
938
939 (* daemon_functions are any functions which cause some action
940  * to take place in the daemon.
941  *)
942
943 let daemon_functions = [
944   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
945    [InitEmpty, Always, TestOutput (
946       [["part_disk"; "/dev/sda"; "mbr"];
947        ["mkfs"; "ext2"; "/dev/sda1"];
948        ["mount"; "/dev/sda1"; "/"];
949        ["write"; "/new"; "new file contents"];
950        ["cat"; "/new"]], "new file contents")],
951    "mount a guest disk at a position in the filesystem",
952    "\
953 Mount a guest disk at a position in the filesystem.  Block devices
954 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
955 the guest.  If those block devices contain partitions, they will have
956 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
957 names can be used.
958
959 The rules are the same as for L<mount(2)>:  A filesystem must
960 first be mounted on C</> before others can be mounted.  Other
961 filesystems can only be mounted on directories which already
962 exist.
963
964 The mounted filesystem is writable, if we have sufficient permissions
965 on the underlying device.
966
967 B<Important note:>
968 When you use this call, the filesystem options C<sync> and C<noatime>
969 are set implicitly.  This was originally done because we thought it
970 would improve reliability, but it turns out that I<-o sync> has a
971 very large negative performance impact and negligible effect on
972 reliability.  Therefore we recommend that you avoid using
973 C<guestfs_mount> in any code that needs performance, and instead
974 use C<guestfs_mount_options> (use an empty string for the first
975 parameter if you don't want any options).");
976
977   ("sync", (RErr, []), 2, [],
978    [ InitEmpty, Always, TestRun [["sync"]]],
979    "sync disks, writes are flushed through to the disk image",
980    "\
981 This syncs the disk, so that any writes are flushed through to the
982 underlying disk image.
983
984 You should always call this if you have modified a disk image, before
985 closing the handle.");
986
987   ("touch", (RErr, [Pathname "path"]), 3, [],
988    [InitBasicFS, Always, TestOutputTrue (
989       [["touch"; "/new"];
990        ["exists"; "/new"]])],
991    "update file timestamps or create a new file",
992    "\
993 Touch acts like the L<touch(1)> command.  It can be used to
994 update the timestamps on a file, or, if the file does not exist,
995 to create a new zero-length file.");
996
997   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
998    [InitISOFS, Always, TestOutput (
999       [["cat"; "/known-2"]], "abcdef\n")],
1000    "list the contents of a file",
1001    "\
1002 Return the contents of the file named C<path>.
1003
1004 Note that this function cannot correctly handle binary files
1005 (specifically, files containing C<\\0> character which is treated
1006 as end of string).  For those you need to use the C<guestfs_read_file>
1007 or C<guestfs_download> functions which have a more complex interface.");
1008
1009   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1010    [], (* XXX Tricky to test because it depends on the exact format
1011         * of the 'ls -l' command, which changes between F10 and F11.
1012         *)
1013    "list the files in a directory (long format)",
1014    "\
1015 List the files in C<directory> (relative to the root directory,
1016 there is no cwd) in the format of 'ls -la'.
1017
1018 This command is mostly useful for interactive sessions.  It
1019 is I<not> intended that you try to parse the output string.");
1020
1021   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1022    [InitBasicFS, Always, TestOutputList (
1023       [["touch"; "/new"];
1024        ["touch"; "/newer"];
1025        ["touch"; "/newest"];
1026        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1027    "list the files in a directory",
1028    "\
1029 List the files in C<directory> (relative to the root directory,
1030 there is no cwd).  The '.' and '..' entries are not returned, but
1031 hidden files are shown.
1032
1033 This command is mostly useful for interactive sessions.  Programs
1034 should probably use C<guestfs_readdir> instead.");
1035
1036   ("list_devices", (RStringList "devices", []), 7, [],
1037    [InitEmpty, Always, TestOutputListOfDevices (
1038       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1039    "list the block devices",
1040    "\
1041 List all the block devices.
1042
1043 The full block device names are returned, eg. C</dev/sda>");
1044
1045   ("list_partitions", (RStringList "partitions", []), 8, [],
1046    [InitBasicFS, Always, TestOutputListOfDevices (
1047       [["list_partitions"]], ["/dev/sda1"]);
1048     InitEmpty, Always, TestOutputListOfDevices (
1049       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1050        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1051    "list the partitions",
1052    "\
1053 List all the partitions detected on all block devices.
1054
1055 The full partition device names are returned, eg. C</dev/sda1>
1056
1057 This does not return logical volumes.  For that you will need to
1058 call C<guestfs_lvs>.");
1059
1060   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1061    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1062       [["pvs"]], ["/dev/sda1"]);
1063     InitEmpty, Always, TestOutputListOfDevices (
1064       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1065        ["pvcreate"; "/dev/sda1"];
1066        ["pvcreate"; "/dev/sda2"];
1067        ["pvcreate"; "/dev/sda3"];
1068        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1069    "list the LVM physical volumes (PVs)",
1070    "\
1071 List all the physical volumes detected.  This is the equivalent
1072 of the L<pvs(8)> command.
1073
1074 This returns a list of just the device names that contain
1075 PVs (eg. C</dev/sda2>).
1076
1077 See also C<guestfs_pvs_full>.");
1078
1079   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1080    [InitBasicFSonLVM, Always, TestOutputList (
1081       [["vgs"]], ["VG"]);
1082     InitEmpty, Always, TestOutputList (
1083       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1084        ["pvcreate"; "/dev/sda1"];
1085        ["pvcreate"; "/dev/sda2"];
1086        ["pvcreate"; "/dev/sda3"];
1087        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1088        ["vgcreate"; "VG2"; "/dev/sda3"];
1089        ["vgs"]], ["VG1"; "VG2"])],
1090    "list the LVM volume groups (VGs)",
1091    "\
1092 List all the volumes groups detected.  This is the equivalent
1093 of the L<vgs(8)> command.
1094
1095 This returns a list of just the volume group names that were
1096 detected (eg. C<VolGroup00>).
1097
1098 See also C<guestfs_vgs_full>.");
1099
1100   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1101    [InitBasicFSonLVM, Always, TestOutputList (
1102       [["lvs"]], ["/dev/VG/LV"]);
1103     InitEmpty, Always, TestOutputList (
1104       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1105        ["pvcreate"; "/dev/sda1"];
1106        ["pvcreate"; "/dev/sda2"];
1107        ["pvcreate"; "/dev/sda3"];
1108        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1109        ["vgcreate"; "VG2"; "/dev/sda3"];
1110        ["lvcreate"; "LV1"; "VG1"; "50"];
1111        ["lvcreate"; "LV2"; "VG1"; "50"];
1112        ["lvcreate"; "LV3"; "VG2"; "50"];
1113        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1114    "list the LVM logical volumes (LVs)",
1115    "\
1116 List all the logical volumes detected.  This is the equivalent
1117 of the L<lvs(8)> command.
1118
1119 This returns a list of the logical volume device names
1120 (eg. C</dev/VolGroup00/LogVol00>).
1121
1122 See also C<guestfs_lvs_full>.");
1123
1124   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1125    [], (* XXX how to test? *)
1126    "list the LVM physical volumes (PVs)",
1127    "\
1128 List all the physical volumes detected.  This is the equivalent
1129 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1130
1131   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1132    [], (* XXX how to test? *)
1133    "list the LVM volume groups (VGs)",
1134    "\
1135 List all the volumes groups detected.  This is the equivalent
1136 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1137
1138   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1139    [], (* XXX how to test? *)
1140    "list the LVM logical volumes (LVs)",
1141    "\
1142 List all the logical volumes detected.  This is the equivalent
1143 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1144
1145   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1146    [InitISOFS, Always, TestOutputList (
1147       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1148     InitISOFS, Always, TestOutputList (
1149       [["read_lines"; "/empty"]], [])],
1150    "read file as lines",
1151    "\
1152 Return the contents of the file named C<path>.
1153
1154 The file contents are returned as a list of lines.  Trailing
1155 C<LF> and C<CRLF> character sequences are I<not> returned.
1156
1157 Note that this function cannot correctly handle binary files
1158 (specifically, files containing C<\\0> character which is treated
1159 as end of line).  For those you need to use the C<guestfs_read_file>
1160 function which has a more complex interface.");
1161
1162   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1163    [], (* XXX Augeas code needs tests. *)
1164    "create a new Augeas handle",
1165    "\
1166 Create a new Augeas handle for editing configuration files.
1167 If there was any previous Augeas handle associated with this
1168 guestfs session, then it is closed.
1169
1170 You must call this before using any other C<guestfs_aug_*>
1171 commands.
1172
1173 C<root> is the filesystem root.  C<root> must not be NULL,
1174 use C</> instead.
1175
1176 The flags are the same as the flags defined in
1177 E<lt>augeas.hE<gt>, the logical I<or> of the following
1178 integers:
1179
1180 =over 4
1181
1182 =item C<AUG_SAVE_BACKUP> = 1
1183
1184 Keep the original file with a C<.augsave> extension.
1185
1186 =item C<AUG_SAVE_NEWFILE> = 2
1187
1188 Save changes into a file with extension C<.augnew>, and
1189 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1190
1191 =item C<AUG_TYPE_CHECK> = 4
1192
1193 Typecheck lenses (can be expensive).
1194
1195 =item C<AUG_NO_STDINC> = 8
1196
1197 Do not use standard load path for modules.
1198
1199 =item C<AUG_SAVE_NOOP> = 16
1200
1201 Make save a no-op, just record what would have been changed.
1202
1203 =item C<AUG_NO_LOAD> = 32
1204
1205 Do not load the tree in C<guestfs_aug_init>.
1206
1207 =back
1208
1209 To close the handle, you can call C<guestfs_aug_close>.
1210
1211 To find out more about Augeas, see L<http://augeas.net/>.");
1212
1213   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1214    [], (* XXX Augeas code needs tests. *)
1215    "close the current Augeas handle",
1216    "\
1217 Close the current Augeas handle and free up any resources
1218 used by it.  After calling this, you have to call
1219 C<guestfs_aug_init> again before you can use any other
1220 Augeas functions.");
1221
1222   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1223    [], (* XXX Augeas code needs tests. *)
1224    "define an Augeas variable",
1225    "\
1226 Defines an Augeas variable C<name> whose value is the result
1227 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1228 undefined.
1229
1230 On success this returns the number of nodes in C<expr>, or
1231 C<0> if C<expr> evaluates to something which is not a nodeset.");
1232
1233   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1234    [], (* XXX Augeas code needs tests. *)
1235    "define an Augeas node",
1236    "\
1237 Defines a variable C<name> whose value is the result of
1238 evaluating C<expr>.
1239
1240 If C<expr> evaluates to an empty nodeset, a node is created,
1241 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1242 C<name> will be the nodeset containing that single node.
1243
1244 On success this returns a pair containing the
1245 number of nodes in the nodeset, and a boolean flag
1246 if a node was created.");
1247
1248   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1249    [], (* XXX Augeas code needs tests. *)
1250    "look up the value of an Augeas path",
1251    "\
1252 Look up the value associated with C<path>.  If C<path>
1253 matches exactly one node, the C<value> is returned.");
1254
1255   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1256    [], (* XXX Augeas code needs tests. *)
1257    "set Augeas path to value",
1258    "\
1259 Set the value associated with C<path> to C<val>.
1260
1261 In the Augeas API, it is possible to clear a node by setting
1262 the value to NULL.  Due to an oversight in the libguestfs API
1263 you cannot do that with this call.  Instead you must use the
1264 C<guestfs_aug_clear> call.");
1265
1266   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1267    [], (* XXX Augeas code needs tests. *)
1268    "insert a sibling Augeas node",
1269    "\
1270 Create a new sibling C<label> for C<path>, inserting it into
1271 the tree before or after C<path> (depending on the boolean
1272 flag C<before>).
1273
1274 C<path> must match exactly one existing node in the tree, and
1275 C<label> must be a label, ie. not contain C</>, C<*> or end
1276 with a bracketed index C<[N]>.");
1277
1278   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "remove an Augeas path",
1281    "\
1282 Remove C<path> and all of its children.
1283
1284 On success this returns the number of entries which were removed.");
1285
1286   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1287    [], (* XXX Augeas code needs tests. *)
1288    "move Augeas node",
1289    "\
1290 Move the node C<src> to C<dest>.  C<src> must match exactly
1291 one node.  C<dest> is overwritten if it exists.");
1292
1293   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1294    [], (* XXX Augeas code needs tests. *)
1295    "return Augeas nodes which match augpath",
1296    "\
1297 Returns a list of paths which match the path expression C<path>.
1298 The returned paths are sufficiently qualified so that they match
1299 exactly one node in the current tree.");
1300
1301   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1302    [], (* XXX Augeas code needs tests. *)
1303    "write all pending Augeas changes to disk",
1304    "\
1305 This writes all pending changes to disk.
1306
1307 The flags which were passed to C<guestfs_aug_init> affect exactly
1308 how files are saved.");
1309
1310   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1311    [], (* XXX Augeas code needs tests. *)
1312    "load files into the tree",
1313    "\
1314 Load files into the tree.
1315
1316 See C<aug_load> in the Augeas documentation for the full gory
1317 details.");
1318
1319   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1320    [], (* XXX Augeas code needs tests. *)
1321    "list Augeas nodes under augpath",
1322    "\
1323 This is just a shortcut for listing C<guestfs_aug_match>
1324 C<path/*> and sorting the resulting nodes into alphabetical order.");
1325
1326   ("rm", (RErr, [Pathname "path"]), 29, [],
1327    [InitBasicFS, Always, TestRun
1328       [["touch"; "/new"];
1329        ["rm"; "/new"]];
1330     InitBasicFS, Always, TestLastFail
1331       [["rm"; "/new"]];
1332     InitBasicFS, Always, TestLastFail
1333       [["mkdir"; "/new"];
1334        ["rm"; "/new"]]],
1335    "remove a file",
1336    "\
1337 Remove the single file C<path>.");
1338
1339   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1340    [InitBasicFS, Always, TestRun
1341       [["mkdir"; "/new"];
1342        ["rmdir"; "/new"]];
1343     InitBasicFS, Always, TestLastFail
1344       [["rmdir"; "/new"]];
1345     InitBasicFS, Always, TestLastFail
1346       [["touch"; "/new"];
1347        ["rmdir"; "/new"]]],
1348    "remove a directory",
1349    "\
1350 Remove the single directory C<path>.");
1351
1352   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1353    [InitBasicFS, Always, TestOutputFalse
1354       [["mkdir"; "/new"];
1355        ["mkdir"; "/new/foo"];
1356        ["touch"; "/new/foo/bar"];
1357        ["rm_rf"; "/new"];
1358        ["exists"; "/new"]]],
1359    "remove a file or directory recursively",
1360    "\
1361 Remove the file or directory C<path>, recursively removing the
1362 contents if its a directory.  This is like the C<rm -rf> shell
1363 command.");
1364
1365   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1366    [InitBasicFS, Always, TestOutputTrue
1367       [["mkdir"; "/new"];
1368        ["is_dir"; "/new"]];
1369     InitBasicFS, Always, TestLastFail
1370       [["mkdir"; "/new/foo/bar"]]],
1371    "create a directory",
1372    "\
1373 Create a directory named C<path>.");
1374
1375   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1376    [InitBasicFS, Always, TestOutputTrue
1377       [["mkdir_p"; "/new/foo/bar"];
1378        ["is_dir"; "/new/foo/bar"]];
1379     InitBasicFS, Always, TestOutputTrue
1380       [["mkdir_p"; "/new/foo/bar"];
1381        ["is_dir"; "/new/foo"]];
1382     InitBasicFS, Always, TestOutputTrue
1383       [["mkdir_p"; "/new/foo/bar"];
1384        ["is_dir"; "/new"]];
1385     (* Regression tests for RHBZ#503133: *)
1386     InitBasicFS, Always, TestRun
1387       [["mkdir"; "/new"];
1388        ["mkdir_p"; "/new"]];
1389     InitBasicFS, Always, TestLastFail
1390       [["touch"; "/new"];
1391        ["mkdir_p"; "/new"]]],
1392    "create a directory and parents",
1393    "\
1394 Create a directory named C<path>, creating any parent directories
1395 as necessary.  This is like the C<mkdir -p> shell command.");
1396
1397   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1398    [], (* XXX Need stat command to test *)
1399    "change file mode",
1400    "\
1401 Change the mode (permissions) of C<path> to C<mode>.  Only
1402 numeric modes are supported.
1403
1404 I<Note>: When using this command from guestfish, C<mode>
1405 by default would be decimal, unless you prefix it with
1406 C<0> to get octal, ie. use C<0700> not C<700>.
1407
1408 The mode actually set is affected by the umask.");
1409
1410   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1411    [], (* XXX Need stat command to test *)
1412    "change file owner and group",
1413    "\
1414 Change the file owner to C<owner> and group to C<group>.
1415
1416 Only numeric uid and gid are supported.  If you want to use
1417 names, you will need to locate and parse the password file
1418 yourself (Augeas support makes this relatively easy).");
1419
1420   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1421    [InitISOFS, Always, TestOutputTrue (
1422       [["exists"; "/empty"]]);
1423     InitISOFS, Always, TestOutputTrue (
1424       [["exists"; "/directory"]])],
1425    "test if file or directory exists",
1426    "\
1427 This returns C<true> if and only if there is a file, directory
1428 (or anything) with the given C<path> name.
1429
1430 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1431
1432   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1433    [InitISOFS, Always, TestOutputTrue (
1434       [["is_file"; "/known-1"]]);
1435     InitISOFS, Always, TestOutputFalse (
1436       [["is_file"; "/directory"]])],
1437    "test if file exists",
1438    "\
1439 This returns C<true> if and only if there is a file
1440 with the given C<path> name.  Note that it returns false for
1441 other objects like directories.
1442
1443 See also C<guestfs_stat>.");
1444
1445   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1446    [InitISOFS, Always, TestOutputFalse (
1447       [["is_dir"; "/known-3"]]);
1448     InitISOFS, Always, TestOutputTrue (
1449       [["is_dir"; "/directory"]])],
1450    "test if file exists",
1451    "\
1452 This returns C<true> if and only if there is a directory
1453 with the given C<path> name.  Note that it returns false for
1454 other objects like files.
1455
1456 See also C<guestfs_stat>.");
1457
1458   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1459    [InitEmpty, Always, TestOutputListOfDevices (
1460       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1461        ["pvcreate"; "/dev/sda1"];
1462        ["pvcreate"; "/dev/sda2"];
1463        ["pvcreate"; "/dev/sda3"];
1464        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1465    "create an LVM physical volume",
1466    "\
1467 This creates an LVM physical volume on the named C<device>,
1468 where C<device> should usually be a partition name such
1469 as C</dev/sda1>.");
1470
1471   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1472    [InitEmpty, Always, TestOutputList (
1473       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1474        ["pvcreate"; "/dev/sda1"];
1475        ["pvcreate"; "/dev/sda2"];
1476        ["pvcreate"; "/dev/sda3"];
1477        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1478        ["vgcreate"; "VG2"; "/dev/sda3"];
1479        ["vgs"]], ["VG1"; "VG2"])],
1480    "create an LVM volume group",
1481    "\
1482 This creates an LVM volume group called C<volgroup>
1483 from the non-empty list of physical volumes C<physvols>.");
1484
1485   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1486    [InitEmpty, Always, TestOutputList (
1487       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1488        ["pvcreate"; "/dev/sda1"];
1489        ["pvcreate"; "/dev/sda2"];
1490        ["pvcreate"; "/dev/sda3"];
1491        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1492        ["vgcreate"; "VG2"; "/dev/sda3"];
1493        ["lvcreate"; "LV1"; "VG1"; "50"];
1494        ["lvcreate"; "LV2"; "VG1"; "50"];
1495        ["lvcreate"; "LV3"; "VG2"; "50"];
1496        ["lvcreate"; "LV4"; "VG2"; "50"];
1497        ["lvcreate"; "LV5"; "VG2"; "50"];
1498        ["lvs"]],
1499       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1500        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1501    "create an LVM logical volume",
1502    "\
1503 This creates an LVM logical volume called C<logvol>
1504 on the volume group C<volgroup>, with C<size> megabytes.");
1505
1506   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1507    [InitEmpty, Always, TestOutput (
1508       [["part_disk"; "/dev/sda"; "mbr"];
1509        ["mkfs"; "ext2"; "/dev/sda1"];
1510        ["mount_options"; ""; "/dev/sda1"; "/"];
1511        ["write"; "/new"; "new file contents"];
1512        ["cat"; "/new"]], "new file contents")],
1513    "make a filesystem",
1514    "\
1515 This creates a filesystem on C<device> (usually a partition
1516 or LVM logical volume).  The filesystem type is C<fstype>, for
1517 example C<ext3>.");
1518
1519   ("sfdisk", (RErr, [Device "device";
1520                      Int "cyls"; Int "heads"; Int "sectors";
1521                      StringList "lines"]), 43, [DangerWillRobinson],
1522    [],
1523    "create partitions on a block device",
1524    "\
1525 This is a direct interface to the L<sfdisk(8)> program for creating
1526 partitions on block devices.
1527
1528 C<device> should be a block device, for example C</dev/sda>.
1529
1530 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1531 and sectors on the device, which are passed directly to sfdisk as
1532 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1533 of these, then the corresponding parameter is omitted.  Usually for
1534 'large' disks, you can just pass C<0> for these, but for small
1535 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1536 out the right geometry and you will need to tell it.
1537
1538 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1539 information refer to the L<sfdisk(8)> manpage.
1540
1541 To create a single partition occupying the whole disk, you would
1542 pass C<lines> as a single element list, when the single element being
1543 the string C<,> (comma).
1544
1545 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1546 C<guestfs_part_init>");
1547
1548   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1549    (* Regression test for RHBZ#597135. *)
1550    [InitBasicFS, Always, TestLastFail
1551       [["write_file"; "/new"; "abc"; "10000"]]],
1552    "create a file",
1553    "\
1554 This call creates a file called C<path>.  The contents of the
1555 file is the string C<content> (which can contain any 8 bit data),
1556 with length C<size>.
1557
1558 As a special case, if C<size> is C<0>
1559 then the length is calculated using C<strlen> (so in this case
1560 the content cannot contain embedded ASCII NULs).
1561
1562 I<NB.> Owing to a bug, writing content containing ASCII NUL
1563 characters does I<not> work, even if the length is specified.");
1564
1565   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1566    [InitEmpty, Always, TestOutputListOfDevices (
1567       [["part_disk"; "/dev/sda"; "mbr"];
1568        ["mkfs"; "ext2"; "/dev/sda1"];
1569        ["mount_options"; ""; "/dev/sda1"; "/"];
1570        ["mounts"]], ["/dev/sda1"]);
1571     InitEmpty, Always, TestOutputList (
1572       [["part_disk"; "/dev/sda"; "mbr"];
1573        ["mkfs"; "ext2"; "/dev/sda1"];
1574        ["mount_options"; ""; "/dev/sda1"; "/"];
1575        ["umount"; "/"];
1576        ["mounts"]], [])],
1577    "unmount a filesystem",
1578    "\
1579 This unmounts the given filesystem.  The filesystem may be
1580 specified either by its mountpoint (path) or the device which
1581 contains the filesystem.");
1582
1583   ("mounts", (RStringList "devices", []), 46, [],
1584    [InitBasicFS, Always, TestOutputListOfDevices (
1585       [["mounts"]], ["/dev/sda1"])],
1586    "show mounted filesystems",
1587    "\
1588 This returns the list of currently mounted filesystems.  It returns
1589 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1590
1591 Some internal mounts are not shown.
1592
1593 See also: C<guestfs_mountpoints>");
1594
1595   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1596    [InitBasicFS, Always, TestOutputList (
1597       [["umount_all"];
1598        ["mounts"]], []);
1599     (* check that umount_all can unmount nested mounts correctly: *)
1600     InitEmpty, Always, TestOutputList (
1601       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1602        ["mkfs"; "ext2"; "/dev/sda1"];
1603        ["mkfs"; "ext2"; "/dev/sda2"];
1604        ["mkfs"; "ext2"; "/dev/sda3"];
1605        ["mount_options"; ""; "/dev/sda1"; "/"];
1606        ["mkdir"; "/mp1"];
1607        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1608        ["mkdir"; "/mp1/mp2"];
1609        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1610        ["mkdir"; "/mp1/mp2/mp3"];
1611        ["umount_all"];
1612        ["mounts"]], [])],
1613    "unmount all filesystems",
1614    "\
1615 This unmounts all mounted filesystems.
1616
1617 Some internal mounts are not unmounted by this call.");
1618
1619   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1620    [],
1621    "remove all LVM LVs, VGs and PVs",
1622    "\
1623 This command removes all LVM logical volumes, volume groups
1624 and physical volumes.");
1625
1626   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1627    [InitISOFS, Always, TestOutput (
1628       [["file"; "/empty"]], "empty");
1629     InitISOFS, Always, TestOutput (
1630       [["file"; "/known-1"]], "ASCII text");
1631     InitISOFS, Always, TestLastFail (
1632       [["file"; "/notexists"]])],
1633    "determine file type",
1634    "\
1635 This call uses the standard L<file(1)> command to determine
1636 the type or contents of the file.  This also works on devices,
1637 for example to find out whether a partition contains a filesystem.
1638
1639 This call will also transparently look inside various types
1640 of compressed file.
1641
1642 The exact command which runs is C<file -zbsL path>.  Note in
1643 particular that the filename is not prepended to the output
1644 (the C<-b> option).");
1645
1646   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1647    [InitBasicFS, Always, TestOutput (
1648       [["upload"; "test-command"; "/test-command"];
1649        ["chmod"; "0o755"; "/test-command"];
1650        ["command"; "/test-command 1"]], "Result1");
1651     InitBasicFS, Always, TestOutput (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command"; "/test-command 2"]], "Result2\n");
1655     InitBasicFS, Always, TestOutput (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command"; "/test-command 3"]], "\nResult3");
1659     InitBasicFS, Always, TestOutput (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command"; "/test-command 4"]], "\nResult4\n");
1663     InitBasicFS, Always, TestOutput (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command"; "/test-command 5"]], "\nResult5\n\n");
1667     InitBasicFS, Always, TestOutput (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1671     InitBasicFS, Always, TestOutput (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command"; "/test-command 7"]], "");
1675     InitBasicFS, Always, TestOutput (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command"; "/test-command 8"]], "\n");
1679     InitBasicFS, Always, TestOutput (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command"; "/test-command 9"]], "\n\n");
1683     InitBasicFS, Always, TestOutput (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1687     InitBasicFS, Always, TestOutput (
1688       [["upload"; "test-command"; "/test-command"];
1689        ["chmod"; "0o755"; "/test-command"];
1690        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1691     InitBasicFS, Always, TestLastFail (
1692       [["upload"; "test-command"; "/test-command"];
1693        ["chmod"; "0o755"; "/test-command"];
1694        ["command"; "/test-command"]])],
1695    "run a command from the guest filesystem",
1696    "\
1697 This call runs a command from the guest filesystem.  The
1698 filesystem must be mounted, and must contain a compatible
1699 operating system (ie. something Linux, with the same
1700 or compatible processor architecture).
1701
1702 The single parameter is an argv-style list of arguments.
1703 The first element is the name of the program to run.
1704 Subsequent elements are parameters.  The list must be
1705 non-empty (ie. must contain a program name).  Note that
1706 the command runs directly, and is I<not> invoked via
1707 the shell (see C<guestfs_sh>).
1708
1709 The return value is anything printed to I<stdout> by
1710 the command.
1711
1712 If the command returns a non-zero exit status, then
1713 this function returns an error message.  The error message
1714 string is the content of I<stderr> from the command.
1715
1716 The C<$PATH> environment variable will contain at least
1717 C</usr/bin> and C</bin>.  If you require a program from
1718 another location, you should provide the full path in the
1719 first parameter.
1720
1721 Shared libraries and data files required by the program
1722 must be available on filesystems which are mounted in the
1723 correct places.  It is the caller's responsibility to ensure
1724 all filesystems that are needed are mounted at the right
1725 locations.");
1726
1727   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1728    [InitBasicFS, Always, TestOutputList (
1729       [["upload"; "test-command"; "/test-command"];
1730        ["chmod"; "0o755"; "/test-command"];
1731        ["command_lines"; "/test-command 1"]], ["Result1"]);
1732     InitBasicFS, Always, TestOutputList (
1733       [["upload"; "test-command"; "/test-command"];
1734        ["chmod"; "0o755"; "/test-command"];
1735        ["command_lines"; "/test-command 2"]], ["Result2"]);
1736     InitBasicFS, Always, TestOutputList (
1737       [["upload"; "test-command"; "/test-command"];
1738        ["chmod"; "0o755"; "/test-command"];
1739        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1740     InitBasicFS, Always, TestOutputList (
1741       [["upload"; "test-command"; "/test-command"];
1742        ["chmod"; "0o755"; "/test-command"];
1743        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1744     InitBasicFS, Always, TestOutputList (
1745       [["upload"; "test-command"; "/test-command"];
1746        ["chmod"; "0o755"; "/test-command"];
1747        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1748     InitBasicFS, Always, TestOutputList (
1749       [["upload"; "test-command"; "/test-command"];
1750        ["chmod"; "0o755"; "/test-command"];
1751        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1752     InitBasicFS, Always, TestOutputList (
1753       [["upload"; "test-command"; "/test-command"];
1754        ["chmod"; "0o755"; "/test-command"];
1755        ["command_lines"; "/test-command 7"]], []);
1756     InitBasicFS, Always, TestOutputList (
1757       [["upload"; "test-command"; "/test-command"];
1758        ["chmod"; "0o755"; "/test-command"];
1759        ["command_lines"; "/test-command 8"]], [""]);
1760     InitBasicFS, Always, TestOutputList (
1761       [["upload"; "test-command"; "/test-command"];
1762        ["chmod"; "0o755"; "/test-command"];
1763        ["command_lines"; "/test-command 9"]], ["";""]);
1764     InitBasicFS, Always, TestOutputList (
1765       [["upload"; "test-command"; "/test-command"];
1766        ["chmod"; "0o755"; "/test-command"];
1767        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1768     InitBasicFS, Always, TestOutputList (
1769       [["upload"; "test-command"; "/test-command"];
1770        ["chmod"; "0o755"; "/test-command"];
1771        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1772    "run a command, returning lines",
1773    "\
1774 This is the same as C<guestfs_command>, but splits the
1775 result into a list of lines.
1776
1777 See also: C<guestfs_sh_lines>");
1778
1779   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1780    [InitISOFS, Always, TestOutputStruct (
1781       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1782    "get file information",
1783    "\
1784 Returns file information for the given C<path>.
1785
1786 This is the same as the C<stat(2)> system call.");
1787
1788   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1789    [InitISOFS, Always, TestOutputStruct (
1790       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1791    "get file information for a symbolic link",
1792    "\
1793 Returns file information for the given C<path>.
1794
1795 This is the same as C<guestfs_stat> except that if C<path>
1796 is a symbolic link, then the link is stat-ed, not the file it
1797 refers to.
1798
1799 This is the same as the C<lstat(2)> system call.");
1800
1801   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1802    [InitISOFS, Always, TestOutputStruct (
1803       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1804    "get file system statistics",
1805    "\
1806 Returns file system statistics for any mounted file system.
1807 C<path> should be a file or directory in the mounted file system
1808 (typically it is the mount point itself, but it doesn't need to be).
1809
1810 This is the same as the C<statvfs(2)> system call.");
1811
1812   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1813    [], (* XXX test *)
1814    "get ext2/ext3/ext4 superblock details",
1815    "\
1816 This returns the contents of the ext2, ext3 or ext4 filesystem
1817 superblock on C<device>.
1818
1819 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1820 manpage for more details.  The list of fields returned isn't
1821 clearly defined, and depends on both the version of C<tune2fs>
1822 that libguestfs was built against, and the filesystem itself.");
1823
1824   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1825    [InitEmpty, Always, TestOutputTrue (
1826       [["blockdev_setro"; "/dev/sda"];
1827        ["blockdev_getro"; "/dev/sda"]])],
1828    "set block device to read-only",
1829    "\
1830 Sets the block device named C<device> to read-only.
1831
1832 This uses the L<blockdev(8)> command.");
1833
1834   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1835    [InitEmpty, Always, TestOutputFalse (
1836       [["blockdev_setrw"; "/dev/sda"];
1837        ["blockdev_getro"; "/dev/sda"]])],
1838    "set block device to read-write",
1839    "\
1840 Sets the block device named C<device> to read-write.
1841
1842 This uses the L<blockdev(8)> command.");
1843
1844   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1845    [InitEmpty, Always, TestOutputTrue (
1846       [["blockdev_setro"; "/dev/sda"];
1847        ["blockdev_getro"; "/dev/sda"]])],
1848    "is block device set to read-only",
1849    "\
1850 Returns a boolean indicating if the block device is read-only
1851 (true if read-only, false if not).
1852
1853 This uses the L<blockdev(8)> command.");
1854
1855   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1856    [InitEmpty, Always, TestOutputInt (
1857       [["blockdev_getss"; "/dev/sda"]], 512)],
1858    "get sectorsize of block device",
1859    "\
1860 This returns the size of sectors on a block device.
1861 Usually 512, but can be larger for modern devices.
1862
1863 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1864 for that).
1865
1866 This uses the L<blockdev(8)> command.");
1867
1868   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1869    [InitEmpty, Always, TestOutputInt (
1870       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1871    "get blocksize of block device",
1872    "\
1873 This returns the block size of a device.
1874
1875 (Note this is different from both I<size in blocks> and
1876 I<filesystem block size>).
1877
1878 This uses the L<blockdev(8)> command.");
1879
1880   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1881    [], (* XXX test *)
1882    "set blocksize of block device",
1883    "\
1884 This sets the block size of a device.
1885
1886 (Note this is different from both I<size in blocks> and
1887 I<filesystem block size>).
1888
1889 This uses the L<blockdev(8)> command.");
1890
1891   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1892    [InitEmpty, Always, TestOutputInt (
1893       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1894    "get total size of device in 512-byte sectors",
1895    "\
1896 This returns the size of the device in units of 512-byte sectors
1897 (even if the sectorsize isn't 512 bytes ... weird).
1898
1899 See also C<guestfs_blockdev_getss> for the real sector size of
1900 the device, and C<guestfs_blockdev_getsize64> for the more
1901 useful I<size in bytes>.
1902
1903 This uses the L<blockdev(8)> command.");
1904
1905   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1906    [InitEmpty, Always, TestOutputInt (
1907       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1908    "get total size of device in bytes",
1909    "\
1910 This returns the size of the device in bytes.
1911
1912 See also C<guestfs_blockdev_getsz>.
1913
1914 This uses the L<blockdev(8)> command.");
1915
1916   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1917    [InitEmpty, Always, TestRun
1918       [["blockdev_flushbufs"; "/dev/sda"]]],
1919    "flush device buffers",
1920    "\
1921 This tells the kernel to flush internal buffers associated
1922 with C<device>.
1923
1924 This uses the L<blockdev(8)> command.");
1925
1926   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1927    [InitEmpty, Always, TestRun
1928       [["blockdev_rereadpt"; "/dev/sda"]]],
1929    "reread partition table",
1930    "\
1931 Reread the partition table on C<device>.
1932
1933 This uses the L<blockdev(8)> command.");
1934
1935   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1936    [InitBasicFS, Always, TestOutput (
1937       (* Pick a file from cwd which isn't likely to change. *)
1938       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1939        ["checksum"; "md5"; "/COPYING.LIB"]],
1940       Digest.to_hex (Digest.file "COPYING.LIB"))],
1941    "upload a file from the local machine",
1942    "\
1943 Upload local file C<filename> to C<remotefilename> on the
1944 filesystem.
1945
1946 C<filename> can also be a named pipe.
1947
1948 See also C<guestfs_download>.");
1949
1950   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1951    [InitBasicFS, Always, TestOutput (
1952       (* Pick a file from cwd which isn't likely to change. *)
1953       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1954        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1955        ["upload"; "testdownload.tmp"; "/upload"];
1956        ["checksum"; "md5"; "/upload"]],
1957       Digest.to_hex (Digest.file "COPYING.LIB"))],
1958    "download a file to the local machine",
1959    "\
1960 Download file C<remotefilename> and save it as C<filename>
1961 on the local machine.
1962
1963 C<filename> can also be a named pipe.
1964
1965 See also C<guestfs_upload>, C<guestfs_cat>.");
1966
1967   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1968    [InitISOFS, Always, TestOutput (
1969       [["checksum"; "crc"; "/known-3"]], "2891671662");
1970     InitISOFS, Always, TestLastFail (
1971       [["checksum"; "crc"; "/notexists"]]);
1972     InitISOFS, Always, TestOutput (
1973       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1978     InitISOFS, Always, TestOutput (
1979       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1980     InitISOFS, Always, TestOutput (
1981       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1982     InitISOFS, Always, TestOutput (
1983       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1984     (* Test for RHBZ#579608, absolute symbolic links. *)
1985     InitISOFS, Always, TestOutput (
1986       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1987    "compute MD5, SHAx or CRC checksum of file",
1988    "\
1989 This call computes the MD5, SHAx or CRC checksum of the
1990 file named C<path>.
1991
1992 The type of checksum to compute is given by the C<csumtype>
1993 parameter which must have one of the following values:
1994
1995 =over 4
1996
1997 =item C<crc>
1998
1999 Compute the cyclic redundancy check (CRC) specified by POSIX
2000 for the C<cksum> command.
2001
2002 =item C<md5>
2003
2004 Compute the MD5 hash (using the C<md5sum> program).
2005
2006 =item C<sha1>
2007
2008 Compute the SHA1 hash (using the C<sha1sum> program).
2009
2010 =item C<sha224>
2011
2012 Compute the SHA224 hash (using the C<sha224sum> program).
2013
2014 =item C<sha256>
2015
2016 Compute the SHA256 hash (using the C<sha256sum> program).
2017
2018 =item C<sha384>
2019
2020 Compute the SHA384 hash (using the C<sha384sum> program).
2021
2022 =item C<sha512>
2023
2024 Compute the SHA512 hash (using the C<sha512sum> program).
2025
2026 =back
2027
2028 The checksum is returned as a printable string.
2029
2030 To get the checksum for a device, use C<guestfs_checksum_device>.
2031
2032 To get the checksums for many files, use C<guestfs_checksums_out>.");
2033
2034   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2035    [InitBasicFS, Always, TestOutput (
2036       [["tar_in"; "../images/helloworld.tar"; "/"];
2037        ["cat"; "/hello"]], "hello\n")],
2038    "unpack tarfile to directory",
2039    "\
2040 This command uploads and unpacks local file C<tarfile> (an
2041 I<uncompressed> tar file) into C<directory>.
2042
2043 To upload a compressed tarball, use C<guestfs_tgz_in>
2044 or C<guestfs_txz_in>.");
2045
2046   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2047    [],
2048    "pack directory into tarfile",
2049    "\
2050 This command packs the contents of C<directory> and downloads
2051 it to local file C<tarfile>.
2052
2053 To download a compressed tarball, use C<guestfs_tgz_out>
2054 or C<guestfs_txz_out>.");
2055
2056   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2057    [InitBasicFS, Always, TestOutput (
2058       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2059        ["cat"; "/hello"]], "hello\n")],
2060    "unpack compressed tarball to directory",
2061    "\
2062 This command uploads and unpacks local file C<tarball> (a
2063 I<gzip compressed> tar file) into C<directory>.
2064
2065 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2066
2067   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2068    [],
2069    "pack directory into compressed tarball",
2070    "\
2071 This command packs the contents of C<directory> and downloads
2072 it to local file C<tarball>.
2073
2074 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2075
2076   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2077    [InitBasicFS, Always, TestLastFail (
2078       [["umount"; "/"];
2079        ["mount_ro"; "/dev/sda1"; "/"];
2080        ["touch"; "/new"]]);
2081     InitBasicFS, Always, TestOutput (
2082       [["write"; "/new"; "data"];
2083        ["umount"; "/"];
2084        ["mount_ro"; "/dev/sda1"; "/"];
2085        ["cat"; "/new"]], "data")],
2086    "mount a guest disk, read-only",
2087    "\
2088 This is the same as the C<guestfs_mount> command, but it
2089 mounts the filesystem with the read-only (I<-o ro>) flag.");
2090
2091   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2092    [],
2093    "mount a guest disk with mount options",
2094    "\
2095 This is the same as the C<guestfs_mount> command, but it
2096 allows you to set the mount options as for the
2097 L<mount(8)> I<-o> flag.
2098
2099 If the C<options> parameter is an empty string, then
2100 no options are passed (all options default to whatever
2101 the filesystem uses).");
2102
2103   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2104    [],
2105    "mount a guest disk with mount options and vfstype",
2106    "\
2107 This is the same as the C<guestfs_mount> command, but it
2108 allows you to set both the mount options and the vfstype
2109 as for the L<mount(8)> I<-o> and I<-t> flags.");
2110
2111   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2112    [],
2113    "debugging and internals",
2114    "\
2115 The C<guestfs_debug> command exposes some internals of
2116 C<guestfsd> (the guestfs daemon) that runs inside the
2117 qemu subprocess.
2118
2119 There is no comprehensive help for this command.  You have
2120 to look at the file C<daemon/debug.c> in the libguestfs source
2121 to find out what you can do.");
2122
2123   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2124    [InitEmpty, Always, TestOutputList (
2125       [["part_disk"; "/dev/sda"; "mbr"];
2126        ["pvcreate"; "/dev/sda1"];
2127        ["vgcreate"; "VG"; "/dev/sda1"];
2128        ["lvcreate"; "LV1"; "VG"; "50"];
2129        ["lvcreate"; "LV2"; "VG"; "50"];
2130        ["lvremove"; "/dev/VG/LV1"];
2131        ["lvs"]], ["/dev/VG/LV2"]);
2132     InitEmpty, Always, TestOutputList (
2133       [["part_disk"; "/dev/sda"; "mbr"];
2134        ["pvcreate"; "/dev/sda1"];
2135        ["vgcreate"; "VG"; "/dev/sda1"];
2136        ["lvcreate"; "LV1"; "VG"; "50"];
2137        ["lvcreate"; "LV2"; "VG"; "50"];
2138        ["lvremove"; "/dev/VG"];
2139        ["lvs"]], []);
2140     InitEmpty, Always, TestOutputList (
2141       [["part_disk"; "/dev/sda"; "mbr"];
2142        ["pvcreate"; "/dev/sda1"];
2143        ["vgcreate"; "VG"; "/dev/sda1"];
2144        ["lvcreate"; "LV1"; "VG"; "50"];
2145        ["lvcreate"; "LV2"; "VG"; "50"];
2146        ["lvremove"; "/dev/VG"];
2147        ["vgs"]], ["VG"])],
2148    "remove an LVM logical volume",
2149    "\
2150 Remove an LVM logical volume C<device>, where C<device> is
2151 the path to the LV, such as C</dev/VG/LV>.
2152
2153 You can also remove all LVs in a volume group by specifying
2154 the VG name, C</dev/VG>.");
2155
2156   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2157    [InitEmpty, Always, TestOutputList (
2158       [["part_disk"; "/dev/sda"; "mbr"];
2159        ["pvcreate"; "/dev/sda1"];
2160        ["vgcreate"; "VG"; "/dev/sda1"];
2161        ["lvcreate"; "LV1"; "VG"; "50"];
2162        ["lvcreate"; "LV2"; "VG"; "50"];
2163        ["vgremove"; "VG"];
2164        ["lvs"]], []);
2165     InitEmpty, Always, TestOutputList (
2166       [["part_disk"; "/dev/sda"; "mbr"];
2167        ["pvcreate"; "/dev/sda1"];
2168        ["vgcreate"; "VG"; "/dev/sda1"];
2169        ["lvcreate"; "LV1"; "VG"; "50"];
2170        ["lvcreate"; "LV2"; "VG"; "50"];
2171        ["vgremove"; "VG"];
2172        ["vgs"]], [])],
2173    "remove an LVM volume group",
2174    "\
2175 Remove an LVM volume group C<vgname>, (for example C<VG>).
2176
2177 This also forcibly removes all logical volumes in the volume
2178 group (if any).");
2179
2180   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
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        ["lvs"]], []);
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        ["vgs"]], []);
2199     InitEmpty, Always, TestOutputListOfDevices (
2200       [["part_disk"; "/dev/sda"; "mbr"];
2201        ["pvcreate"; "/dev/sda1"];
2202        ["vgcreate"; "VG"; "/dev/sda1"];
2203        ["lvcreate"; "LV1"; "VG"; "50"];
2204        ["lvcreate"; "LV2"; "VG"; "50"];
2205        ["vgremove"; "VG"];
2206        ["pvremove"; "/dev/sda1"];
2207        ["pvs"]], [])],
2208    "remove an LVM physical volume",
2209    "\
2210 This wipes a physical volume C<device> so that LVM will no longer
2211 recognise it.
2212
2213 The implementation uses the C<pvremove> command which refuses to
2214 wipe physical volumes that contain any volume groups, so you have
2215 to remove those first.");
2216
2217   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2218    [InitBasicFS, Always, TestOutput (
2219       [["set_e2label"; "/dev/sda1"; "testlabel"];
2220        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2221    "set the ext2/3/4 filesystem label",
2222    "\
2223 This sets the ext2/3/4 filesystem label of the filesystem on
2224 C<device> to C<label>.  Filesystem labels are limited to
2225 16 characters.
2226
2227 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2228 to return the existing label on a filesystem.");
2229
2230   ("get_e2label", (RString "label", [Device "device"]), 81, [DeprecatedBy "vfs_label"],
2231    [],
2232    "get the ext2/3/4 filesystem label",
2233    "\
2234 This returns the ext2/3/4 filesystem label of the filesystem on
2235 C<device>.");
2236
2237   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2238    (let uuid = uuidgen () in
2239     [InitBasicFS, Always, TestOutput (
2240        [["set_e2uuid"; "/dev/sda1"; uuid];
2241         ["get_e2uuid"; "/dev/sda1"]], uuid);
2242      InitBasicFS, Always, TestOutput (
2243        [["set_e2uuid"; "/dev/sda1"; "clear"];
2244         ["get_e2uuid"; "/dev/sda1"]], "");
2245      (* We can't predict what UUIDs will be, so just check the commands run. *)
2246      InitBasicFS, Always, TestRun (
2247        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2248      InitBasicFS, Always, TestRun (
2249        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2250    "set the ext2/3/4 filesystem UUID",
2251    "\
2252 This sets the ext2/3/4 filesystem UUID of the filesystem on
2253 C<device> to C<uuid>.  The format of the UUID and alternatives
2254 such as C<clear>, C<random> and C<time> are described in the
2255 L<tune2fs(8)> manpage.
2256
2257 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2258 to return the existing UUID of a filesystem.");
2259
2260   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [DeprecatedBy "vfs_uuid"],
2261    (* Regression test for RHBZ#597112. *)
2262    (let uuid = uuidgen () in
2263     [InitBasicFS, Always, TestOutput (
2264        [["mke2journal"; "1024"; "/dev/sdb"];
2265         ["set_e2uuid"; "/dev/sdb"; uuid];
2266         ["get_e2uuid"; "/dev/sdb"]], uuid)]),
2267    "get the ext2/3/4 filesystem UUID",
2268    "\
2269 This returns the ext2/3/4 filesystem UUID of the filesystem on
2270 C<device>.");
2271
2272   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2273    [InitBasicFS, Always, TestOutputInt (
2274       [["umount"; "/dev/sda1"];
2275        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2276     InitBasicFS, Always, TestOutputInt (
2277       [["umount"; "/dev/sda1"];
2278        ["zero"; "/dev/sda1"];
2279        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2280    "run the filesystem checker",
2281    "\
2282 This runs the filesystem checker (fsck) on C<device> which
2283 should have filesystem type C<fstype>.
2284
2285 The returned integer is the status.  See L<fsck(8)> for the
2286 list of status codes from C<fsck>.
2287
2288 Notes:
2289
2290 =over 4
2291
2292 =item *
2293
2294 Multiple status codes can be summed together.
2295
2296 =item *
2297
2298 A non-zero return code can mean \"success\", for example if
2299 errors have been corrected on the filesystem.
2300
2301 =item *
2302
2303 Checking or repairing NTFS volumes is not supported
2304 (by linux-ntfs).
2305
2306 =back
2307
2308 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2309
2310   ("zero", (RErr, [Device "device"]), 85, [],
2311    [InitBasicFS, Always, TestOutput (
2312       [["umount"; "/dev/sda1"];
2313        ["zero"; "/dev/sda1"];
2314        ["file"; "/dev/sda1"]], "data")],
2315    "write zeroes to the device",
2316    "\
2317 This command writes zeroes over the first few blocks of C<device>.
2318
2319 How many blocks are zeroed isn't specified (but it's I<not> enough
2320 to securely wipe the device).  It should be sufficient to remove
2321 any partition tables, filesystem superblocks and so on.
2322
2323 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2324
2325   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2326    (* See:
2327     * https://bugzilla.redhat.com/show_bug.cgi?id=484986
2328     * https://bugzilla.redhat.com/show_bug.cgi?id=479760
2329     *)
2330    [InitBasicFS, Always, TestOutputTrue (
2331       [["mkdir_p"; "/boot/grub"];
2332        ["write"; "/boot/grub/device.map"; "(hd0) /dev/vda"];
2333        ["grub_install"; "/"; "/dev/vda"];
2334        ["is_dir"; "/boot"]])],
2335    "install GRUB",
2336    "\
2337 This command installs GRUB (the Grand Unified Bootloader) on
2338 C<device>, with the root directory being C<root>.
2339
2340 Note: If grub-install reports the error
2341 \"No suitable drive was found in the generated device map.\"
2342 it may be that you need to create a C</boot/grub/device.map>
2343 file first that contains the mapping between grub device names
2344 and Linux device names.  It is usually sufficient to create
2345 a file containing:
2346
2347  (hd0) /dev/vda
2348
2349 replacing C</dev/vda> with the name of the installation device.");
2350
2351   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2352    [InitBasicFS, Always, TestOutput (
2353       [["write"; "/old"; "file content"];
2354        ["cp"; "/old"; "/new"];
2355        ["cat"; "/new"]], "file content");
2356     InitBasicFS, Always, TestOutputTrue (
2357       [["write"; "/old"; "file content"];
2358        ["cp"; "/old"; "/new"];
2359        ["is_file"; "/old"]]);
2360     InitBasicFS, Always, TestOutput (
2361       [["write"; "/old"; "file content"];
2362        ["mkdir"; "/dir"];
2363        ["cp"; "/old"; "/dir/new"];
2364        ["cat"; "/dir/new"]], "file content")],
2365    "copy a file",
2366    "\
2367 This copies a file from C<src> to C<dest> where C<dest> is
2368 either a destination filename or destination directory.");
2369
2370   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2371    [InitBasicFS, Always, TestOutput (
2372       [["mkdir"; "/olddir"];
2373        ["mkdir"; "/newdir"];
2374        ["write"; "/olddir/file"; "file content"];
2375        ["cp_a"; "/olddir"; "/newdir"];
2376        ["cat"; "/newdir/olddir/file"]], "file content")],
2377    "copy a file or directory recursively",
2378    "\
2379 This copies a file or directory from C<src> to C<dest>
2380 recursively using the C<cp -a> command.");
2381
2382   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2383    [InitBasicFS, Always, TestOutput (
2384       [["write"; "/old"; "file content"];
2385        ["mv"; "/old"; "/new"];
2386        ["cat"; "/new"]], "file content");
2387     InitBasicFS, Always, TestOutputFalse (
2388       [["write"; "/old"; "file content"];
2389        ["mv"; "/old"; "/new"];
2390        ["is_file"; "/old"]])],
2391    "move a file",
2392    "\
2393 This moves a file from C<src> to C<dest> where C<dest> is
2394 either a destination filename or destination directory.");
2395
2396   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2397    [InitEmpty, Always, TestRun (
2398       [["drop_caches"; "3"]])],
2399    "drop kernel page cache, dentries and inodes",
2400    "\
2401 This instructs the guest kernel to drop its page cache,
2402 and/or dentries and inode caches.  The parameter C<whattodrop>
2403 tells the kernel what precisely to drop, see
2404 L<http://linux-mm.org/Drop_Caches>
2405
2406 Setting C<whattodrop> to 3 should drop everything.
2407
2408 This automatically calls L<sync(2)> before the operation,
2409 so that the maximum guest memory is freed.");
2410
2411   ("dmesg", (RString "kmsgs", []), 91, [],
2412    [InitEmpty, Always, TestRun (
2413       [["dmesg"]])],
2414    "return kernel messages",
2415    "\
2416 This returns the kernel messages (C<dmesg> output) from
2417 the guest kernel.  This is sometimes useful for extended
2418 debugging of problems.
2419
2420 Another way to get the same information is to enable
2421 verbose messages with C<guestfs_set_verbose> or by setting
2422 the environment variable C<LIBGUESTFS_DEBUG=1> before
2423 running the program.");
2424
2425   ("ping_daemon", (RErr, []), 92, [],
2426    [InitEmpty, Always, TestRun (
2427       [["ping_daemon"]])],
2428    "ping the guest daemon",
2429    "\
2430 This is a test probe into the guestfs daemon running inside
2431 the qemu subprocess.  Calling this function checks that the
2432 daemon responds to the ping message, without affecting the daemon
2433 or attached block device(s) in any other way.");
2434
2435   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2436    [InitBasicFS, Always, TestOutputTrue (
2437       [["write"; "/file1"; "contents of a file"];
2438        ["cp"; "/file1"; "/file2"];
2439        ["equal"; "/file1"; "/file2"]]);
2440     InitBasicFS, Always, TestOutputFalse (
2441       [["write"; "/file1"; "contents of a file"];
2442        ["write"; "/file2"; "contents of another file"];
2443        ["equal"; "/file1"; "/file2"]]);
2444     InitBasicFS, Always, TestLastFail (
2445       [["equal"; "/file1"; "/file2"]])],
2446    "test if two files have equal contents",
2447    "\
2448 This compares the two files C<file1> and C<file2> and returns
2449 true if their content is exactly equal, or false otherwise.
2450
2451 The external L<cmp(1)> program is used for the comparison.");
2452
2453   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2454    [InitISOFS, Always, TestOutputList (
2455       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2456     InitISOFS, Always, TestOutputList (
2457       [["strings"; "/empty"]], []);
2458     (* Test for RHBZ#579608, absolute symbolic links. *)
2459     InitISOFS, Always, TestRun (
2460       [["strings"; "/abssymlink"]])],
2461    "print the printable strings in a file",
2462    "\
2463 This runs the L<strings(1)> command on a file and returns
2464 the list of printable strings found.");
2465
2466   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2467    [InitISOFS, Always, TestOutputList (
2468       [["strings_e"; "b"; "/known-5"]], []);
2469     InitBasicFS, Always, TestOutputList (
2470       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2471        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2472    "print the printable strings in a file",
2473    "\
2474 This is like the C<guestfs_strings> command, but allows you to
2475 specify the encoding of strings that are looked for in
2476 the source file C<path>.
2477
2478 Allowed encodings are:
2479
2480 =over 4
2481
2482 =item s
2483
2484 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2485 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2486
2487 =item S
2488
2489 Single 8-bit-byte characters.
2490
2491 =item b
2492
2493 16-bit big endian strings such as those encoded in
2494 UTF-16BE or UCS-2BE.
2495
2496 =item l (lower case letter L)
2497
2498 16-bit little endian such as UTF-16LE and UCS-2LE.
2499 This is useful for examining binaries in Windows guests.
2500
2501 =item B
2502
2503 32-bit big endian such as UCS-4BE.
2504
2505 =item L
2506
2507 32-bit little endian such as UCS-4LE.
2508
2509 =back
2510
2511 The returned strings are transcoded to UTF-8.");
2512
2513   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2514    [InitISOFS, Always, TestOutput (
2515       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2516     (* Test for RHBZ#501888c2 regression which caused large hexdump
2517      * commands to segfault.
2518      *)
2519     InitISOFS, Always, TestRun (
2520       [["hexdump"; "/100krandom"]]);
2521     (* Test for RHBZ#579608, absolute symbolic links. *)
2522     InitISOFS, Always, TestRun (
2523       [["hexdump"; "/abssymlink"]])],
2524    "dump a file in hexadecimal",
2525    "\
2526 This runs C<hexdump -C> on the given C<path>.  The result is
2527 the human-readable, canonical hex dump of the file.");
2528
2529   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2530    [InitNone, Always, TestOutput (
2531       [["part_disk"; "/dev/sda"; "mbr"];
2532        ["mkfs"; "ext3"; "/dev/sda1"];
2533        ["mount_options"; ""; "/dev/sda1"; "/"];
2534        ["write"; "/new"; "test file"];
2535        ["umount"; "/dev/sda1"];
2536        ["zerofree"; "/dev/sda1"];
2537        ["mount_options"; ""; "/dev/sda1"; "/"];
2538        ["cat"; "/new"]], "test file")],
2539    "zero unused inodes and disk blocks on ext2/3 filesystem",
2540    "\
2541 This runs the I<zerofree> program on C<device>.  This program
2542 claims to zero unused inodes and disk blocks on an ext2/3
2543 filesystem, thus making it possible to compress the filesystem
2544 more effectively.
2545
2546 You should B<not> run this program if the filesystem is
2547 mounted.
2548
2549 It is possible that using this program can damage the filesystem
2550 or data on the filesystem.");
2551
2552   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2553    [],
2554    "resize an LVM physical volume",
2555    "\
2556 This resizes (expands or shrinks) an existing LVM physical
2557 volume to match the new size of the underlying device.");
2558
2559   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2560                        Int "cyls"; Int "heads"; Int "sectors";
2561                        String "line"]), 99, [DangerWillRobinson],
2562    [],
2563    "modify a single partition on a block device",
2564    "\
2565 This runs L<sfdisk(8)> option to modify just the single
2566 partition C<n> (note: C<n> counts from 1).
2567
2568 For other parameters, see C<guestfs_sfdisk>.  You should usually
2569 pass C<0> for the cyls/heads/sectors parameters.
2570
2571 See also: C<guestfs_part_add>");
2572
2573   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2574    [],
2575    "display the partition table",
2576    "\
2577 This displays the partition table on C<device>, in the
2578 human-readable output of the L<sfdisk(8)> command.  It is
2579 not intended to be parsed.
2580
2581 See also: C<guestfs_part_list>");
2582
2583   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2584    [],
2585    "display the kernel geometry",
2586    "\
2587 This displays the kernel's idea of the geometry of C<device>.
2588
2589 The result is in human-readable format, and not designed to
2590 be parsed.");
2591
2592   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2593    [],
2594    "display the disk geometry from the partition table",
2595    "\
2596 This displays the disk geometry of C<device> read from the
2597 partition table.  Especially in the case where the underlying
2598 block device has been resized, this can be different from the
2599 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2600
2601 The result is in human-readable format, and not designed to
2602 be parsed.");
2603
2604   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2605    [],
2606    "activate or deactivate all volume groups",
2607    "\
2608 This command activates or (if C<activate> is false) deactivates
2609 all logical volumes in all volume groups.
2610 If activated, then they are made known to the
2611 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2612 then those devices disappear.
2613
2614 This command is the same as running C<vgchange -a y|n>");
2615
2616   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2617    [],
2618    "activate or deactivate some volume groups",
2619    "\
2620 This command activates or (if C<activate> is false) deactivates
2621 all logical volumes in the listed volume groups C<volgroups>.
2622 If activated, then they are made known to the
2623 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2624 then those devices disappear.
2625
2626 This command is the same as running C<vgchange -a y|n volgroups...>
2627
2628 Note that if C<volgroups> is an empty list then B<all> volume groups
2629 are activated or deactivated.");
2630
2631   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2632    [InitNone, Always, TestOutput (
2633       [["part_disk"; "/dev/sda"; "mbr"];
2634        ["pvcreate"; "/dev/sda1"];
2635        ["vgcreate"; "VG"; "/dev/sda1"];
2636        ["lvcreate"; "LV"; "VG"; "10"];
2637        ["mkfs"; "ext2"; "/dev/VG/LV"];
2638        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2639        ["write"; "/new"; "test content"];
2640        ["umount"; "/"];
2641        ["lvresize"; "/dev/VG/LV"; "20"];
2642        ["e2fsck_f"; "/dev/VG/LV"];
2643        ["resize2fs"; "/dev/VG/LV"];
2644        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2645        ["cat"; "/new"]], "test content");
2646     InitNone, Always, TestRun (
2647       (* Make an LV smaller to test RHBZ#587484. *)
2648       [["part_disk"; "/dev/sda"; "mbr"];
2649        ["pvcreate"; "/dev/sda1"];
2650        ["vgcreate"; "VG"; "/dev/sda1"];
2651        ["lvcreate"; "LV"; "VG"; "20"];
2652        ["lvresize"; "/dev/VG/LV"; "10"]])],
2653    "resize an LVM logical volume",
2654    "\
2655 This resizes (expands or shrinks) an existing LVM logical
2656 volume to C<mbytes>.  When reducing, data in the reduced part
2657 is lost.");
2658
2659   ("resize2fs", (RErr, [Device "device"]), 106, [],
2660    [], (* lvresize tests this *)
2661    "resize an ext2, ext3 or ext4 filesystem",
2662    "\
2663 This resizes an ext2, ext3 or ext4 filesystem to match the size of
2664 the underlying device.
2665
2666 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2667 on the C<device> before calling this command.  For unknown reasons
2668 C<resize2fs> sometimes gives an error about this and sometimes not.
2669 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2670 calling this function.");
2671
2672   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2673    [InitBasicFS, Always, TestOutputList (
2674       [["find"; "/"]], ["lost+found"]);
2675     InitBasicFS, Always, TestOutputList (
2676       [["touch"; "/a"];
2677        ["mkdir"; "/b"];
2678        ["touch"; "/b/c"];
2679        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2680     InitBasicFS, Always, TestOutputList (
2681       [["mkdir_p"; "/a/b/c"];
2682        ["touch"; "/a/b/c/d"];
2683        ["find"; "/a/b/"]], ["c"; "c/d"])],
2684    "find all files and directories",
2685    "\
2686 This command lists out all files and directories, recursively,
2687 starting at C<directory>.  It is essentially equivalent to
2688 running the shell command C<find directory -print> but some
2689 post-processing happens on the output, described below.
2690
2691 This returns a list of strings I<without any prefix>.  Thus
2692 if the directory structure was:
2693
2694  /tmp/a
2695  /tmp/b
2696  /tmp/c/d
2697
2698 then the returned list from C<guestfs_find> C</tmp> would be
2699 4 elements:
2700
2701  a
2702  b
2703  c
2704  c/d
2705
2706 If C<directory> is not a directory, then this command returns
2707 an error.
2708
2709 The returned list is sorted.
2710
2711 See also C<guestfs_find0>.");
2712
2713   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2714    [], (* lvresize tests this *)
2715    "check an ext2/ext3 filesystem",
2716    "\
2717 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2718 filesystem checker on C<device>, noninteractively (C<-p>),
2719 even if the filesystem appears to be clean (C<-f>).
2720
2721 This command is only needed because of C<guestfs_resize2fs>
2722 (q.v.).  Normally you should use C<guestfs_fsck>.");
2723
2724   ("sleep", (RErr, [Int "secs"]), 109, [],
2725    [InitNone, Always, TestRun (
2726       [["sleep"; "1"]])],
2727    "sleep for some seconds",
2728    "\
2729 Sleep for C<secs> seconds.");
2730
2731   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2732    [InitNone, Always, TestOutputInt (
2733       [["part_disk"; "/dev/sda"; "mbr"];
2734        ["mkfs"; "ntfs"; "/dev/sda1"];
2735        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2736     InitNone, Always, TestOutputInt (
2737       [["part_disk"; "/dev/sda"; "mbr"];
2738        ["mkfs"; "ext2"; "/dev/sda1"];
2739        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2740    "probe NTFS volume",
2741    "\
2742 This command runs the L<ntfs-3g.probe(8)> command which probes
2743 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2744 be mounted read-write, and some cannot be mounted at all).
2745
2746 C<rw> is a boolean flag.  Set it to true if you want to test
2747 if the volume can be mounted read-write.  Set it to false if
2748 you want to test if the volume can be mounted read-only.
2749
2750 The return value is an integer which C<0> if the operation
2751 would succeed, or some non-zero value documented in the
2752 L<ntfs-3g.probe(8)> manual page.");
2753
2754   ("sh", (RString "output", [String "command"]), 111, [],
2755    [], (* XXX needs tests *)
2756    "run a command via the shell",
2757    "\
2758 This call runs a command from the guest filesystem via the
2759 guest's C</bin/sh>.
2760
2761 This is like C<guestfs_command>, but passes the command to:
2762
2763  /bin/sh -c \"command\"
2764
2765 Depending on the guest's shell, this usually results in
2766 wildcards being expanded, shell expressions being interpolated
2767 and so on.
2768
2769 All the provisos about C<guestfs_command> apply to this call.");
2770
2771   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2772    [], (* XXX needs tests *)
2773    "run a command via the shell returning lines",
2774    "\
2775 This is the same as C<guestfs_sh>, but splits the result
2776 into a list of lines.
2777
2778 See also: C<guestfs_command_lines>");
2779
2780   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2781    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2782     * code in stubs.c, since all valid glob patterns must start with "/".
2783     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2784     *)
2785    [InitBasicFS, Always, TestOutputList (
2786       [["mkdir_p"; "/a/b/c"];
2787        ["touch"; "/a/b/c/d"];
2788        ["touch"; "/a/b/c/e"];
2789        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2790     InitBasicFS, Always, TestOutputList (
2791       [["mkdir_p"; "/a/b/c"];
2792        ["touch"; "/a/b/c/d"];
2793        ["touch"; "/a/b/c/e"];
2794        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2795     InitBasicFS, Always, TestOutputList (
2796       [["mkdir_p"; "/a/b/c"];
2797        ["touch"; "/a/b/c/d"];
2798        ["touch"; "/a/b/c/e"];
2799        ["glob_expand"; "/a/*/x/*"]], [])],
2800    "expand a wildcard path",
2801    "\
2802 This command searches for all the pathnames matching
2803 C<pattern> according to the wildcard expansion rules
2804 used by the shell.
2805
2806 If no paths match, then this returns an empty list
2807 (note: not an error).
2808
2809 It is just a wrapper around the C L<glob(3)> function
2810 with flags C<GLOB_MARK|GLOB_BRACE>.
2811 See that manual page for more details.");
2812
2813   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2814    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2815       [["scrub_device"; "/dev/sdc"]])],
2816    "scrub (securely wipe) a device",
2817    "\
2818 This command writes patterns over C<device> to make data retrieval
2819 more difficult.
2820
2821 It is an interface to the L<scrub(1)> program.  See that
2822 manual page for more details.");
2823
2824   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2825    [InitBasicFS, Always, TestRun (
2826       [["write"; "/file"; "content"];
2827        ["scrub_file"; "/file"]])],
2828    "scrub (securely wipe) a file",
2829    "\
2830 This command writes patterns over a file to make data retrieval
2831 more difficult.
2832
2833 The file is I<removed> after scrubbing.
2834
2835 It is an interface to the L<scrub(1)> program.  See that
2836 manual page for more details.");
2837
2838   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2839    [], (* XXX needs testing *)
2840    "scrub (securely wipe) free space",
2841    "\
2842 This command creates the directory C<dir> and then fills it
2843 with files until the filesystem is full, and scrubs the files
2844 as for C<guestfs_scrub_file>, and deletes them.
2845 The intention is to scrub any free space on the partition
2846 containing C<dir>.
2847
2848 It is an interface to the L<scrub(1)> program.  See that
2849 manual page for more details.");
2850
2851   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2852    [InitBasicFS, Always, TestRun (
2853       [["mkdir"; "/tmp"];
2854        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2855    "create a temporary directory",
2856    "\
2857 This command creates a temporary directory.  The
2858 C<template> parameter should be a full pathname for the
2859 temporary directory name with the final six characters being
2860 \"XXXXXX\".
2861
2862 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2863 the second one being suitable for Windows filesystems.
2864
2865 The name of the temporary directory that was created
2866 is returned.
2867
2868 The temporary directory is created with mode 0700
2869 and is owned by root.
2870
2871 The caller is responsible for deleting the temporary
2872 directory and its contents after use.
2873
2874 See also: L<mkdtemp(3)>");
2875
2876   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2877    [InitISOFS, Always, TestOutputInt (
2878       [["wc_l"; "/10klines"]], 10000);
2879     (* Test for RHBZ#579608, absolute symbolic links. *)
2880     InitISOFS, Always, TestOutputInt (
2881       [["wc_l"; "/abssymlink"]], 10000)],
2882    "count lines in a file",
2883    "\
2884 This command counts the lines in a file, using the
2885 C<wc -l> external command.");
2886
2887   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2888    [InitISOFS, Always, TestOutputInt (
2889       [["wc_w"; "/10klines"]], 10000)],
2890    "count words in a file",
2891    "\
2892 This command counts the words in a file, using the
2893 C<wc -w> external command.");
2894
2895   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2896    [InitISOFS, Always, TestOutputInt (
2897       [["wc_c"; "/100kallspaces"]], 102400)],
2898    "count characters in a file",
2899    "\
2900 This command counts the characters in a file, using the
2901 C<wc -c> external command.");
2902
2903   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2904    [InitISOFS, Always, TestOutputList (
2905       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2906     (* Test for RHBZ#579608, absolute symbolic links. *)
2907     InitISOFS, Always, TestOutputList (
2908       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2909    "return first 10 lines of a file",
2910    "\
2911 This command returns up to the first 10 lines of a file as
2912 a list of strings.");
2913
2914   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2915    [InitISOFS, Always, TestOutputList (
2916       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2917     InitISOFS, Always, TestOutputList (
2918       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2919     InitISOFS, Always, TestOutputList (
2920       [["head_n"; "0"; "/10klines"]], [])],
2921    "return first N lines of a file",
2922    "\
2923 If the parameter C<nrlines> is a positive number, this returns the first
2924 C<nrlines> lines of the file C<path>.
2925
2926 If the parameter C<nrlines> is a negative number, this returns lines
2927 from the file C<path>, excluding the last C<nrlines> lines.
2928
2929 If the parameter C<nrlines> is zero, this returns an empty list.");
2930
2931   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2932    [InitISOFS, Always, TestOutputList (
2933       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2934    "return last 10 lines of a file",
2935    "\
2936 This command returns up to the last 10 lines of a file as
2937 a list of strings.");
2938
2939   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2940    [InitISOFS, Always, TestOutputList (
2941       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2942     InitISOFS, Always, TestOutputList (
2943       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2944     InitISOFS, Always, TestOutputList (
2945       [["tail_n"; "0"; "/10klines"]], [])],
2946    "return last N lines of a file",
2947    "\
2948 If the parameter C<nrlines> is a positive number, this returns the last
2949 C<nrlines> lines of the file C<path>.
2950
2951 If the parameter C<nrlines> is a negative number, this returns lines
2952 from the file C<path>, starting with the C<-nrlines>th line.
2953
2954 If the parameter C<nrlines> is zero, this returns an empty list.");
2955
2956   ("df", (RString "output", []), 125, [],
2957    [], (* XXX Tricky to test because it depends on the exact format
2958         * of the 'df' command and other imponderables.
2959         *)
2960    "report file system disk space usage",
2961    "\
2962 This command runs the C<df> command to report disk space used.
2963
2964 This command is mostly useful for interactive sessions.  It
2965 is I<not> intended that you try to parse the output string.
2966 Use C<statvfs> from programs.");
2967
2968   ("df_h", (RString "output", []), 126, [],
2969    [], (* XXX Tricky to test because it depends on the exact format
2970         * of the 'df' command and other imponderables.
2971         *)
2972    "report file system disk space usage (human readable)",
2973    "\
2974 This command runs the C<df -h> command to report disk space used
2975 in human-readable format.
2976
2977 This command is mostly useful for interactive sessions.  It
2978 is I<not> intended that you try to parse the output string.
2979 Use C<statvfs> from programs.");
2980
2981   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2982    [InitISOFS, Always, TestOutputInt (
2983       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2984    "estimate file space usage",
2985    "\
2986 This command runs the C<du -s> command to estimate file space
2987 usage for C<path>.
2988
2989 C<path> can be a file or a directory.  If C<path> is a directory
2990 then the estimate includes the contents of the directory and all
2991 subdirectories (recursively).
2992
2993 The result is the estimated size in I<kilobytes>
2994 (ie. units of 1024 bytes).");
2995
2996   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2997    [InitISOFS, Always, TestOutputList (
2998       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2999    "list files in an initrd",
3000    "\
3001 This command lists out files contained in an initrd.
3002
3003 The files are listed without any initial C</> character.  The
3004 files are listed in the order they appear (not necessarily
3005 alphabetical).  Directory names are listed as separate items.
3006
3007 Old Linux kernels (2.4 and earlier) used a compressed ext2
3008 filesystem as initrd.  We I<only> support the newer initramfs
3009 format (compressed cpio files).");
3010
3011   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3012    [],
3013    "mount a file using the loop device",
3014    "\
3015 This command lets you mount C<file> (a filesystem image
3016 in a file) on a mount point.  It is entirely equivalent to
3017 the command C<mount -o loop file mountpoint>.");
3018
3019   ("mkswap", (RErr, [Device "device"]), 130, [],
3020    [InitEmpty, Always, TestRun (
3021       [["part_disk"; "/dev/sda"; "mbr"];
3022        ["mkswap"; "/dev/sda1"]])],
3023    "create a swap partition",
3024    "\
3025 Create a swap partition on C<device>.");
3026
3027   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3028    [InitEmpty, Always, TestRun (
3029       [["part_disk"; "/dev/sda"; "mbr"];
3030        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3031    "create a swap partition with a label",
3032    "\
3033 Create a swap partition on C<device> with label C<label>.
3034
3035 Note that you cannot attach a swap label to a block device
3036 (eg. C</dev/sda>), just to a partition.  This appears to be
3037 a limitation of the kernel or swap tools.");
3038
3039   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3040    (let uuid = uuidgen () in
3041     [InitEmpty, Always, TestRun (
3042        [["part_disk"; "/dev/sda"; "mbr"];
3043         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3044    "create a swap partition with an explicit UUID",
3045    "\
3046 Create a swap partition on C<device> with UUID C<uuid>.");
3047
3048   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3049    [InitBasicFS, Always, TestOutputStruct (
3050       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3051        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3052        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3053     InitBasicFS, Always, TestOutputStruct (
3054       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3055        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3056    "make block, character or FIFO devices",
3057    "\
3058 This call creates block or character special devices, or
3059 named pipes (FIFOs).
3060
3061 The C<mode> parameter should be the mode, using the standard
3062 constants.  C<devmajor> and C<devminor> are the
3063 device major and minor numbers, only used when creating block
3064 and character special devices.
3065
3066 Note that, just like L<mknod(2)>, the mode must be bitwise
3067 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3068 just creates a regular file).  These constants are
3069 available in the standard Linux header files, or you can use
3070 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3071 which are wrappers around this command which bitwise OR
3072 in the appropriate constant for you.
3073
3074 The mode actually set is affected by the umask.");
3075
3076   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3077    [InitBasicFS, Always, TestOutputStruct (
3078       [["mkfifo"; "0o777"; "/node"];
3079        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3080    "make FIFO (named pipe)",
3081    "\
3082 This call creates a FIFO (named pipe) called C<path> with
3083 mode C<mode>.  It is just a convenient wrapper around
3084 C<guestfs_mknod>.
3085
3086 The mode actually set is affected by the umask.");
3087
3088   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3089    [InitBasicFS, Always, TestOutputStruct (
3090       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3091        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3092    "make block device node",
3093    "\
3094 This call creates a block device node called C<path> with
3095 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3096 It is just a convenient wrapper around C<guestfs_mknod>.
3097
3098 The mode actually set is affected by the umask.");
3099
3100   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3101    [InitBasicFS, Always, TestOutputStruct (
3102       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3103        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3104    "make char device node",
3105    "\
3106 This call creates a char device node called C<path> with
3107 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3108 It is just a convenient wrapper around C<guestfs_mknod>.
3109
3110 The mode actually set is affected by the umask.");
3111
3112   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3113    [InitEmpty, Always, TestOutputInt (
3114       [["umask"; "0o22"]], 0o22)],
3115    "set file mode creation mask (umask)",
3116    "\
3117 This function sets the mask used for creating new files and
3118 device nodes to C<mask & 0777>.
3119
3120 Typical umask values would be C<022> which creates new files
3121 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3122 C<002> which creates new files with permissions like
3123 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3124
3125 The default umask is C<022>.  This is important because it
3126 means that directories and device nodes will be created with
3127 C<0644> or C<0755> mode even if you specify C<0777>.
3128
3129 See also C<guestfs_get_umask>,
3130 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3131
3132 This call returns the previous umask.");
3133
3134   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3135    [],
3136    "read directories entries",
3137    "\
3138 This returns the list of directory entries in directory C<dir>.
3139
3140 All entries in the directory are returned, including C<.> and
3141 C<..>.  The entries are I<not> sorted, but returned in the same
3142 order as the underlying filesystem.
3143
3144 Also this call returns basic file type information about each
3145 file.  The C<ftyp> field will contain one of the following characters:
3146
3147 =over 4
3148
3149 =item 'b'
3150
3151 Block special
3152
3153 =item 'c'
3154
3155 Char special
3156
3157 =item 'd'
3158
3159 Directory
3160
3161 =item 'f'
3162
3163 FIFO (named pipe)
3164
3165 =item 'l'
3166
3167 Symbolic link
3168
3169 =item 'r'
3170
3171 Regular file
3172
3173 =item 's'
3174
3175 Socket
3176
3177 =item 'u'
3178
3179 Unknown file type
3180
3181 =item '?'
3182
3183 The L<readdir(3)> call returned a C<d_type> field with an
3184 unexpected value
3185
3186 =back
3187
3188 This function is primarily intended for use by programs.  To
3189 get a simple list of names, use C<guestfs_ls>.  To get a printable
3190 directory for human consumption, use C<guestfs_ll>.");
3191
3192   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3193    [],
3194    "create partitions on a block device",
3195    "\
3196 This is a simplified interface to the C<guestfs_sfdisk>
3197 command, where partition sizes are specified in megabytes
3198 only (rounded to the nearest cylinder) and you don't need
3199 to specify the cyls, heads and sectors parameters which
3200 were rarely if ever used anyway.
3201
3202 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3203 and C<guestfs_part_disk>");
3204
3205   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3206    [],
3207    "determine file type inside a compressed file",
3208    "\
3209 This command runs C<file> after first decompressing C<path>
3210 using C<method>.
3211
3212 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3213
3214 Since 1.0.63, use C<guestfs_file> instead which can now
3215 process compressed files.");
3216
3217   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3218    [],
3219    "list extended attributes of a file or directory",
3220    "\
3221 This call lists the extended attributes of the file or directory
3222 C<path>.
3223
3224 At the system call level, this is a combination of the
3225 L<listxattr(2)> and L<getxattr(2)> calls.
3226
3227 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3228
3229   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3230    [],
3231    "list extended attributes of a file or directory",
3232    "\
3233 This is the same as C<guestfs_getxattrs>, but if C<path>
3234 is a symbolic link, then it returns the extended attributes
3235 of the link itself.");
3236
3237   ("setxattr", (RErr, [String "xattr";
3238                        String "val"; Int "vallen"; (* will be BufferIn *)
3239                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3240    [],
3241    "set extended attribute of a file or directory",
3242    "\
3243 This call sets the extended attribute named C<xattr>
3244 of the file C<path> to the value C<val> (of length C<vallen>).
3245 The value is arbitrary 8 bit data.
3246
3247 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3248
3249   ("lsetxattr", (RErr, [String "xattr";
3250                         String "val"; Int "vallen"; (* will be BufferIn *)
3251                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3252    [],
3253    "set extended attribute of a file or directory",
3254    "\
3255 This is the same as C<guestfs_setxattr>, but if C<path>
3256 is a symbolic link, then it sets an extended attribute
3257 of the link itself.");
3258
3259   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3260    [],
3261    "remove extended attribute of a file or directory",
3262    "\
3263 This call removes the extended attribute named C<xattr>
3264 of the file C<path>.
3265
3266 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3267
3268   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3269    [],
3270    "remove extended attribute of a file or directory",
3271    "\
3272 This is the same as C<guestfs_removexattr>, but if C<path>
3273 is a symbolic link, then it removes an extended attribute
3274 of the link itself.");
3275
3276   ("mountpoints", (RHashtable "mps", []), 147, [],
3277    [],
3278    "show mountpoints",
3279    "\
3280 This call is similar to C<guestfs_mounts>.  That call returns
3281 a list of devices.  This one returns a hash table (map) of
3282 device name to directory where the device is mounted.");
3283
3284   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3285    (* This is a special case: while you would expect a parameter
3286     * of type "Pathname", that doesn't work, because it implies
3287     * NEED_ROOT in the generated calling code in stubs.c, and
3288     * this function cannot use NEED_ROOT.
3289     *)
3290    [],
3291    "create a mountpoint",
3292    "\
3293 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3294 specialized calls that can be used to create extra mountpoints
3295 before mounting the first filesystem.
3296
3297 These calls are I<only> necessary in some very limited circumstances,
3298 mainly the case where you want to mount a mix of unrelated and/or
3299 read-only filesystems together.
3300
3301 For example, live CDs often contain a \"Russian doll\" nest of
3302 filesystems, an ISO outer layer, with a squashfs image inside, with
3303 an ext2/3 image inside that.  You can unpack this as follows
3304 in guestfish:
3305
3306  add-ro Fedora-11-i686-Live.iso
3307  run
3308  mkmountpoint /cd
3309  mkmountpoint /squash
3310  mkmountpoint /ext3
3311  mount /dev/sda /cd
3312  mount-loop /cd/LiveOS/squashfs.img /squash
3313  mount-loop /squash/LiveOS/ext3fs.img /ext3
3314
3315 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3316
3317   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3318    [],
3319    "remove a mountpoint",
3320    "\
3321 This calls removes a mountpoint that was previously created
3322 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3323 for full details.");
3324
3325   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3326    [InitISOFS, Always, TestOutputBuffer (
3327       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3328     (* Test various near large, large and too large files (RHBZ#589039). *)
3329     InitBasicFS, Always, TestLastFail (
3330       [["touch"; "/a"];
3331        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3332        ["read_file"; "/a"]]);
3333     InitBasicFS, Always, TestLastFail (
3334       [["touch"; "/a"];
3335        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3336        ["read_file"; "/a"]]);
3337     InitBasicFS, Always, TestLastFail (
3338       [["touch"; "/a"];
3339        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3340        ["read_file"; "/a"]])],
3341    "read a file",
3342    "\
3343 This calls returns the contents of the file C<path> as a
3344 buffer.
3345
3346 Unlike C<guestfs_cat>, this function can correctly
3347 handle files that contain embedded ASCII NUL characters.
3348 However unlike C<guestfs_download>, this function is limited
3349 in the total size of file that can be handled.");
3350
3351   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3352    [InitISOFS, Always, TestOutputList (
3353       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3354     InitISOFS, Always, TestOutputList (
3355       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3356     (* Test for RHBZ#579608, absolute symbolic links. *)
3357     InitISOFS, Always, TestOutputList (
3358       [["grep"; "nomatch"; "/abssymlink"]], [])],
3359    "return lines matching a pattern",
3360    "\
3361 This calls the external C<grep> program and returns the
3362 matching lines.");
3363
3364   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3365    [InitISOFS, Always, TestOutputList (
3366       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3367    "return lines matching a pattern",
3368    "\
3369 This calls the external C<egrep> program and returns the
3370 matching lines.");
3371
3372   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3373    [InitISOFS, Always, TestOutputList (
3374       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3375    "return lines matching a pattern",
3376    "\
3377 This calls the external C<fgrep> program and returns the
3378 matching lines.");
3379
3380   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3381    [InitISOFS, Always, TestOutputList (
3382       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3383    "return lines matching a pattern",
3384    "\
3385 This calls the external C<grep -i> program and returns the
3386 matching lines.");
3387
3388   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3389    [InitISOFS, Always, TestOutputList (
3390       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3391    "return lines matching a pattern",
3392    "\
3393 This calls the external C<egrep -i> program and returns the
3394 matching lines.");
3395
3396   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3397    [InitISOFS, Always, TestOutputList (
3398       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3399    "return lines matching a pattern",
3400    "\
3401 This calls the external C<fgrep -i> program and returns the
3402 matching lines.");
3403
3404   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3405    [InitISOFS, Always, TestOutputList (
3406       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3407    "return lines matching a pattern",
3408    "\
3409 This calls the external C<zgrep> program and returns the
3410 matching lines.");
3411
3412   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3413    [InitISOFS, Always, TestOutputList (
3414       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3415    "return lines matching a pattern",
3416    "\
3417 This calls the external C<zegrep> program and returns the
3418 matching lines.");
3419
3420   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3421    [InitISOFS, Always, TestOutputList (
3422       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3423    "return lines matching a pattern",
3424    "\
3425 This calls the external C<zfgrep> program and returns the
3426 matching lines.");
3427
3428   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3429    [InitISOFS, Always, TestOutputList (
3430       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3431    "return lines matching a pattern",
3432    "\
3433 This calls the external C<zgrep -i> program and returns the
3434 matching lines.");
3435
3436   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3437    [InitISOFS, Always, TestOutputList (
3438       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3439    "return lines matching a pattern",
3440    "\
3441 This calls the external C<zegrep -i> program and returns the
3442 matching lines.");
3443
3444   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3445    [InitISOFS, Always, TestOutputList (
3446       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3447    "return lines matching a pattern",
3448    "\
3449 This calls the external C<zfgrep -i> program and returns the
3450 matching lines.");
3451
3452   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3453    [InitISOFS, Always, TestOutput (
3454       [["realpath"; "/../directory"]], "/directory")],
3455    "canonicalized absolute pathname",
3456    "\
3457 Return the canonicalized absolute pathname of C<path>.  The
3458 returned path has no C<.>, C<..> or symbolic link path elements.");
3459
3460   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3461    [InitBasicFS, Always, TestOutputStruct (
3462       [["touch"; "/a"];
3463        ["ln"; "/a"; "/b"];
3464        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3465    "create a hard link",
3466    "\
3467 This command creates a hard link using the C<ln> command.");
3468
3469   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3470    [InitBasicFS, Always, TestOutputStruct (
3471       [["touch"; "/a"];
3472        ["touch"; "/b"];
3473        ["ln_f"; "/a"; "/b"];
3474        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3475    "create a hard link",
3476    "\
3477 This command creates a hard link using the C<ln -f> command.
3478 The C<-f> option removes the link (C<linkname>) if it exists already.");
3479
3480   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3481    [InitBasicFS, Always, TestOutputStruct (
3482       [["touch"; "/a"];
3483        ["ln_s"; "a"; "/b"];
3484        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3485    "create a symbolic link",
3486    "\
3487 This command creates a symbolic link using the C<ln -s> command.");
3488
3489   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3490    [InitBasicFS, Always, TestOutput (
3491       [["mkdir_p"; "/a/b"];
3492        ["touch"; "/a/b/c"];
3493        ["ln_sf"; "../d"; "/a/b/c"];
3494        ["readlink"; "/a/b/c"]], "../d")],
3495    "create a symbolic link",
3496    "\
3497 This command creates a symbolic link using the C<ln -sf> command,
3498 The C<-f> option removes the link (C<linkname>) if it exists already.");
3499
3500   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3501    [] (* XXX tested above *),
3502    "read the target of a symbolic link",
3503    "\
3504 This command reads the target of a symbolic link.");
3505
3506   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3507    [InitBasicFS, Always, TestOutputStruct (
3508       [["fallocate"; "/a"; "1000000"];
3509        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3510    "preallocate a file in the guest filesystem",
3511    "\
3512 This command preallocates a file (containing zero bytes) named
3513 C<path> of size C<len> bytes.  If the file exists already, it
3514 is overwritten.
3515
3516 Do not confuse this with the guestfish-specific
3517 C<alloc> command which allocates a file in the host and
3518 attaches it as a device.");
3519
3520   ("swapon_device", (RErr, [Device "device"]), 170, [],
3521    [InitPartition, Always, TestRun (
3522       [["mkswap"; "/dev/sda1"];
3523        ["swapon_device"; "/dev/sda1"];
3524        ["swapoff_device"; "/dev/sda1"]])],
3525    "enable swap on device",
3526    "\
3527 This command enables the libguestfs appliance to use the
3528 swap device or partition named C<device>.  The increased
3529 memory is made available for all commands, for example
3530 those run using C<guestfs_command> or C<guestfs_sh>.
3531
3532 Note that you should not swap to existing guest swap
3533 partitions unless you know what you are doing.  They may
3534 contain hibernation information, or other information that
3535 the guest doesn't want you to trash.  You also risk leaking
3536 information about the host to the guest this way.  Instead,
3537 attach a new host device to the guest and swap on that.");
3538
3539   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3540    [], (* XXX tested by swapon_device *)
3541    "disable swap on device",
3542    "\
3543 This command disables the libguestfs appliance swap
3544 device or partition named C<device>.
3545 See C<guestfs_swapon_device>.");
3546
3547   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3548    [InitBasicFS, Always, TestRun (
3549       [["fallocate"; "/swap"; "8388608"];
3550        ["mkswap_file"; "/swap"];
3551        ["swapon_file"; "/swap"];
3552        ["swapoff_file"; "/swap"]])],
3553    "enable swap on file",
3554    "\
3555 This command enables swap to a file.
3556 See C<guestfs_swapon_device> for other notes.");
3557
3558   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3559    [], (* XXX tested by swapon_file *)
3560    "disable swap on file",
3561    "\
3562 This command disables the libguestfs appliance swap on file.");
3563
3564   ("swapon_label", (RErr, [String "label"]), 174, [],
3565    [InitEmpty, Always, TestRun (
3566       [["part_disk"; "/dev/sdb"; "mbr"];
3567        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3568        ["swapon_label"; "swapit"];
3569        ["swapoff_label"; "swapit"];
3570        ["zero"; "/dev/sdb"];
3571        ["blockdev_rereadpt"; "/dev/sdb"]])],
3572    "enable swap on labeled swap partition",
3573    "\
3574 This command enables swap to a labeled swap partition.
3575 See C<guestfs_swapon_device> for other notes.");
3576
3577   ("swapoff_label", (RErr, [String "label"]), 175, [],
3578    [], (* XXX tested by swapon_label *)
3579    "disable swap on labeled swap partition",
3580    "\
3581 This command disables the libguestfs appliance swap on
3582 labeled swap partition.");
3583
3584   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3585    (let uuid = uuidgen () in
3586     [InitEmpty, Always, TestRun (
3587        [["mkswap_U"; uuid; "/dev/sdb"];
3588         ["swapon_uuid"; uuid];
3589         ["swapoff_uuid"; uuid]])]),
3590    "enable swap on swap partition by UUID",
3591    "\
3592 This command enables swap to a swap partition with the given UUID.
3593 See C<guestfs_swapon_device> for other notes.");
3594
3595   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3596    [], (* XXX tested by swapon_uuid *)
3597    "disable swap on swap partition by UUID",
3598    "\
3599 This command disables the libguestfs appliance swap partition
3600 with the given UUID.");
3601
3602   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3603    [InitBasicFS, Always, TestRun (
3604       [["fallocate"; "/swap"; "8388608"];
3605        ["mkswap_file"; "/swap"]])],
3606    "create a swap file",
3607    "\
3608 Create a swap file.
3609
3610 This command just writes a swap file signature to an existing
3611 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3612
3613   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3614    [InitISOFS, Always, TestRun (
3615       [["inotify_init"; "0"]])],
3616    "create an inotify handle",
3617    "\
3618 This command creates a new inotify handle.
3619 The inotify subsystem can be used to notify events which happen to
3620 objects in the guest filesystem.
3621
3622 C<maxevents> is the maximum number of events which will be
3623 queued up between calls to C<guestfs_inotify_read> or
3624 C<guestfs_inotify_files>.
3625 If this is passed as C<0>, then the kernel (or previously set)
3626 default is used.  For Linux 2.6.29 the default was 16384 events.
3627 Beyond this limit, the kernel throws away events, but records
3628 the fact that it threw them away by setting a flag
3629 C<IN_Q_OVERFLOW> in the returned structure list (see
3630 C<guestfs_inotify_read>).
3631
3632 Before any events are generated, you have to add some
3633 watches to the internal watch list.  See:
3634 C<guestfs_inotify_add_watch>,
3635 C<guestfs_inotify_rm_watch> and
3636 C<guestfs_inotify_watch_all>.
3637
3638 Queued up events should be read periodically by calling
3639 C<guestfs_inotify_read>
3640 (or C<guestfs_inotify_files> which is just a helpful
3641 wrapper around C<guestfs_inotify_read>).  If you don't
3642 read the events out often enough then you risk the internal
3643 queue overflowing.
3644
3645 The handle should be closed after use by calling
3646 C<guestfs_inotify_close>.  This also removes any
3647 watches automatically.
3648
3649 See also L<inotify(7)> for an overview of the inotify interface
3650 as exposed by the Linux kernel, which is roughly what we expose
3651 via libguestfs.  Note that there is one global inotify handle
3652 per libguestfs instance.");
3653
3654   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3655    [InitBasicFS, Always, TestOutputList (
3656       [["inotify_init"; "0"];
3657        ["inotify_add_watch"; "/"; "1073741823"];
3658        ["touch"; "/a"];
3659        ["touch"; "/b"];
3660        ["inotify_files"]], ["a"; "b"])],
3661    "add an inotify watch",
3662    "\
3663 Watch C<path> for the events listed in C<mask>.
3664
3665 Note that if C<path> is a directory then events within that
3666 directory are watched, but this does I<not> happen recursively
3667 (in subdirectories).
3668
3669 Note for non-C or non-Linux callers: the inotify events are
3670 defined by the Linux kernel ABI and are listed in
3671 C</usr/include/sys/inotify.h>.");
3672
3673   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3674    [],
3675    "remove an inotify watch",
3676    "\
3677 Remove a previously defined inotify watch.
3678 See C<guestfs_inotify_add_watch>.");
3679
3680   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3681    [],
3682    "return list of inotify events",
3683    "\
3684 Return the complete queue of events that have happened
3685 since the previous read call.
3686
3687 If no events have happened, this returns an empty list.
3688
3689 I<Note>: In order to make sure that all events have been
3690 read, you must call this function repeatedly until it
3691 returns an empty list.  The reason is that the call will
3692 read events up to the maximum appliance-to-host message
3693 size and leave remaining events in the queue.");
3694
3695   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3696    [],
3697    "return list of watched files that had events",
3698    "\
3699 This function is a helpful wrapper around C<guestfs_inotify_read>
3700 which just returns a list of pathnames of objects that were
3701 touched.  The returned pathnames are sorted and deduplicated.");
3702
3703   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3704    [],
3705    "close the inotify handle",
3706    "\
3707 This closes the inotify handle which was previously
3708 opened by inotify_init.  It removes all watches, throws
3709 away any pending events, and deallocates all resources.");
3710
3711   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3712    [],
3713    "set SELinux security context",
3714    "\
3715 This sets the SELinux security context of the daemon
3716 to the string C<context>.
3717
3718 See the documentation about SELINUX in L<guestfs(3)>.");
3719
3720   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3721    [],
3722    "get SELinux security context",
3723    "\
3724 This gets the SELinux security context of the daemon.
3725
3726 See the documentation about SELINUX in L<guestfs(3)>,
3727 and C<guestfs_setcon>");
3728
3729   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3730    [InitEmpty, Always, TestOutput (
3731       [["part_disk"; "/dev/sda"; "mbr"];
3732        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3733        ["mount_options"; ""; "/dev/sda1"; "/"];
3734        ["write"; "/new"; "new file contents"];
3735        ["cat"; "/new"]], "new file contents");
3736     InitEmpty, Always, TestRun (
3737       [["part_disk"; "/dev/sda"; "mbr"];
3738        ["mkfs_b"; "vfat"; "32768"; "/dev/sda1"]]);
3739     InitEmpty, Always, TestLastFail (
3740       [["part_disk"; "/dev/sda"; "mbr"];
3741        ["mkfs_b"; "vfat"; "32769"; "/dev/sda1"]]);
3742     InitEmpty, Always, TestLastFail (
3743       [["part_disk"; "/dev/sda"; "mbr"];
3744        ["mkfs_b"; "vfat"; "33280"; "/dev/sda1"]]);
3745     InitEmpty, IfAvailable "ntfsprogs", TestRun (
3746       [["part_disk"; "/dev/sda"; "mbr"];
3747        ["mkfs_b"; "ntfs"; "32768"; "/dev/sda1"]])],
3748    "make a filesystem with block size",
3749    "\
3750 This call is similar to C<guestfs_mkfs>, but it allows you to
3751 control the block size of the resulting filesystem.  Supported
3752 block sizes depend on the filesystem type, but typically they
3753 are C<1024>, C<2048> or C<4096> only.
3754
3755 For VFAT and NTFS the C<blocksize> parameter is treated as
3756 the requested cluster size.");
3757
3758   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3759    [InitEmpty, Always, TestOutput (
3760       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3761        ["mke2journal"; "4096"; "/dev/sda1"];
3762        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3763        ["mount_options"; ""; "/dev/sda2"; "/"];
3764        ["write"; "/new"; "new file contents"];
3765        ["cat"; "/new"]], "new file contents")],
3766    "make ext2/3/4 external journal",
3767    "\
3768 This creates an ext2 external journal on C<device>.  It is equivalent
3769 to the command:
3770
3771  mke2fs -O journal_dev -b blocksize device");
3772
3773   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3774    [InitEmpty, Always, TestOutput (
3775       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3776        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3777        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3778        ["mount_options"; ""; "/dev/sda2"; "/"];
3779        ["write"; "/new"; "new file contents"];
3780        ["cat"; "/new"]], "new file contents")],
3781    "make ext2/3/4 external journal with label",
3782    "\
3783 This creates an ext2 external journal on C<device> with label C<label>.");
3784
3785   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3786    (let uuid = uuidgen () in
3787     [InitEmpty, Always, TestOutput (
3788        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3789         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3790         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3791         ["mount_options"; ""; "/dev/sda2"; "/"];
3792         ["write"; "/new"; "new file contents"];
3793         ["cat"; "/new"]], "new file contents")]),
3794    "make ext2/3/4 external journal with UUID",
3795    "\
3796 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3797
3798   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3799    [],
3800    "make ext2/3/4 filesystem with external journal",
3801    "\
3802 This creates an ext2/3/4 filesystem on C<device> with
3803 an external journal on C<journal>.  It is equivalent
3804 to the command:
3805
3806  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3807
3808 See also C<guestfs_mke2journal>.");
3809
3810   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3811    [],
3812    "make ext2/3/4 filesystem with external journal",
3813    "\
3814 This creates an ext2/3/4 filesystem on C<device> with
3815 an external journal on the journal labeled C<label>.
3816
3817 See also C<guestfs_mke2journal_L>.");
3818
3819   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3820    [],
3821    "make ext2/3/4 filesystem with external journal",
3822    "\
3823 This creates an ext2/3/4 filesystem on C<device> with
3824 an external journal on the journal with UUID C<uuid>.
3825
3826 See also C<guestfs_mke2journal_U>.");
3827
3828   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3829    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3830    "load a kernel module",
3831    "\
3832 This loads a kernel module in the appliance.
3833
3834 The kernel module must have been whitelisted when libguestfs
3835 was built (see C<appliance/kmod.whitelist.in> in the source).");
3836
3837   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3838    [InitNone, Always, TestOutput (
3839       [["echo_daemon"; "This is a test"]], "This is a test"
3840     )],
3841    "echo arguments back to the client",
3842    "\
3843 This command concatenates the list of C<words> passed with single spaces
3844 between them and returns the resulting string.
3845
3846 You can use this command to test the connection through to the daemon.
3847
3848 See also C<guestfs_ping_daemon>.");
3849
3850   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3851    [], (* There is a regression test for this. *)
3852    "find all files and directories, returning NUL-separated list",
3853    "\
3854 This command lists out all files and directories, recursively,
3855 starting at C<directory>, placing the resulting list in the
3856 external file called C<files>.
3857
3858 This command works the same way as C<guestfs_find> with the
3859 following exceptions:
3860
3861 =over 4
3862
3863 =item *
3864
3865 The resulting list is written to an external file.
3866
3867 =item *
3868
3869 Items (filenames) in the result are separated
3870 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3871
3872 =item *
3873
3874 This command is not limited in the number of names that it
3875 can return.
3876
3877 =item *
3878
3879 The result list is not sorted.
3880
3881 =back");
3882
3883   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3884    [InitISOFS, Always, TestOutput (
3885       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3886     InitISOFS, Always, TestOutput (
3887       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3888     InitISOFS, Always, TestOutput (
3889       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3890     InitISOFS, Always, TestLastFail (
3891       [["case_sensitive_path"; "/Known-1/"]]);
3892     InitBasicFS, Always, TestOutput (
3893       [["mkdir"; "/a"];
3894        ["mkdir"; "/a/bbb"];
3895        ["touch"; "/a/bbb/c"];
3896        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3897     InitBasicFS, Always, TestOutput (
3898       [["mkdir"; "/a"];
3899        ["mkdir"; "/a/bbb"];
3900        ["touch"; "/a/bbb/c"];
3901        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3902     InitBasicFS, Always, TestLastFail (
3903       [["mkdir"; "/a"];
3904        ["mkdir"; "/a/bbb"];
3905        ["touch"; "/a/bbb/c"];
3906        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3907    "return true path on case-insensitive filesystem",
3908    "\
3909 This can be used to resolve case insensitive paths on
3910 a filesystem which is case sensitive.  The use case is
3911 to resolve paths which you have read from Windows configuration
3912 files or the Windows Registry, to the true path.
3913
3914 The command handles a peculiarity of the Linux ntfs-3g
3915 filesystem driver (and probably others), which is that although
3916 the underlying filesystem is case-insensitive, the driver
3917 exports the filesystem to Linux as case-sensitive.
3918
3919 One consequence of this is that special directories such
3920 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3921 (or other things) depending on the precise details of how
3922 they were created.  In Windows itself this would not be
3923 a problem.
3924
3925 Bug or feature?  You decide:
3926 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3927
3928 This function resolves the true case of each element in the
3929 path and returns the case-sensitive path.
3930
3931 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3932 might return C<\"/WINDOWS/system32\"> (the exact return value
3933 would depend on details of how the directories were originally
3934 created under Windows).
3935
3936 I<Note>:
3937 This function does not handle drive names, backslashes etc.
3938
3939 See also C<guestfs_realpath>.");
3940
3941   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3942    [InitBasicFS, Always, TestOutput (
3943       [["vfs_type"; "/dev/sda1"]], "ext2")],
3944    "get the Linux VFS type corresponding to a mounted device",
3945    "\
3946 This command gets the filesystem type corresponding to
3947 the filesystem on C<device>.
3948
3949 For most filesystems, the result is the name of the Linux
3950 VFS module which would be used to mount this filesystem
3951 if you mounted it without specifying the filesystem type.
3952 For example a string such as C<ext3> or C<ntfs>.");
3953
3954   ("truncate", (RErr, [Pathname "path"]), 199, [],
3955    [InitBasicFS, Always, TestOutputStruct (
3956       [["write"; "/test"; "some stuff so size is not zero"];
3957        ["truncate"; "/test"];
3958        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3959    "truncate a file to zero size",
3960    "\
3961 This command truncates C<path> to a zero-length file.  The
3962 file must exist already.");
3963
3964   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3965    [InitBasicFS, Always, TestOutputStruct (
3966       [["touch"; "/test"];
3967        ["truncate_size"; "/test"; "1000"];
3968        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3969    "truncate a file to a particular size",
3970    "\
3971 This command truncates C<path> to size C<size> bytes.  The file
3972 must exist already.
3973
3974 If the current file size is less than C<size> then
3975 the file is extended to the required size with zero bytes.
3976 This creates a sparse file (ie. disk blocks are not allocated
3977 for the file until you write to it).  To create a non-sparse
3978 file of zeroes, use C<guestfs_fallocate64> instead.");
3979
3980   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3981    [InitBasicFS, Always, TestOutputStruct (
3982       [["touch"; "/test"];
3983        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3984        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3985    "set timestamp of a file with nanosecond precision",
3986    "\
3987 This command sets the timestamps of a file with nanosecond
3988 precision.
3989
3990 C<atsecs, atnsecs> are the last access time (atime) in secs and
3991 nanoseconds from the epoch.
3992
3993 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3994 secs and nanoseconds from the epoch.
3995
3996 If the C<*nsecs> field contains the special value C<-1> then
3997 the corresponding timestamp is set to the current time.  (The
3998 C<*secs> field is ignored in this case).
3999
4000 If the C<*nsecs> field contains the special value C<-2> then
4001 the corresponding timestamp is left unchanged.  (The
4002 C<*secs> field is ignored in this case).");
4003
4004   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
4005    [InitBasicFS, Always, TestOutputStruct (
4006       [["mkdir_mode"; "/test"; "0o111"];
4007        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
4008    "create a directory with a particular mode",
4009    "\
4010 This command creates a directory, setting the initial permissions
4011 of the directory to C<mode>.
4012
4013 For common Linux filesystems, the actual mode which is set will
4014 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
4015 interpret the mode in other ways.
4016
4017 See also C<guestfs_mkdir>, C<guestfs_umask>");
4018
4019   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
4020    [], (* XXX *)
4021    "change file owner and group",
4022    "\
4023 Change the file owner to C<owner> and group to C<group>.
4024 This is like C<guestfs_chown> but if C<path> is a symlink then
4025 the link itself is changed, not the target.
4026
4027 Only numeric uid and gid are supported.  If you want to use
4028 names, you will need to locate and parse the password file
4029 yourself (Augeas support makes this relatively easy).");
4030
4031   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4032    [], (* XXX *)
4033    "lstat on multiple files",
4034    "\
4035 This call allows you to perform the C<guestfs_lstat> operation
4036 on multiple files, where all files are in the directory C<path>.
4037 C<names> is the list of files from this directory.
4038
4039 On return you get a list of stat structs, with a one-to-one
4040 correspondence to the C<names> list.  If any name did not exist
4041 or could not be lstat'd, then the C<ino> field of that structure
4042 is set to C<-1>.
4043
4044 This call is intended for programs that want to efficiently
4045 list a directory contents without making many round-trips.
4046 See also C<guestfs_lxattrlist> for a similarly efficient call
4047 for getting extended attributes.  Very long directory listings
4048 might cause the protocol message size to be exceeded, causing
4049 this call to fail.  The caller must split up such requests
4050 into smaller groups of names.");
4051
4052   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4053    [], (* XXX *)
4054    "lgetxattr on multiple files",
4055    "\
4056 This call allows you to get the extended attributes
4057 of multiple files, where all files are in the directory C<path>.
4058 C<names> is the list of files from this directory.
4059
4060 On return you get a flat list of xattr structs which must be
4061 interpreted sequentially.  The first xattr struct always has a zero-length
4062 C<attrname>.  C<attrval> in this struct is zero-length
4063 to indicate there was an error doing C<lgetxattr> for this
4064 file, I<or> is a C string which is a decimal number
4065 (the number of following attributes for this file, which could
4066 be C<\"0\">).  Then after the first xattr struct are the
4067 zero or more attributes for the first named file.
4068 This repeats for the second and subsequent files.
4069
4070 This call is intended for programs that want to efficiently
4071 list a directory contents without making many round-trips.
4072 See also C<guestfs_lstatlist> for a similarly efficient call
4073 for getting standard stats.  Very long directory listings
4074 might cause the protocol message size to be exceeded, causing
4075 this call to fail.  The caller must split up such requests
4076 into smaller groups of names.");
4077
4078   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4079    [], (* XXX *)
4080    "readlink on multiple files",
4081    "\
4082 This call allows you to do a C<readlink> operation
4083 on multiple files, where all files are in the directory C<path>.
4084 C<names> is the list of files from this directory.
4085
4086 On return you get a list of strings, with a one-to-one
4087 correspondence to the C<names> list.  Each string is the
4088 value of the symbolic link.
4089
4090 If the C<readlink(2)> operation fails on any name, then
4091 the corresponding result string is the empty string C<\"\">.
4092 However the whole operation is completed even if there
4093 were C<readlink(2)> errors, and so you can call this
4094 function with names where you don't know if they are
4095 symbolic links already (albeit slightly less efficient).
4096
4097 This call is intended for programs that want to efficiently
4098 list a directory contents without making many round-trips.
4099 Very long directory listings might cause the protocol
4100 message size to be exceeded, causing
4101 this call to fail.  The caller must split up such requests
4102 into smaller groups of names.");
4103
4104   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4105    [InitISOFS, Always, TestOutputBuffer (
4106       [["pread"; "/known-4"; "1"; "3"]], "\n");
4107     InitISOFS, Always, TestOutputBuffer (
4108       [["pread"; "/empty"; "0"; "100"]], "")],
4109    "read part of a file",
4110    "\
4111 This command lets you read part of a file.  It reads C<count>
4112 bytes of the file, starting at C<offset>, from file C<path>.
4113
4114 This may read fewer bytes than requested.  For further details
4115 see the L<pread(2)> system call.
4116
4117 See also C<guestfs_pwrite>.");
4118
4119   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4120    [InitEmpty, Always, TestRun (
4121       [["part_init"; "/dev/sda"; "gpt"]])],
4122    "create an empty partition table",
4123    "\
4124 This creates an empty partition table on C<device> of one of the
4125 partition types listed below.  Usually C<parttype> should be
4126 either C<msdos> or C<gpt> (for large disks).
4127
4128 Initially there are no partitions.  Following this, you should
4129 call C<guestfs_part_add> for each partition required.
4130
4131 Possible values for C<parttype> are:
4132
4133 =over 4
4134
4135 =item B<efi> | B<gpt>
4136
4137 Intel EFI / GPT partition table.
4138
4139 This is recommended for >= 2 TB partitions that will be accessed
4140 from Linux and Intel-based Mac OS X.  It also has limited backwards
4141 compatibility with the C<mbr> format.
4142
4143 =item B<mbr> | B<msdos>
4144
4145 The standard PC \"Master Boot Record\" (MBR) format used
4146 by MS-DOS and Windows.  This partition type will B<only> work
4147 for device sizes up to 2 TB.  For large disks we recommend
4148 using C<gpt>.
4149
4150 =back
4151
4152 Other partition table types that may work but are not
4153 supported include:
4154
4155 =over 4
4156
4157 =item B<aix>
4158
4159 AIX disk labels.
4160
4161 =item B<amiga> | B<rdb>
4162
4163 Amiga \"Rigid Disk Block\" format.
4164
4165 =item B<bsd>
4166
4167 BSD disk labels.
4168
4169 =item B<dasd>
4170
4171 DASD, used on IBM mainframes.
4172
4173 =item B<dvh>
4174
4175 MIPS/SGI volumes.
4176
4177 =item B<mac>
4178
4179 Old Mac partition format.  Modern Macs use C<gpt>.
4180
4181 =item B<pc98>
4182
4183 NEC PC-98 format, common in Japan apparently.
4184
4185 =item B<sun>
4186
4187 Sun disk labels.
4188
4189 =back");
4190
4191   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4192    [InitEmpty, Always, TestRun (
4193       [["part_init"; "/dev/sda"; "mbr"];
4194        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4195     InitEmpty, Always, TestRun (
4196       [["part_init"; "/dev/sda"; "gpt"];
4197        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4198        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4199     InitEmpty, Always, TestRun (
4200       [["part_init"; "/dev/sda"; "mbr"];
4201        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4202        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4203        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4204        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4205    "add a partition to the device",
4206    "\
4207 This command adds a partition to C<device>.  If there is no partition
4208 table on the device, call C<guestfs_part_init> first.
4209
4210 The C<prlogex> parameter is the type of partition.  Normally you
4211 should pass C<p> or C<primary> here, but MBR partition tables also
4212 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4213 types.
4214
4215 C<startsect> and C<endsect> are the start and end of the partition
4216 in I<sectors>.  C<endsect> may be negative, which means it counts
4217 backwards from the end of the disk (C<-1> is the last sector).
4218
4219 Creating a partition which covers the whole disk is not so easy.
4220 Use C<guestfs_part_disk> to do that.");
4221
4222   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4223    [InitEmpty, Always, TestRun (
4224       [["part_disk"; "/dev/sda"; "mbr"]]);
4225     InitEmpty, Always, TestRun (
4226       [["part_disk"; "/dev/sda"; "gpt"]])],
4227    "partition whole disk with a single primary partition",
4228    "\
4229 This command is simply a combination of C<guestfs_part_init>
4230 followed by C<guestfs_part_add> to create a single primary partition
4231 covering the whole disk.
4232
4233 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4234 but other possible values are described in C<guestfs_part_init>.");
4235
4236   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4237    [InitEmpty, Always, TestRun (
4238       [["part_disk"; "/dev/sda"; "mbr"];
4239        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4240    "make a partition bootable",
4241    "\
4242 This sets the bootable flag on partition numbered C<partnum> on
4243 device C<device>.  Note that partitions are numbered from 1.
4244
4245 The bootable flag is used by some operating systems (notably
4246 Windows) to determine which partition to boot from.  It is by
4247 no means universally recognized.");
4248
4249   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4250    [InitEmpty, Always, TestRun (
4251       [["part_disk"; "/dev/sda"; "gpt"];
4252        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4253    "set partition name",
4254    "\
4255 This sets the partition name on partition numbered C<partnum> on
4256 device C<device>.  Note that partitions are numbered from 1.
4257
4258 The partition name can only be set on certain types of partition
4259 table.  This works on C<gpt> but not on C<mbr> partitions.");
4260
4261   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4262    [], (* XXX Add a regression test for this. *)
4263    "list partitions on a device",
4264    "\
4265 This command parses the partition table on C<device> and
4266 returns the list of partitions found.
4267
4268 The fields in the returned structure are:
4269
4270 =over 4
4271
4272 =item B<part_num>
4273
4274 Partition number, counting from 1.
4275
4276 =item B<part_start>
4277
4278 Start of the partition I<in bytes>.  To get sectors you have to
4279 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4280
4281 =item B<part_end>
4282
4283 End of the partition in bytes.
4284
4285 =item B<part_size>
4286
4287 Size of the partition in bytes.
4288
4289 =back");
4290
4291   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4292    [InitEmpty, Always, TestOutput (
4293       [["part_disk"; "/dev/sda"; "gpt"];
4294        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4295    "get the partition table type",
4296    "\
4297 This command examines the partition table on C<device> and
4298 returns the partition table type (format) being used.
4299
4300 Common return values include: C<msdos> (a DOS/Windows style MBR
4301 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4302 values are possible, although unusual.  See C<guestfs_part_init>
4303 for a full list.");
4304
4305   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4306    [InitBasicFS, Always, TestOutputBuffer (
4307       [["fill"; "0x63"; "10"; "/test"];
4308        ["read_file"; "/test"]], "cccccccccc")],
4309    "fill a file with octets",
4310    "\
4311 This command creates a new file called C<path>.  The initial
4312 content of the file is C<len> octets of C<c>, where C<c>
4313 must be a number in the range C<[0..255]>.
4314
4315 To fill a file with zero bytes (sparsely), it is
4316 much more efficient to use C<guestfs_truncate_size>.
4317 To create a file with a pattern of repeating bytes
4318 use C<guestfs_fill_pattern>.");
4319
4320   ("available", (RErr, [StringList "groups"]), 216, [],
4321    [InitNone, Always, TestRun [["available"; ""]]],
4322    "test availability of some parts of the API",
4323    "\
4324 This command is used to check the availability of some
4325 groups of functionality in the appliance, which not all builds of
4326 the libguestfs appliance will be able to provide.
4327
4328 The libguestfs groups, and the functions that those
4329 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4330 You can also fetch this list at runtime by calling
4331 C<guestfs_available_all_groups>.
4332
4333 The argument C<groups> is a list of group names, eg:
4334 C<[\"inotify\", \"augeas\"]> would check for the availability of
4335 the Linux inotify functions and Augeas (configuration file
4336 editing) functions.
4337
4338 The command returns no error if I<all> requested groups are available.
4339
4340 It fails with an error if one or more of the requested
4341 groups is unavailable in the appliance.
4342
4343 If an unknown group name is included in the
4344 list of groups then an error is always returned.
4345
4346 I<Notes:>
4347
4348 =over 4
4349
4350 =item *
4351
4352 You must call C<guestfs_launch> before calling this function.
4353
4354 The reason is because we don't know what groups are
4355 supported by the appliance/daemon until it is running and can
4356 be queried.
4357
4358 =item *
4359
4360 If a group of functions is available, this does not necessarily
4361 mean that they will work.  You still have to check for errors
4362 when calling individual API functions even if they are
4363 available.
4364
4365 =item *
4366
4367 It is usually the job of distro packagers to build
4368 complete functionality into the libguestfs appliance.
4369 Upstream libguestfs, if built from source with all
4370 requirements satisfied, will support everything.
4371
4372 =item *
4373
4374 This call was added in version C<1.0.80>.  In previous
4375 versions of libguestfs all you could do would be to speculatively
4376 execute a command to find out if the daemon implemented it.
4377 See also C<guestfs_version>.
4378
4379 =back");
4380
4381   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4382    [InitBasicFS, Always, TestOutputBuffer (
4383       [["write"; "/src"; "hello, world"];
4384        ["dd"; "/src"; "/dest"];
4385        ["read_file"; "/dest"]], "hello, world")],
4386    "copy from source to destination using dd",
4387    "\
4388 This command copies from one source device or file C<src>
4389 to another destination device or file C<dest>.  Normally you
4390 would use this to copy to or from a device or partition, for
4391 example to duplicate a filesystem.
4392
4393 If the destination is a device, it must be as large or larger
4394 than the source file or device, otherwise the copy will fail.
4395 This command cannot do partial copies (see C<guestfs_copy_size>).");
4396
4397   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4398    [InitBasicFS, Always, TestOutputInt (
4399       [["write"; "/file"; "hello, world"];
4400        ["filesize"; "/file"]], 12)],
4401    "return the size of the file in bytes",
4402    "\
4403 This command returns the size of C<file> in bytes.
4404
4405 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4406 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4407 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4408
4409   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4410    [InitBasicFSonLVM, Always, TestOutputList (
4411       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4412        ["lvs"]], ["/dev/VG/LV2"])],
4413    "rename an LVM logical volume",
4414    "\
4415 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4416
4417   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4418    [InitBasicFSonLVM, Always, TestOutputList (
4419       [["umount"; "/"];
4420        ["vg_activate"; "false"; "VG"];
4421        ["vgrename"; "VG"; "VG2"];
4422        ["vg_activate"; "true"; "VG2"];
4423        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4424        ["vgs"]], ["VG2"])],
4425    "rename an LVM volume group",
4426    "\
4427 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4428
4429   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4430    [InitISOFS, Always, TestOutputBuffer (
4431       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4432    "list the contents of a single file in an initrd",
4433    "\
4434 This command unpacks the file C<filename> from the initrd file
4435 called C<initrdpath>.  The filename must be given I<without> the
4436 initial C</> character.
4437
4438 For example, in guestfish you could use the following command
4439 to examine the boot script (usually called C</init>)
4440 contained in a Linux initrd or initramfs image:
4441
4442  initrd-cat /boot/initrd-<version>.img init
4443
4444 See also C<guestfs_initrd_list>.");
4445
4446   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4447    [],
4448    "get the UUID of a physical volume",
4449    "\
4450 This command returns the UUID of the LVM PV C<device>.");
4451
4452   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4453    [],
4454    "get the UUID of a volume group",
4455    "\
4456 This command returns the UUID of the LVM VG named C<vgname>.");
4457
4458   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4459    [],
4460    "get the UUID of a logical volume",
4461    "\
4462 This command returns the UUID of the LVM LV C<device>.");
4463
4464   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4465    [],
4466    "get the PV UUIDs containing the volume group",
4467    "\
4468 Given a VG called C<vgname>, this returns the UUIDs of all
4469 the physical volumes that this volume group resides on.
4470
4471 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4472 calls to associate physical volumes and volume groups.
4473
4474 See also C<guestfs_vglvuuids>.");
4475
4476   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4477    [],
4478    "get the LV UUIDs of all LVs in the volume group",
4479    "\
4480 Given a VG called C<vgname>, this returns the UUIDs of all
4481 the logical volumes created in this volume group.
4482
4483 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4484 calls to associate logical volumes and volume groups.
4485
4486 See also C<guestfs_vgpvuuids>.");
4487
4488   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4489    [InitBasicFS, Always, TestOutputBuffer (
4490       [["write"; "/src"; "hello, world"];
4491        ["copy_size"; "/src"; "/dest"; "5"];
4492        ["read_file"; "/dest"]], "hello")],
4493    "copy size bytes from source to destination using dd",
4494    "\
4495 This command copies exactly C<size> bytes from one source device
4496 or file C<src> to another destination device or file C<dest>.
4497
4498 Note this will fail if the source is too short or if the destination
4499 is not large enough.");
4500
4501   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4502    [InitBasicFSonLVM, Always, TestRun (
4503       [["zero_device"; "/dev/VG/LV"]])],
4504    "write zeroes to an entire device",
4505    "\
4506 This command writes zeroes over the entire C<device>.  Compare
4507 with C<guestfs_zero> which just zeroes the first few blocks of
4508 a device.");
4509
4510   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4511    [InitBasicFS, Always, TestOutput (
4512       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4513        ["cat"; "/hello"]], "hello\n")],
4514    "unpack compressed tarball to directory",
4515    "\
4516 This command uploads and unpacks local file C<tarball> (an
4517 I<xz compressed> tar file) into C<directory>.");
4518
4519   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4520    [],
4521    "pack directory into compressed tarball",
4522    "\
4523 This command packs the contents of C<directory> and downloads
4524 it to local file C<tarball> (as an xz compressed tar archive).");
4525
4526   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4527    [],
4528    "resize an NTFS filesystem",
4529    "\
4530 This command resizes an NTFS filesystem, expanding or
4531 shrinking it to the size of the underlying device.
4532 See also L<ntfsresize(8)>.");
4533
4534   ("vgscan", (RErr, []), 232, [],
4535    [InitEmpty, Always, TestRun (
4536       [["vgscan"]])],
4537    "rescan for LVM physical volumes, volume groups and logical volumes",
4538    "\
4539 This rescans all block devices and rebuilds the list of LVM
4540 physical volumes, volume groups and logical volumes.");
4541
4542   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4543    [InitEmpty, Always, TestRun (
4544       [["part_init"; "/dev/sda"; "mbr"];
4545        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4546        ["part_del"; "/dev/sda"; "1"]])],
4547    "delete a partition",
4548    "\
4549 This command deletes the partition numbered C<partnum> on C<device>.
4550
4551 Note that in the case of MBR partitioning, deleting an
4552 extended partition also deletes any logical partitions
4553 it contains.");
4554
4555   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4556    [InitEmpty, Always, TestOutputTrue (
4557       [["part_init"; "/dev/sda"; "mbr"];
4558        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4559        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4560        ["part_get_bootable"; "/dev/sda"; "1"]])],
4561    "return true if a partition is bootable",
4562    "\
4563 This command returns true if the partition C<partnum> on
4564 C<device> has the bootable flag set.
4565
4566 See also C<guestfs_part_set_bootable>.");
4567
4568   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4569    [InitEmpty, Always, TestOutputInt (
4570       [["part_init"; "/dev/sda"; "mbr"];
4571        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4572        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4573        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4574    "get the MBR type byte (ID byte) from a partition",
4575    "\
4576 Returns the MBR type byte (also known as the ID byte) from
4577 the numbered partition C<partnum>.
4578
4579 Note that only MBR (old DOS-style) partitions have type bytes.
4580 You will get undefined results for other partition table
4581 types (see C<guestfs_part_get_parttype>).");
4582
4583   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4584    [], (* tested by part_get_mbr_id *)
4585    "set the MBR type byte (ID byte) of a partition",
4586    "\
4587 Sets the MBR type byte (also known as the ID byte) of
4588 the numbered partition C<partnum> to C<idbyte>.  Note
4589 that the type bytes quoted in most documentation are
4590 in fact hexadecimal numbers, but usually documented
4591 without any leading \"0x\" which might be confusing.
4592
4593 Note that only MBR (old DOS-style) partitions have type bytes.
4594 You will get undefined results for other partition table
4595 types (see C<guestfs_part_get_parttype>).");
4596
4597   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4598    [InitISOFS, Always, TestOutput (
4599       [["checksum_device"; "md5"; "/dev/sdd"]],
4600       (Digest.to_hex (Digest.file "images/test.iso")))],
4601    "compute MD5, SHAx or CRC checksum of the contents of a device",
4602    "\
4603 This call computes the MD5, SHAx or CRC checksum of the
4604 contents of the device named C<device>.  For the types of
4605 checksums supported see the C<guestfs_checksum> command.");
4606
4607   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4608    [InitNone, Always, TestRun (
4609       [["part_disk"; "/dev/sda"; "mbr"];
4610        ["pvcreate"; "/dev/sda1"];
4611        ["vgcreate"; "VG"; "/dev/sda1"];
4612        ["lvcreate"; "LV"; "VG"; "10"];
4613        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4614    "expand an LV to fill free space",
4615    "\
4616 This expands an existing logical volume C<lv> so that it fills
4617 C<pc>% of the remaining free space in the volume group.  Commonly
4618 you would call this with pc = 100 which expands the logical volume
4619 as much as possible, using all remaining free space in the volume
4620 group.");
4621
4622   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4623    [], (* XXX Augeas code needs tests. *)
4624    "clear Augeas path",
4625    "\
4626 Set the value associated with C<path> to C<NULL>.  This
4627 is the same as the L<augtool(1)> C<clear> command.");
4628
4629   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4630    [InitEmpty, Always, TestOutputInt (
4631       [["get_umask"]], 0o22)],
4632    "get the current umask",
4633    "\
4634 Return the current umask.  By default the umask is C<022>
4635 unless it has been set by calling C<guestfs_umask>.");
4636
4637   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4638    [],
4639    "upload a file to the appliance (internal use only)",
4640    "\
4641 The C<guestfs_debug_upload> command uploads a file to
4642 the libguestfs appliance.
4643
4644 There is no comprehensive help for this command.  You have
4645 to look at the file C<daemon/debug.c> in the libguestfs source
4646 to find out what it is for.");
4647
4648   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4649    [InitBasicFS, Always, TestOutput (
4650       [["base64_in"; "../images/hello.b64"; "/hello"];
4651        ["cat"; "/hello"]], "hello\n")],
4652    "upload base64-encoded data to file",
4653    "\
4654 This command uploads base64-encoded data from C<base64file>
4655 to C<filename>.");
4656
4657   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4658    [],
4659    "download file and encode as base64",
4660    "\
4661 This command downloads the contents of C<filename>, writing
4662 it out to local file C<base64file> encoded as base64.");
4663
4664   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4665    [],
4666    "compute MD5, SHAx or CRC checksum of files in a directory",
4667    "\
4668 This command computes the checksums of all regular files in
4669 C<directory> and then emits a list of those checksums to
4670 the local output file C<sumsfile>.
4671
4672 This can be used for verifying the integrity of a virtual
4673 machine.  However to be properly secure you should pay
4674 attention to the output of the checksum command (it uses
4675 the ones from GNU coreutils).  In particular when the
4676 filename is not printable, coreutils uses a special
4677 backslash syntax.  For more information, see the GNU
4678 coreutils info file.");
4679
4680   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4681    [InitBasicFS, Always, TestOutputBuffer (
4682       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4683        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4684    "fill a file with a repeating pattern of bytes",
4685    "\
4686 This function is like C<guestfs_fill> except that it creates
4687 a new file of length C<len> containing the repeating pattern
4688 of bytes in C<pattern>.  The pattern is truncated if necessary
4689 to ensure the length of the file is exactly C<len> bytes.");
4690
4691   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4692    [InitBasicFS, Always, TestOutput (
4693       [["write"; "/new"; "new file contents"];
4694        ["cat"; "/new"]], "new file contents");
4695     InitBasicFS, Always, TestOutput (
4696       [["write"; "/new"; "\nnew file contents\n"];
4697        ["cat"; "/new"]], "\nnew file contents\n");
4698     InitBasicFS, Always, TestOutput (
4699       [["write"; "/new"; "\n\n"];
4700        ["cat"; "/new"]], "\n\n");
4701     InitBasicFS, Always, TestOutput (
4702       [["write"; "/new"; ""];
4703        ["cat"; "/new"]], "");
4704     InitBasicFS, Always, TestOutput (
4705       [["write"; "/new"; "\n\n\n"];
4706        ["cat"; "/new"]], "\n\n\n");
4707     InitBasicFS, Always, TestOutput (
4708       [["write"; "/new"; "\n"];
4709        ["cat"; "/new"]], "\n")],
4710    "create a new file",
4711    "\
4712 This call creates a file called C<path>.  The content of the
4713 file is the string C<content> (which can contain any 8 bit data).");
4714
4715   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4716    [InitBasicFS, Always, TestOutput (
4717       [["write"; "/new"; "new file contents"];
4718        ["pwrite"; "/new"; "data"; "4"];
4719        ["cat"; "/new"]], "new data contents");
4720     InitBasicFS, Always, TestOutput (
4721       [["write"; "/new"; "new file contents"];
4722        ["pwrite"; "/new"; "is extended"; "9"];
4723        ["cat"; "/new"]], "new file is extended");
4724     InitBasicFS, Always, TestOutput (
4725       [["write"; "/new"; "new file contents"];
4726        ["pwrite"; "/new"; ""; "4"];
4727        ["cat"; "/new"]], "new file contents")],
4728    "write to part of a file",
4729    "\
4730 This command writes to part of a file.  It writes the data
4731 buffer C<content> to the file C<path> starting at offset C<offset>.
4732
4733 This command implements the L<pwrite(2)> system call, and like
4734 that system call it may not write the full data requested.  The
4735 return value is the number of bytes that were actually written
4736 to the file.  This could even be 0, although short writes are
4737 unlikely for regular files in ordinary circumstances.
4738
4739 See also C<guestfs_pread>.");
4740
4741   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4742    [],
4743    "resize an ext2, ext3 or ext4 filesystem (with size)",
4744    "\
4745 This command is the same as C<guestfs_resize2fs> except that it
4746 allows you to specify the new size (in bytes) explicitly.");
4747
4748   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4749    [],
4750    "resize an LVM physical volume (with size)",
4751    "\
4752 This command is the same as C<guestfs_pvresize> except that it
4753 allows you to specify the new size (in bytes) explicitly.");
4754
4755   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4756    [],
4757    "resize an NTFS filesystem (with size)",
4758    "\
4759 This command is the same as C<guestfs_ntfsresize> except that it
4760 allows you to specify the new size (in bytes) explicitly.");
4761
4762   ("available_all_groups", (RStringList "groups", []), 251, [],
4763    [InitNone, Always, TestRun [["available_all_groups"]]],
4764    "return a list of all optional groups",
4765    "\
4766 This command returns a list of all optional groups that this
4767 daemon knows about.  Note this returns both supported and unsupported
4768 groups.  To find out which ones the daemon can actually support
4769 you have to call C<guestfs_available> on each member of the
4770 returned list.
4771
4772 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4773
4774   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4775    [InitBasicFS, Always, TestOutputStruct (
4776       [["fallocate64"; "/a"; "1000000"];
4777        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4778    "preallocate a file in the guest filesystem",
4779    "\
4780 This command preallocates a file (containing zero bytes) named
4781 C<path> of size C<len> bytes.  If the file exists already, it
4782 is overwritten.
4783
4784 Note that this call allocates disk blocks for the file.
4785 To create a sparse file use C<guestfs_truncate_size> instead.
4786
4787 The deprecated call C<guestfs_fallocate> does the same,
4788 but owing to an oversight it only allowed 30 bit lengths
4789 to be specified, effectively limiting the maximum size
4790 of files created through that call to 1GB.
4791
4792 Do not confuse this with the guestfish-specific
4793 C<alloc> and C<sparse> commands which create
4794 a file in the host and attach it as a device.");
4795
4796   ("vfs_label", (RString "label", [Device "device"]), 253, [],
4797    [InitBasicFS, Always, TestOutput (
4798        [["set_e2label"; "/dev/sda1"; "LTEST"];
4799         ["vfs_label"; "/dev/sda1"]], "LTEST")],
4800    "get the filesystem label",
4801    "\
4802 This returns the filesystem label of the filesystem on
4803 C<device>.
4804
4805 If the filesystem is unlabeled, this returns the empty string.");
4806
4807   ("vfs_uuid", (RString "uuid", [Device "device"]), 254, [],
4808    (let uuid = uuidgen () in
4809     [InitBasicFS, Always, TestOutput (
4810        [["set_e2uuid"; "/dev/sda1"; uuid];
4811         ["vfs_uuid"; "/dev/sda1"]], uuid)]),
4812    "get the filesystem UUID",
4813    "\
4814 This returns the filesystem UUID of the filesystem on
4815 C<device>.
4816
4817 If the filesystem does not have a UUID, this returns the empty string.");
4818
4819 ]
4820
4821 let all_functions = non_daemon_functions @ daemon_functions
4822
4823 (* In some places we want the functions to be displayed sorted
4824  * alphabetically, so this is useful:
4825  *)
4826 let all_functions_sorted =
4827   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4828                compare n1 n2) all_functions
4829
4830 (* This is used to generate the src/MAX_PROC_NR file which
4831  * contains the maximum procedure number, a surrogate for the
4832  * ABI version number.  See src/Makefile.am for the details.
4833  *)
4834 let max_proc_nr =
4835   let proc_nrs = List.map (
4836     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4837   ) daemon_functions in
4838   List.fold_left max 0 proc_nrs
4839
4840 (* Field types for structures. *)
4841 type field =
4842   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4843   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4844   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4845   | FUInt32
4846   | FInt32
4847   | FUInt64
4848   | FInt64
4849   | FBytes                      (* Any int measure that counts bytes. *)
4850   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4851   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4852
4853 (* Because we generate extra parsing code for LVM command line tools,
4854  * we have to pull out the LVM columns separately here.
4855  *)
4856 let lvm_pv_cols = [
4857   "pv_name", FString;
4858   "pv_uuid", FUUID;
4859   "pv_fmt", FString;
4860   "pv_size", FBytes;
4861   "dev_size", FBytes;
4862   "pv_free", FBytes;
4863   "pv_used", FBytes;
4864   "pv_attr", FString (* XXX *);
4865   "pv_pe_count", FInt64;
4866   "pv_pe_alloc_count", FInt64;
4867   "pv_tags", FString;
4868   "pe_start", FBytes;
4869   "pv_mda_count", FInt64;
4870   "pv_mda_free", FBytes;
4871   (* Not in Fedora 10:
4872      "pv_mda_size", FBytes;
4873   *)
4874 ]
4875 let lvm_vg_cols = [
4876   "vg_name", FString;
4877   "vg_uuid", FUUID;
4878   "vg_fmt", FString;
4879   "vg_attr", FString (* XXX *);
4880   "vg_size", FBytes;
4881   "vg_free", FBytes;
4882   "vg_sysid", FString;
4883   "vg_extent_size", FBytes;
4884   "vg_extent_count", FInt64;
4885   "vg_free_count", FInt64;
4886   "max_lv", FInt64;
4887   "max_pv", FInt64;
4888   "pv_count", FInt64;
4889   "lv_count", FInt64;
4890   "snap_count", FInt64;
4891   "vg_seqno", FInt64;
4892   "vg_tags", FString;
4893   "vg_mda_count", FInt64;
4894   "vg_mda_free", FBytes;
4895   (* Not in Fedora 10:
4896      "vg_mda_size", FBytes;
4897   *)
4898 ]
4899 let lvm_lv_cols = [
4900   "lv_name", FString;
4901   "lv_uuid", FUUID;
4902   "lv_attr", FString (* XXX *);
4903   "lv_major", FInt64;
4904   "lv_minor", FInt64;
4905   "lv_kernel_major", FInt64;
4906   "lv_kernel_minor", FInt64;
4907   "lv_size", FBytes;
4908   "seg_count", FInt64;
4909   "origin", FString;
4910   "snap_percent", FOptPercent;
4911   "copy_percent", FOptPercent;
4912   "move_pv", FString;
4913   "lv_tags", FString;
4914   "mirror_log", FString;
4915   "modules", FString;
4916 ]
4917
4918 (* Names and fields in all structures (in RStruct and RStructList)
4919  * that we support.
4920  *)
4921 let structs = [
4922   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4923    * not use this struct in any new code.
4924    *)
4925   "int_bool", [
4926     "i", FInt32;                (* for historical compatibility *)
4927     "b", FInt32;                (* for historical compatibility *)
4928   ];
4929
4930   (* LVM PVs, VGs, LVs. *)
4931   "lvm_pv", lvm_pv_cols;
4932   "lvm_vg", lvm_vg_cols;
4933   "lvm_lv", lvm_lv_cols;
4934
4935   (* Column names and types from stat structures.
4936    * NB. Can't use things like 'st_atime' because glibc header files
4937    * define some of these as macros.  Ugh.
4938    *)
4939   "stat", [
4940     "dev", FInt64;
4941     "ino", FInt64;
4942     "mode", FInt64;
4943     "nlink", FInt64;
4944     "uid", FInt64;
4945     "gid", FInt64;
4946     "rdev", FInt64;
4947     "size", FInt64;
4948     "blksize", FInt64;
4949     "blocks", FInt64;
4950     "atime", FInt64;
4951     "mtime", FInt64;
4952     "ctime", FInt64;
4953   ];
4954   "statvfs", [
4955     "bsize", FInt64;
4956     "frsize", FInt64;
4957     "blocks", FInt64;
4958     "bfree", FInt64;
4959     "bavail", FInt64;
4960     "files", FInt64;
4961     "ffree", FInt64;
4962     "favail", FInt64;
4963     "fsid", FInt64;
4964     "flag", FInt64;
4965     "namemax", FInt64;
4966   ];
4967
4968   (* Column names in dirent structure. *)
4969   "dirent", [
4970     "ino", FInt64;
4971     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4972     "ftyp", FChar;
4973     "name", FString;
4974   ];
4975
4976   (* Version numbers. *)
4977   "version", [
4978     "major", FInt64;
4979     "minor", FInt64;
4980     "release", FInt64;
4981     "extra", FString;
4982   ];
4983
4984   (* Extended attribute. *)
4985   "xattr", [
4986     "attrname", FString;
4987     "attrval", FBuffer;
4988   ];
4989
4990   (* Inotify events. *)
4991   "inotify_event", [
4992     "in_wd", FInt64;
4993     "in_mask", FUInt32;
4994     "in_cookie", FUInt32;
4995     "in_name", FString;
4996   ];
4997
4998   (* Partition table entry. *)
4999   "partition", [
5000     "part_num", FInt32;
5001     "part_start", FBytes;
5002     "part_end", FBytes;
5003     "part_size", FBytes;
5004   ];
5005 ] (* end of structs *)
5006
5007 (* Ugh, Java has to be different ..
5008  * These names are also used by the Haskell bindings.
5009  *)
5010 let java_structs = [
5011   "int_bool", "IntBool";
5012   "lvm_pv", "PV";
5013   "lvm_vg", "VG";
5014   "lvm_lv", "LV";
5015   "stat", "Stat";
5016   "statvfs", "StatVFS";
5017   "dirent", "Dirent";
5018   "version", "Version";
5019   "xattr", "XAttr";
5020   "inotify_event", "INotifyEvent";
5021   "partition", "Partition";
5022 ]
5023
5024 (* What structs are actually returned. *)
5025 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
5026
5027 (* Returns a list of RStruct/RStructList structs that are returned
5028  * by any function.  Each element of returned list is a pair:
5029  *
5030  * (structname, RStructOnly)
5031  *    == there exists function which returns RStruct (_, structname)
5032  * (structname, RStructListOnly)
5033  *    == there exists function which returns RStructList (_, structname)
5034  * (structname, RStructAndList)
5035  *    == there are functions returning both RStruct (_, structname)
5036  *                                      and RStructList (_, structname)
5037  *)
5038 let rstructs_used_by functions =
5039   (* ||| is a "logical OR" for rstructs_used_t *)
5040   let (|||) a b =
5041     match a, b with
5042     | RStructAndList, _
5043     | _, RStructAndList -> RStructAndList
5044     | RStructOnly, RStructListOnly
5045     | RStructListOnly, RStructOnly -> RStructAndList
5046     | RStructOnly, RStructOnly -> RStructOnly
5047     | RStructListOnly, RStructListOnly -> RStructListOnly
5048   in
5049
5050   let h = Hashtbl.create 13 in
5051
5052   (* if elem->oldv exists, update entry using ||| operator,
5053    * else just add elem->newv to the hash
5054    *)
5055   let update elem newv =
5056     try  let oldv = Hashtbl.find h elem in
5057          Hashtbl.replace h elem (newv ||| oldv)
5058     with Not_found -> Hashtbl.add h elem newv
5059   in
5060
5061   List.iter (
5062     fun (_, style, _, _, _, _, _) ->
5063       match fst style with
5064       | RStruct (_, structname) -> update structname RStructOnly
5065       | RStructList (_, structname) -> update structname RStructListOnly
5066       | _ -> ()
5067   ) functions;
5068
5069   (* return key->values as a list of (key,value) *)
5070   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5071
5072 (* Used for testing language bindings. *)
5073 type callt =
5074   | CallString of string
5075   | CallOptString of string option
5076   | CallStringList of string list
5077   | CallInt of int
5078   | CallInt64 of int64
5079   | CallBool of bool
5080   | CallBuffer of string
5081
5082 (* Used to memoize the result of pod2text. *)
5083 let pod2text_memo_filename = "src/.pod2text.data"
5084 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5085   try
5086     let chan = open_in pod2text_memo_filename in
5087     let v = input_value chan in
5088     close_in chan;
5089     v
5090   with
5091     _ -> Hashtbl.create 13
5092 let pod2text_memo_updated () =
5093   let chan = open_out pod2text_memo_filename in
5094   output_value chan pod2text_memo;
5095   close_out chan
5096
5097 (* Useful functions.
5098  * Note we don't want to use any external OCaml libraries which
5099  * makes this a bit harder than it should be.
5100  *)
5101 module StringMap = Map.Make (String)
5102
5103 let failwithf fs = ksprintf failwith fs
5104
5105 let unique = let i = ref 0 in fun () -> incr i; !i
5106
5107 let replace_char s c1 c2 =
5108   let s2 = String.copy s in
5109   let r = ref false in
5110   for i = 0 to String.length s2 - 1 do
5111     if String.unsafe_get s2 i = c1 then (
5112       String.unsafe_set s2 i c2;
5113       r := true
5114     )
5115   done;
5116   if not !r then s else s2
5117
5118 let isspace c =
5119   c = ' '
5120   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5121
5122 let triml ?(test = isspace) str =
5123   let i = ref 0 in
5124   let n = ref (String.length str) in
5125   while !n > 0 && test str.[!i]; do
5126     decr n;
5127     incr i
5128   done;
5129   if !i = 0 then str
5130   else String.sub str !i !n
5131
5132 let trimr ?(test = isspace) str =
5133   let n = ref (String.length str) in
5134   while !n > 0 && test str.[!n-1]; do
5135     decr n
5136   done;
5137   if !n = String.length str then str
5138   else String.sub str 0 !n
5139
5140 let trim ?(test = isspace) str =
5141   trimr ~test (triml ~test str)
5142
5143 let rec find s sub =
5144   let len = String.length s in
5145   let sublen = String.length sub in
5146   let rec loop i =
5147     if i <= len-sublen then (
5148       let rec loop2 j =
5149         if j < sublen then (
5150           if s.[i+j] = sub.[j] then loop2 (j+1)
5151           else -1
5152         ) else
5153           i (* found *)
5154       in
5155       let r = loop2 0 in
5156       if r = -1 then loop (i+1) else r
5157     ) else
5158       -1 (* not found *)
5159   in
5160   loop 0
5161
5162 let rec replace_str s s1 s2 =
5163   let len = String.length s in
5164   let sublen = String.length s1 in
5165   let i = find s s1 in
5166   if i = -1 then s
5167   else (
5168     let s' = String.sub s 0 i in
5169     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5170     s' ^ s2 ^ replace_str s'' s1 s2
5171   )
5172
5173 let rec string_split sep str =
5174   let len = String.length str in
5175   let seplen = String.length sep in
5176   let i = find str sep in
5177   if i = -1 then [str]
5178   else (
5179     let s' = String.sub str 0 i in
5180     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5181     s' :: string_split sep s''
5182   )
5183
5184 let files_equal n1 n2 =
5185   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5186   match Sys.command cmd with
5187   | 0 -> true
5188   | 1 -> false
5189   | i -> failwithf "%s: failed with error code %d" cmd i
5190
5191 let rec filter_map f = function
5192   | [] -> []
5193   | x :: xs ->
5194       match f x with
5195       | Some y -> y :: filter_map f xs
5196       | None -> filter_map f xs
5197
5198 let rec find_map f = function
5199   | [] -> raise Not_found
5200   | x :: xs ->
5201       match f x with
5202       | Some y -> y
5203       | None -> find_map f xs
5204
5205 let iteri f xs =
5206   let rec loop i = function
5207     | [] -> ()
5208     | x :: xs -> f i x; loop (i+1) xs
5209   in
5210   loop 0 xs
5211
5212 let mapi f xs =
5213   let rec loop i = function
5214     | [] -> []
5215     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5216   in
5217   loop 0 xs
5218
5219 let count_chars c str =
5220   let count = ref 0 in
5221   for i = 0 to String.length str - 1 do
5222     if c = String.unsafe_get str i then incr count
5223   done;
5224   !count
5225
5226 let explode str =
5227   let r = ref [] in
5228   for i = 0 to String.length str - 1 do
5229     let c = String.unsafe_get str i in
5230     r := c :: !r;
5231   done;
5232   List.rev !r
5233
5234 let map_chars f str =
5235   List.map f (explode str)
5236
5237 let name_of_argt = function
5238   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5239   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5240   | FileIn n | FileOut n | BufferIn n -> n
5241
5242 let java_name_of_struct typ =
5243   try List.assoc typ java_structs
5244   with Not_found ->
5245     failwithf
5246       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5247
5248 let cols_of_struct typ =
5249   try List.assoc typ structs
5250   with Not_found ->
5251     failwithf "cols_of_struct: unknown struct %s" typ
5252
5253 let seq_of_test = function
5254   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5255   | TestOutputListOfDevices (s, _)
5256   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5257   | TestOutputTrue s | TestOutputFalse s
5258   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5259   | TestOutputStruct (s, _)
5260   | TestLastFail s -> s
5261
5262 (* Handling for function flags. *)
5263 let protocol_limit_warning =
5264   "Because of the message protocol, there is a transfer limit
5265 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5266
5267 let danger_will_robinson =
5268   "B<This command is dangerous.  Without careful use you
5269 can easily destroy all your data>."
5270
5271 let deprecation_notice flags =
5272   try
5273     let alt =
5274       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5275     let txt =
5276       sprintf "This function is deprecated.
5277 In new code, use the C<%s> call instead.
5278
5279 Deprecated functions will not be removed from the API, but the
5280 fact that they are deprecated indicates that there are problems
5281 with correct use of these functions." alt in
5282     Some txt
5283   with
5284     Not_found -> None
5285
5286 (* Create list of optional groups. *)
5287 let optgroups =
5288   let h = Hashtbl.create 13 in
5289   List.iter (
5290     fun (name, _, _, flags, _, _, _) ->
5291       List.iter (
5292         function
5293         | Optional group ->
5294             let names = try Hashtbl.find h group with Not_found -> [] in
5295             Hashtbl.replace h group (name :: names)
5296         | _ -> ()
5297       ) flags
5298   ) daemon_functions;
5299   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5300   let groups =
5301     List.map (
5302       fun group -> group, List.sort compare (Hashtbl.find h group)
5303     ) groups in
5304   List.sort (fun x y -> compare (fst x) (fst y)) groups
5305
5306 (* Check function names etc. for consistency. *)
5307 let check_functions () =
5308   let contains_uppercase str =
5309     let len = String.length str in
5310     let rec loop i =
5311       if i >= len then false
5312       else (
5313         let c = str.[i] in
5314         if c >= 'A' && c <= 'Z' then true
5315         else loop (i+1)
5316       )
5317     in
5318     loop 0
5319   in
5320
5321   (* Check function names. *)
5322   List.iter (
5323     fun (name, _, _, _, _, _, _) ->
5324       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5325         failwithf "function name %s does not need 'guestfs' prefix" name;
5326       if name = "" then
5327         failwithf "function name is empty";
5328       if name.[0] < 'a' || name.[0] > 'z' then
5329         failwithf "function name %s must start with lowercase a-z" name;
5330       if String.contains name '-' then
5331         failwithf "function name %s should not contain '-', use '_' instead."
5332           name
5333   ) all_functions;
5334
5335   (* Check function parameter/return names. *)
5336   List.iter (
5337     fun (name, style, _, _, _, _, _) ->
5338       let check_arg_ret_name n =
5339         if contains_uppercase n then
5340           failwithf "%s param/ret %s should not contain uppercase chars"
5341             name n;
5342         if String.contains n '-' || String.contains n '_' then
5343           failwithf "%s param/ret %s should not contain '-' or '_'"
5344             name n;
5345         if n = "value" then
5346           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;
5347         if n = "int" || n = "char" || n = "short" || n = "long" then
5348           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5349         if n = "i" || n = "n" then
5350           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5351         if n = "argv" || n = "args" then
5352           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5353
5354         (* List Haskell, OCaml and C keywords here.
5355          * http://www.haskell.org/haskellwiki/Keywords
5356          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5357          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5358          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5359          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5360          * Omitting _-containing words, since they're handled above.
5361          * Omitting the OCaml reserved word, "val", is ok,
5362          * and saves us from renaming several parameters.
5363          *)
5364         let reserved = [
5365           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5366           "char"; "class"; "const"; "constraint"; "continue"; "data";
5367           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5368           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5369           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5370           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5371           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5372           "interface";
5373           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5374           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5375           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5376           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5377           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5378           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5379           "volatile"; "when"; "where"; "while";
5380           ] in
5381         if List.mem n reserved then
5382           failwithf "%s has param/ret using reserved word %s" name n;
5383       in
5384
5385       (match fst style with
5386        | RErr -> ()
5387        | RInt n | RInt64 n | RBool n
5388        | RConstString n | RConstOptString n | RString n
5389        | RStringList n | RStruct (n, _) | RStructList (n, _)
5390        | RHashtable n | RBufferOut n ->
5391            check_arg_ret_name n
5392       );
5393       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5394   ) all_functions;
5395
5396   (* Check short descriptions. *)
5397   List.iter (
5398     fun (name, _, _, _, _, shortdesc, _) ->
5399       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5400         failwithf "short description of %s should begin with lowercase." name;
5401       let c = shortdesc.[String.length shortdesc-1] in
5402       if c = '\n' || c = '.' then
5403         failwithf "short description of %s should not end with . or \\n." name
5404   ) all_functions;
5405
5406   (* Check long descriptions. *)
5407   List.iter (
5408     fun (name, _, _, _, _, _, longdesc) ->
5409       if longdesc.[String.length longdesc-1] = '\n' then
5410         failwithf "long description of %s should not end with \\n." name
5411   ) all_functions;
5412
5413   (* Check proc_nrs. *)
5414   List.iter (
5415     fun (name, _, proc_nr, _, _, _, _) ->
5416       if proc_nr <= 0 then
5417         failwithf "daemon function %s should have proc_nr > 0" name
5418   ) daemon_functions;
5419
5420   List.iter (
5421     fun (name, _, proc_nr, _, _, _, _) ->
5422       if proc_nr <> -1 then
5423         failwithf "non-daemon function %s should have proc_nr -1" name
5424   ) non_daemon_functions;
5425
5426   let proc_nrs =
5427     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5428       daemon_functions in
5429   let proc_nrs =
5430     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5431   let rec loop = function
5432     | [] -> ()
5433     | [_] -> ()
5434     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5435         loop rest
5436     | (name1,nr1) :: (name2,nr2) :: _ ->
5437         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5438           name1 name2 nr1 nr2
5439   in
5440   loop proc_nrs;
5441
5442   (* Check tests. *)
5443   List.iter (
5444     function
5445       (* Ignore functions that have no tests.  We generate a
5446        * warning when the user does 'make check' instead.
5447        *)
5448     | name, _, _, _, [], _, _ -> ()
5449     | name, _, _, _, tests, _, _ ->
5450         let funcs =
5451           List.map (
5452             fun (_, _, test) ->
5453               match seq_of_test test with
5454               | [] ->
5455                   failwithf "%s has a test containing an empty sequence" name
5456               | cmds -> List.map List.hd cmds
5457           ) tests in
5458         let funcs = List.flatten funcs in
5459
5460         let tested = List.mem name funcs in
5461
5462         if not tested then
5463           failwithf "function %s has tests but does not test itself" name
5464   ) all_functions
5465
5466 (* 'pr' prints to the current output file. *)
5467 let chan = ref Pervasives.stdout
5468 let lines = ref 0
5469 let pr fs =
5470   ksprintf
5471     (fun str ->
5472        let i = count_chars '\n' str in
5473        lines := !lines + i;
5474        output_string !chan str
5475     ) fs
5476
5477 let copyright_years =
5478   let this_year = 1900 + (localtime (time ())).tm_year in
5479   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5480
5481 (* Generate a header block in a number of standard styles. *)
5482 type comment_style =
5483     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5484 type license = GPLv2plus | LGPLv2plus
5485
5486 let generate_header ?(extra_inputs = []) comment license =
5487   let inputs = "src/generator.ml" :: extra_inputs in
5488   let c = match comment with
5489     | CStyle ->         pr "/* "; " *"
5490     | CPlusPlusStyle -> pr "// "; "//"
5491     | HashStyle ->      pr "# ";  "#"
5492     | OCamlStyle ->     pr "(* "; " *"
5493     | HaskellStyle ->   pr "{- "; "  " in
5494   pr "libguestfs generated file\n";
5495   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5496   List.iter (pr "%s   %s\n" c) inputs;
5497   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5498   pr "%s\n" c;
5499   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5500   pr "%s\n" c;
5501   (match license with
5502    | GPLv2plus ->
5503        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5504        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5505        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5506        pr "%s (at your option) any later version.\n" c;
5507        pr "%s\n" c;
5508        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5509        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5510        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5511        pr "%s GNU General Public License for more details.\n" c;
5512        pr "%s\n" c;
5513        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5514        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5515        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5516
5517    | LGPLv2plus ->
5518        pr "%s This library is free software; you can redistribute it and/or\n" c;
5519        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5520        pr "%s License as published by the Free Software Foundation; either\n" c;
5521        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5522        pr "%s\n" c;
5523        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5524        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5525        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5526        pr "%s Lesser General Public License for more details.\n" c;
5527        pr "%s\n" c;
5528        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5529        pr "%s License along with this library; if not, write to the Free Software\n" c;
5530        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5531   );
5532   (match comment with
5533    | CStyle -> pr " */\n"
5534    | CPlusPlusStyle
5535    | HashStyle -> ()
5536    | OCamlStyle -> pr " *)\n"
5537    | HaskellStyle -> pr "-}\n"
5538   );
5539   pr "\n"
5540
5541 (* Start of main code generation functions below this line. *)
5542
5543 (* Generate the pod documentation for the C API. *)
5544 let rec generate_actions_pod () =
5545   List.iter (
5546     fun (shortname, style, _, flags, _, _, longdesc) ->
5547       if not (List.mem NotInDocs flags) then (
5548         let name = "guestfs_" ^ shortname in
5549         pr "=head2 %s\n\n" name;
5550         pr " ";
5551         generate_prototype ~extern:false ~handle:"g" name style;
5552         pr "\n\n";
5553         pr "%s\n\n" longdesc;
5554         (match fst style with
5555          | RErr ->
5556              pr "This function returns 0 on success or -1 on error.\n\n"
5557          | RInt _ ->
5558              pr "On error this function returns -1.\n\n"
5559          | RInt64 _ ->
5560              pr "On error this function returns -1.\n\n"
5561          | RBool _ ->
5562              pr "This function returns a C truth value on success or -1 on error.\n\n"
5563          | RConstString _ ->
5564              pr "This function returns a string, or NULL on error.
5565 The string is owned by the guest handle and must I<not> be freed.\n\n"
5566          | RConstOptString _ ->
5567              pr "This function returns a string which may be NULL.
5568 There is way to return an error from this function.
5569 The string is owned by the guest handle and must I<not> be freed.\n\n"
5570          | RString _ ->
5571              pr "This function returns a string, or NULL on error.
5572 I<The caller must free the returned string after use>.\n\n"
5573          | RStringList _ ->
5574              pr "This function returns a NULL-terminated array of strings
5575 (like L<environ(3)>), or NULL if there was an error.
5576 I<The caller must free the strings and the array after use>.\n\n"
5577          | RStruct (_, typ) ->
5578              pr "This function returns a C<struct guestfs_%s *>,
5579 or NULL if there was an error.
5580 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5581          | RStructList (_, typ) ->
5582              pr "This function returns a C<struct guestfs_%s_list *>
5583 (see E<lt>guestfs-structs.hE<gt>),
5584 or NULL if there was an error.
5585 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5586          | RHashtable _ ->
5587              pr "This function returns a NULL-terminated array of
5588 strings, or NULL if there was an error.
5589 The array of strings will always have length C<2n+1>, where
5590 C<n> keys and values alternate, followed by the trailing NULL entry.
5591 I<The caller must free the strings and the array after use>.\n\n"
5592          | RBufferOut _ ->
5593              pr "This function returns a buffer, or NULL on error.
5594 The size of the returned buffer is written to C<*size_r>.
5595 I<The caller must free the returned buffer after use>.\n\n"
5596         );
5597         if List.mem ProtocolLimitWarning flags then
5598           pr "%s\n\n" protocol_limit_warning;
5599         if List.mem DangerWillRobinson flags then
5600           pr "%s\n\n" danger_will_robinson;
5601         match deprecation_notice flags with
5602         | None -> ()
5603         | Some txt -> pr "%s\n\n" txt
5604       )
5605   ) all_functions_sorted
5606
5607 and generate_structs_pod () =
5608   (* Structs documentation. *)
5609   List.iter (
5610     fun (typ, cols) ->
5611       pr "=head2 guestfs_%s\n" typ;
5612       pr "\n";
5613       pr " struct guestfs_%s {\n" typ;
5614       List.iter (
5615         function
5616         | name, FChar -> pr "   char %s;\n" name
5617         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5618         | name, FInt32 -> pr "   int32_t %s;\n" name
5619         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5620         | name, FInt64 -> pr "   int64_t %s;\n" name
5621         | name, FString -> pr "   char *%s;\n" name
5622         | name, FBuffer ->
5623             pr "   /* The next two fields describe a byte array. */\n";
5624             pr "   uint32_t %s_len;\n" name;
5625             pr "   char *%s;\n" name
5626         | name, FUUID ->
5627             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5628             pr "   char %s[32];\n" name
5629         | name, FOptPercent ->
5630             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5631             pr "   float %s;\n" name
5632       ) cols;
5633       pr " };\n";
5634       pr " \n";
5635       pr " struct guestfs_%s_list {\n" typ;
5636       pr "   uint32_t len; /* Number of elements in list. */\n";
5637       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5638       pr " };\n";
5639       pr " \n";
5640       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5641       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5642         typ typ;
5643       pr "\n"
5644   ) structs
5645
5646 and generate_availability_pod () =
5647   (* Availability documentation. *)
5648   pr "=over 4\n";
5649   pr "\n";
5650   List.iter (
5651     fun (group, functions) ->
5652       pr "=item B<%s>\n" group;
5653       pr "\n";
5654       pr "The following functions:\n";
5655       List.iter (pr "L</guestfs_%s>\n") functions;
5656       pr "\n"
5657   ) optgroups;
5658   pr "=back\n";
5659   pr "\n"
5660
5661 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5662  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5663  *
5664  * We have to use an underscore instead of a dash because otherwise
5665  * rpcgen generates incorrect code.
5666  *
5667  * This header is NOT exported to clients, but see also generate_structs_h.
5668  *)
5669 and generate_xdr () =
5670   generate_header CStyle LGPLv2plus;
5671
5672   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5673   pr "typedef string str<>;\n";
5674   pr "\n";
5675
5676   (* Internal structures. *)
5677   List.iter (
5678     function
5679     | typ, cols ->
5680         pr "struct guestfs_int_%s {\n" typ;
5681         List.iter (function
5682                    | name, FChar -> pr "  char %s;\n" name
5683                    | name, FString -> pr "  string %s<>;\n" name
5684                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5685                    | name, FUUID -> pr "  opaque %s[32];\n" name
5686                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5687                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5688                    | name, FOptPercent -> pr "  float %s;\n" name
5689                   ) cols;
5690         pr "};\n";
5691         pr "\n";
5692         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5693         pr "\n";
5694   ) structs;
5695
5696   List.iter (
5697     fun (shortname, style, _, _, _, _, _) ->
5698       let name = "guestfs_" ^ shortname in
5699
5700       (match snd style with
5701        | [] -> ()
5702        | args ->
5703            pr "struct %s_args {\n" name;
5704            List.iter (
5705              function
5706              | Pathname n | Device n | Dev_or_Path n | String n ->
5707                  pr "  string %s<>;\n" n
5708              | OptString n -> pr "  str *%s;\n" n
5709              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5710              | Bool n -> pr "  bool %s;\n" n
5711              | Int n -> pr "  int %s;\n" n
5712              | Int64 n -> pr "  hyper %s;\n" n
5713              | BufferIn n ->
5714                  pr "  opaque %s<>;\n" n
5715              | FileIn _ | FileOut _ -> ()
5716            ) args;
5717            pr "};\n\n"
5718       );
5719       (match fst style with
5720        | RErr -> ()
5721        | RInt n ->
5722            pr "struct %s_ret {\n" name;
5723            pr "  int %s;\n" n;
5724            pr "};\n\n"
5725        | RInt64 n ->
5726            pr "struct %s_ret {\n" name;
5727            pr "  hyper %s;\n" n;
5728            pr "};\n\n"
5729        | RBool n ->
5730            pr "struct %s_ret {\n" name;
5731            pr "  bool %s;\n" n;
5732            pr "};\n\n"
5733        | RConstString _ | RConstOptString _ ->
5734            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5735        | RString n ->
5736            pr "struct %s_ret {\n" name;
5737            pr "  string %s<>;\n" n;
5738            pr "};\n\n"
5739        | RStringList n ->
5740            pr "struct %s_ret {\n" name;
5741            pr "  str %s<>;\n" n;
5742            pr "};\n\n"
5743        | RStruct (n, typ) ->
5744            pr "struct %s_ret {\n" name;
5745            pr "  guestfs_int_%s %s;\n" typ n;
5746            pr "};\n\n"
5747        | RStructList (n, typ) ->
5748            pr "struct %s_ret {\n" name;
5749            pr "  guestfs_int_%s_list %s;\n" typ n;
5750            pr "};\n\n"
5751        | RHashtable n ->
5752            pr "struct %s_ret {\n" name;
5753            pr "  str %s<>;\n" n;
5754            pr "};\n\n"
5755        | RBufferOut n ->
5756            pr "struct %s_ret {\n" name;
5757            pr "  opaque %s<>;\n" n;
5758            pr "};\n\n"
5759       );
5760   ) daemon_functions;
5761
5762   (* Table of procedure numbers. *)
5763   pr "enum guestfs_procedure {\n";
5764   List.iter (
5765     fun (shortname, _, proc_nr, _, _, _, _) ->
5766       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5767   ) daemon_functions;
5768   pr "  GUESTFS_PROC_NR_PROCS\n";
5769   pr "};\n";
5770   pr "\n";
5771
5772   (* Having to choose a maximum message size is annoying for several
5773    * reasons (it limits what we can do in the API), but it (a) makes
5774    * the protocol a lot simpler, and (b) provides a bound on the size
5775    * of the daemon which operates in limited memory space.
5776    *)
5777   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5778   pr "\n";
5779
5780   (* Message header, etc. *)
5781   pr "\
5782 /* The communication protocol is now documented in the guestfs(3)
5783  * manpage.
5784  */
5785
5786 const GUESTFS_PROGRAM = 0x2000F5F5;
5787 const GUESTFS_PROTOCOL_VERSION = 1;
5788
5789 /* These constants must be larger than any possible message length. */
5790 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5791 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5792
5793 enum guestfs_message_direction {
5794   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5795   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5796 };
5797
5798 enum guestfs_message_status {
5799   GUESTFS_STATUS_OK = 0,
5800   GUESTFS_STATUS_ERROR = 1
5801 };
5802
5803 const GUESTFS_ERROR_LEN = 256;
5804
5805 struct guestfs_message_error {
5806   string error_message<GUESTFS_ERROR_LEN>;
5807 };
5808
5809 struct guestfs_message_header {
5810   unsigned prog;                     /* GUESTFS_PROGRAM */
5811   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5812   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5813   guestfs_message_direction direction;
5814   unsigned serial;                   /* message serial number */
5815   guestfs_message_status status;
5816 };
5817
5818 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5819
5820 struct guestfs_chunk {
5821   int cancel;                        /* if non-zero, transfer is cancelled */
5822   /* data size is 0 bytes if the transfer has finished successfully */
5823   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5824 };
5825 "
5826
5827 (* Generate the guestfs-structs.h file. *)
5828 and generate_structs_h () =
5829   generate_header CStyle LGPLv2plus;
5830
5831   (* This is a public exported header file containing various
5832    * structures.  The structures are carefully written to have
5833    * exactly the same in-memory format as the XDR structures that
5834    * we use on the wire to the daemon.  The reason for creating
5835    * copies of these structures here is just so we don't have to
5836    * export the whole of guestfs_protocol.h (which includes much
5837    * unrelated and XDR-dependent stuff that we don't want to be
5838    * public, or required by clients).
5839    *
5840    * To reiterate, we will pass these structures to and from the
5841    * client with a simple assignment or memcpy, so the format
5842    * must be identical to what rpcgen / the RFC defines.
5843    *)
5844
5845   (* Public structures. *)
5846   List.iter (
5847     fun (typ, cols) ->
5848       pr "struct guestfs_%s {\n" typ;
5849       List.iter (
5850         function
5851         | name, FChar -> pr "  char %s;\n" name
5852         | name, FString -> pr "  char *%s;\n" name
5853         | name, FBuffer ->
5854             pr "  uint32_t %s_len;\n" name;
5855             pr "  char *%s;\n" name
5856         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5857         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5858         | name, FInt32 -> pr "  int32_t %s;\n" name
5859         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5860         | name, FInt64 -> pr "  int64_t %s;\n" name
5861         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5862       ) cols;
5863       pr "};\n";
5864       pr "\n";
5865       pr "struct guestfs_%s_list {\n" typ;
5866       pr "  uint32_t len;\n";
5867       pr "  struct guestfs_%s *val;\n" typ;
5868       pr "};\n";
5869       pr "\n";
5870       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5871       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5872       pr "\n"
5873   ) structs
5874
5875 (* Generate the guestfs-actions.h file. *)
5876 and generate_actions_h () =
5877   generate_header CStyle LGPLv2plus;
5878   List.iter (
5879     fun (shortname, style, _, _, _, _, _) ->
5880       let name = "guestfs_" ^ shortname in
5881       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5882         name style
5883   ) all_functions
5884
5885 (* Generate the guestfs-internal-actions.h file. *)
5886 and generate_internal_actions_h () =
5887   generate_header CStyle LGPLv2plus;
5888   List.iter (
5889     fun (shortname, style, _, _, _, _, _) ->
5890       let name = "guestfs__" ^ shortname in
5891       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5892         name style
5893   ) non_daemon_functions
5894
5895 (* Generate the client-side dispatch stubs. *)
5896 and generate_client_actions () =
5897   generate_header CStyle LGPLv2plus;
5898
5899   pr "\
5900 #include <stdio.h>
5901 #include <stdlib.h>
5902 #include <stdint.h>
5903 #include <string.h>
5904 #include <inttypes.h>
5905
5906 #include \"guestfs.h\"
5907 #include \"guestfs-internal.h\"
5908 #include \"guestfs-internal-actions.h\"
5909 #include \"guestfs_protocol.h\"
5910
5911 #define error guestfs_error
5912 //#define perrorf guestfs_perrorf
5913 #define safe_malloc guestfs_safe_malloc
5914 #define safe_realloc guestfs_safe_realloc
5915 //#define safe_strdup guestfs_safe_strdup
5916 #define safe_memdup guestfs_safe_memdup
5917
5918 /* Check the return message from a call for validity. */
5919 static int
5920 check_reply_header (guestfs_h *g,
5921                     const struct guestfs_message_header *hdr,
5922                     unsigned int proc_nr, unsigned int serial)
5923 {
5924   if (hdr->prog != GUESTFS_PROGRAM) {
5925     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5926     return -1;
5927   }
5928   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5929     error (g, \"wrong protocol version (%%d/%%d)\",
5930            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5931     return -1;
5932   }
5933   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5934     error (g, \"unexpected message direction (%%d/%%d)\",
5935            hdr->direction, GUESTFS_DIRECTION_REPLY);
5936     return -1;
5937   }
5938   if (hdr->proc != proc_nr) {
5939     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5940     return -1;
5941   }
5942   if (hdr->serial != serial) {
5943     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5944     return -1;
5945   }
5946
5947   return 0;
5948 }
5949
5950 /* Check we are in the right state to run a high-level action. */
5951 static int
5952 check_state (guestfs_h *g, const char *caller)
5953 {
5954   if (!guestfs__is_ready (g)) {
5955     if (guestfs__is_config (g) || guestfs__is_launching (g))
5956       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5957         caller);
5958     else
5959       error (g, \"%%s called from the wrong state, %%d != READY\",
5960         caller, guestfs__get_state (g));
5961     return -1;
5962   }
5963   return 0;
5964 }
5965
5966 ";
5967
5968   let error_code_of = function
5969     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5970     | RConstString _ | RConstOptString _
5971     | RString _ | RStringList _
5972     | RStruct _ | RStructList _
5973     | RHashtable _ | RBufferOut _ -> "NULL"
5974   in
5975
5976   (* Generate code to check String-like parameters are not passed in
5977    * as NULL (returning an error if they are).
5978    *)
5979   let check_null_strings shortname style =
5980     let pr_newline = ref false in
5981     List.iter (
5982       function
5983       (* parameters which should not be NULL *)
5984       | String n
5985       | Device n
5986       | Pathname n
5987       | Dev_or_Path n
5988       | FileIn n
5989       | FileOut n
5990       | BufferIn n
5991       | StringList n
5992       | DeviceList n ->
5993           pr "  if (%s == NULL) {\n" n;
5994           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
5995           pr "           \"%s\", \"%s\");\n" shortname n;
5996           pr "    return %s;\n" (error_code_of (fst style));
5997           pr "  }\n";
5998           pr_newline := true
5999
6000       (* can be NULL *)
6001       | OptString _
6002
6003       (* not applicable *)
6004       | Bool _
6005       | Int _
6006       | Int64 _ -> ()
6007     ) (snd style);
6008
6009     if !pr_newline then pr "\n";
6010   in
6011
6012   (* Generate code to generate guestfish call traces. *)
6013   let trace_call shortname style =
6014     pr "  if (guestfs__get_trace (g)) {\n";
6015
6016     let needs_i =
6017       List.exists (function
6018                    | StringList _ | DeviceList _ -> true
6019                    | _ -> false) (snd style) in
6020     if needs_i then (
6021       pr "    int i;\n";
6022       pr "\n"
6023     );
6024
6025     pr "    printf (\"%s\");\n" shortname;
6026     List.iter (
6027       function
6028       | String n                        (* strings *)
6029       | Device n
6030       | Pathname n
6031       | Dev_or_Path n
6032       | FileIn n
6033       | FileOut n
6034       | BufferIn n ->
6035           (* guestfish doesn't support string escaping, so neither do we *)
6036           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
6037       | OptString n ->                  (* string option *)
6038           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
6039           pr "    else printf (\" null\");\n"
6040       | StringList n
6041       | DeviceList n ->                 (* string list *)
6042           pr "    putchar (' ');\n";
6043           pr "    putchar ('\"');\n";
6044           pr "    for (i = 0; %s[i]; ++i) {\n" n;
6045           pr "      if (i > 0) putchar (' ');\n";
6046           pr "      fputs (%s[i], stdout);\n" n;
6047           pr "    }\n";
6048           pr "    putchar ('\"');\n";
6049       | Bool n ->                       (* boolean *)
6050           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
6051       | Int n ->                        (* int *)
6052           pr "    printf (\" %%d\", %s);\n" n
6053       | Int64 n ->
6054           pr "    printf (\" %%\" PRIi64, %s);\n" n
6055     ) (snd style);
6056     pr "    putchar ('\\n');\n";
6057     pr "  }\n";
6058     pr "\n";
6059   in
6060
6061   (* For non-daemon functions, generate a wrapper around each function. *)
6062   List.iter (
6063     fun (shortname, style, _, _, _, _, _) ->
6064       let name = "guestfs_" ^ shortname in
6065
6066       generate_prototype ~extern:false ~semicolon:false ~newline:true
6067         ~handle:"g" name style;
6068       pr "{\n";
6069       check_null_strings shortname style;
6070       trace_call shortname style;
6071       pr "  return guestfs__%s " shortname;
6072       generate_c_call_args ~handle:"g" style;
6073       pr ";\n";
6074       pr "}\n";
6075       pr "\n"
6076   ) non_daemon_functions;
6077
6078   (* Client-side stubs for each function. *)
6079   List.iter (
6080     fun (shortname, style, _, _, _, _, _) ->
6081       let name = "guestfs_" ^ shortname in
6082       let error_code = error_code_of (fst style) in
6083
6084       (* Generate the action stub. *)
6085       generate_prototype ~extern:false ~semicolon:false ~newline:true
6086         ~handle:"g" name style;
6087
6088       pr "{\n";
6089
6090       (match snd style with
6091        | [] -> ()
6092        | _ -> pr "  struct %s_args args;\n" name
6093       );
6094
6095       pr "  guestfs_message_header hdr;\n";
6096       pr "  guestfs_message_error err;\n";
6097       let has_ret =
6098         match fst style with
6099         | RErr -> false
6100         | RConstString _ | RConstOptString _ ->
6101             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6102         | RInt _ | RInt64 _
6103         | RBool _ | RString _ | RStringList _
6104         | RStruct _ | RStructList _
6105         | RHashtable _ | RBufferOut _ ->
6106             pr "  struct %s_ret ret;\n" name;
6107             true in
6108
6109       pr "  int serial;\n";
6110       pr "  int r;\n";
6111       pr "\n";
6112       check_null_strings shortname style;
6113       trace_call shortname style;
6114       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6115         shortname error_code;
6116       pr "  guestfs___set_busy (g);\n";
6117       pr "\n";
6118
6119       (* Send the main header and arguments. *)
6120       (match snd style with
6121        | [] ->
6122            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6123              (String.uppercase shortname)
6124        | args ->
6125            List.iter (
6126              function
6127              | Pathname n | Device n | Dev_or_Path n | String n ->
6128                  pr "  args.%s = (char *) %s;\n" n n
6129              | OptString n ->
6130                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6131              | StringList n | DeviceList n ->
6132                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6133                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6134              | Bool n ->
6135                  pr "  args.%s = %s;\n" n n
6136              | Int n ->
6137                  pr "  args.%s = %s;\n" n n
6138              | Int64 n ->
6139                  pr "  args.%s = %s;\n" n n
6140              | FileIn _ | FileOut _ -> ()
6141              | BufferIn n ->
6142                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6143                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6144                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6145                    shortname;
6146                  pr "    guestfs___end_busy (g);\n";
6147                  pr "    return %s;\n" error_code;
6148                  pr "  }\n";
6149                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6150                  pr "  args.%s.%s_len = %s_size;\n" n n n
6151            ) args;
6152            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6153              (String.uppercase shortname);
6154            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6155              name;
6156       );
6157       pr "  if (serial == -1) {\n";
6158       pr "    guestfs___end_busy (g);\n";
6159       pr "    return %s;\n" error_code;
6160       pr "  }\n";
6161       pr "\n";
6162
6163       (* Send any additional files (FileIn) requested. *)
6164       let need_read_reply_label = ref false in
6165       List.iter (
6166         function
6167         | FileIn n ->
6168             pr "  r = guestfs___send_file (g, %s);\n" n;
6169             pr "  if (r == -1) {\n";
6170             pr "    guestfs___end_busy (g);\n";
6171             pr "    return %s;\n" error_code;
6172             pr "  }\n";
6173             pr "  if (r == -2) /* daemon cancelled */\n";
6174             pr "    goto read_reply;\n";
6175             need_read_reply_label := true;
6176             pr "\n";
6177         | _ -> ()
6178       ) (snd style);
6179
6180       (* Wait for the reply from the remote end. *)
6181       if !need_read_reply_label then pr " read_reply:\n";
6182       pr "  memset (&hdr, 0, sizeof hdr);\n";
6183       pr "  memset (&err, 0, sizeof err);\n";
6184       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6185       pr "\n";
6186       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6187       if not has_ret then
6188         pr "NULL, NULL"
6189       else
6190         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6191       pr ");\n";
6192
6193       pr "  if (r == -1) {\n";
6194       pr "    guestfs___end_busy (g);\n";
6195       pr "    return %s;\n" error_code;
6196       pr "  }\n";
6197       pr "\n";
6198
6199       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6200         (String.uppercase shortname);
6201       pr "    guestfs___end_busy (g);\n";
6202       pr "    return %s;\n" error_code;
6203       pr "  }\n";
6204       pr "\n";
6205
6206       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6207       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6208       pr "    free (err.error_message);\n";
6209       pr "    guestfs___end_busy (g);\n";
6210       pr "    return %s;\n" error_code;
6211       pr "  }\n";
6212       pr "\n";
6213
6214       (* Expecting to receive further files (FileOut)? *)
6215       List.iter (
6216         function
6217         | FileOut n ->
6218             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6219             pr "    guestfs___end_busy (g);\n";
6220             pr "    return %s;\n" error_code;
6221             pr "  }\n";
6222             pr "\n";
6223         | _ -> ()
6224       ) (snd style);
6225
6226       pr "  guestfs___end_busy (g);\n";
6227
6228       (match fst style with
6229        | RErr -> pr "  return 0;\n"
6230        | RInt n | RInt64 n | RBool n ->
6231            pr "  return ret.%s;\n" n
6232        | RConstString _ | RConstOptString _ ->
6233            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6234        | RString n ->
6235            pr "  return ret.%s; /* caller will free */\n" n
6236        | RStringList n | RHashtable n ->
6237            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6238            pr "  ret.%s.%s_val =\n" n n;
6239            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6240            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6241              n n;
6242            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6243            pr "  return ret.%s.%s_val;\n" n n
6244        | RStruct (n, _) ->
6245            pr "  /* caller will free this */\n";
6246            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6247        | RStructList (n, _) ->
6248            pr "  /* caller will free this */\n";
6249            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6250        | RBufferOut n ->
6251            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6252            pr "   * _val might be NULL here.  To make the API saner for\n";
6253            pr "   * callers, we turn this case into a unique pointer (using\n";
6254            pr "   * malloc(1)).\n";
6255            pr "   */\n";
6256            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6257            pr "    *size_r = ret.%s.%s_len;\n" n n;
6258            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6259            pr "  } else {\n";
6260            pr "    free (ret.%s.%s_val);\n" n n;
6261            pr "    char *p = safe_malloc (g, 1);\n";
6262            pr "    *size_r = ret.%s.%s_len;\n" n n;
6263            pr "    return p;\n";
6264            pr "  }\n";
6265       );
6266
6267       pr "}\n\n"
6268   ) daemon_functions;
6269
6270   (* Functions to free structures. *)
6271   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6272   pr " * structure format is identical to the XDR format.  See note in\n";
6273   pr " * generator.ml.\n";
6274   pr " */\n";
6275   pr "\n";
6276
6277   List.iter (
6278     fun (typ, _) ->
6279       pr "void\n";
6280       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6281       pr "{\n";
6282       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6283       pr "  free (x);\n";
6284       pr "}\n";
6285       pr "\n";
6286
6287       pr "void\n";
6288       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6289       pr "{\n";
6290       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6291       pr "  free (x);\n";
6292       pr "}\n";
6293       pr "\n";
6294
6295   ) structs;
6296
6297 (* Generate daemon/actions.h. *)
6298 and generate_daemon_actions_h () =
6299   generate_header CStyle GPLv2plus;
6300
6301   pr "#include \"../src/guestfs_protocol.h\"\n";
6302   pr "\n";
6303
6304   List.iter (
6305     fun (name, style, _, _, _, _, _) ->
6306       generate_prototype
6307         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6308         name style;
6309   ) daemon_functions
6310
6311 (* Generate the linker script which controls the visibility of
6312  * symbols in the public ABI and ensures no other symbols get
6313  * exported accidentally.
6314  *)
6315 and generate_linker_script () =
6316   generate_header HashStyle GPLv2plus;
6317
6318   let globals = [
6319     "guestfs_create";
6320     "guestfs_close";
6321     "guestfs_get_error_handler";
6322     "guestfs_get_out_of_memory_handler";
6323     "guestfs_last_error";
6324     "guestfs_set_error_handler";
6325     "guestfs_set_launch_done_callback";
6326     "guestfs_set_log_message_callback";
6327     "guestfs_set_out_of_memory_handler";
6328     "guestfs_set_subprocess_quit_callback";
6329
6330     (* Unofficial parts of the API: the bindings code use these
6331      * functions, so it is useful to export them.
6332      *)
6333     "guestfs_safe_calloc";
6334     "guestfs_safe_malloc";
6335   ] in
6336   let functions =
6337     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6338       all_functions in
6339   let structs =
6340     List.concat (
6341       List.map (fun (typ, _) ->
6342                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6343         structs
6344     ) in
6345   let globals = List.sort compare (globals @ functions @ structs) in
6346
6347   pr "{\n";
6348   pr "    global:\n";
6349   List.iter (pr "        %s;\n") globals;
6350   pr "\n";
6351
6352   pr "    local:\n";
6353   pr "        *;\n";
6354   pr "};\n"
6355
6356 (* Generate the server-side stubs. *)
6357 and generate_daemon_actions () =
6358   generate_header CStyle GPLv2plus;
6359
6360   pr "#include <config.h>\n";
6361   pr "\n";
6362   pr "#include <stdio.h>\n";
6363   pr "#include <stdlib.h>\n";
6364   pr "#include <string.h>\n";
6365   pr "#include <inttypes.h>\n";
6366   pr "#include <rpc/types.h>\n";
6367   pr "#include <rpc/xdr.h>\n";
6368   pr "\n";
6369   pr "#include \"daemon.h\"\n";
6370   pr "#include \"c-ctype.h\"\n";
6371   pr "#include \"../src/guestfs_protocol.h\"\n";
6372   pr "#include \"actions.h\"\n";
6373   pr "\n";
6374
6375   List.iter (
6376     fun (name, style, _, _, _, _, _) ->
6377       (* Generate server-side stubs. *)
6378       pr "static void %s_stub (XDR *xdr_in)\n" name;
6379       pr "{\n";
6380       let error_code =
6381         match fst style with
6382         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6383         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6384         | RBool _ -> pr "  int r;\n"; "-1"
6385         | RConstString _ | RConstOptString _ ->
6386             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6387         | RString _ -> pr "  char *r;\n"; "NULL"
6388         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6389         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6390         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6391         | RBufferOut _ ->
6392             pr "  size_t size = 1;\n";
6393             pr "  char *r;\n";
6394             "NULL" in
6395
6396       (match snd style with
6397        | [] -> ()
6398        | args ->
6399            pr "  struct guestfs_%s_args args;\n" name;
6400            List.iter (
6401              function
6402              | Device n | Dev_or_Path n
6403              | Pathname n
6404              | String n -> ()
6405              | OptString n -> pr "  char *%s;\n" n
6406              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6407              | Bool n -> pr "  int %s;\n" n
6408              | Int n -> pr "  int %s;\n" n
6409              | Int64 n -> pr "  int64_t %s;\n" n
6410              | FileIn _ | FileOut _ -> ()
6411              | BufferIn n ->
6412                  pr "  const char *%s;\n" n;
6413                  pr "  size_t %s_size;\n" n
6414            ) args
6415       );
6416       pr "\n";
6417
6418       let is_filein =
6419         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6420
6421       (match snd style with
6422        | [] -> ()
6423        | args ->
6424            pr "  memset (&args, 0, sizeof args);\n";
6425            pr "\n";
6426            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6427            if is_filein then
6428              pr "    if (cancel_receive () != -2)\n";
6429            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6430            pr "    goto done;\n";
6431            pr "  }\n";
6432            let pr_args n =
6433              pr "  char *%s = args.%s;\n" n n
6434            in
6435            let pr_list_handling_code n =
6436              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6437              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6438              pr "  if (%s == NULL) {\n" n;
6439              if is_filein then
6440                pr "    if (cancel_receive () != -2)\n";
6441              pr "      reply_with_perror (\"realloc\");\n";
6442              pr "    goto done;\n";
6443              pr "  }\n";
6444              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6445              pr "  args.%s.%s_val = %s;\n" n n n;
6446            in
6447            List.iter (
6448              function
6449              | Pathname n ->
6450                  pr_args n;
6451                  pr "  ABS_PATH (%s, %s, goto done);\n"
6452                    n (if is_filein then "cancel_receive ()" else "0");
6453              | Device n ->
6454                  pr_args n;
6455                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6456                    n (if is_filein then "cancel_receive ()" else "0");
6457              | Dev_or_Path n ->
6458                  pr_args n;
6459                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6460                    n (if is_filein then "cancel_receive ()" else "0");
6461              | String n -> pr_args n
6462              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6463              | StringList n ->
6464                  pr_list_handling_code n;
6465              | DeviceList n ->
6466                  pr_list_handling_code n;
6467                  pr "  /* Ensure that each is a device,\n";
6468                  pr "   * and perform device name translation. */\n";
6469                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6470                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6471                    (if is_filein then "cancel_receive ()" else "0");
6472                  pr "  }\n";
6473              | Bool n -> pr "  %s = args.%s;\n" n n
6474              | Int n -> pr "  %s = args.%s;\n" n n
6475              | Int64 n -> pr "  %s = args.%s;\n" n n
6476              | FileIn _ | FileOut _ -> ()
6477              | BufferIn n ->
6478                  pr "  %s = args.%s.%s_val;\n" n n n;
6479                  pr "  %s_size = args.%s.%s_len;\n" n n n
6480            ) args;
6481            pr "\n"
6482       );
6483
6484       (* this is used at least for do_equal *)
6485       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6486         (* Emit NEED_ROOT just once, even when there are two or
6487            more Pathname args *)
6488         pr "  NEED_ROOT (%s, goto done);\n"
6489           (if is_filein then "cancel_receive ()" else "0");
6490       );
6491
6492       (* Don't want to call the impl with any FileIn or FileOut
6493        * parameters, since these go "outside" the RPC protocol.
6494        *)
6495       let args' =
6496         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6497           (snd style) in
6498       pr "  r = do_%s " name;
6499       generate_c_call_args (fst style, args');
6500       pr ";\n";
6501
6502       (match fst style with
6503        | RErr | RInt _ | RInt64 _ | RBool _
6504        | RConstString _ | RConstOptString _
6505        | RString _ | RStringList _ | RHashtable _
6506        | RStruct (_, _) | RStructList (_, _) ->
6507            pr "  if (r == %s)\n" error_code;
6508            pr "    /* do_%s has already called reply_with_error */\n" name;
6509            pr "    goto done;\n";
6510            pr "\n"
6511        | RBufferOut _ ->
6512            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6513            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6514            pr "   */\n";
6515            pr "  if (size == 1 && r == %s)\n" error_code;
6516            pr "    /* do_%s has already called reply_with_error */\n" name;
6517            pr "    goto done;\n";
6518            pr "\n"
6519       );
6520
6521       (* If there are any FileOut parameters, then the impl must
6522        * send its own reply.
6523        *)
6524       let no_reply =
6525         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6526       if no_reply then
6527         pr "  /* do_%s has already sent a reply */\n" name
6528       else (
6529         match fst style with
6530         | RErr -> pr "  reply (NULL, NULL);\n"
6531         | RInt n | RInt64 n | RBool n ->
6532             pr "  struct guestfs_%s_ret ret;\n" name;
6533             pr "  ret.%s = r;\n" n;
6534             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6535               name
6536         | RConstString _ | RConstOptString _ ->
6537             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6538         | RString n ->
6539             pr "  struct guestfs_%s_ret ret;\n" name;
6540             pr "  ret.%s = r;\n" n;
6541             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6542               name;
6543             pr "  free (r);\n"
6544         | RStringList n | RHashtable n ->
6545             pr "  struct guestfs_%s_ret ret;\n" name;
6546             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6547             pr "  ret.%s.%s_val = r;\n" n n;
6548             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6549               name;
6550             pr "  free_strings (r);\n"
6551         | RStruct (n, _) ->
6552             pr "  struct guestfs_%s_ret ret;\n" name;
6553             pr "  ret.%s = *r;\n" n;
6554             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6555               name;
6556             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6557               name
6558         | RStructList (n, _) ->
6559             pr "  struct guestfs_%s_ret ret;\n" name;
6560             pr "  ret.%s = *r;\n" n;
6561             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6562               name;
6563             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6564               name
6565         | RBufferOut n ->
6566             pr "  struct guestfs_%s_ret ret;\n" name;
6567             pr "  ret.%s.%s_val = r;\n" n n;
6568             pr "  ret.%s.%s_len = size;\n" n n;
6569             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6570               name;
6571             pr "  free (r);\n"
6572       );
6573
6574       (* Free the args. *)
6575       pr "done:\n";
6576       (match snd style with
6577        | [] -> ()
6578        | _ ->
6579            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6580              name
6581       );
6582       pr "  return;\n";
6583       pr "}\n\n";
6584   ) daemon_functions;
6585
6586   (* Dispatch function. *)
6587   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6588   pr "{\n";
6589   pr "  switch (proc_nr) {\n";
6590
6591   List.iter (
6592     fun (name, style, _, _, _, _, _) ->
6593       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6594       pr "      %s_stub (xdr_in);\n" name;
6595       pr "      break;\n"
6596   ) daemon_functions;
6597
6598   pr "    default:\n";
6599   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";
6600   pr "  }\n";
6601   pr "}\n";
6602   pr "\n";
6603
6604   (* LVM columns and tokenization functions. *)
6605   (* XXX This generates crap code.  We should rethink how we
6606    * do this parsing.
6607    *)
6608   List.iter (
6609     function
6610     | typ, cols ->
6611         pr "static const char *lvm_%s_cols = \"%s\";\n"
6612           typ (String.concat "," (List.map fst cols));
6613         pr "\n";
6614
6615         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6616         pr "{\n";
6617         pr "  char *tok, *p, *next;\n";
6618         pr "  int i, j;\n";
6619         pr "\n";
6620         (*
6621           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6622           pr "\n";
6623         *)
6624         pr "  if (!str) {\n";
6625         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6626         pr "    return -1;\n";
6627         pr "  }\n";
6628         pr "  if (!*str || c_isspace (*str)) {\n";
6629         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6630         pr "    return -1;\n";
6631         pr "  }\n";
6632         pr "  tok = str;\n";
6633         List.iter (
6634           fun (name, coltype) ->
6635             pr "  if (!tok) {\n";
6636             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6637             pr "    return -1;\n";
6638             pr "  }\n";
6639             pr "  p = strchrnul (tok, ',');\n";
6640             pr "  if (*p) next = p+1; else next = NULL;\n";
6641             pr "  *p = '\\0';\n";
6642             (match coltype with
6643              | FString ->
6644                  pr "  r->%s = strdup (tok);\n" name;
6645                  pr "  if (r->%s == NULL) {\n" name;
6646                  pr "    perror (\"strdup\");\n";
6647                  pr "    return -1;\n";
6648                  pr "  }\n"
6649              | FUUID ->
6650                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6651                  pr "    if (tok[j] == '\\0') {\n";
6652                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6653                  pr "      return -1;\n";
6654                  pr "    } else if (tok[j] != '-')\n";
6655                  pr "      r->%s[i++] = tok[j];\n" name;
6656                  pr "  }\n";
6657              | FBytes ->
6658                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6659                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6660                  pr "    return -1;\n";
6661                  pr "  }\n";
6662              | FInt64 ->
6663                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6664                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6665                  pr "    return -1;\n";
6666                  pr "  }\n";
6667              | FOptPercent ->
6668                  pr "  if (tok[0] == '\\0')\n";
6669                  pr "    r->%s = -1;\n" name;
6670                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6671                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6672                  pr "    return -1;\n";
6673                  pr "  }\n";
6674              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6675                  assert false (* can never be an LVM column *)
6676             );
6677             pr "  tok = next;\n";
6678         ) cols;
6679
6680         pr "  if (tok != NULL) {\n";
6681         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6682         pr "    return -1;\n";
6683         pr "  }\n";
6684         pr "  return 0;\n";
6685         pr "}\n";
6686         pr "\n";
6687
6688         pr "guestfs_int_lvm_%s_list *\n" typ;
6689         pr "parse_command_line_%ss (void)\n" typ;
6690         pr "{\n";
6691         pr "  char *out, *err;\n";
6692         pr "  char *p, *pend;\n";
6693         pr "  int r, i;\n";
6694         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6695         pr "  void *newp;\n";
6696         pr "\n";
6697         pr "  ret = malloc (sizeof *ret);\n";
6698         pr "  if (!ret) {\n";
6699         pr "    reply_with_perror (\"malloc\");\n";
6700         pr "    return NULL;\n";
6701         pr "  }\n";
6702         pr "\n";
6703         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6704         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6705         pr "\n";
6706         pr "  r = command (&out, &err,\n";
6707         pr "           \"lvm\", \"%ss\",\n" typ;
6708         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6709         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6710         pr "  if (r == -1) {\n";
6711         pr "    reply_with_error (\"%%s\", err);\n";
6712         pr "    free (out);\n";
6713         pr "    free (err);\n";
6714         pr "    free (ret);\n";
6715         pr "    return NULL;\n";
6716         pr "  }\n";
6717         pr "\n";
6718         pr "  free (err);\n";
6719         pr "\n";
6720         pr "  /* Tokenize each line of the output. */\n";
6721         pr "  p = out;\n";
6722         pr "  i = 0;\n";
6723         pr "  while (p) {\n";
6724         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6725         pr "    if (pend) {\n";
6726         pr "      *pend = '\\0';\n";
6727         pr "      pend++;\n";
6728         pr "    }\n";
6729         pr "\n";
6730         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6731         pr "      p++;\n";
6732         pr "\n";
6733         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6734         pr "      p = pend;\n";
6735         pr "      continue;\n";
6736         pr "    }\n";
6737         pr "\n";
6738         pr "    /* Allocate some space to store this next entry. */\n";
6739         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6740         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6741         pr "    if (newp == NULL) {\n";
6742         pr "      reply_with_perror (\"realloc\");\n";
6743         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6744         pr "      free (ret);\n";
6745         pr "      free (out);\n";
6746         pr "      return NULL;\n";
6747         pr "    }\n";
6748         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6749         pr "\n";
6750         pr "    /* Tokenize the next entry. */\n";
6751         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6752         pr "    if (r == -1) {\n";
6753         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6754         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6755         pr "      free (ret);\n";
6756         pr "      free (out);\n";
6757         pr "      return NULL;\n";
6758         pr "    }\n";
6759         pr "\n";
6760         pr "    ++i;\n";
6761         pr "    p = pend;\n";
6762         pr "  }\n";
6763         pr "\n";
6764         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6765         pr "\n";
6766         pr "  free (out);\n";
6767         pr "  return ret;\n";
6768         pr "}\n"
6769
6770   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6771
6772 (* Generate a list of function names, for debugging in the daemon.. *)
6773 and generate_daemon_names () =
6774   generate_header CStyle GPLv2plus;
6775
6776   pr "#include <config.h>\n";
6777   pr "\n";
6778   pr "#include \"daemon.h\"\n";
6779   pr "\n";
6780
6781   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6782   pr "const char *function_names[] = {\n";
6783   List.iter (
6784     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6785   ) daemon_functions;
6786   pr "};\n";
6787
6788 (* Generate the optional groups for the daemon to implement
6789  * guestfs_available.
6790  *)
6791 and generate_daemon_optgroups_c () =
6792   generate_header CStyle GPLv2plus;
6793
6794   pr "#include <config.h>\n";
6795   pr "\n";
6796   pr "#include \"daemon.h\"\n";
6797   pr "#include \"optgroups.h\"\n";
6798   pr "\n";
6799
6800   pr "struct optgroup optgroups[] = {\n";
6801   List.iter (
6802     fun (group, _) ->
6803       pr "  { \"%s\", optgroup_%s_available },\n" group group
6804   ) optgroups;
6805   pr "  { NULL, NULL }\n";
6806   pr "};\n"
6807
6808 and generate_daemon_optgroups_h () =
6809   generate_header CStyle GPLv2plus;
6810
6811   List.iter (
6812     fun (group, _) ->
6813       pr "extern int optgroup_%s_available (void);\n" group
6814   ) optgroups
6815
6816 (* Generate the tests. *)
6817 and generate_tests () =
6818   generate_header CStyle GPLv2plus;
6819
6820   pr "\
6821 #include <stdio.h>
6822 #include <stdlib.h>
6823 #include <string.h>
6824 #include <unistd.h>
6825 #include <sys/types.h>
6826 #include <fcntl.h>
6827
6828 #include \"guestfs.h\"
6829 #include \"guestfs-internal.h\"
6830
6831 static guestfs_h *g;
6832 static int suppress_error = 0;
6833
6834 static void print_error (guestfs_h *g, void *data, const char *msg)
6835 {
6836   if (!suppress_error)
6837     fprintf (stderr, \"%%s\\n\", msg);
6838 }
6839
6840 /* FIXME: nearly identical code appears in fish.c */
6841 static void print_strings (char *const *argv)
6842 {
6843   int argc;
6844
6845   for (argc = 0; argv[argc] != NULL; ++argc)
6846     printf (\"\\t%%s\\n\", argv[argc]);
6847 }
6848
6849 /*
6850 static void print_table (char const *const *argv)
6851 {
6852   int i;
6853
6854   for (i = 0; argv[i] != NULL; i += 2)
6855     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6856 }
6857 */
6858
6859 static int
6860 is_available (const char *group)
6861 {
6862   const char *groups[] = { group, NULL };
6863   int r;
6864
6865   suppress_error = 1;
6866   r = guestfs_available (g, (char **) groups);
6867   suppress_error = 0;
6868
6869   return r == 0;
6870 }
6871
6872 ";
6873
6874   (* Generate a list of commands which are not tested anywhere. *)
6875   pr "static void no_test_warnings (void)\n";
6876   pr "{\n";
6877
6878   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6879   List.iter (
6880     fun (_, _, _, _, tests, _, _) ->
6881       let tests = filter_map (
6882         function
6883         | (_, (Always|If _|Unless _|IfAvailable _), test) -> Some test
6884         | (_, Disabled, _) -> None
6885       ) tests in
6886       let seq = List.concat (List.map seq_of_test tests) in
6887       let cmds_tested = List.map List.hd seq in
6888       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6889   ) all_functions;
6890
6891   List.iter (
6892     fun (name, _, _, _, _, _, _) ->
6893       if not (Hashtbl.mem hash name) then
6894         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6895   ) all_functions;
6896
6897   pr "}\n";
6898   pr "\n";
6899
6900   (* Generate the actual tests.  Note that we generate the tests
6901    * in reverse order, deliberately, so that (in general) the
6902    * newest tests run first.  This makes it quicker and easier to
6903    * debug them.
6904    *)
6905   let test_names =
6906     List.map (
6907       fun (name, _, _, flags, tests, _, _) ->
6908         mapi (generate_one_test name flags) tests
6909     ) (List.rev all_functions) in
6910   let test_names = List.concat test_names in
6911   let nr_tests = List.length test_names in
6912
6913   pr "\
6914 int main (int argc, char *argv[])
6915 {
6916   char c = 0;
6917   unsigned long int n_failed = 0;
6918   const char *filename;
6919   int fd;
6920   int nr_tests, test_num = 0;
6921
6922   setbuf (stdout, NULL);
6923
6924   no_test_warnings ();
6925
6926   g = guestfs_create ();
6927   if (g == NULL) {
6928     printf (\"guestfs_create FAILED\\n\");
6929     exit (EXIT_FAILURE);
6930   }
6931
6932   guestfs_set_error_handler (g, print_error, NULL);
6933
6934   guestfs_set_path (g, \"../appliance\");
6935
6936   filename = \"test1.img\";
6937   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6938   if (fd == -1) {
6939     perror (filename);
6940     exit (EXIT_FAILURE);
6941   }
6942   if (lseek (fd, %d, SEEK_SET) == -1) {
6943     perror (\"lseek\");
6944     close (fd);
6945     unlink (filename);
6946     exit (EXIT_FAILURE);
6947   }
6948   if (write (fd, &c, 1) == -1) {
6949     perror (\"write\");
6950     close (fd);
6951     unlink (filename);
6952     exit (EXIT_FAILURE);
6953   }
6954   if (close (fd) == -1) {
6955     perror (filename);
6956     unlink (filename);
6957     exit (EXIT_FAILURE);
6958   }
6959   if (guestfs_add_drive (g, filename) == -1) {
6960     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6961     exit (EXIT_FAILURE);
6962   }
6963
6964   filename = \"test2.img\";
6965   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6966   if (fd == -1) {
6967     perror (filename);
6968     exit (EXIT_FAILURE);
6969   }
6970   if (lseek (fd, %d, SEEK_SET) == -1) {
6971     perror (\"lseek\");
6972     close (fd);
6973     unlink (filename);
6974     exit (EXIT_FAILURE);
6975   }
6976   if (write (fd, &c, 1) == -1) {
6977     perror (\"write\");
6978     close (fd);
6979     unlink (filename);
6980     exit (EXIT_FAILURE);
6981   }
6982   if (close (fd) == -1) {
6983     perror (filename);
6984     unlink (filename);
6985     exit (EXIT_FAILURE);
6986   }
6987   if (guestfs_add_drive (g, filename) == -1) {
6988     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6989     exit (EXIT_FAILURE);
6990   }
6991
6992   filename = \"test3.img\";
6993   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6994   if (fd == -1) {
6995     perror (filename);
6996     exit (EXIT_FAILURE);
6997   }
6998   if (lseek (fd, %d, SEEK_SET) == -1) {
6999     perror (\"lseek\");
7000     close (fd);
7001     unlink (filename);
7002     exit (EXIT_FAILURE);
7003   }
7004   if (write (fd, &c, 1) == -1) {
7005     perror (\"write\");
7006     close (fd);
7007     unlink (filename);
7008     exit (EXIT_FAILURE);
7009   }
7010   if (close (fd) == -1) {
7011     perror (filename);
7012     unlink (filename);
7013     exit (EXIT_FAILURE);
7014   }
7015   if (guestfs_add_drive (g, filename) == -1) {
7016     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7017     exit (EXIT_FAILURE);
7018   }
7019
7020   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
7021     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
7022     exit (EXIT_FAILURE);
7023   }
7024
7025   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
7026   alarm (600);
7027
7028   if (guestfs_launch (g) == -1) {
7029     printf (\"guestfs_launch FAILED\\n\");
7030     exit (EXIT_FAILURE);
7031   }
7032
7033   /* Cancel previous alarm. */
7034   alarm (0);
7035
7036   nr_tests = %d;
7037
7038 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
7039
7040   iteri (
7041     fun i test_name ->
7042       pr "  test_num++;\n";
7043       pr "  if (guestfs_get_verbose (g))\n";
7044       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
7045       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
7046       pr "  if (%s () == -1) {\n" test_name;
7047       pr "    printf (\"%s FAILED\\n\");\n" test_name;
7048       pr "    n_failed++;\n";
7049       pr "  }\n";
7050   ) test_names;
7051   pr "\n";
7052
7053   pr "  guestfs_close (g);\n";
7054   pr "  unlink (\"test1.img\");\n";
7055   pr "  unlink (\"test2.img\");\n";
7056   pr "  unlink (\"test3.img\");\n";
7057   pr "\n";
7058
7059   pr "  if (n_failed > 0) {\n";
7060   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7061   pr "    exit (EXIT_FAILURE);\n";
7062   pr "  }\n";
7063   pr "\n";
7064
7065   pr "  exit (EXIT_SUCCESS);\n";
7066   pr "}\n"
7067
7068 and generate_one_test name flags i (init, prereq, test) =
7069   let test_name = sprintf "test_%s_%d" name i in
7070
7071   pr "\
7072 static int %s_skip (void)
7073 {
7074   const char *str;
7075
7076   str = getenv (\"TEST_ONLY\");
7077   if (str)
7078     return strstr (str, \"%s\") == NULL;
7079   str = getenv (\"SKIP_%s\");
7080   if (str && STREQ (str, \"1\")) return 1;
7081   str = getenv (\"SKIP_TEST_%s\");
7082   if (str && STREQ (str, \"1\")) return 1;
7083   return 0;
7084 }
7085
7086 " test_name name (String.uppercase test_name) (String.uppercase name);
7087
7088   (match prereq with
7089    | Disabled | Always | IfAvailable _ -> ()
7090    | If code | Unless code ->
7091        pr "static int %s_prereq (void)\n" test_name;
7092        pr "{\n";
7093        pr "  %s\n" code;
7094        pr "}\n";
7095        pr "\n";
7096   );
7097
7098   pr "\
7099 static int %s (void)
7100 {
7101   if (%s_skip ()) {
7102     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7103     return 0;
7104   }
7105
7106 " test_name test_name test_name;
7107
7108   (* Optional functions should only be tested if the relevant
7109    * support is available in the daemon.
7110    *)
7111   List.iter (
7112     function
7113     | Optional group ->
7114         pr "  if (!is_available (\"%s\")) {\n" group;
7115         pr "    printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", \"%s\");\n" test_name group;
7116         pr "    return 0;\n";
7117         pr "  }\n";
7118     | _ -> ()
7119   ) flags;
7120
7121   (match prereq with
7122    | Disabled ->
7123        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7124    | If _ ->
7125        pr "  if (! %s_prereq ()) {\n" test_name;
7126        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7127        pr "    return 0;\n";
7128        pr "  }\n";
7129        pr "\n";
7130        generate_one_test_body name i test_name init test;
7131    | Unless _ ->
7132        pr "  if (%s_prereq ()) {\n" test_name;
7133        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7134        pr "    return 0;\n";
7135        pr "  }\n";
7136        pr "\n";
7137        generate_one_test_body name i test_name init test;
7138    | IfAvailable group ->
7139        pr "  if (!is_available (\"%s\")) {\n" group;
7140        pr "    printf (\"        %%s skipped (reason: %%s not available)\\n\", \"%s\", \"%s\");\n" test_name group;
7141        pr "    return 0;\n";
7142        pr "  }\n";
7143        pr "\n";
7144        generate_one_test_body name i test_name init test;
7145    | Always ->
7146        generate_one_test_body name i test_name init test
7147   );
7148
7149   pr "  return 0;\n";
7150   pr "}\n";
7151   pr "\n";
7152   test_name
7153
7154 and generate_one_test_body name i test_name init test =
7155   (match init with
7156    | InitNone (* XXX at some point, InitNone and InitEmpty became
7157                * folded together as the same thing.  Really we should
7158                * make InitNone do nothing at all, but the tests may
7159                * need to be checked to make sure this is OK.
7160                *)
7161    | InitEmpty ->
7162        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7163        List.iter (generate_test_command_call test_name)
7164          [["blockdev_setrw"; "/dev/sda"];
7165           ["umount_all"];
7166           ["lvm_remove_all"]]
7167    | InitPartition ->
7168        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7169        List.iter (generate_test_command_call test_name)
7170          [["blockdev_setrw"; "/dev/sda"];
7171           ["umount_all"];
7172           ["lvm_remove_all"];
7173           ["part_disk"; "/dev/sda"; "mbr"]]
7174    | InitBasicFS ->
7175        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7176        List.iter (generate_test_command_call test_name)
7177          [["blockdev_setrw"; "/dev/sda"];
7178           ["umount_all"];
7179           ["lvm_remove_all"];
7180           ["part_disk"; "/dev/sda"; "mbr"];
7181           ["mkfs"; "ext2"; "/dev/sda1"];
7182           ["mount_options"; ""; "/dev/sda1"; "/"]]
7183    | InitBasicFSonLVM ->
7184        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7185          test_name;
7186        List.iter (generate_test_command_call test_name)
7187          [["blockdev_setrw"; "/dev/sda"];
7188           ["umount_all"];
7189           ["lvm_remove_all"];
7190           ["part_disk"; "/dev/sda"; "mbr"];
7191           ["pvcreate"; "/dev/sda1"];
7192           ["vgcreate"; "VG"; "/dev/sda1"];
7193           ["lvcreate"; "LV"; "VG"; "8"];
7194           ["mkfs"; "ext2"; "/dev/VG/LV"];
7195           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7196    | InitISOFS ->
7197        pr "  /* InitISOFS for %s */\n" test_name;
7198        List.iter (generate_test_command_call test_name)
7199          [["blockdev_setrw"; "/dev/sda"];
7200           ["umount_all"];
7201           ["lvm_remove_all"];
7202           ["mount_ro"; "/dev/sdd"; "/"]]
7203   );
7204
7205   let get_seq_last = function
7206     | [] ->
7207         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7208           test_name
7209     | seq ->
7210         let seq = List.rev seq in
7211         List.rev (List.tl seq), List.hd seq
7212   in
7213
7214   match test with
7215   | TestRun seq ->
7216       pr "  /* TestRun for %s (%d) */\n" name i;
7217       List.iter (generate_test_command_call test_name) seq
7218   | TestOutput (seq, expected) ->
7219       pr "  /* TestOutput for %s (%d) */\n" name i;
7220       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7221       let seq, last = get_seq_last seq in
7222       let test () =
7223         pr "    if (STRNEQ (r, expected)) {\n";
7224         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7225         pr "      return -1;\n";
7226         pr "    }\n"
7227       in
7228       List.iter (generate_test_command_call test_name) seq;
7229       generate_test_command_call ~test test_name last
7230   | TestOutputList (seq, expected) ->
7231       pr "  /* TestOutputList for %s (%d) */\n" name i;
7232       let seq, last = get_seq_last seq in
7233       let test () =
7234         iteri (
7235           fun i str ->
7236             pr "    if (!r[%d]) {\n" i;
7237             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7238             pr "      print_strings (r);\n";
7239             pr "      return -1;\n";
7240             pr "    }\n";
7241             pr "    {\n";
7242             pr "      const char *expected = \"%s\";\n" (c_quote str);
7243             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7244             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7245             pr "        return -1;\n";
7246             pr "      }\n";
7247             pr "    }\n"
7248         ) expected;
7249         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7250         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7251           test_name;
7252         pr "      print_strings (r);\n";
7253         pr "      return -1;\n";
7254         pr "    }\n"
7255       in
7256       List.iter (generate_test_command_call test_name) seq;
7257       generate_test_command_call ~test test_name last
7258   | TestOutputListOfDevices (seq, expected) ->
7259       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7260       let seq, last = get_seq_last seq in
7261       let test () =
7262         iteri (
7263           fun i str ->
7264             pr "    if (!r[%d]) {\n" i;
7265             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7266             pr "      print_strings (r);\n";
7267             pr "      return -1;\n";
7268             pr "    }\n";
7269             pr "    {\n";
7270             pr "      const char *expected = \"%s\";\n" (c_quote str);
7271             pr "      r[%d][5] = 's';\n" i;
7272             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7273             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7274             pr "        return -1;\n";
7275             pr "      }\n";
7276             pr "    }\n"
7277         ) expected;
7278         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7279         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7280           test_name;
7281         pr "      print_strings (r);\n";
7282         pr "      return -1;\n";
7283         pr "    }\n"
7284       in
7285       List.iter (generate_test_command_call test_name) seq;
7286       generate_test_command_call ~test test_name last
7287   | TestOutputInt (seq, expected) ->
7288       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7289       let seq, last = get_seq_last seq in
7290       let test () =
7291         pr "    if (r != %d) {\n" expected;
7292         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7293           test_name expected;
7294         pr "               (int) r);\n";
7295         pr "      return -1;\n";
7296         pr "    }\n"
7297       in
7298       List.iter (generate_test_command_call test_name) seq;
7299       generate_test_command_call ~test test_name last
7300   | TestOutputIntOp (seq, op, expected) ->
7301       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7302       let seq, last = get_seq_last seq in
7303       let test () =
7304         pr "    if (! (r %s %d)) {\n" op expected;
7305         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7306           test_name op expected;
7307         pr "               (int) r);\n";
7308         pr "      return -1;\n";
7309         pr "    }\n"
7310       in
7311       List.iter (generate_test_command_call test_name) seq;
7312       generate_test_command_call ~test test_name last
7313   | TestOutputTrue seq ->
7314       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7315       let seq, last = get_seq_last seq in
7316       let test () =
7317         pr "    if (!r) {\n";
7318         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7319           test_name;
7320         pr "      return -1;\n";
7321         pr "    }\n"
7322       in
7323       List.iter (generate_test_command_call test_name) seq;
7324       generate_test_command_call ~test test_name last
7325   | TestOutputFalse seq ->
7326       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7327       let seq, last = get_seq_last seq in
7328       let test () =
7329         pr "    if (r) {\n";
7330         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7331           test_name;
7332         pr "      return -1;\n";
7333         pr "    }\n"
7334       in
7335       List.iter (generate_test_command_call test_name) seq;
7336       generate_test_command_call ~test test_name last
7337   | TestOutputLength (seq, expected) ->
7338       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7339       let seq, last = get_seq_last seq in
7340       let test () =
7341         pr "    int j;\n";
7342         pr "    for (j = 0; j < %d; ++j)\n" expected;
7343         pr "      if (r[j] == NULL) {\n";
7344         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7345           test_name;
7346         pr "        print_strings (r);\n";
7347         pr "        return -1;\n";
7348         pr "      }\n";
7349         pr "    if (r[j] != NULL) {\n";
7350         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7351           test_name;
7352         pr "      print_strings (r);\n";
7353         pr "      return -1;\n";
7354         pr "    }\n"
7355       in
7356       List.iter (generate_test_command_call test_name) seq;
7357       generate_test_command_call ~test test_name last
7358   | TestOutputBuffer (seq, expected) ->
7359       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7360       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7361       let seq, last = get_seq_last seq in
7362       let len = String.length expected in
7363       let test () =
7364         pr "    if (size != %d) {\n" len;
7365         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7366         pr "      return -1;\n";
7367         pr "    }\n";
7368         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7369         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7370         pr "      return -1;\n";
7371         pr "    }\n"
7372       in
7373       List.iter (generate_test_command_call test_name) seq;
7374       generate_test_command_call ~test test_name last
7375   | TestOutputStruct (seq, checks) ->
7376       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7377       let seq, last = get_seq_last seq in
7378       let test () =
7379         List.iter (
7380           function
7381           | CompareWithInt (field, expected) ->
7382               pr "    if (r->%s != %d) {\n" field expected;
7383               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7384                 test_name field expected;
7385               pr "               (int) r->%s);\n" field;
7386               pr "      return -1;\n";
7387               pr "    }\n"
7388           | CompareWithIntOp (field, op, expected) ->
7389               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7390               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7391                 test_name field op expected;
7392               pr "               (int) r->%s);\n" field;
7393               pr "      return -1;\n";
7394               pr "    }\n"
7395           | CompareWithString (field, expected) ->
7396               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7397               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7398                 test_name field expected;
7399               pr "               r->%s);\n" field;
7400               pr "      return -1;\n";
7401               pr "    }\n"
7402           | CompareFieldsIntEq (field1, field2) ->
7403               pr "    if (r->%s != r->%s) {\n" field1 field2;
7404               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7405                 test_name field1 field2;
7406               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7407               pr "      return -1;\n";
7408               pr "    }\n"
7409           | CompareFieldsStrEq (field1, field2) ->
7410               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7411               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7412                 test_name field1 field2;
7413               pr "               r->%s, r->%s);\n" field1 field2;
7414               pr "      return -1;\n";
7415               pr "    }\n"
7416         ) checks
7417       in
7418       List.iter (generate_test_command_call test_name) seq;
7419       generate_test_command_call ~test test_name last
7420   | TestLastFail seq ->
7421       pr "  /* TestLastFail for %s (%d) */\n" name i;
7422       let seq, last = get_seq_last seq in
7423       List.iter (generate_test_command_call test_name) seq;
7424       generate_test_command_call test_name ~expect_error:true last
7425
7426 (* Generate the code to run a command, leaving the result in 'r'.
7427  * If you expect to get an error then you should set expect_error:true.
7428  *)
7429 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7430   match cmd with
7431   | [] -> assert false
7432   | name :: args ->
7433       (* Look up the command to find out what args/ret it has. *)
7434       let style =
7435         try
7436           let _, style, _, _, _, _, _ =
7437             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7438           style
7439         with Not_found ->
7440           failwithf "%s: in test, command %s was not found" test_name name in
7441
7442       if List.length (snd style) <> List.length args then
7443         failwithf "%s: in test, wrong number of args given to %s"
7444           test_name name;
7445
7446       pr "  {\n";
7447
7448       List.iter (
7449         function
7450         | OptString n, "NULL" -> ()
7451         | Pathname n, arg
7452         | Device n, arg
7453         | Dev_or_Path n, arg
7454         | String n, arg
7455         | OptString n, arg ->
7456             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7457         | BufferIn n, arg ->
7458             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7459             pr "    size_t %s_size = %d;\n" n (String.length arg)
7460         | Int _, _
7461         | Int64 _, _
7462         | Bool _, _
7463         | FileIn _, _ | FileOut _, _ -> ()
7464         | StringList n, "" | DeviceList n, "" ->
7465             pr "    const char *const %s[1] = { NULL };\n" n
7466         | StringList n, arg | DeviceList n, arg ->
7467             let strs = string_split " " arg in
7468             iteri (
7469               fun i str ->
7470                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7471             ) strs;
7472             pr "    const char *const %s[] = {\n" n;
7473             iteri (
7474               fun i _ -> pr "      %s_%d,\n" n i
7475             ) strs;
7476             pr "      NULL\n";
7477             pr "    };\n";
7478       ) (List.combine (snd style) args);
7479
7480       let error_code =
7481         match fst style with
7482         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7483         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7484         | RConstString _ | RConstOptString _ ->
7485             pr "    const char *r;\n"; "NULL"
7486         | RString _ -> pr "    char *r;\n"; "NULL"
7487         | RStringList _ | RHashtable _ ->
7488             pr "    char **r;\n";
7489             pr "    int i;\n";
7490             "NULL"
7491         | RStruct (_, typ) ->
7492             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7493         | RStructList (_, typ) ->
7494             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7495         | RBufferOut _ ->
7496             pr "    char *r;\n";
7497             pr "    size_t size;\n";
7498             "NULL" in
7499
7500       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7501       pr "    r = guestfs_%s (g" name;
7502
7503       (* Generate the parameters. *)
7504       List.iter (
7505         function
7506         | OptString _, "NULL" -> pr ", NULL"
7507         | Pathname n, _
7508         | Device n, _ | Dev_or_Path n, _
7509         | String n, _
7510         | OptString n, _ ->
7511             pr ", %s" n
7512         | BufferIn n, _ ->
7513             pr ", %s, %s_size" n n
7514         | FileIn _, arg | FileOut _, arg ->
7515             pr ", \"%s\"" (c_quote arg)
7516         | StringList n, _ | DeviceList n, _ ->
7517             pr ", (char **) %s" n
7518         | Int _, arg ->
7519             let i =
7520               try int_of_string arg
7521               with Failure "int_of_string" ->
7522                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7523             pr ", %d" i
7524         | Int64 _, arg ->
7525             let i =
7526               try Int64.of_string arg
7527               with Failure "int_of_string" ->
7528                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7529             pr ", %Ld" i
7530         | Bool _, arg ->
7531             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7532       ) (List.combine (snd style) args);
7533
7534       (match fst style with
7535        | RBufferOut _ -> pr ", &size"
7536        | _ -> ()
7537       );
7538
7539       pr ");\n";
7540
7541       if not expect_error then
7542         pr "    if (r == %s)\n" error_code
7543       else
7544         pr "    if (r != %s)\n" error_code;
7545       pr "      return -1;\n";
7546
7547       (* Insert the test code. *)
7548       (match test with
7549        | None -> ()
7550        | Some f -> f ()
7551       );
7552
7553       (match fst style with
7554        | RErr | RInt _ | RInt64 _ | RBool _
7555        | RConstString _ | RConstOptString _ -> ()
7556        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7557        | RStringList _ | RHashtable _ ->
7558            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7559            pr "      free (r[i]);\n";
7560            pr "    free (r);\n"
7561        | RStruct (_, typ) ->
7562            pr "    guestfs_free_%s (r);\n" typ
7563        | RStructList (_, typ) ->
7564            pr "    guestfs_free_%s_list (r);\n" typ
7565       );
7566
7567       pr "  }\n"
7568
7569 and c_quote str =
7570   let str = replace_str str "\r" "\\r" in
7571   let str = replace_str str "\n" "\\n" in
7572   let str = replace_str str "\t" "\\t" in
7573   let str = replace_str str "\000" "\\0" in
7574   str
7575
7576 (* Generate a lot of different functions for guestfish. *)
7577 and generate_fish_cmds () =
7578   generate_header CStyle GPLv2plus;
7579
7580   let all_functions =
7581     List.filter (
7582       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7583     ) all_functions in
7584   let all_functions_sorted =
7585     List.filter (
7586       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7587     ) all_functions_sorted in
7588
7589   pr "#include <config.h>\n";
7590   pr "\n";
7591   pr "#include <stdio.h>\n";
7592   pr "#include <stdlib.h>\n";
7593   pr "#include <string.h>\n";
7594   pr "#include <inttypes.h>\n";
7595   pr "\n";
7596   pr "#include <guestfs.h>\n";
7597   pr "#include \"c-ctype.h\"\n";
7598   pr "#include \"full-write.h\"\n";
7599   pr "#include \"xstrtol.h\"\n";
7600   pr "#include \"fish.h\"\n";
7601   pr "\n";
7602   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7603   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7604   pr "\n";
7605
7606   (* list_commands function, which implements guestfish -h *)
7607   pr "void list_commands (void)\n";
7608   pr "{\n";
7609   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7610   pr "  list_builtin_commands ();\n";
7611   List.iter (
7612     fun (name, _, _, flags, _, shortdesc, _) ->
7613       let name = replace_char name '_' '-' in
7614       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7615         name shortdesc
7616   ) all_functions_sorted;
7617   pr "  printf (\"    %%s\\n\",";
7618   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7619   pr "}\n";
7620   pr "\n";
7621
7622   (* display_command function, which implements guestfish -h cmd *)
7623   pr "int display_command (const char *cmd)\n";
7624   pr "{\n";
7625   List.iter (
7626     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7627       let name2 = replace_char name '_' '-' in
7628       let alias =
7629         try find_map (function FishAlias n -> Some n | _ -> None) flags
7630         with Not_found -> name in
7631       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7632       let synopsis =
7633         match snd style with
7634         | [] -> name2
7635         | args ->
7636             sprintf "%s %s"
7637               name2 (String.concat " " (List.map name_of_argt args)) in
7638
7639       let warnings =
7640         if List.mem ProtocolLimitWarning flags then
7641           ("\n\n" ^ protocol_limit_warning)
7642         else "" in
7643
7644       (* For DangerWillRobinson commands, we should probably have
7645        * guestfish prompt before allowing you to use them (especially
7646        * in interactive mode). XXX
7647        *)
7648       let warnings =
7649         warnings ^
7650           if List.mem DangerWillRobinson flags then
7651             ("\n\n" ^ danger_will_robinson)
7652           else "" in
7653
7654       let warnings =
7655         warnings ^
7656           match deprecation_notice flags with
7657           | None -> ""
7658           | Some txt -> "\n\n" ^ txt in
7659
7660       let describe_alias =
7661         if name <> alias then
7662           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7663         else "" in
7664
7665       pr "  if (";
7666       pr "STRCASEEQ (cmd, \"%s\")" name;
7667       if name <> name2 then
7668         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7669       if name <> alias then
7670         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7671       pr ") {\n";
7672       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7673         name2 shortdesc
7674         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7675          "=head1 DESCRIPTION\n\n" ^
7676          longdesc ^ warnings ^ describe_alias);
7677       pr "    return 0;\n";
7678       pr "  }\n";
7679       pr "  else\n"
7680   ) all_functions;
7681   pr "    return display_builtin_command (cmd);\n";
7682   pr "}\n";
7683   pr "\n";
7684
7685   let emit_print_list_function typ =
7686     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7687       typ typ typ;
7688     pr "{\n";
7689     pr "  unsigned int i;\n";
7690     pr "\n";
7691     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7692     pr "    printf (\"[%%d] = {\\n\", i);\n";
7693     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7694     pr "    printf (\"}\\n\");\n";
7695     pr "  }\n";
7696     pr "}\n";
7697     pr "\n";
7698   in
7699
7700   (* print_* functions *)
7701   List.iter (
7702     fun (typ, cols) ->
7703       let needs_i =
7704         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7705
7706       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7707       pr "{\n";
7708       if needs_i then (
7709         pr "  unsigned int i;\n";
7710         pr "\n"
7711       );
7712       List.iter (
7713         function
7714         | name, FString ->
7715             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7716         | name, FUUID ->
7717             pr "  printf (\"%%s%s: \", indent);\n" name;
7718             pr "  for (i = 0; i < 32; ++i)\n";
7719             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7720             pr "  printf (\"\\n\");\n"
7721         | name, FBuffer ->
7722             pr "  printf (\"%%s%s: \", indent);\n" name;
7723             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7724             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7725             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7726             pr "    else\n";
7727             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7728             pr "  printf (\"\\n\");\n"
7729         | name, (FUInt64|FBytes) ->
7730             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7731               name typ name
7732         | name, FInt64 ->
7733             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7734               name typ name
7735         | name, FUInt32 ->
7736             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7737               name typ name
7738         | name, FInt32 ->
7739             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7740               name typ name
7741         | name, FChar ->
7742             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7743               name typ name
7744         | name, FOptPercent ->
7745             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7746               typ name name typ name;
7747             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7748       ) cols;
7749       pr "}\n";
7750       pr "\n";
7751   ) structs;
7752
7753   (* Emit a print_TYPE_list function definition only if that function is used. *)
7754   List.iter (
7755     function
7756     | typ, (RStructListOnly | RStructAndList) ->
7757         (* generate the function for typ *)
7758         emit_print_list_function typ
7759     | typ, _ -> () (* empty *)
7760   ) (rstructs_used_by all_functions);
7761
7762   (* Emit a print_TYPE function definition only if that function is used. *)
7763   List.iter (
7764     function
7765     | typ, (RStructOnly | RStructAndList) ->
7766         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7767         pr "{\n";
7768         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7769         pr "}\n";
7770         pr "\n";
7771     | typ, _ -> () (* empty *)
7772   ) (rstructs_used_by all_functions);
7773
7774   (* run_<action> actions *)
7775   List.iter (
7776     fun (name, style, _, flags, _, _, _) ->
7777       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7778       pr "{\n";
7779       (match fst style with
7780        | RErr
7781        | RInt _
7782        | RBool _ -> pr "  int r;\n"
7783        | RInt64 _ -> pr "  int64_t r;\n"
7784        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7785        | RString _ -> pr "  char *r;\n"
7786        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7787        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7788        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7789        | RBufferOut _ ->
7790            pr "  char *r;\n";
7791            pr "  size_t size;\n";
7792       );
7793       List.iter (
7794         function
7795         | Device n
7796         | String n
7797         | OptString n -> pr "  const char *%s;\n" n
7798         | Pathname n
7799         | Dev_or_Path n
7800         | FileIn n
7801         | FileOut n -> pr "  char *%s;\n" n
7802         | BufferIn n ->
7803             pr "  const char *%s;\n" n;
7804             pr "  size_t %s_size;\n" n
7805         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7806         | Bool n -> pr "  int %s;\n" n
7807         | Int n -> pr "  int %s;\n" n
7808         | Int64 n -> pr "  int64_t %s;\n" n
7809       ) (snd style);
7810
7811       (* Check and convert parameters. *)
7812       let argc_expected = List.length (snd style) in
7813       pr "  if (argc != %d) {\n" argc_expected;
7814       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7815         argc_expected;
7816       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7817       pr "    return -1;\n";
7818       pr "  }\n";
7819
7820       let parse_integer fn fntyp rtyp range name i =
7821         pr "  {\n";
7822         pr "    strtol_error xerr;\n";
7823         pr "    %s r;\n" fntyp;
7824         pr "\n";
7825         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7826         pr "    if (xerr != LONGINT_OK) {\n";
7827         pr "      fprintf (stderr,\n";
7828         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7829         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7830         pr "      return -1;\n";
7831         pr "    }\n";
7832         (match range with
7833          | None -> ()
7834          | Some (min, max, comment) ->
7835              pr "    /* %s */\n" comment;
7836              pr "    if (r < %s || r > %s) {\n" min max;
7837              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7838                name;
7839              pr "      return -1;\n";
7840              pr "    }\n";
7841              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7842         );
7843         pr "    %s = r;\n" name;
7844         pr "  }\n";
7845       in
7846
7847       iteri (
7848         fun i ->
7849           function
7850           | Device name
7851           | String name ->
7852               pr "  %s = argv[%d];\n" name i
7853           | Pathname name
7854           | Dev_or_Path name ->
7855               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7856               pr "  if (%s == NULL) return -1;\n" name
7857           | OptString name ->
7858               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7859                 name i i
7860           | BufferIn name ->
7861               pr "  %s = argv[%d];\n" name i;
7862               pr "  %s_size = strlen (argv[%d]);\n" name i
7863           | FileIn name ->
7864               pr "  %s = file_in (argv[%d]);\n" name i;
7865               pr "  if (%s == NULL) return -1;\n" name
7866           | FileOut name ->
7867               pr "  %s = file_out (argv[%d]);\n" name i;
7868               pr "  if (%s == NULL) return -1;\n" name
7869           | StringList name | DeviceList name ->
7870               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7871               pr "  if (%s == NULL) return -1;\n" name;
7872           | Bool name ->
7873               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7874           | Int name ->
7875               let range =
7876                 let min = "(-(2LL<<30))"
7877                 and max = "((2LL<<30)-1)"
7878                 and comment =
7879                   "The Int type in the generator is a signed 31 bit int." in
7880                 Some (min, max, comment) in
7881               parse_integer "xstrtoll" "long long" "int" range name i
7882           | Int64 name ->
7883               parse_integer "xstrtoll" "long long" "int64_t" None name i
7884       ) (snd style);
7885
7886       (* Call C API function. *)
7887       pr "  r = guestfs_%s " name;
7888       generate_c_call_args ~handle:"g" style;
7889       pr ";\n";
7890
7891       List.iter (
7892         function
7893         | Device name | String name
7894         | OptString name | Bool name
7895         | Int name | Int64 name
7896         | BufferIn name -> ()
7897         | Pathname name | Dev_or_Path name | FileOut name ->
7898             pr "  free (%s);\n" name
7899         | FileIn name ->
7900             pr "  free_file_in (%s);\n" name
7901         | StringList name | DeviceList name ->
7902             pr "  free_strings (%s);\n" name
7903       ) (snd style);
7904
7905       (* Any output flags? *)
7906       let fish_output =
7907         let flags = filter_map (
7908           function FishOutput flag -> Some flag | _ -> None
7909         ) flags in
7910         match flags with
7911         | [] -> None
7912         | [f] -> Some f
7913         | _ ->
7914             failwithf "%s: more than one FishOutput flag is not allowed" name in
7915
7916       (* Check return value for errors and display command results. *)
7917       (match fst style with
7918        | RErr -> pr "  return r;\n"
7919        | RInt _ ->
7920            pr "  if (r == -1) return -1;\n";
7921            (match fish_output with
7922             | None ->
7923                 pr "  printf (\"%%d\\n\", r);\n";
7924             | Some FishOutputOctal ->
7925                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7926             | Some FishOutputHexadecimal ->
7927                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7928            pr "  return 0;\n"
7929        | RInt64 _ ->
7930            pr "  if (r == -1) return -1;\n";
7931            (match fish_output with
7932             | None ->
7933                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7934             | Some FishOutputOctal ->
7935                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7936             | Some FishOutputHexadecimal ->
7937                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7938            pr "  return 0;\n"
7939        | RBool _ ->
7940            pr "  if (r == -1) return -1;\n";
7941            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7942            pr "  return 0;\n"
7943        | RConstString _ ->
7944            pr "  if (r == NULL) return -1;\n";
7945            pr "  printf (\"%%s\\n\", r);\n";
7946            pr "  return 0;\n"
7947        | RConstOptString _ ->
7948            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7949            pr "  return 0;\n"
7950        | RString _ ->
7951            pr "  if (r == NULL) return -1;\n";
7952            pr "  printf (\"%%s\\n\", r);\n";
7953            pr "  free (r);\n";
7954            pr "  return 0;\n"
7955        | RStringList _ ->
7956            pr "  if (r == NULL) return -1;\n";
7957            pr "  print_strings (r);\n";
7958            pr "  free_strings (r);\n";
7959            pr "  return 0;\n"
7960        | RStruct (_, typ) ->
7961            pr "  if (r == NULL) return -1;\n";
7962            pr "  print_%s (r);\n" typ;
7963            pr "  guestfs_free_%s (r);\n" typ;
7964            pr "  return 0;\n"
7965        | RStructList (_, typ) ->
7966            pr "  if (r == NULL) return -1;\n";
7967            pr "  print_%s_list (r);\n" typ;
7968            pr "  guestfs_free_%s_list (r);\n" typ;
7969            pr "  return 0;\n"
7970        | RHashtable _ ->
7971            pr "  if (r == NULL) return -1;\n";
7972            pr "  print_table (r);\n";
7973            pr "  free_strings (r);\n";
7974            pr "  return 0;\n"
7975        | RBufferOut _ ->
7976            pr "  if (r == NULL) return -1;\n";
7977            pr "  if (full_write (1, r, size) != size) {\n";
7978            pr "    perror (\"write\");\n";
7979            pr "    free (r);\n";
7980            pr "    return -1;\n";
7981            pr "  }\n";
7982            pr "  free (r);\n";
7983            pr "  return 0;\n"
7984       );
7985       pr "}\n";
7986       pr "\n"
7987   ) all_functions;
7988
7989   (* run_action function *)
7990   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7991   pr "{\n";
7992   List.iter (
7993     fun (name, _, _, flags, _, _, _) ->
7994       let name2 = replace_char name '_' '-' in
7995       let alias =
7996         try find_map (function FishAlias n -> Some n | _ -> None) flags
7997         with Not_found -> name in
7998       pr "  if (";
7999       pr "STRCASEEQ (cmd, \"%s\")" name;
8000       if name <> name2 then
8001         pr " || STRCASEEQ (cmd, \"%s\")" name2;
8002       if name <> alias then
8003         pr " || STRCASEEQ (cmd, \"%s\")" alias;
8004       pr ")\n";
8005       pr "    return run_%s (cmd, argc, argv);\n" name;
8006       pr "  else\n";
8007   ) all_functions;
8008   pr "    {\n";
8009   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
8010   pr "      if (command_num == 1)\n";
8011   pr "        extended_help_message ();\n";
8012   pr "      return -1;\n";
8013   pr "    }\n";
8014   pr "  return 0;\n";
8015   pr "}\n";
8016   pr "\n"
8017
8018 (* Readline completion for guestfish. *)
8019 and generate_fish_completion () =
8020   generate_header CStyle GPLv2plus;
8021
8022   let all_functions =
8023     List.filter (
8024       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
8025     ) all_functions in
8026
8027   pr "\
8028 #include <config.h>
8029
8030 #include <stdio.h>
8031 #include <stdlib.h>
8032 #include <string.h>
8033
8034 #ifdef HAVE_LIBREADLINE
8035 #include <readline/readline.h>
8036 #endif
8037
8038 #include \"fish.h\"
8039
8040 #ifdef HAVE_LIBREADLINE
8041
8042 static const char *const commands[] = {
8043   BUILTIN_COMMANDS_FOR_COMPLETION,
8044 ";
8045
8046   (* Get the commands, including the aliases.  They don't need to be
8047    * sorted - the generator() function just does a dumb linear search.
8048    *)
8049   let commands =
8050     List.map (
8051       fun (name, _, _, flags, _, _, _) ->
8052         let name2 = replace_char name '_' '-' in
8053         let alias =
8054           try find_map (function FishAlias n -> Some n | _ -> None) flags
8055           with Not_found -> name in
8056
8057         if name <> alias then [name2; alias] else [name2]
8058     ) all_functions in
8059   let commands = List.flatten commands in
8060
8061   List.iter (pr "  \"%s\",\n") commands;
8062
8063   pr "  NULL
8064 };
8065
8066 static char *
8067 generator (const char *text, int state)
8068 {
8069   static int index, len;
8070   const char *name;
8071
8072   if (!state) {
8073     index = 0;
8074     len = strlen (text);
8075   }
8076
8077   rl_attempted_completion_over = 1;
8078
8079   while ((name = commands[index]) != NULL) {
8080     index++;
8081     if (STRCASEEQLEN (name, text, len))
8082       return strdup (name);
8083   }
8084
8085   return NULL;
8086 }
8087
8088 #endif /* HAVE_LIBREADLINE */
8089
8090 #ifdef HAVE_RL_COMPLETION_MATCHES
8091 #define RL_COMPLETION_MATCHES rl_completion_matches
8092 #else
8093 #ifdef HAVE_COMPLETION_MATCHES
8094 #define RL_COMPLETION_MATCHES completion_matches
8095 #endif
8096 #endif /* else just fail if we don't have either symbol */
8097
8098 char **
8099 do_completion (const char *text, int start, int end)
8100 {
8101   char **matches = NULL;
8102
8103 #ifdef HAVE_LIBREADLINE
8104   rl_completion_append_character = ' ';
8105
8106   if (start == 0)
8107     matches = RL_COMPLETION_MATCHES (text, generator);
8108   else if (complete_dest_paths)
8109     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8110 #endif
8111
8112   return matches;
8113 }
8114 ";
8115
8116 (* Generate the POD documentation for guestfish. *)
8117 and generate_fish_actions_pod () =
8118   let all_functions_sorted =
8119     List.filter (
8120       fun (_, _, _, flags, _, _, _) ->
8121         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8122     ) all_functions_sorted in
8123
8124   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8125
8126   List.iter (
8127     fun (name, style, _, flags, _, _, longdesc) ->
8128       let longdesc =
8129         Str.global_substitute rex (
8130           fun s ->
8131             let sub =
8132               try Str.matched_group 1 s
8133               with Not_found ->
8134                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8135             "C<" ^ replace_char sub '_' '-' ^ ">"
8136         ) longdesc in
8137       let name = replace_char name '_' '-' in
8138       let alias =
8139         try find_map (function FishAlias n -> Some n | _ -> None) flags
8140         with Not_found -> name in
8141
8142       pr "=head2 %s" name;
8143       if name <> alias then
8144         pr " | %s" alias;
8145       pr "\n";
8146       pr "\n";
8147       pr " %s" name;
8148       List.iter (
8149         function
8150         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8151         | OptString n -> pr " %s" n
8152         | StringList n | DeviceList n -> pr " '%s ...'" n
8153         | Bool _ -> pr " true|false"
8154         | Int n -> pr " %s" n
8155         | Int64 n -> pr " %s" n
8156         | FileIn n | FileOut n -> pr " (%s|-)" n
8157         | BufferIn n -> pr " %s" n
8158       ) (snd style);
8159       pr "\n";
8160       pr "\n";
8161       pr "%s\n\n" longdesc;
8162
8163       if List.exists (function FileIn _ | FileOut _ -> true
8164                       | _ -> false) (snd style) then
8165         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8166
8167       if List.mem ProtocolLimitWarning flags then
8168         pr "%s\n\n" protocol_limit_warning;
8169
8170       if List.mem DangerWillRobinson flags then
8171         pr "%s\n\n" danger_will_robinson;
8172
8173       match deprecation_notice flags with
8174       | None -> ()
8175       | Some txt -> pr "%s\n\n" txt
8176   ) all_functions_sorted
8177
8178 (* Generate a C function prototype. *)
8179 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8180     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8181     ?(prefix = "")
8182     ?handle name style =
8183   if extern then pr "extern ";
8184   if static then pr "static ";
8185   (match fst style with
8186    | RErr -> pr "int "
8187    | RInt _ -> pr "int "
8188    | RInt64 _ -> pr "int64_t "
8189    | RBool _ -> pr "int "
8190    | RConstString _ | RConstOptString _ -> pr "const char *"
8191    | RString _ | RBufferOut _ -> pr "char *"
8192    | RStringList _ | RHashtable _ -> pr "char **"
8193    | RStruct (_, typ) ->
8194        if not in_daemon then pr "struct guestfs_%s *" typ
8195        else pr "guestfs_int_%s *" typ
8196    | RStructList (_, typ) ->
8197        if not in_daemon then pr "struct guestfs_%s_list *" typ
8198        else pr "guestfs_int_%s_list *" typ
8199   );
8200   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8201   pr "%s%s (" prefix name;
8202   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8203     pr "void"
8204   else (
8205     let comma = ref false in
8206     (match handle with
8207      | None -> ()
8208      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8209     );
8210     let next () =
8211       if !comma then (
8212         if single_line then pr ", " else pr ",\n\t\t"
8213       );
8214       comma := true
8215     in
8216     List.iter (
8217       function
8218       | Pathname n
8219       | Device n | Dev_or_Path n
8220       | String n
8221       | OptString n ->
8222           next ();
8223           pr "const char *%s" n
8224       | StringList n | DeviceList n ->
8225           next ();
8226           pr "char *const *%s" n
8227       | Bool n -> next (); pr "int %s" n
8228       | Int n -> next (); pr "int %s" n
8229       | Int64 n -> next (); pr "int64_t %s" n
8230       | FileIn n
8231       | FileOut n ->
8232           if not in_daemon then (next (); pr "const char *%s" n)
8233       | BufferIn n ->
8234           next ();
8235           pr "const char *%s" n;
8236           next ();
8237           pr "size_t %s_size" n
8238     ) (snd style);
8239     if is_RBufferOut then (next (); pr "size_t *size_r");
8240   );
8241   pr ")";
8242   if semicolon then pr ";";
8243   if newline then pr "\n"
8244
8245 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8246 and generate_c_call_args ?handle ?(decl = false) style =
8247   pr "(";
8248   let comma = ref false in
8249   let next () =
8250     if !comma then pr ", ";
8251     comma := true
8252   in
8253   (match handle with
8254    | None -> ()
8255    | Some handle -> pr "%s" handle; comma := true
8256   );
8257   List.iter (
8258     function
8259     | BufferIn n ->
8260         next ();
8261         pr "%s, %s_size" n n
8262     | arg ->
8263         next ();
8264         pr "%s" (name_of_argt arg)
8265   ) (snd style);
8266   (* For RBufferOut calls, add implicit &size parameter. *)
8267   if not decl then (
8268     match fst style with
8269     | RBufferOut _ ->
8270         next ();
8271         pr "&size"
8272     | _ -> ()
8273   );
8274   pr ")"
8275
8276 (* Generate the OCaml bindings interface. *)
8277 and generate_ocaml_mli () =
8278   generate_header OCamlStyle LGPLv2plus;
8279
8280   pr "\
8281 (** For API documentation you should refer to the C API
8282     in the guestfs(3) manual page.  The OCaml API uses almost
8283     exactly the same calls. *)
8284
8285 type t
8286 (** A [guestfs_h] handle. *)
8287
8288 exception Error of string
8289 (** This exception is raised when there is an error. *)
8290
8291 exception Handle_closed of string
8292 (** This exception is raised if you use a {!Guestfs.t} handle
8293     after calling {!close} on it.  The string is the name of
8294     the function. *)
8295
8296 val create : unit -> t
8297 (** Create a {!Guestfs.t} handle. *)
8298
8299 val close : t -> unit
8300 (** Close the {!Guestfs.t} handle and free up all resources used
8301     by it immediately.
8302
8303     Handles are closed by the garbage collector when they become
8304     unreferenced, but callers can call this in order to provide
8305     predictable cleanup. *)
8306
8307 ";
8308   generate_ocaml_structure_decls ();
8309
8310   (* The actions. *)
8311   List.iter (
8312     fun (name, style, _, _, _, shortdesc, _) ->
8313       generate_ocaml_prototype name style;
8314       pr "(** %s *)\n" shortdesc;
8315       pr "\n"
8316   ) all_functions_sorted
8317
8318 (* Generate the OCaml bindings implementation. *)
8319 and generate_ocaml_ml () =
8320   generate_header OCamlStyle LGPLv2plus;
8321
8322   pr "\
8323 type t
8324
8325 exception Error of string
8326 exception Handle_closed of string
8327
8328 external create : unit -> t = \"ocaml_guestfs_create\"
8329 external close : t -> unit = \"ocaml_guestfs_close\"
8330
8331 (* Give the exceptions names, so they can be raised from the C code. *)
8332 let () =
8333   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8334   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8335
8336 ";
8337
8338   generate_ocaml_structure_decls ();
8339
8340   (* The actions. *)
8341   List.iter (
8342     fun (name, style, _, _, _, shortdesc, _) ->
8343       generate_ocaml_prototype ~is_external:true name style;
8344   ) all_functions_sorted
8345
8346 (* Generate the OCaml bindings C implementation. *)
8347 and generate_ocaml_c () =
8348   generate_header CStyle LGPLv2plus;
8349
8350   pr "\
8351 #include <stdio.h>
8352 #include <stdlib.h>
8353 #include <string.h>
8354
8355 #include <caml/config.h>
8356 #include <caml/alloc.h>
8357 #include <caml/callback.h>
8358 #include <caml/fail.h>
8359 #include <caml/memory.h>
8360 #include <caml/mlvalues.h>
8361 #include <caml/signals.h>
8362
8363 #include <guestfs.h>
8364
8365 #include \"guestfs_c.h\"
8366
8367 /* Copy a hashtable of string pairs into an assoc-list.  We return
8368  * the list in reverse order, but hashtables aren't supposed to be
8369  * ordered anyway.
8370  */
8371 static CAMLprim value
8372 copy_table (char * const * argv)
8373 {
8374   CAMLparam0 ();
8375   CAMLlocal5 (rv, pairv, kv, vv, cons);
8376   int i;
8377
8378   rv = Val_int (0);
8379   for (i = 0; argv[i] != NULL; i += 2) {
8380     kv = caml_copy_string (argv[i]);
8381     vv = caml_copy_string (argv[i+1]);
8382     pairv = caml_alloc (2, 0);
8383     Store_field (pairv, 0, kv);
8384     Store_field (pairv, 1, vv);
8385     cons = caml_alloc (2, 0);
8386     Store_field (cons, 1, rv);
8387     rv = cons;
8388     Store_field (cons, 0, pairv);
8389   }
8390
8391   CAMLreturn (rv);
8392 }
8393
8394 ";
8395
8396   (* Struct copy functions. *)
8397
8398   let emit_ocaml_copy_list_function typ =
8399     pr "static CAMLprim value\n";
8400     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8401     pr "{\n";
8402     pr "  CAMLparam0 ();\n";
8403     pr "  CAMLlocal2 (rv, v);\n";
8404     pr "  unsigned int i;\n";
8405     pr "\n";
8406     pr "  if (%ss->len == 0)\n" typ;
8407     pr "    CAMLreturn (Atom (0));\n";
8408     pr "  else {\n";
8409     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8410     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8411     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8412     pr "      caml_modify (&Field (rv, i), v);\n";
8413     pr "    }\n";
8414     pr "    CAMLreturn (rv);\n";
8415     pr "  }\n";
8416     pr "}\n";
8417     pr "\n";
8418   in
8419
8420   List.iter (
8421     fun (typ, cols) ->
8422       let has_optpercent_col =
8423         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8424
8425       pr "static CAMLprim value\n";
8426       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8427       pr "{\n";
8428       pr "  CAMLparam0 ();\n";
8429       if has_optpercent_col then
8430         pr "  CAMLlocal3 (rv, v, v2);\n"
8431       else
8432         pr "  CAMLlocal2 (rv, v);\n";
8433       pr "\n";
8434       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8435       iteri (
8436         fun i col ->
8437           (match col with
8438            | name, FString ->
8439                pr "  v = caml_copy_string (%s->%s);\n" typ name
8440            | name, FBuffer ->
8441                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8442                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8443                  typ name typ name
8444            | name, FUUID ->
8445                pr "  v = caml_alloc_string (32);\n";
8446                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8447            | name, (FBytes|FInt64|FUInt64) ->
8448                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8449            | name, (FInt32|FUInt32) ->
8450                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8451            | name, FOptPercent ->
8452                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8453                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8454                pr "    v = caml_alloc (1, 0);\n";
8455                pr "    Store_field (v, 0, v2);\n";
8456                pr "  } else /* None */\n";
8457                pr "    v = Val_int (0);\n";
8458            | name, FChar ->
8459                pr "  v = Val_int (%s->%s);\n" typ name
8460           );
8461           pr "  Store_field (rv, %d, v);\n" i
8462       ) cols;
8463       pr "  CAMLreturn (rv);\n";
8464       pr "}\n";
8465       pr "\n";
8466   ) structs;
8467
8468   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8469   List.iter (
8470     function
8471     | typ, (RStructListOnly | RStructAndList) ->
8472         (* generate the function for typ *)
8473         emit_ocaml_copy_list_function typ
8474     | typ, _ -> () (* empty *)
8475   ) (rstructs_used_by all_functions);
8476
8477   (* The wrappers. *)
8478   List.iter (
8479     fun (name, style, _, _, _, _, _) ->
8480       pr "/* Automatically generated wrapper for function\n";
8481       pr " * ";
8482       generate_ocaml_prototype name style;
8483       pr " */\n";
8484       pr "\n";
8485
8486       let params =
8487         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8488
8489       let needs_extra_vs =
8490         match fst style with RConstOptString _ -> true | _ -> false in
8491
8492       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8493       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8494       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8495       pr "\n";
8496
8497       pr "CAMLprim value\n";
8498       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8499       List.iter (pr ", value %s") (List.tl params);
8500       pr ")\n";
8501       pr "{\n";
8502
8503       (match params with
8504        | [p1; p2; p3; p4; p5] ->
8505            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8506        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8507            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8508            pr "  CAMLxparam%d (%s);\n"
8509              (List.length rest) (String.concat ", " rest)
8510        | ps ->
8511            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8512       );
8513       if not needs_extra_vs then
8514         pr "  CAMLlocal1 (rv);\n"
8515       else
8516         pr "  CAMLlocal3 (rv, v, v2);\n";
8517       pr "\n";
8518
8519       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8520       pr "  if (g == NULL)\n";
8521       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8522       pr "\n";
8523
8524       List.iter (
8525         function
8526         | Pathname n
8527         | Device n | Dev_or_Path n
8528         | String n
8529         | FileIn n
8530         | FileOut n ->
8531             pr "  const char *%s = String_val (%sv);\n" n n
8532         | OptString n ->
8533             pr "  const char *%s =\n" n;
8534             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8535               n n
8536         | BufferIn n ->
8537             pr "  const char *%s = String_val (%sv);\n" n n;
8538             pr "  size_t %s_size = caml_string_length (%sv);\n" n n
8539         | StringList n | DeviceList n ->
8540             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8541         | Bool n ->
8542             pr "  int %s = Bool_val (%sv);\n" n n
8543         | Int n ->
8544             pr "  int %s = Int_val (%sv);\n" n n
8545         | Int64 n ->
8546             pr "  int64_t %s = Int64_val (%sv);\n" n n
8547       ) (snd style);
8548       let error_code =
8549         match fst style with
8550         | RErr -> pr "  int r;\n"; "-1"
8551         | RInt _ -> pr "  int r;\n"; "-1"
8552         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8553         | RBool _ -> pr "  int r;\n"; "-1"
8554         | RConstString _ | RConstOptString _ ->
8555             pr "  const char *r;\n"; "NULL"
8556         | RString _ -> pr "  char *r;\n"; "NULL"
8557         | RStringList _ ->
8558             pr "  int i;\n";
8559             pr "  char **r;\n";
8560             "NULL"
8561         | RStruct (_, typ) ->
8562             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8563         | RStructList (_, typ) ->
8564             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8565         | RHashtable _ ->
8566             pr "  int i;\n";
8567             pr "  char **r;\n";
8568             "NULL"
8569         | RBufferOut _ ->
8570             pr "  char *r;\n";
8571             pr "  size_t size;\n";
8572             "NULL" in
8573       pr "\n";
8574
8575       pr "  caml_enter_blocking_section ();\n";
8576       pr "  r = guestfs_%s " name;
8577       generate_c_call_args ~handle:"g" style;
8578       pr ";\n";
8579       pr "  caml_leave_blocking_section ();\n";
8580
8581       List.iter (
8582         function
8583         | StringList n | DeviceList n ->
8584             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8585         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8586         | Bool _ | Int _ | Int64 _
8587         | FileIn _ | FileOut _ | BufferIn _ -> ()
8588       ) (snd style);
8589
8590       pr "  if (r == %s)\n" error_code;
8591       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8592       pr "\n";
8593
8594       (match fst style with
8595        | RErr -> pr "  rv = Val_unit;\n"
8596        | RInt _ -> pr "  rv = Val_int (r);\n"
8597        | RInt64 _ ->
8598            pr "  rv = caml_copy_int64 (r);\n"
8599        | RBool _ -> pr "  rv = Val_bool (r);\n"
8600        | RConstString _ ->
8601            pr "  rv = caml_copy_string (r);\n"
8602        | RConstOptString _ ->
8603            pr "  if (r) { /* Some string */\n";
8604            pr "    v = caml_alloc (1, 0);\n";
8605            pr "    v2 = caml_copy_string (r);\n";
8606            pr "    Store_field (v, 0, v2);\n";
8607            pr "  } else /* None */\n";
8608            pr "    v = Val_int (0);\n";
8609        | RString _ ->
8610            pr "  rv = caml_copy_string (r);\n";
8611            pr "  free (r);\n"
8612        | RStringList _ ->
8613            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8614            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8615            pr "  free (r);\n"
8616        | RStruct (_, typ) ->
8617            pr "  rv = copy_%s (r);\n" typ;
8618            pr "  guestfs_free_%s (r);\n" typ;
8619        | RStructList (_, typ) ->
8620            pr "  rv = copy_%s_list (r);\n" typ;
8621            pr "  guestfs_free_%s_list (r);\n" typ;
8622        | RHashtable _ ->
8623            pr "  rv = copy_table (r);\n";
8624            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8625            pr "  free (r);\n";
8626        | RBufferOut _ ->
8627            pr "  rv = caml_alloc_string (size);\n";
8628            pr "  memcpy (String_val (rv), r, size);\n";
8629       );
8630
8631       pr "  CAMLreturn (rv);\n";
8632       pr "}\n";
8633       pr "\n";
8634
8635       if List.length params > 5 then (
8636         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8637         pr "CAMLprim value ";
8638         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8639         pr "CAMLprim value\n";
8640         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8641         pr "{\n";
8642         pr "  return ocaml_guestfs_%s (argv[0]" name;
8643         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8644         pr ");\n";
8645         pr "}\n";
8646         pr "\n"
8647       )
8648   ) all_functions_sorted
8649
8650 and generate_ocaml_structure_decls () =
8651   List.iter (
8652     fun (typ, cols) ->
8653       pr "type %s = {\n" typ;
8654       List.iter (
8655         function
8656         | name, FString -> pr "  %s : string;\n" name
8657         | name, FBuffer -> pr "  %s : string;\n" name
8658         | name, FUUID -> pr "  %s : string;\n" name
8659         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8660         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8661         | name, FChar -> pr "  %s : char;\n" name
8662         | name, FOptPercent -> pr "  %s : float option;\n" name
8663       ) cols;
8664       pr "}\n";
8665       pr "\n"
8666   ) structs
8667
8668 and generate_ocaml_prototype ?(is_external = false) name style =
8669   if is_external then pr "external " else pr "val ";
8670   pr "%s : t -> " name;
8671   List.iter (
8672     function
8673     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8674     | BufferIn _ -> pr "string -> "
8675     | OptString _ -> pr "string option -> "
8676     | StringList _ | DeviceList _ -> pr "string array -> "
8677     | Bool _ -> pr "bool -> "
8678     | Int _ -> pr "int -> "
8679     | Int64 _ -> pr "int64 -> "
8680   ) (snd style);
8681   (match fst style with
8682    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8683    | RInt _ -> pr "int"
8684    | RInt64 _ -> pr "int64"
8685    | RBool _ -> pr "bool"
8686    | RConstString _ -> pr "string"
8687    | RConstOptString _ -> pr "string option"
8688    | RString _ | RBufferOut _ -> pr "string"
8689    | RStringList _ -> pr "string array"
8690    | RStruct (_, typ) -> pr "%s" typ
8691    | RStructList (_, typ) -> pr "%s array" typ
8692    | RHashtable _ -> pr "(string * string) list"
8693   );
8694   if is_external then (
8695     pr " = ";
8696     if List.length (snd style) + 1 > 5 then
8697       pr "\"ocaml_guestfs_%s_byte\" " name;
8698     pr "\"ocaml_guestfs_%s\"" name
8699   );
8700   pr "\n"
8701
8702 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8703 and generate_perl_xs () =
8704   generate_header CStyle LGPLv2plus;
8705
8706   pr "\
8707 #include \"EXTERN.h\"
8708 #include \"perl.h\"
8709 #include \"XSUB.h\"
8710
8711 #include <guestfs.h>
8712
8713 #ifndef PRId64
8714 #define PRId64 \"lld\"
8715 #endif
8716
8717 static SV *
8718 my_newSVll(long long val) {
8719 #ifdef USE_64_BIT_ALL
8720   return newSViv(val);
8721 #else
8722   char buf[100];
8723   int len;
8724   len = snprintf(buf, 100, \"%%\" PRId64, val);
8725   return newSVpv(buf, len);
8726 #endif
8727 }
8728
8729 #ifndef PRIu64
8730 #define PRIu64 \"llu\"
8731 #endif
8732
8733 static SV *
8734 my_newSVull(unsigned long long val) {
8735 #ifdef USE_64_BIT_ALL
8736   return newSVuv(val);
8737 #else
8738   char buf[100];
8739   int len;
8740   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8741   return newSVpv(buf, len);
8742 #endif
8743 }
8744
8745 /* http://www.perlmonks.org/?node_id=680842 */
8746 static char **
8747 XS_unpack_charPtrPtr (SV *arg) {
8748   char **ret;
8749   AV *av;
8750   I32 i;
8751
8752   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8753     croak (\"array reference expected\");
8754
8755   av = (AV *)SvRV (arg);
8756   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8757   if (!ret)
8758     croak (\"malloc failed\");
8759
8760   for (i = 0; i <= av_len (av); i++) {
8761     SV **elem = av_fetch (av, i, 0);
8762
8763     if (!elem || !*elem)
8764       croak (\"missing element in list\");
8765
8766     ret[i] = SvPV_nolen (*elem);
8767   }
8768
8769   ret[i] = NULL;
8770
8771   return ret;
8772 }
8773
8774 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8775
8776 PROTOTYPES: ENABLE
8777
8778 guestfs_h *
8779 _create ()
8780    CODE:
8781       RETVAL = guestfs_create ();
8782       if (!RETVAL)
8783         croak (\"could not create guestfs handle\");
8784       guestfs_set_error_handler (RETVAL, NULL, NULL);
8785  OUTPUT:
8786       RETVAL
8787
8788 void
8789 DESTROY (g)
8790       guestfs_h *g;
8791  PPCODE:
8792       guestfs_close (g);
8793
8794 ";
8795
8796   List.iter (
8797     fun (name, style, _, _, _, _, _) ->
8798       (match fst style with
8799        | RErr -> pr "void\n"
8800        | RInt _ -> pr "SV *\n"
8801        | RInt64 _ -> pr "SV *\n"
8802        | RBool _ -> pr "SV *\n"
8803        | RConstString _ -> pr "SV *\n"
8804        | RConstOptString _ -> pr "SV *\n"
8805        | RString _ -> pr "SV *\n"
8806        | RBufferOut _ -> pr "SV *\n"
8807        | RStringList _
8808        | RStruct _ | RStructList _
8809        | RHashtable _ ->
8810            pr "void\n" (* all lists returned implictly on the stack *)
8811       );
8812       (* Call and arguments. *)
8813       pr "%s (g" name;
8814       List.iter (
8815         fun arg -> pr ", %s" (name_of_argt arg)
8816       ) (snd style);
8817       pr ")\n";
8818       pr "      guestfs_h *g;\n";
8819       iteri (
8820         fun i ->
8821           function
8822           | Pathname n | Device n | Dev_or_Path n | String n
8823           | FileIn n | FileOut n ->
8824               pr "      char *%s;\n" n
8825           | BufferIn n ->
8826               pr "      char *%s;\n" n;
8827               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8828           | OptString n ->
8829               (* http://www.perlmonks.org/?node_id=554277
8830                * Note that the implicit handle argument means we have
8831                * to add 1 to the ST(x) operator.
8832                *)
8833               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8834           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8835           | Bool n -> pr "      int %s;\n" n
8836           | Int n -> pr "      int %s;\n" n
8837           | Int64 n -> pr "      int64_t %s;\n" n
8838       ) (snd style);
8839
8840       let do_cleanups () =
8841         List.iter (
8842           function
8843           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8844           | Bool _ | Int _ | Int64 _
8845           | FileIn _ | FileOut _
8846           | BufferIn _ -> ()
8847           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8848         ) (snd style)
8849       in
8850
8851       (* Code. *)
8852       (match fst style with
8853        | RErr ->
8854            pr "PREINIT:\n";
8855            pr "      int r;\n";
8856            pr " PPCODE:\n";
8857            pr "      r = guestfs_%s " name;
8858            generate_c_call_args ~handle:"g" style;
8859            pr ";\n";
8860            do_cleanups ();
8861            pr "      if (r == -1)\n";
8862            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8863        | RInt n
8864        | RBool n ->
8865            pr "PREINIT:\n";
8866            pr "      int %s;\n" n;
8867            pr "   CODE:\n";
8868            pr "      %s = guestfs_%s " n name;
8869            generate_c_call_args ~handle:"g" style;
8870            pr ";\n";
8871            do_cleanups ();
8872            pr "      if (%s == -1)\n" n;
8873            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8874            pr "      RETVAL = newSViv (%s);\n" n;
8875            pr " OUTPUT:\n";
8876            pr "      RETVAL\n"
8877        | RInt64 n ->
8878            pr "PREINIT:\n";
8879            pr "      int64_t %s;\n" n;
8880            pr "   CODE:\n";
8881            pr "      %s = guestfs_%s " n name;
8882            generate_c_call_args ~handle:"g" style;
8883            pr ";\n";
8884            do_cleanups ();
8885            pr "      if (%s == -1)\n" n;
8886            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8887            pr "      RETVAL = my_newSVll (%s);\n" n;
8888            pr " OUTPUT:\n";
8889            pr "      RETVAL\n"
8890        | RConstString n ->
8891            pr "PREINIT:\n";
8892            pr "      const char *%s;\n" n;
8893            pr "   CODE:\n";
8894            pr "      %s = guestfs_%s " n name;
8895            generate_c_call_args ~handle:"g" style;
8896            pr ";\n";
8897            do_cleanups ();
8898            pr "      if (%s == NULL)\n" n;
8899            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8900            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8901            pr " OUTPUT:\n";
8902            pr "      RETVAL\n"
8903        | RConstOptString n ->
8904            pr "PREINIT:\n";
8905            pr "      const char *%s;\n" n;
8906            pr "   CODE:\n";
8907            pr "      %s = guestfs_%s " n name;
8908            generate_c_call_args ~handle:"g" style;
8909            pr ";\n";
8910            do_cleanups ();
8911            pr "      if (%s == NULL)\n" n;
8912            pr "        RETVAL = &PL_sv_undef;\n";
8913            pr "      else\n";
8914            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8915            pr " OUTPUT:\n";
8916            pr "      RETVAL\n"
8917        | RString n ->
8918            pr "PREINIT:\n";
8919            pr "      char *%s;\n" n;
8920            pr "   CODE:\n";
8921            pr "      %s = guestfs_%s " n name;
8922            generate_c_call_args ~handle:"g" style;
8923            pr ";\n";
8924            do_cleanups ();
8925            pr "      if (%s == NULL)\n" n;
8926            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8927            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8928            pr "      free (%s);\n" n;
8929            pr " OUTPUT:\n";
8930            pr "      RETVAL\n"
8931        | RStringList n | RHashtable n ->
8932            pr "PREINIT:\n";
8933            pr "      char **%s;\n" n;
8934            pr "      int i, n;\n";
8935            pr " PPCODE:\n";
8936            pr "      %s = guestfs_%s " n name;
8937            generate_c_call_args ~handle:"g" style;
8938            pr ";\n";
8939            do_cleanups ();
8940            pr "      if (%s == NULL)\n" n;
8941            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8942            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8943            pr "      EXTEND (SP, n);\n";
8944            pr "      for (i = 0; i < n; ++i) {\n";
8945            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8946            pr "        free (%s[i]);\n" n;
8947            pr "      }\n";
8948            pr "      free (%s);\n" n;
8949        | RStruct (n, typ) ->
8950            let cols = cols_of_struct typ in
8951            generate_perl_struct_code typ cols name style n do_cleanups
8952        | RStructList (n, typ) ->
8953            let cols = cols_of_struct typ in
8954            generate_perl_struct_list_code typ cols name style n do_cleanups
8955        | RBufferOut n ->
8956            pr "PREINIT:\n";
8957            pr "      char *%s;\n" n;
8958            pr "      size_t size;\n";
8959            pr "   CODE:\n";
8960            pr "      %s = guestfs_%s " n name;
8961            generate_c_call_args ~handle:"g" style;
8962            pr ";\n";
8963            do_cleanups ();
8964            pr "      if (%s == NULL)\n" n;
8965            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8966            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8967            pr "      free (%s);\n" n;
8968            pr " OUTPUT:\n";
8969            pr "      RETVAL\n"
8970       );
8971
8972       pr "\n"
8973   ) all_functions
8974
8975 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8976   pr "PREINIT:\n";
8977   pr "      struct guestfs_%s_list *%s;\n" typ n;
8978   pr "      int i;\n";
8979   pr "      HV *hv;\n";
8980   pr " PPCODE:\n";
8981   pr "      %s = guestfs_%s " n name;
8982   generate_c_call_args ~handle:"g" style;
8983   pr ";\n";
8984   do_cleanups ();
8985   pr "      if (%s == NULL)\n" n;
8986   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8987   pr "      EXTEND (SP, %s->len);\n" n;
8988   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8989   pr "        hv = newHV ();\n";
8990   List.iter (
8991     function
8992     | name, FString ->
8993         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8994           name (String.length name) n name
8995     | name, FUUID ->
8996         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8997           name (String.length name) n name
8998     | name, FBuffer ->
8999         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
9000           name (String.length name) n name n name
9001     | name, (FBytes|FUInt64) ->
9002         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
9003           name (String.length name) n name
9004     | name, FInt64 ->
9005         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
9006           name (String.length name) n name
9007     | name, (FInt32|FUInt32) ->
9008         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9009           name (String.length name) n name
9010     | name, FChar ->
9011         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
9012           name (String.length name) n name
9013     | name, FOptPercent ->
9014         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9015           name (String.length name) n name
9016   ) cols;
9017   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
9018   pr "      }\n";
9019   pr "      guestfs_free_%s_list (%s);\n" typ n
9020
9021 and generate_perl_struct_code typ cols name style n do_cleanups =
9022   pr "PREINIT:\n";
9023   pr "      struct guestfs_%s *%s;\n" typ n;
9024   pr " PPCODE:\n";
9025   pr "      %s = guestfs_%s " n name;
9026   generate_c_call_args ~handle:"g" style;
9027   pr ";\n";
9028   do_cleanups ();
9029   pr "      if (%s == NULL)\n" n;
9030   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9031   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
9032   List.iter (
9033     fun ((name, _) as col) ->
9034       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
9035
9036       match col with
9037       | name, FString ->
9038           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
9039             n name
9040       | name, FBuffer ->
9041           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
9042             n name n name
9043       | name, FUUID ->
9044           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
9045             n name
9046       | name, (FBytes|FUInt64) ->
9047           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
9048             n name
9049       | name, FInt64 ->
9050           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
9051             n name
9052       | name, (FInt32|FUInt32) ->
9053           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9054             n name
9055       | name, FChar ->
9056           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9057             n name
9058       | name, FOptPercent ->
9059           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9060             n name
9061   ) cols;
9062   pr "      free (%s);\n" n
9063
9064 (* Generate Sys/Guestfs.pm. *)
9065 and generate_perl_pm () =
9066   generate_header HashStyle LGPLv2plus;
9067
9068   pr "\
9069 =pod
9070
9071 =head1 NAME
9072
9073 Sys::Guestfs - Perl bindings for libguestfs
9074
9075 =head1 SYNOPSIS
9076
9077  use Sys::Guestfs;
9078
9079  my $h = Sys::Guestfs->new ();
9080  $h->add_drive ('guest.img');
9081  $h->launch ();
9082  $h->mount ('/dev/sda1', '/');
9083  $h->touch ('/hello');
9084  $h->sync ();
9085
9086 =head1 DESCRIPTION
9087
9088 The C<Sys::Guestfs> module provides a Perl XS binding to the
9089 libguestfs API for examining and modifying virtual machine
9090 disk images.
9091
9092 Amongst the things this is good for: making batch configuration
9093 changes to guests, getting disk used/free statistics (see also:
9094 virt-df), migrating between virtualization systems (see also:
9095 virt-p2v), performing partial backups, performing partial guest
9096 clones, cloning guests and changing registry/UUID/hostname info, and
9097 much else besides.
9098
9099 Libguestfs uses Linux kernel and qemu code, and can access any type of
9100 guest filesystem that Linux and qemu can, including but not limited
9101 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9102 schemes, qcow, qcow2, vmdk.
9103
9104 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9105 LVs, what filesystem is in each LV, etc.).  It can also run commands
9106 in the context of the guest.  Also you can access filesystems over
9107 FUSE.
9108
9109 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9110 functions for using libguestfs from Perl, including integration
9111 with libvirt.
9112
9113 =head1 ERRORS
9114
9115 All errors turn into calls to C<croak> (see L<Carp(3)>).
9116
9117 =head1 METHODS
9118
9119 =over 4
9120
9121 =cut
9122
9123 package Sys::Guestfs;
9124
9125 use strict;
9126 use warnings;
9127
9128 # This version number changes whenever a new function
9129 # is added to the libguestfs API.  It is not directly
9130 # related to the libguestfs version number.
9131 use vars qw($VERSION);
9132 $VERSION = '0.%d';
9133
9134 require XSLoader;
9135 XSLoader::load ('Sys::Guestfs');
9136
9137 =item $h = Sys::Guestfs->new ();
9138
9139 Create a new guestfs handle.
9140
9141 =cut
9142
9143 sub new {
9144   my $proto = shift;
9145   my $class = ref ($proto) || $proto;
9146
9147   my $self = Sys::Guestfs::_create ();
9148   bless $self, $class;
9149   return $self;
9150 }
9151
9152 " max_proc_nr;
9153
9154   (* Actions.  We only need to print documentation for these as
9155    * they are pulled in from the XS code automatically.
9156    *)
9157   List.iter (
9158     fun (name, style, _, flags, _, _, longdesc) ->
9159       if not (List.mem NotInDocs flags) then (
9160         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9161         pr "=item ";
9162         generate_perl_prototype name style;
9163         pr "\n\n";
9164         pr "%s\n\n" longdesc;
9165         if List.mem ProtocolLimitWarning flags then
9166           pr "%s\n\n" protocol_limit_warning;
9167         if List.mem DangerWillRobinson flags then
9168           pr "%s\n\n" danger_will_robinson;
9169         match deprecation_notice flags with
9170         | None -> ()
9171         | Some txt -> pr "%s\n\n" txt
9172       )
9173   ) all_functions_sorted;
9174
9175   (* End of file. *)
9176   pr "\
9177 =cut
9178
9179 1;
9180
9181 =back
9182
9183 =head1 COPYRIGHT
9184
9185 Copyright (C) %s Red Hat Inc.
9186
9187 =head1 LICENSE
9188
9189 Please see the file COPYING.LIB for the full license.
9190
9191 =head1 SEE ALSO
9192
9193 L<guestfs(3)>,
9194 L<guestfish(1)>,
9195 L<http://libguestfs.org>,
9196 L<Sys::Guestfs::Lib(3)>.
9197
9198 =cut
9199 " copyright_years
9200
9201 and generate_perl_prototype name style =
9202   (match fst style with
9203    | RErr -> ()
9204    | RBool n
9205    | RInt n
9206    | RInt64 n
9207    | RConstString n
9208    | RConstOptString n
9209    | RString n
9210    | RBufferOut n -> pr "$%s = " n
9211    | RStruct (n,_)
9212    | RHashtable n -> pr "%%%s = " n
9213    | RStringList n
9214    | RStructList (n,_) -> pr "@%s = " n
9215   );
9216   pr "$h->%s (" name;
9217   let comma = ref false in
9218   List.iter (
9219     fun arg ->
9220       if !comma then pr ", ";
9221       comma := true;
9222       match arg with
9223       | Pathname n | Device n | Dev_or_Path n | String n
9224       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9225       | BufferIn n ->
9226           pr "$%s" n
9227       | StringList n | DeviceList n ->
9228           pr "\\@%s" n
9229   ) (snd style);
9230   pr ");"
9231
9232 (* Generate Python C module. *)
9233 and generate_python_c () =
9234   generate_header CStyle LGPLv2plus;
9235
9236   pr "\
9237 #define PY_SSIZE_T_CLEAN 1
9238 #include <Python.h>
9239
9240 #if PY_VERSION_HEX < 0x02050000
9241 typedef int Py_ssize_t;
9242 #define PY_SSIZE_T_MAX INT_MAX
9243 #define PY_SSIZE_T_MIN INT_MIN
9244 #endif
9245
9246 #include <stdio.h>
9247 #include <stdlib.h>
9248 #include <assert.h>
9249
9250 #include \"guestfs.h\"
9251
9252 typedef struct {
9253   PyObject_HEAD
9254   guestfs_h *g;
9255 } Pyguestfs_Object;
9256
9257 static guestfs_h *
9258 get_handle (PyObject *obj)
9259 {
9260   assert (obj);
9261   assert (obj != Py_None);
9262   return ((Pyguestfs_Object *) obj)->g;
9263 }
9264
9265 static PyObject *
9266 put_handle (guestfs_h *g)
9267 {
9268   assert (g);
9269   return
9270     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9271 }
9272
9273 /* This list should be freed (but not the strings) after use. */
9274 static char **
9275 get_string_list (PyObject *obj)
9276 {
9277   int i, len;
9278   char **r;
9279
9280   assert (obj);
9281
9282   if (!PyList_Check (obj)) {
9283     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9284     return NULL;
9285   }
9286
9287   len = PyList_Size (obj);
9288   r = malloc (sizeof (char *) * (len+1));
9289   if (r == NULL) {
9290     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9291     return NULL;
9292   }
9293
9294   for (i = 0; i < len; ++i)
9295     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9296   r[len] = NULL;
9297
9298   return r;
9299 }
9300
9301 static PyObject *
9302 put_string_list (char * const * const argv)
9303 {
9304   PyObject *list;
9305   int argc, i;
9306
9307   for (argc = 0; argv[argc] != NULL; ++argc)
9308     ;
9309
9310   list = PyList_New (argc);
9311   for (i = 0; i < argc; ++i)
9312     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9313
9314   return list;
9315 }
9316
9317 static PyObject *
9318 put_table (char * const * const argv)
9319 {
9320   PyObject *list, *item;
9321   int argc, i;
9322
9323   for (argc = 0; argv[argc] != NULL; ++argc)
9324     ;
9325
9326   list = PyList_New (argc >> 1);
9327   for (i = 0; i < argc; i += 2) {
9328     item = PyTuple_New (2);
9329     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9330     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9331     PyList_SetItem (list, i >> 1, item);
9332   }
9333
9334   return list;
9335 }
9336
9337 static void
9338 free_strings (char **argv)
9339 {
9340   int argc;
9341
9342   for (argc = 0; argv[argc] != NULL; ++argc)
9343     free (argv[argc]);
9344   free (argv);
9345 }
9346
9347 static PyObject *
9348 py_guestfs_create (PyObject *self, PyObject *args)
9349 {
9350   guestfs_h *g;
9351
9352   g = guestfs_create ();
9353   if (g == NULL) {
9354     PyErr_SetString (PyExc_RuntimeError,
9355                      \"guestfs.create: failed to allocate handle\");
9356     return NULL;
9357   }
9358   guestfs_set_error_handler (g, NULL, NULL);
9359   return put_handle (g);
9360 }
9361
9362 static PyObject *
9363 py_guestfs_close (PyObject *self, PyObject *args)
9364 {
9365   PyObject *py_g;
9366   guestfs_h *g;
9367
9368   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9369     return NULL;
9370   g = get_handle (py_g);
9371
9372   guestfs_close (g);
9373
9374   Py_INCREF (Py_None);
9375   return Py_None;
9376 }
9377
9378 ";
9379
9380   let emit_put_list_function typ =
9381     pr "static PyObject *\n";
9382     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9383     pr "{\n";
9384     pr "  PyObject *list;\n";
9385     pr "  int i;\n";
9386     pr "\n";
9387     pr "  list = PyList_New (%ss->len);\n" typ;
9388     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9389     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9390     pr "  return list;\n";
9391     pr "};\n";
9392     pr "\n"
9393   in
9394
9395   (* Structures, turned into Python dictionaries. *)
9396   List.iter (
9397     fun (typ, cols) ->
9398       pr "static PyObject *\n";
9399       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9400       pr "{\n";
9401       pr "  PyObject *dict;\n";
9402       pr "\n";
9403       pr "  dict = PyDict_New ();\n";
9404       List.iter (
9405         function
9406         | name, FString ->
9407             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9408             pr "                        PyString_FromString (%s->%s));\n"
9409               typ name
9410         | name, FBuffer ->
9411             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9412             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9413               typ name typ name
9414         | name, FUUID ->
9415             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9416             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9417               typ name
9418         | name, (FBytes|FUInt64) ->
9419             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9420             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9421               typ name
9422         | name, FInt64 ->
9423             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9424             pr "                        PyLong_FromLongLong (%s->%s));\n"
9425               typ name
9426         | name, FUInt32 ->
9427             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9428             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9429               typ name
9430         | name, FInt32 ->
9431             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9432             pr "                        PyLong_FromLong (%s->%s));\n"
9433               typ name
9434         | name, FOptPercent ->
9435             pr "  if (%s->%s >= 0)\n" typ name;
9436             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9437             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9438               typ name;
9439             pr "  else {\n";
9440             pr "    Py_INCREF (Py_None);\n";
9441             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9442             pr "  }\n"
9443         | name, FChar ->
9444             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9445             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9446       ) cols;
9447       pr "  return dict;\n";
9448       pr "};\n";
9449       pr "\n";
9450
9451   ) structs;
9452
9453   (* Emit a put_TYPE_list function definition only if that function is used. *)
9454   List.iter (
9455     function
9456     | typ, (RStructListOnly | RStructAndList) ->
9457         (* generate the function for typ *)
9458         emit_put_list_function typ
9459     | typ, _ -> () (* empty *)
9460   ) (rstructs_used_by all_functions);
9461
9462   (* Python wrapper functions. *)
9463   List.iter (
9464     fun (name, style, _, _, _, _, _) ->
9465       pr "static PyObject *\n";
9466       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9467       pr "{\n";
9468
9469       pr "  PyObject *py_g;\n";
9470       pr "  guestfs_h *g;\n";
9471       pr "  PyObject *py_r;\n";
9472
9473       let error_code =
9474         match fst style with
9475         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9476         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9477         | RConstString _ | RConstOptString _ ->
9478             pr "  const char *r;\n"; "NULL"
9479         | RString _ -> pr "  char *r;\n"; "NULL"
9480         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9481         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9482         | RStructList (_, typ) ->
9483             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9484         | RBufferOut _ ->
9485             pr "  char *r;\n";
9486             pr "  size_t size;\n";
9487             "NULL" in
9488
9489       List.iter (
9490         function
9491         | Pathname n | Device n | Dev_or_Path n | String n
9492         | FileIn n | FileOut n ->
9493             pr "  const char *%s;\n" n
9494         | OptString n -> pr "  const char *%s;\n" n
9495         | BufferIn n ->
9496             pr "  const char *%s;\n" n;
9497             pr "  Py_ssize_t %s_size;\n" n
9498         | StringList n | DeviceList n ->
9499             pr "  PyObject *py_%s;\n" n;
9500             pr "  char **%s;\n" n
9501         | Bool n -> pr "  int %s;\n" n
9502         | Int n -> pr "  int %s;\n" n
9503         | Int64 n -> pr "  long long %s;\n" n
9504       ) (snd style);
9505
9506       pr "\n";
9507
9508       (* Convert the parameters. *)
9509       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9510       List.iter (
9511         function
9512         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9513         | OptString _ -> pr "z"
9514         | StringList _ | DeviceList _ -> pr "O"
9515         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9516         | Int _ -> pr "i"
9517         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9518                              * emulate C's int/long/long long in Python?
9519                              *)
9520         | BufferIn _ -> pr "s#"
9521       ) (snd style);
9522       pr ":guestfs_%s\",\n" name;
9523       pr "                         &py_g";
9524       List.iter (
9525         function
9526         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9527         | OptString n -> pr ", &%s" n
9528         | StringList n | DeviceList n -> pr ", &py_%s" n
9529         | Bool n -> pr ", &%s" n
9530         | Int n -> pr ", &%s" n
9531         | Int64 n -> pr ", &%s" n
9532         | BufferIn n -> pr ", &%s, &%s_size" n n
9533       ) (snd style);
9534
9535       pr "))\n";
9536       pr "    return NULL;\n";
9537
9538       pr "  g = get_handle (py_g);\n";
9539       List.iter (
9540         function
9541         | Pathname _ | Device _ | Dev_or_Path _ | String _
9542         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9543         | BufferIn _ -> ()
9544         | StringList n | DeviceList n ->
9545             pr "  %s = get_string_list (py_%s);\n" n n;
9546             pr "  if (!%s) return NULL;\n" n
9547       ) (snd style);
9548
9549       pr "\n";
9550
9551       pr "  r = guestfs_%s " name;
9552       generate_c_call_args ~handle:"g" style;
9553       pr ";\n";
9554
9555       List.iter (
9556         function
9557         | Pathname _ | Device _ | Dev_or_Path _ | String _
9558         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9559         | BufferIn _ -> ()
9560         | StringList n | DeviceList n ->
9561             pr "  free (%s);\n" n
9562       ) (snd style);
9563
9564       pr "  if (r == %s) {\n" error_code;
9565       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9566       pr "    return NULL;\n";
9567       pr "  }\n";
9568       pr "\n";
9569
9570       (match fst style with
9571        | RErr ->
9572            pr "  Py_INCREF (Py_None);\n";
9573            pr "  py_r = Py_None;\n"
9574        | RInt _
9575        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9576        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9577        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9578        | RConstOptString _ ->
9579            pr "  if (r)\n";
9580            pr "    py_r = PyString_FromString (r);\n";
9581            pr "  else {\n";
9582            pr "    Py_INCREF (Py_None);\n";
9583            pr "    py_r = Py_None;\n";
9584            pr "  }\n"
9585        | RString _ ->
9586            pr "  py_r = PyString_FromString (r);\n";
9587            pr "  free (r);\n"
9588        | RStringList _ ->
9589            pr "  py_r = put_string_list (r);\n";
9590            pr "  free_strings (r);\n"
9591        | RStruct (_, typ) ->
9592            pr "  py_r = put_%s (r);\n" typ;
9593            pr "  guestfs_free_%s (r);\n" typ
9594        | RStructList (_, typ) ->
9595            pr "  py_r = put_%s_list (r);\n" typ;
9596            pr "  guestfs_free_%s_list (r);\n" typ
9597        | RHashtable n ->
9598            pr "  py_r = put_table (r);\n";
9599            pr "  free_strings (r);\n"
9600        | RBufferOut _ ->
9601            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9602            pr "  free (r);\n"
9603       );
9604
9605       pr "  return py_r;\n";
9606       pr "}\n";
9607       pr "\n"
9608   ) all_functions;
9609
9610   (* Table of functions. *)
9611   pr "static PyMethodDef methods[] = {\n";
9612   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9613   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9614   List.iter (
9615     fun (name, _, _, _, _, _, _) ->
9616       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9617         name name
9618   ) all_functions;
9619   pr "  { NULL, NULL, 0, NULL }\n";
9620   pr "};\n";
9621   pr "\n";
9622
9623   (* Init function. *)
9624   pr "\
9625 void
9626 initlibguestfsmod (void)
9627 {
9628   static int initialized = 0;
9629
9630   if (initialized) return;
9631   Py_InitModule ((char *) \"libguestfsmod\", methods);
9632   initialized = 1;
9633 }
9634 "
9635
9636 (* Generate Python module. *)
9637 and generate_python_py () =
9638   generate_header HashStyle LGPLv2plus;
9639
9640   pr "\
9641 u\"\"\"Python bindings for libguestfs
9642
9643 import guestfs
9644 g = guestfs.GuestFS ()
9645 g.add_drive (\"guest.img\")
9646 g.launch ()
9647 parts = g.list_partitions ()
9648
9649 The guestfs module provides a Python binding to the libguestfs API
9650 for examining and modifying virtual machine disk images.
9651
9652 Amongst the things this is good for: making batch configuration
9653 changes to guests, getting disk used/free statistics (see also:
9654 virt-df), migrating between virtualization systems (see also:
9655 virt-p2v), performing partial backups, performing partial guest
9656 clones, cloning guests and changing registry/UUID/hostname info, and
9657 much else besides.
9658
9659 Libguestfs uses Linux kernel and qemu code, and can access any type of
9660 guest filesystem that Linux and qemu can, including but not limited
9661 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9662 schemes, qcow, qcow2, vmdk.
9663
9664 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9665 LVs, what filesystem is in each LV, etc.).  It can also run commands
9666 in the context of the guest.  Also you can access filesystems over
9667 FUSE.
9668
9669 Errors which happen while using the API are turned into Python
9670 RuntimeError exceptions.
9671
9672 To create a guestfs handle you usually have to perform the following
9673 sequence of calls:
9674
9675 # Create the handle, call add_drive at least once, and possibly
9676 # several times if the guest has multiple block devices:
9677 g = guestfs.GuestFS ()
9678 g.add_drive (\"guest.img\")
9679
9680 # Launch the qemu subprocess and wait for it to become ready:
9681 g.launch ()
9682
9683 # Now you can issue commands, for example:
9684 logvols = g.lvs ()
9685
9686 \"\"\"
9687
9688 import libguestfsmod
9689
9690 class GuestFS:
9691     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9692
9693     def __init__ (self):
9694         \"\"\"Create a new libguestfs handle.\"\"\"
9695         self._o = libguestfsmod.create ()
9696
9697     def __del__ (self):
9698         libguestfsmod.close (self._o)
9699
9700 ";
9701
9702   List.iter (
9703     fun (name, style, _, flags, _, _, longdesc) ->
9704       pr "    def %s " name;
9705       generate_py_call_args ~handle:"self" (snd style);
9706       pr ":\n";
9707
9708       if not (List.mem NotInDocs flags) then (
9709         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9710         let doc =
9711           match fst style with
9712           | RErr | RInt _ | RInt64 _ | RBool _
9713           | RConstOptString _ | RConstString _
9714           | RString _ | RBufferOut _ -> doc
9715           | RStringList _ ->
9716               doc ^ "\n\nThis function returns a list of strings."
9717           | RStruct (_, typ) ->
9718               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9719           | RStructList (_, typ) ->
9720               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9721           | RHashtable _ ->
9722               doc ^ "\n\nThis function returns a dictionary." in
9723         let doc =
9724           if List.mem ProtocolLimitWarning flags then
9725             doc ^ "\n\n" ^ protocol_limit_warning
9726           else doc in
9727         let doc =
9728           if List.mem DangerWillRobinson flags then
9729             doc ^ "\n\n" ^ danger_will_robinson
9730           else doc in
9731         let doc =
9732           match deprecation_notice flags with
9733           | None -> doc
9734           | Some txt -> doc ^ "\n\n" ^ txt in
9735         let doc = pod2text ~width:60 name doc in
9736         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9737         let doc = String.concat "\n        " doc in
9738         pr "        u\"\"\"%s\"\"\"\n" doc;
9739       );
9740       pr "        return libguestfsmod.%s " name;
9741       generate_py_call_args ~handle:"self._o" (snd style);
9742       pr "\n";
9743       pr "\n";
9744   ) all_functions
9745
9746 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9747 and generate_py_call_args ~handle args =
9748   pr "(%s" handle;
9749   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9750   pr ")"
9751
9752 (* Useful if you need the longdesc POD text as plain text.  Returns a
9753  * list of lines.
9754  *
9755  * Because this is very slow (the slowest part of autogeneration),
9756  * we memoize the results.
9757  *)
9758 and pod2text ~width name longdesc =
9759   let key = width, name, longdesc in
9760   try Hashtbl.find pod2text_memo key
9761   with Not_found ->
9762     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9763     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9764     close_out chan;
9765     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9766     let chan = open_process_in cmd in
9767     let lines = ref [] in
9768     let rec loop i =
9769       let line = input_line chan in
9770       if i = 1 then             (* discard the first line of output *)
9771         loop (i+1)
9772       else (
9773         let line = triml line in
9774         lines := line :: !lines;
9775         loop (i+1)
9776       ) in
9777     let lines = try loop 1 with End_of_file -> List.rev !lines in
9778     unlink filename;
9779     (match close_process_in chan with
9780      | WEXITED 0 -> ()
9781      | WEXITED i ->
9782          failwithf "pod2text: process exited with non-zero status (%d)" i
9783      | WSIGNALED i | WSTOPPED i ->
9784          failwithf "pod2text: process signalled or stopped by signal %d" i
9785     );
9786     Hashtbl.add pod2text_memo key lines;
9787     pod2text_memo_updated ();
9788     lines
9789
9790 (* Generate ruby bindings. *)
9791 and generate_ruby_c () =
9792   generate_header CStyle LGPLv2plus;
9793
9794   pr "\
9795 #include <stdio.h>
9796 #include <stdlib.h>
9797
9798 #include <ruby.h>
9799
9800 #include \"guestfs.h\"
9801
9802 #include \"extconf.h\"
9803
9804 /* For Ruby < 1.9 */
9805 #ifndef RARRAY_LEN
9806 #define RARRAY_LEN(r) (RARRAY((r))->len)
9807 #endif
9808
9809 static VALUE m_guestfs;                 /* guestfs module */
9810 static VALUE c_guestfs;                 /* guestfs_h handle */
9811 static VALUE e_Error;                   /* used for all errors */
9812
9813 static void ruby_guestfs_free (void *p)
9814 {
9815   if (!p) return;
9816   guestfs_close ((guestfs_h *) p);
9817 }
9818
9819 static VALUE ruby_guestfs_create (VALUE m)
9820 {
9821   guestfs_h *g;
9822
9823   g = guestfs_create ();
9824   if (!g)
9825     rb_raise (e_Error, \"failed to create guestfs handle\");
9826
9827   /* Don't print error messages to stderr by default. */
9828   guestfs_set_error_handler (g, NULL, NULL);
9829
9830   /* Wrap it, and make sure the close function is called when the
9831    * handle goes away.
9832    */
9833   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9834 }
9835
9836 static VALUE ruby_guestfs_close (VALUE gv)
9837 {
9838   guestfs_h *g;
9839   Data_Get_Struct (gv, guestfs_h, g);
9840
9841   ruby_guestfs_free (g);
9842   DATA_PTR (gv) = NULL;
9843
9844   return Qnil;
9845 }
9846
9847 ";
9848
9849   List.iter (
9850     fun (name, style, _, _, _, _, _) ->
9851       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9852       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9853       pr ")\n";
9854       pr "{\n";
9855       pr "  guestfs_h *g;\n";
9856       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9857       pr "  if (!g)\n";
9858       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9859         name;
9860       pr "\n";
9861
9862       List.iter (
9863         function
9864         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9865             pr "  Check_Type (%sv, T_STRING);\n" n;
9866             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9867             pr "  if (!%s)\n" n;
9868             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9869             pr "              \"%s\", \"%s\");\n" n name
9870         | BufferIn n ->
9871             pr "  Check_Type (%sv, T_STRING);\n" n;
9872             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9873             pr "  if (!%s)\n" n;
9874             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9875             pr "              \"%s\", \"%s\");\n" n name;
9876             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9877         | OptString n ->
9878             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9879         | StringList n | DeviceList n ->
9880             pr "  char **%s;\n" n;
9881             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9882             pr "  {\n";
9883             pr "    int i, len;\n";
9884             pr "    len = RARRAY_LEN (%sv);\n" n;
9885             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9886               n;
9887             pr "    for (i = 0; i < len; ++i) {\n";
9888             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9889             pr "      %s[i] = StringValueCStr (v);\n" n;
9890             pr "    }\n";
9891             pr "    %s[len] = NULL;\n" n;
9892             pr "  }\n";
9893         | Bool n ->
9894             pr "  int %s = RTEST (%sv);\n" n n
9895         | Int n ->
9896             pr "  int %s = NUM2INT (%sv);\n" n n
9897         | Int64 n ->
9898             pr "  long long %s = NUM2LL (%sv);\n" n n
9899       ) (snd style);
9900       pr "\n";
9901
9902       let error_code =
9903         match fst style with
9904         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9905         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9906         | RConstString _ | RConstOptString _ ->
9907             pr "  const char *r;\n"; "NULL"
9908         | RString _ -> pr "  char *r;\n"; "NULL"
9909         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9910         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9911         | RStructList (_, typ) ->
9912             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9913         | RBufferOut _ ->
9914             pr "  char *r;\n";
9915             pr "  size_t size;\n";
9916             "NULL" in
9917       pr "\n";
9918
9919       pr "  r = guestfs_%s " name;
9920       generate_c_call_args ~handle:"g" style;
9921       pr ";\n";
9922
9923       List.iter (
9924         function
9925         | Pathname _ | Device _ | Dev_or_Path _ | String _
9926         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9927         | BufferIn _ -> ()
9928         | StringList n | DeviceList n ->
9929             pr "  free (%s);\n" n
9930       ) (snd style);
9931
9932       pr "  if (r == %s)\n" error_code;
9933       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9934       pr "\n";
9935
9936       (match fst style with
9937        | RErr ->
9938            pr "  return Qnil;\n"
9939        | RInt _ | RBool _ ->
9940            pr "  return INT2NUM (r);\n"
9941        | RInt64 _ ->
9942            pr "  return ULL2NUM (r);\n"
9943        | RConstString _ ->
9944            pr "  return rb_str_new2 (r);\n";
9945        | RConstOptString _ ->
9946            pr "  if (r)\n";
9947            pr "    return rb_str_new2 (r);\n";
9948            pr "  else\n";
9949            pr "    return Qnil;\n";
9950        | RString _ ->
9951            pr "  VALUE rv = rb_str_new2 (r);\n";
9952            pr "  free (r);\n";
9953            pr "  return rv;\n";
9954        | RStringList _ ->
9955            pr "  int i, len = 0;\n";
9956            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9957            pr "  VALUE rv = rb_ary_new2 (len);\n";
9958            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9959            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9960            pr "    free (r[i]);\n";
9961            pr "  }\n";
9962            pr "  free (r);\n";
9963            pr "  return rv;\n"
9964        | RStruct (_, typ) ->
9965            let cols = cols_of_struct typ in
9966            generate_ruby_struct_code typ cols
9967        | RStructList (_, typ) ->
9968            let cols = cols_of_struct typ in
9969            generate_ruby_struct_list_code typ cols
9970        | RHashtable _ ->
9971            pr "  VALUE rv = rb_hash_new ();\n";
9972            pr "  int i;\n";
9973            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9974            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9975            pr "    free (r[i]);\n";
9976            pr "    free (r[i+1]);\n";
9977            pr "  }\n";
9978            pr "  free (r);\n";
9979            pr "  return rv;\n"
9980        | RBufferOut _ ->
9981            pr "  VALUE rv = rb_str_new (r, size);\n";
9982            pr "  free (r);\n";
9983            pr "  return rv;\n";
9984       );
9985
9986       pr "}\n";
9987       pr "\n"
9988   ) all_functions;
9989
9990   pr "\
9991 /* Initialize the module. */
9992 void Init__guestfs ()
9993 {
9994   m_guestfs = rb_define_module (\"Guestfs\");
9995   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9996   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9997
9998   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9999   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
10000
10001 ";
10002   (* Define the rest of the methods. *)
10003   List.iter (
10004     fun (name, style, _, _, _, _, _) ->
10005       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
10006       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
10007   ) all_functions;
10008
10009   pr "}\n"
10010
10011 (* Ruby code to return a struct. *)
10012 and generate_ruby_struct_code typ cols =
10013   pr "  VALUE rv = rb_hash_new ();\n";
10014   List.iter (
10015     function
10016     | name, FString ->
10017         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
10018     | name, FBuffer ->
10019         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
10020     | name, FUUID ->
10021         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
10022     | name, (FBytes|FUInt64) ->
10023         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10024     | name, FInt64 ->
10025         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
10026     | name, FUInt32 ->
10027         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
10028     | name, FInt32 ->
10029         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
10030     | name, FOptPercent ->
10031         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
10032     | name, FChar -> (* XXX wrong? *)
10033         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10034   ) cols;
10035   pr "  guestfs_free_%s (r);\n" typ;
10036   pr "  return rv;\n"
10037
10038 (* Ruby code to return a struct list. *)
10039 and generate_ruby_struct_list_code typ cols =
10040   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
10041   pr "  int i;\n";
10042   pr "  for (i = 0; i < r->len; ++i) {\n";
10043   pr "    VALUE hv = rb_hash_new ();\n";
10044   List.iter (
10045     function
10046     | name, FString ->
10047         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
10048     | name, FBuffer ->
10049         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
10050     | name, FUUID ->
10051         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
10052     | name, (FBytes|FUInt64) ->
10053         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10054     | name, FInt64 ->
10055         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10056     | name, FUInt32 ->
10057         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10058     | name, FInt32 ->
10059         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10060     | name, FOptPercent ->
10061         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10062     | name, FChar -> (* XXX wrong? *)
10063         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10064   ) cols;
10065   pr "    rb_ary_push (rv, hv);\n";
10066   pr "  }\n";
10067   pr "  guestfs_free_%s_list (r);\n" typ;
10068   pr "  return rv;\n"
10069
10070 (* Generate Java bindings GuestFS.java file. *)
10071 and generate_java_java () =
10072   generate_header CStyle LGPLv2plus;
10073
10074   pr "\
10075 package com.redhat.et.libguestfs;
10076
10077 import java.util.HashMap;
10078 import com.redhat.et.libguestfs.LibGuestFSException;
10079 import com.redhat.et.libguestfs.PV;
10080 import com.redhat.et.libguestfs.VG;
10081 import com.redhat.et.libguestfs.LV;
10082 import com.redhat.et.libguestfs.Stat;
10083 import com.redhat.et.libguestfs.StatVFS;
10084 import com.redhat.et.libguestfs.IntBool;
10085 import com.redhat.et.libguestfs.Dirent;
10086
10087 /**
10088  * The GuestFS object is a libguestfs handle.
10089  *
10090  * @author rjones
10091  */
10092 public class GuestFS {
10093   // Load the native code.
10094   static {
10095     System.loadLibrary (\"guestfs_jni\");
10096   }
10097
10098   /**
10099    * The native guestfs_h pointer.
10100    */
10101   long g;
10102
10103   /**
10104    * Create a libguestfs handle.
10105    *
10106    * @throws LibGuestFSException
10107    */
10108   public GuestFS () throws LibGuestFSException
10109   {
10110     g = _create ();
10111   }
10112   private native long _create () throws LibGuestFSException;
10113
10114   /**
10115    * Close a libguestfs handle.
10116    *
10117    * You can also leave handles to be collected by the garbage
10118    * collector, but this method ensures that the resources used
10119    * by the handle are freed up immediately.  If you call any
10120    * other methods after closing the handle, you will get an
10121    * exception.
10122    *
10123    * @throws LibGuestFSException
10124    */
10125   public void close () throws LibGuestFSException
10126   {
10127     if (g != 0)
10128       _close (g);
10129     g = 0;
10130   }
10131   private native void _close (long g) throws LibGuestFSException;
10132
10133   public void finalize () throws LibGuestFSException
10134   {
10135     close ();
10136   }
10137
10138 ";
10139
10140   List.iter (
10141     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10142       if not (List.mem NotInDocs flags); then (
10143         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10144         let doc =
10145           if List.mem ProtocolLimitWarning flags then
10146             doc ^ "\n\n" ^ protocol_limit_warning
10147           else doc in
10148         let doc =
10149           if List.mem DangerWillRobinson flags then
10150             doc ^ "\n\n" ^ danger_will_robinson
10151           else doc in
10152         let doc =
10153           match deprecation_notice flags with
10154           | None -> doc
10155           | Some txt -> doc ^ "\n\n" ^ txt in
10156         let doc = pod2text ~width:60 name doc in
10157         let doc = List.map (            (* RHBZ#501883 *)
10158           function
10159           | "" -> "<p>"
10160           | nonempty -> nonempty
10161         ) doc in
10162         let doc = String.concat "\n   * " doc in
10163
10164         pr "  /**\n";
10165         pr "   * %s\n" shortdesc;
10166         pr "   * <p>\n";
10167         pr "   * %s\n" doc;
10168         pr "   * @throws LibGuestFSException\n";
10169         pr "   */\n";
10170         pr "  ";
10171       );
10172       generate_java_prototype ~public:true ~semicolon:false name style;
10173       pr "\n";
10174       pr "  {\n";
10175       pr "    if (g == 0)\n";
10176       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10177         name;
10178       pr "    ";
10179       if fst style <> RErr then pr "return ";
10180       pr "_%s " name;
10181       generate_java_call_args ~handle:"g" (snd style);
10182       pr ";\n";
10183       pr "  }\n";
10184       pr "  ";
10185       generate_java_prototype ~privat:true ~native:true name style;
10186       pr "\n";
10187       pr "\n";
10188   ) all_functions;
10189
10190   pr "}\n"
10191
10192 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10193 and generate_java_call_args ~handle args =
10194   pr "(%s" handle;
10195   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10196   pr ")"
10197
10198 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10199     ?(semicolon=true) name style =
10200   if privat then pr "private ";
10201   if public then pr "public ";
10202   if native then pr "native ";
10203
10204   (* return type *)
10205   (match fst style with
10206    | RErr -> pr "void ";
10207    | RInt _ -> pr "int ";
10208    | RInt64 _ -> pr "long ";
10209    | RBool _ -> pr "boolean ";
10210    | RConstString _ | RConstOptString _ | RString _
10211    | RBufferOut _ -> pr "String ";
10212    | RStringList _ -> pr "String[] ";
10213    | RStruct (_, typ) ->
10214        let name = java_name_of_struct typ in
10215        pr "%s " name;
10216    | RStructList (_, typ) ->
10217        let name = java_name_of_struct typ in
10218        pr "%s[] " name;
10219    | RHashtable _ -> pr "HashMap<String,String> ";
10220   );
10221
10222   if native then pr "_%s " name else pr "%s " name;
10223   pr "(";
10224   let needs_comma = ref false in
10225   if native then (
10226     pr "long g";
10227     needs_comma := true
10228   );
10229
10230   (* args *)
10231   List.iter (
10232     fun arg ->
10233       if !needs_comma then pr ", ";
10234       needs_comma := true;
10235
10236       match arg with
10237       | Pathname n
10238       | Device n | Dev_or_Path n
10239       | String n
10240       | OptString n
10241       | FileIn n
10242       | FileOut n ->
10243           pr "String %s" n
10244       | BufferIn n ->
10245           pr "byte[] %s" n
10246       | StringList n | DeviceList n ->
10247           pr "String[] %s" n
10248       | Bool n ->
10249           pr "boolean %s" n
10250       | Int n ->
10251           pr "int %s" n
10252       | Int64 n ->
10253           pr "long %s" n
10254   ) (snd style);
10255
10256   pr ")\n";
10257   pr "    throws LibGuestFSException";
10258   if semicolon then pr ";"
10259
10260 and generate_java_struct jtyp cols () =
10261   generate_header CStyle LGPLv2plus;
10262
10263   pr "\
10264 package com.redhat.et.libguestfs;
10265
10266 /**
10267  * Libguestfs %s structure.
10268  *
10269  * @author rjones
10270  * @see GuestFS
10271  */
10272 public class %s {
10273 " jtyp jtyp;
10274
10275   List.iter (
10276     function
10277     | name, FString
10278     | name, FUUID
10279     | name, FBuffer -> pr "  public String %s;\n" name
10280     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10281     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10282     | name, FChar -> pr "  public char %s;\n" name
10283     | name, FOptPercent ->
10284         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10285         pr "  public float %s;\n" name
10286   ) cols;
10287
10288   pr "}\n"
10289
10290 and generate_java_c () =
10291   generate_header CStyle LGPLv2plus;
10292
10293   pr "\
10294 #include <stdio.h>
10295 #include <stdlib.h>
10296 #include <string.h>
10297
10298 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10299 #include \"guestfs.h\"
10300
10301 /* Note that this function returns.  The exception is not thrown
10302  * until after the wrapper function returns.
10303  */
10304 static void
10305 throw_exception (JNIEnv *env, const char *msg)
10306 {
10307   jclass cl;
10308   cl = (*env)->FindClass (env,
10309                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10310   (*env)->ThrowNew (env, cl, msg);
10311 }
10312
10313 JNIEXPORT jlong JNICALL
10314 Java_com_redhat_et_libguestfs_GuestFS__1create
10315   (JNIEnv *env, jobject obj)
10316 {
10317   guestfs_h *g;
10318
10319   g = guestfs_create ();
10320   if (g == NULL) {
10321     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10322     return 0;
10323   }
10324   guestfs_set_error_handler (g, NULL, NULL);
10325   return (jlong) (long) g;
10326 }
10327
10328 JNIEXPORT void JNICALL
10329 Java_com_redhat_et_libguestfs_GuestFS__1close
10330   (JNIEnv *env, jobject obj, jlong jg)
10331 {
10332   guestfs_h *g = (guestfs_h *) (long) jg;
10333   guestfs_close (g);
10334 }
10335
10336 ";
10337
10338   List.iter (
10339     fun (name, style, _, _, _, _, _) ->
10340       pr "JNIEXPORT ";
10341       (match fst style with
10342        | RErr -> pr "void ";
10343        | RInt _ -> pr "jint ";
10344        | RInt64 _ -> pr "jlong ";
10345        | RBool _ -> pr "jboolean ";
10346        | RConstString _ | RConstOptString _ | RString _
10347        | RBufferOut _ -> pr "jstring ";
10348        | RStruct _ | RHashtable _ ->
10349            pr "jobject ";
10350        | RStringList _ | RStructList _ ->
10351            pr "jobjectArray ";
10352       );
10353       pr "JNICALL\n";
10354       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10355       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10356       pr "\n";
10357       pr "  (JNIEnv *env, jobject obj, jlong jg";
10358       List.iter (
10359         function
10360         | Pathname n
10361         | Device n | Dev_or_Path n
10362         | String n
10363         | OptString n
10364         | FileIn n
10365         | FileOut n ->
10366             pr ", jstring j%s" n
10367         | BufferIn n ->
10368             pr ", jbyteArray j%s" n
10369         | StringList n | DeviceList n ->
10370             pr ", jobjectArray j%s" n
10371         | Bool n ->
10372             pr ", jboolean j%s" n
10373         | Int n ->
10374             pr ", jint j%s" n
10375         | Int64 n ->
10376             pr ", jlong j%s" n
10377       ) (snd style);
10378       pr ")\n";
10379       pr "{\n";
10380       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10381       let error_code, no_ret =
10382         match fst style with
10383         | RErr -> pr "  int r;\n"; "-1", ""
10384         | RBool _
10385         | RInt _ -> pr "  int r;\n"; "-1", "0"
10386         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10387         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10388         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10389         | RString _ ->
10390             pr "  jstring jr;\n";
10391             pr "  char *r;\n"; "NULL", "NULL"
10392         | RStringList _ ->
10393             pr "  jobjectArray jr;\n";
10394             pr "  int r_len;\n";
10395             pr "  jclass cl;\n";
10396             pr "  jstring jstr;\n";
10397             pr "  char **r;\n"; "NULL", "NULL"
10398         | RStruct (_, typ) ->
10399             pr "  jobject jr;\n";
10400             pr "  jclass cl;\n";
10401             pr "  jfieldID fl;\n";
10402             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10403         | RStructList (_, typ) ->
10404             pr "  jobjectArray jr;\n";
10405             pr "  jclass cl;\n";
10406             pr "  jfieldID fl;\n";
10407             pr "  jobject jfl;\n";
10408             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10409         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10410         | RBufferOut _ ->
10411             pr "  jstring jr;\n";
10412             pr "  char *r;\n";
10413             pr "  size_t size;\n";
10414             "NULL", "NULL" in
10415       List.iter (
10416         function
10417         | Pathname n
10418         | Device n | Dev_or_Path n
10419         | String n
10420         | OptString n
10421         | FileIn n
10422         | FileOut n ->
10423             pr "  const char *%s;\n" n
10424         | BufferIn n ->
10425             pr "  jbyte *%s;\n" n;
10426             pr "  size_t %s_size;\n" n
10427         | StringList n | DeviceList n ->
10428             pr "  int %s_len;\n" n;
10429             pr "  const char **%s;\n" n
10430         | Bool n
10431         | Int n ->
10432             pr "  int %s;\n" n
10433         | Int64 n ->
10434             pr "  int64_t %s;\n" n
10435       ) (snd style);
10436
10437       let needs_i =
10438         (match fst style with
10439          | RStringList _ | RStructList _ -> true
10440          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10441          | RConstOptString _
10442          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10443           List.exists (function
10444                        | StringList _ -> true
10445                        | DeviceList _ -> true
10446                        | _ -> false) (snd style) in
10447       if needs_i then
10448         pr "  int i;\n";
10449
10450       pr "\n";
10451
10452       (* Get the parameters. *)
10453       List.iter (
10454         function
10455         | Pathname n
10456         | Device n | Dev_or_Path n
10457         | String n
10458         | FileIn n
10459         | FileOut n ->
10460             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10461         | OptString n ->
10462             (* This is completely undocumented, but Java null becomes
10463              * a NULL parameter.
10464              *)
10465             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10466         | BufferIn n ->
10467             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10468             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10469         | StringList n | DeviceList n ->
10470             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10471             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10472             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10473             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10474               n;
10475             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10476             pr "  }\n";
10477             pr "  %s[%s_len] = NULL;\n" n n;
10478         | Bool n
10479         | Int n
10480         | Int64 n ->
10481             pr "  %s = j%s;\n" n n
10482       ) (snd style);
10483
10484       (* Make the call. *)
10485       pr "  r = guestfs_%s " name;
10486       generate_c_call_args ~handle:"g" style;
10487       pr ";\n";
10488
10489       (* Release the parameters. *)
10490       List.iter (
10491         function
10492         | Pathname n
10493         | Device n | Dev_or_Path n
10494         | String n
10495         | FileIn n
10496         | FileOut n ->
10497             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10498         | OptString n ->
10499             pr "  if (j%s)\n" n;
10500             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10501         | BufferIn n ->
10502             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10503         | StringList n | DeviceList n ->
10504             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10505             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10506               n;
10507             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10508             pr "  }\n";
10509             pr "  free (%s);\n" n
10510         | Bool n
10511         | Int n
10512         | Int64 n -> ()
10513       ) (snd style);
10514
10515       (* Check for errors. *)
10516       pr "  if (r == %s) {\n" error_code;
10517       pr "    throw_exception (env, guestfs_last_error (g));\n";
10518       pr "    return %s;\n" no_ret;
10519       pr "  }\n";
10520
10521       (* Return value. *)
10522       (match fst style with
10523        | RErr -> ()
10524        | RInt _ -> pr "  return (jint) r;\n"
10525        | RBool _ -> pr "  return (jboolean) r;\n"
10526        | RInt64 _ -> pr "  return (jlong) r;\n"
10527        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10528        | RConstOptString _ ->
10529            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10530        | RString _ ->
10531            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10532            pr "  free (r);\n";
10533            pr "  return jr;\n"
10534        | RStringList _ ->
10535            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10536            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10537            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10538            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10539            pr "  for (i = 0; i < r_len; ++i) {\n";
10540            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10541            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10542            pr "    free (r[i]);\n";
10543            pr "  }\n";
10544            pr "  free (r);\n";
10545            pr "  return jr;\n"
10546        | RStruct (_, typ) ->
10547            let jtyp = java_name_of_struct typ in
10548            let cols = cols_of_struct typ in
10549            generate_java_struct_return typ jtyp cols
10550        | RStructList (_, typ) ->
10551            let jtyp = java_name_of_struct typ in
10552            let cols = cols_of_struct typ in
10553            generate_java_struct_list_return typ jtyp cols
10554        | RHashtable _ ->
10555            (* XXX *)
10556            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10557            pr "  return NULL;\n"
10558        | RBufferOut _ ->
10559            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10560            pr "  free (r);\n";
10561            pr "  return jr;\n"
10562       );
10563
10564       pr "}\n";
10565       pr "\n"
10566   ) all_functions
10567
10568 and generate_java_struct_return typ jtyp cols =
10569   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10570   pr "  jr = (*env)->AllocObject (env, cl);\n";
10571   List.iter (
10572     function
10573     | name, FString ->
10574         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10575         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10576     | name, FUUID ->
10577         pr "  {\n";
10578         pr "    char s[33];\n";
10579         pr "    memcpy (s, r->%s, 32);\n" name;
10580         pr "    s[32] = 0;\n";
10581         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10582         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10583         pr "  }\n";
10584     | name, FBuffer ->
10585         pr "  {\n";
10586         pr "    int len = r->%s_len;\n" name;
10587         pr "    char s[len+1];\n";
10588         pr "    memcpy (s, r->%s, len);\n" name;
10589         pr "    s[len] = 0;\n";
10590         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10591         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10592         pr "  }\n";
10593     | name, (FBytes|FUInt64|FInt64) ->
10594         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10595         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10596     | name, (FUInt32|FInt32) ->
10597         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10598         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10599     | name, FOptPercent ->
10600         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10601         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10602     | name, FChar ->
10603         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10604         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10605   ) cols;
10606   pr "  free (r);\n";
10607   pr "  return jr;\n"
10608
10609 and generate_java_struct_list_return typ jtyp cols =
10610   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10611   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10612   pr "  for (i = 0; i < r->len; ++i) {\n";
10613   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10614   List.iter (
10615     function
10616     | name, FString ->
10617         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10618         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10619     | name, FUUID ->
10620         pr "    {\n";
10621         pr "      char s[33];\n";
10622         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10623         pr "      s[32] = 0;\n";
10624         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10625         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10626         pr "    }\n";
10627     | name, FBuffer ->
10628         pr "    {\n";
10629         pr "      int len = r->val[i].%s_len;\n" name;
10630         pr "      char s[len+1];\n";
10631         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10632         pr "      s[len] = 0;\n";
10633         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10634         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10635         pr "    }\n";
10636     | name, (FBytes|FUInt64|FInt64) ->
10637         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10638         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10639     | name, (FUInt32|FInt32) ->
10640         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10641         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10642     | name, FOptPercent ->
10643         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10644         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10645     | name, FChar ->
10646         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10647         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10648   ) cols;
10649   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10650   pr "  }\n";
10651   pr "  guestfs_free_%s_list (r);\n" typ;
10652   pr "  return jr;\n"
10653
10654 and generate_java_makefile_inc () =
10655   generate_header HashStyle GPLv2plus;
10656
10657   pr "java_built_sources = \\\n";
10658   List.iter (
10659     fun (typ, jtyp) ->
10660         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10661   ) java_structs;
10662   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10663
10664 and generate_haskell_hs () =
10665   generate_header HaskellStyle LGPLv2plus;
10666
10667   (* XXX We only know how to generate partial FFI for Haskell
10668    * at the moment.  Please help out!
10669    *)
10670   let can_generate style =
10671     match style with
10672     | RErr, _
10673     | RInt _, _
10674     | RInt64 _, _ -> true
10675     | RBool _, _
10676     | RConstString _, _
10677     | RConstOptString _, _
10678     | RString _, _
10679     | RStringList _, _
10680     | RStruct _, _
10681     | RStructList _, _
10682     | RHashtable _, _
10683     | RBufferOut _, _ -> false in
10684
10685   pr "\
10686 {-# INCLUDE <guestfs.h> #-}
10687 {-# LANGUAGE ForeignFunctionInterface #-}
10688
10689 module Guestfs (
10690   create";
10691
10692   (* List out the names of the actions we want to export. *)
10693   List.iter (
10694     fun (name, style, _, _, _, _, _) ->
10695       if can_generate style then pr ",\n  %s" name
10696   ) all_functions;
10697
10698   pr "
10699   ) where
10700
10701 -- Unfortunately some symbols duplicate ones already present
10702 -- in Prelude.  We don't know which, so we hard-code a list
10703 -- here.
10704 import Prelude hiding (truncate)
10705
10706 import Foreign
10707 import Foreign.C
10708 import Foreign.C.Types
10709 import IO
10710 import Control.Exception
10711 import Data.Typeable
10712
10713 data GuestfsS = GuestfsS            -- represents the opaque C struct
10714 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10715 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10716
10717 -- XXX define properly later XXX
10718 data PV = PV
10719 data VG = VG
10720 data LV = LV
10721 data IntBool = IntBool
10722 data Stat = Stat
10723 data StatVFS = StatVFS
10724 data Hashtable = Hashtable
10725
10726 foreign import ccall unsafe \"guestfs_create\" c_create
10727   :: IO GuestfsP
10728 foreign import ccall unsafe \"&guestfs_close\" c_close
10729   :: FunPtr (GuestfsP -> IO ())
10730 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10731   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10732
10733 create :: IO GuestfsH
10734 create = do
10735   p <- c_create
10736   c_set_error_handler p nullPtr nullPtr
10737   h <- newForeignPtr c_close p
10738   return h
10739
10740 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10741   :: GuestfsP -> IO CString
10742
10743 -- last_error :: GuestfsH -> IO (Maybe String)
10744 -- last_error h = do
10745 --   str <- withForeignPtr h (\\p -> c_last_error p)
10746 --   maybePeek peekCString str
10747
10748 last_error :: GuestfsH -> IO (String)
10749 last_error h = do
10750   str <- withForeignPtr h (\\p -> c_last_error p)
10751   if (str == nullPtr)
10752     then return \"no error\"
10753     else peekCString str
10754
10755 ";
10756
10757   (* Generate wrappers for each foreign function. *)
10758   List.iter (
10759     fun (name, style, _, _, _, _, _) ->
10760       if can_generate style then (
10761         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10762         pr "  :: ";
10763         generate_haskell_prototype ~handle:"GuestfsP" style;
10764         pr "\n";
10765         pr "\n";
10766         pr "%s :: " name;
10767         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10768         pr "\n";
10769         pr "%s %s = do\n" name
10770           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10771         pr "  r <- ";
10772         (* Convert pointer arguments using with* functions. *)
10773         List.iter (
10774           function
10775           | FileIn n
10776           | FileOut n
10777           | Pathname n | Device n | Dev_or_Path n | String n ->
10778               pr "withCString %s $ \\%s -> " n n
10779           | BufferIn n ->
10780               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10781           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10782           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10783           | Bool _ | Int _ | Int64 _ -> ()
10784         ) (snd style);
10785         (* Convert integer arguments. *)
10786         let args =
10787           List.map (
10788             function
10789             | Bool n -> sprintf "(fromBool %s)" n
10790             | Int n -> sprintf "(fromIntegral %s)" n
10791             | Int64 n -> sprintf "(fromIntegral %s)" n
10792             | FileIn n | FileOut n
10793             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10794             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10795           ) (snd style) in
10796         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10797           (String.concat " " ("p" :: args));
10798         (match fst style with
10799          | RErr | RInt _ | RInt64 _ | RBool _ ->
10800              pr "  if (r == -1)\n";
10801              pr "    then do\n";
10802              pr "      err <- last_error h\n";
10803              pr "      fail err\n";
10804          | RConstString _ | RConstOptString _ | RString _
10805          | RStringList _ | RStruct _
10806          | RStructList _ | RHashtable _ | RBufferOut _ ->
10807              pr "  if (r == nullPtr)\n";
10808              pr "    then do\n";
10809              pr "      err <- last_error h\n";
10810              pr "      fail err\n";
10811         );
10812         (match fst style with
10813          | RErr ->
10814              pr "    else return ()\n"
10815          | RInt _ ->
10816              pr "    else return (fromIntegral r)\n"
10817          | RInt64 _ ->
10818              pr "    else return (fromIntegral r)\n"
10819          | RBool _ ->
10820              pr "    else return (toBool r)\n"
10821          | RConstString _
10822          | RConstOptString _
10823          | RString _
10824          | RStringList _
10825          | RStruct _
10826          | RStructList _
10827          | RHashtable _
10828          | RBufferOut _ ->
10829              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10830         );
10831         pr "\n";
10832       )
10833   ) all_functions
10834
10835 and generate_haskell_prototype ~handle ?(hs = false) style =
10836   pr "%s -> " handle;
10837   let string = if hs then "String" else "CString" in
10838   let int = if hs then "Int" else "CInt" in
10839   let bool = if hs then "Bool" else "CInt" in
10840   let int64 = if hs then "Integer" else "Int64" in
10841   List.iter (
10842     fun arg ->
10843       (match arg with
10844        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10845        | BufferIn _ ->
10846            if hs then pr "String"
10847            else pr "CString -> CInt"
10848        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10849        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10850        | Bool _ -> pr "%s" bool
10851        | Int _ -> pr "%s" int
10852        | Int64 _ -> pr "%s" int
10853        | FileIn _ -> pr "%s" string
10854        | FileOut _ -> pr "%s" string
10855       );
10856       pr " -> ";
10857   ) (snd style);
10858   pr "IO (";
10859   (match fst style with
10860    | RErr -> if not hs then pr "CInt"
10861    | RInt _ -> pr "%s" int
10862    | RInt64 _ -> pr "%s" int64
10863    | RBool _ -> pr "%s" bool
10864    | RConstString _ -> pr "%s" string
10865    | RConstOptString _ -> pr "Maybe %s" string
10866    | RString _ -> pr "%s" string
10867    | RStringList _ -> pr "[%s]" string
10868    | RStruct (_, typ) ->
10869        let name = java_name_of_struct typ in
10870        pr "%s" name
10871    | RStructList (_, typ) ->
10872        let name = java_name_of_struct typ in
10873        pr "[%s]" name
10874    | RHashtable _ -> pr "Hashtable"
10875    | RBufferOut _ -> pr "%s" string
10876   );
10877   pr ")"
10878
10879 and generate_csharp () =
10880   generate_header CPlusPlusStyle LGPLv2plus;
10881
10882   (* XXX Make this configurable by the C# assembly users. *)
10883   let library = "libguestfs.so.0" in
10884
10885   pr "\
10886 // These C# bindings are highly experimental at present.
10887 //
10888 // Firstly they only work on Linux (ie. Mono).  In order to get them
10889 // to work on Windows (ie. .Net) you would need to port the library
10890 // itself to Windows first.
10891 //
10892 // The second issue is that some calls are known to be incorrect and
10893 // can cause Mono to segfault.  Particularly: calls which pass or
10894 // return string[], or return any structure value.  This is because
10895 // we haven't worked out the correct way to do this from C#.
10896 //
10897 // The third issue is that when compiling you get a lot of warnings.
10898 // We are not sure whether the warnings are important or not.
10899 //
10900 // Fourthly we do not routinely build or test these bindings as part
10901 // of the make && make check cycle, which means that regressions might
10902 // go unnoticed.
10903 //
10904 // Suggestions and patches are welcome.
10905
10906 // To compile:
10907 //
10908 // gmcs Libguestfs.cs
10909 // mono Libguestfs.exe
10910 //
10911 // (You'll probably want to add a Test class / static main function
10912 // otherwise this won't do anything useful).
10913
10914 using System;
10915 using System.IO;
10916 using System.Runtime.InteropServices;
10917 using System.Runtime.Serialization;
10918 using System.Collections;
10919
10920 namespace Guestfs
10921 {
10922   class Error : System.ApplicationException
10923   {
10924     public Error (string message) : base (message) {}
10925     protected Error (SerializationInfo info, StreamingContext context) {}
10926   }
10927
10928   class Guestfs
10929   {
10930     IntPtr _handle;
10931
10932     [DllImport (\"%s\")]
10933     static extern IntPtr guestfs_create ();
10934
10935     public Guestfs ()
10936     {
10937       _handle = guestfs_create ();
10938       if (_handle == IntPtr.Zero)
10939         throw new Error (\"could not create guestfs handle\");
10940     }
10941
10942     [DllImport (\"%s\")]
10943     static extern void guestfs_close (IntPtr h);
10944
10945     ~Guestfs ()
10946     {
10947       guestfs_close (_handle);
10948     }
10949
10950     [DllImport (\"%s\")]
10951     static extern string guestfs_last_error (IntPtr h);
10952
10953 " library library library;
10954
10955   (* Generate C# structure bindings.  We prefix struct names with
10956    * underscore because C# cannot have conflicting struct names and
10957    * method names (eg. "class stat" and "stat").
10958    *)
10959   List.iter (
10960     fun (typ, cols) ->
10961       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10962       pr "    public class _%s {\n" typ;
10963       List.iter (
10964         function
10965         | name, FChar -> pr "      char %s;\n" name
10966         | name, FString -> pr "      string %s;\n" name
10967         | name, FBuffer ->
10968             pr "      uint %s_len;\n" name;
10969             pr "      string %s;\n" name
10970         | name, FUUID ->
10971             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10972             pr "      string %s;\n" name
10973         | name, FUInt32 -> pr "      uint %s;\n" name
10974         | name, FInt32 -> pr "      int %s;\n" name
10975         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10976         | name, FInt64 -> pr "      long %s;\n" name
10977         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10978       ) cols;
10979       pr "    }\n";
10980       pr "\n"
10981   ) structs;
10982
10983   (* Generate C# function bindings. *)
10984   List.iter (
10985     fun (name, style, _, _, _, shortdesc, _) ->
10986       let rec csharp_return_type () =
10987         match fst style with
10988         | RErr -> "void"
10989         | RBool n -> "bool"
10990         | RInt n -> "int"
10991         | RInt64 n -> "long"
10992         | RConstString n
10993         | RConstOptString n
10994         | RString n
10995         | RBufferOut n -> "string"
10996         | RStruct (_,n) -> "_" ^ n
10997         | RHashtable n -> "Hashtable"
10998         | RStringList n -> "string[]"
10999         | RStructList (_,n) -> sprintf "_%s[]" n
11000
11001       and c_return_type () =
11002         match fst style with
11003         | RErr
11004         | RBool _
11005         | RInt _ -> "int"
11006         | RInt64 _ -> "long"
11007         | RConstString _
11008         | RConstOptString _
11009         | RString _
11010         | RBufferOut _ -> "string"
11011         | RStruct (_,n) -> "_" ^ n
11012         | RHashtable _
11013         | RStringList _ -> "string[]"
11014         | RStructList (_,n) -> sprintf "_%s[]" n
11015
11016       and c_error_comparison () =
11017         match fst style with
11018         | RErr
11019         | RBool _
11020         | RInt _
11021         | RInt64 _ -> "== -1"
11022         | RConstString _
11023         | RConstOptString _
11024         | RString _
11025         | RBufferOut _
11026         | RStruct (_,_)
11027         | RHashtable _
11028         | RStringList _
11029         | RStructList (_,_) -> "== null"
11030
11031       and generate_extern_prototype () =
11032         pr "    static extern %s guestfs_%s (IntPtr h"
11033           (c_return_type ()) name;
11034         List.iter (
11035           function
11036           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11037           | FileIn n | FileOut n
11038           | BufferIn n ->
11039               pr ", [In] string %s" n
11040           | StringList n | DeviceList n ->
11041               pr ", [In] string[] %s" n
11042           | Bool n ->
11043               pr ", bool %s" n
11044           | Int n ->
11045               pr ", int %s" n
11046           | Int64 n ->
11047               pr ", long %s" n
11048         ) (snd style);
11049         pr ");\n"
11050
11051       and generate_public_prototype () =
11052         pr "    public %s %s (" (csharp_return_type ()) name;
11053         let comma = ref false in
11054         let next () =
11055           if !comma then pr ", ";
11056           comma := true
11057         in
11058         List.iter (
11059           function
11060           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11061           | FileIn n | FileOut n
11062           | BufferIn n ->
11063               next (); pr "string %s" n
11064           | StringList n | DeviceList n ->
11065               next (); pr "string[] %s" n
11066           | Bool n ->
11067               next (); pr "bool %s" n
11068           | Int n ->
11069               next (); pr "int %s" n
11070           | Int64 n ->
11071               next (); pr "long %s" n
11072         ) (snd style);
11073         pr ")\n"
11074
11075       and generate_call () =
11076         pr "guestfs_%s (_handle" name;
11077         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11078         pr ");\n";
11079       in
11080
11081       pr "    [DllImport (\"%s\")]\n" library;
11082       generate_extern_prototype ();
11083       pr "\n";
11084       pr "    /// <summary>\n";
11085       pr "    /// %s\n" shortdesc;
11086       pr "    /// </summary>\n";
11087       generate_public_prototype ();
11088       pr "    {\n";
11089       pr "      %s r;\n" (c_return_type ());
11090       pr "      r = ";
11091       generate_call ();
11092       pr "      if (r %s)\n" (c_error_comparison ());
11093       pr "        throw new Error (guestfs_last_error (_handle));\n";
11094       (match fst style with
11095        | RErr -> ()
11096        | RBool _ ->
11097            pr "      return r != 0 ? true : false;\n"
11098        | RHashtable _ ->
11099            pr "      Hashtable rr = new Hashtable ();\n";
11100            pr "      for (int i = 0; i < r.Length; i += 2)\n";
11101            pr "        rr.Add (r[i], r[i+1]);\n";
11102            pr "      return rr;\n"
11103        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11104        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11105        | RStructList _ ->
11106            pr "      return r;\n"
11107       );
11108       pr "    }\n";
11109       pr "\n";
11110   ) all_functions_sorted;
11111
11112   pr "  }
11113 }
11114 "
11115
11116 and generate_bindtests () =
11117   generate_header CStyle LGPLv2plus;
11118
11119   pr "\
11120 #include <stdio.h>
11121 #include <stdlib.h>
11122 #include <inttypes.h>
11123 #include <string.h>
11124
11125 #include \"guestfs.h\"
11126 #include \"guestfs-internal.h\"
11127 #include \"guestfs-internal-actions.h\"
11128 #include \"guestfs_protocol.h\"
11129
11130 #define error guestfs_error
11131 #define safe_calloc guestfs_safe_calloc
11132 #define safe_malloc guestfs_safe_malloc
11133
11134 static void
11135 print_strings (char *const *argv)
11136 {
11137   int argc;
11138
11139   printf (\"[\");
11140   for (argc = 0; argv[argc] != NULL; ++argc) {
11141     if (argc > 0) printf (\", \");
11142     printf (\"\\\"%%s\\\"\", argv[argc]);
11143   }
11144   printf (\"]\\n\");
11145 }
11146
11147 /* The test0 function prints its parameters to stdout. */
11148 ";
11149
11150   let test0, tests =
11151     match test_functions with
11152     | [] -> assert false
11153     | test0 :: tests -> test0, tests in
11154
11155   let () =
11156     let (name, style, _, _, _, _, _) = test0 in
11157     generate_prototype ~extern:false ~semicolon:false ~newline:true
11158       ~handle:"g" ~prefix:"guestfs__" name style;
11159     pr "{\n";
11160     List.iter (
11161       function
11162       | Pathname n
11163       | Device n | Dev_or_Path n
11164       | String n
11165       | FileIn n
11166       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11167       | BufferIn n ->
11168           pr "  {\n";
11169           pr "    size_t i;\n";
11170           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11171           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11172           pr "    printf (\"\\n\");\n";
11173           pr "  }\n";
11174       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11175       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11176       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11177       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11178       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11179     ) (snd style);
11180     pr "  /* Java changes stdout line buffering so we need this: */\n";
11181     pr "  fflush (stdout);\n";
11182     pr "  return 0;\n";
11183     pr "}\n";
11184     pr "\n" in
11185
11186   List.iter (
11187     fun (name, style, _, _, _, _, _) ->
11188       if String.sub name (String.length name - 3) 3 <> "err" then (
11189         pr "/* Test normal return. */\n";
11190         generate_prototype ~extern:false ~semicolon:false ~newline:true
11191           ~handle:"g" ~prefix:"guestfs__" name style;
11192         pr "{\n";
11193         (match fst style with
11194          | RErr ->
11195              pr "  return 0;\n"
11196          | RInt _ ->
11197              pr "  int r;\n";
11198              pr "  sscanf (val, \"%%d\", &r);\n";
11199              pr "  return r;\n"
11200          | RInt64 _ ->
11201              pr "  int64_t r;\n";
11202              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11203              pr "  return r;\n"
11204          | RBool _ ->
11205              pr "  return STREQ (val, \"true\");\n"
11206          | RConstString _
11207          | RConstOptString _ ->
11208              (* Can't return the input string here.  Return a static
11209               * string so we ensure we get a segfault if the caller
11210               * tries to free it.
11211               *)
11212              pr "  return \"static string\";\n"
11213          | RString _ ->
11214              pr "  return strdup (val);\n"
11215          | RStringList _ ->
11216              pr "  char **strs;\n";
11217              pr "  int n, i;\n";
11218              pr "  sscanf (val, \"%%d\", &n);\n";
11219              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11220              pr "  for (i = 0; i < n; ++i) {\n";
11221              pr "    strs[i] = safe_malloc (g, 16);\n";
11222              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11223              pr "  }\n";
11224              pr "  strs[n] = NULL;\n";
11225              pr "  return strs;\n"
11226          | RStruct (_, typ) ->
11227              pr "  struct guestfs_%s *r;\n" typ;
11228              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11229              pr "  return r;\n"
11230          | RStructList (_, typ) ->
11231              pr "  struct guestfs_%s_list *r;\n" typ;
11232              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11233              pr "  sscanf (val, \"%%d\", &r->len);\n";
11234              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11235              pr "  return r;\n"
11236          | RHashtable _ ->
11237              pr "  char **strs;\n";
11238              pr "  int n, i;\n";
11239              pr "  sscanf (val, \"%%d\", &n);\n";
11240              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11241              pr "  for (i = 0; i < n; ++i) {\n";
11242              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11243              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11244              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11245              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11246              pr "  }\n";
11247              pr "  strs[n*2] = NULL;\n";
11248              pr "  return strs;\n"
11249          | RBufferOut _ ->
11250              pr "  return strdup (val);\n"
11251         );
11252         pr "}\n";
11253         pr "\n"
11254       ) else (
11255         pr "/* Test error return. */\n";
11256         generate_prototype ~extern:false ~semicolon:false ~newline:true
11257           ~handle:"g" ~prefix:"guestfs__" name style;
11258         pr "{\n";
11259         pr "  error (g, \"error\");\n";
11260         (match fst style with
11261          | RErr | RInt _ | RInt64 _ | RBool _ ->
11262              pr "  return -1;\n"
11263          | RConstString _ | RConstOptString _
11264          | RString _ | RStringList _ | RStruct _
11265          | RStructList _
11266          | RHashtable _
11267          | RBufferOut _ ->
11268              pr "  return NULL;\n"
11269         );
11270         pr "}\n";
11271         pr "\n"
11272       )
11273   ) tests
11274
11275 and generate_ocaml_bindtests () =
11276   generate_header OCamlStyle GPLv2plus;
11277
11278   pr "\
11279 let () =
11280   let g = Guestfs.create () in
11281 ";
11282
11283   let mkargs args =
11284     String.concat " " (
11285       List.map (
11286         function
11287         | CallString s -> "\"" ^ s ^ "\""
11288         | CallOptString None -> "None"
11289         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11290         | CallStringList xs ->
11291             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11292         | CallInt i when i >= 0 -> string_of_int i
11293         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11294         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11295         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11296         | CallBool b -> string_of_bool b
11297         | CallBuffer s -> sprintf "%S" s
11298       ) args
11299     )
11300   in
11301
11302   generate_lang_bindtests (
11303     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11304   );
11305
11306   pr "print_endline \"EOF\"\n"
11307
11308 and generate_perl_bindtests () =
11309   pr "#!/usr/bin/perl -w\n";
11310   generate_header HashStyle GPLv2plus;
11311
11312   pr "\
11313 use strict;
11314
11315 use Sys::Guestfs;
11316
11317 my $g = Sys::Guestfs->new ();
11318 ";
11319
11320   let mkargs args =
11321     String.concat ", " (
11322       List.map (
11323         function
11324         | CallString s -> "\"" ^ s ^ "\""
11325         | CallOptString None -> "undef"
11326         | CallOptString (Some s) -> sprintf "\"%s\"" s
11327         | CallStringList xs ->
11328             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11329         | CallInt i -> string_of_int i
11330         | CallInt64 i -> Int64.to_string i
11331         | CallBool b -> if b then "1" else "0"
11332         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11333       ) args
11334     )
11335   in
11336
11337   generate_lang_bindtests (
11338     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11339   );
11340
11341   pr "print \"EOF\\n\"\n"
11342
11343 and generate_python_bindtests () =
11344   generate_header HashStyle GPLv2plus;
11345
11346   pr "\
11347 import guestfs
11348
11349 g = guestfs.GuestFS ()
11350 ";
11351
11352   let mkargs args =
11353     String.concat ", " (
11354       List.map (
11355         function
11356         | CallString s -> "\"" ^ s ^ "\""
11357         | CallOptString None -> "None"
11358         | CallOptString (Some s) -> sprintf "\"%s\"" s
11359         | CallStringList xs ->
11360             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11361         | CallInt i -> string_of_int i
11362         | CallInt64 i -> Int64.to_string i
11363         | CallBool b -> if b then "1" else "0"
11364         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11365       ) args
11366     )
11367   in
11368
11369   generate_lang_bindtests (
11370     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11371   );
11372
11373   pr "print \"EOF\"\n"
11374
11375 and generate_ruby_bindtests () =
11376   generate_header HashStyle GPLv2plus;
11377
11378   pr "\
11379 require 'guestfs'
11380
11381 g = Guestfs::create()
11382 ";
11383
11384   let mkargs args =
11385     String.concat ", " (
11386       List.map (
11387         function
11388         | CallString s -> "\"" ^ s ^ "\""
11389         | CallOptString None -> "nil"
11390         | CallOptString (Some s) -> sprintf "\"%s\"" s
11391         | CallStringList xs ->
11392             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11393         | CallInt i -> string_of_int i
11394         | CallInt64 i -> Int64.to_string i
11395         | CallBool b -> string_of_bool b
11396         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11397       ) args
11398     )
11399   in
11400
11401   generate_lang_bindtests (
11402     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11403   );
11404
11405   pr "print \"EOF\\n\"\n"
11406
11407 and generate_java_bindtests () =
11408   generate_header CStyle GPLv2plus;
11409
11410   pr "\
11411 import com.redhat.et.libguestfs.*;
11412
11413 public class Bindtests {
11414     public static void main (String[] argv)
11415     {
11416         try {
11417             GuestFS g = new GuestFS ();
11418 ";
11419
11420   let mkargs args =
11421     String.concat ", " (
11422       List.map (
11423         function
11424         | CallString s -> "\"" ^ s ^ "\""
11425         | CallOptString None -> "null"
11426         | CallOptString (Some s) -> sprintf "\"%s\"" s
11427         | CallStringList xs ->
11428             "new String[]{" ^
11429               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11430         | CallInt i -> string_of_int i
11431         | CallInt64 i -> Int64.to_string i
11432         | CallBool b -> string_of_bool b
11433         | CallBuffer s ->
11434             "new byte[] { " ^ String.concat "," (
11435               map_chars (fun c -> string_of_int (Char.code c)) s
11436             ) ^ " }"
11437       ) args
11438     )
11439   in
11440
11441   generate_lang_bindtests (
11442     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11443   );
11444
11445   pr "
11446             System.out.println (\"EOF\");
11447         }
11448         catch (Exception exn) {
11449             System.err.println (exn);
11450             System.exit (1);
11451         }
11452     }
11453 }
11454 "
11455
11456 and generate_haskell_bindtests () =
11457   generate_header HaskellStyle GPLv2plus;
11458
11459   pr "\
11460 module Bindtests where
11461 import qualified Guestfs
11462
11463 main = do
11464   g <- Guestfs.create
11465 ";
11466
11467   let mkargs args =
11468     String.concat " " (
11469       List.map (
11470         function
11471         | CallString s -> "\"" ^ s ^ "\""
11472         | CallOptString None -> "Nothing"
11473         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11474         | CallStringList xs ->
11475             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11476         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11477         | CallInt i -> string_of_int i
11478         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11479         | CallInt64 i -> Int64.to_string i
11480         | CallBool true -> "True"
11481         | CallBool false -> "False"
11482         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11483       ) args
11484     )
11485   in
11486
11487   generate_lang_bindtests (
11488     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11489   );
11490
11491   pr "  putStrLn \"EOF\"\n"
11492
11493 (* Language-independent bindings tests - we do it this way to
11494  * ensure there is parity in testing bindings across all languages.
11495  *)
11496 and generate_lang_bindtests call =
11497   call "test0" [CallString "abc"; CallOptString (Some "def");
11498                 CallStringList []; CallBool false;
11499                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11500                 CallBuffer "abc\000abc"];
11501   call "test0" [CallString "abc"; CallOptString None;
11502                 CallStringList []; CallBool false;
11503                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11504                 CallBuffer "abc\000abc"];
11505   call "test0" [CallString ""; CallOptString (Some "def");
11506                 CallStringList []; CallBool false;
11507                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11508                 CallBuffer "abc\000abc"];
11509   call "test0" [CallString ""; CallOptString (Some "");
11510                 CallStringList []; CallBool false;
11511                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11512                 CallBuffer "abc\000abc"];
11513   call "test0" [CallString "abc"; CallOptString (Some "def");
11514                 CallStringList ["1"]; CallBool false;
11515                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11516                 CallBuffer "abc\000abc"];
11517   call "test0" [CallString "abc"; CallOptString (Some "def");
11518                 CallStringList ["1"; "2"]; CallBool false;
11519                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11520                 CallBuffer "abc\000abc"];
11521   call "test0" [CallString "abc"; CallOptString (Some "def");
11522                 CallStringList ["1"]; CallBool true;
11523                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11524                 CallBuffer "abc\000abc"];
11525   call "test0" [CallString "abc"; CallOptString (Some "def");
11526                 CallStringList ["1"]; CallBool false;
11527                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11528                 CallBuffer "abc\000abc"];
11529   call "test0" [CallString "abc"; CallOptString (Some "def");
11530                 CallStringList ["1"]; CallBool false;
11531                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11532                 CallBuffer "abc\000abc"];
11533   call "test0" [CallString "abc"; CallOptString (Some "def");
11534                 CallStringList ["1"]; CallBool false;
11535                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11536                 CallBuffer "abc\000abc"];
11537   call "test0" [CallString "abc"; CallOptString (Some "def");
11538                 CallStringList ["1"]; CallBool false;
11539                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11540                 CallBuffer "abc\000abc"];
11541   call "test0" [CallString "abc"; CallOptString (Some "def");
11542                 CallStringList ["1"]; CallBool false;
11543                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11544                 CallBuffer "abc\000abc"];
11545   call "test0" [CallString "abc"; CallOptString (Some "def");
11546                 CallStringList ["1"]; CallBool false;
11547                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11548                 CallBuffer "abc\000abc"]
11549
11550 (* XXX Add here tests of the return and error functions. *)
11551
11552 (* Code to generator bindings for virt-inspector.  Currently only
11553  * implemented for OCaml code (for virt-p2v 2.0).
11554  *)
11555 let rng_input = "inspector/virt-inspector.rng"
11556
11557 (* Read the input file and parse it into internal structures.  This is
11558  * by no means a complete RELAX NG parser, but is just enough to be
11559  * able to parse the specific input file.
11560  *)
11561 type rng =
11562   | Element of string * rng list        (* <element name=name/> *)
11563   | Attribute of string * rng list        (* <attribute name=name/> *)
11564   | Interleave of rng list                (* <interleave/> *)
11565   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11566   | OneOrMore of rng                        (* <oneOrMore/> *)
11567   | Optional of rng                        (* <optional/> *)
11568   | Choice of string list                (* <choice><value/>*</choice> *)
11569   | Value of string                        (* <value>str</value> *)
11570   | Text                                (* <text/> *)
11571
11572 let rec string_of_rng = function
11573   | Element (name, xs) ->
11574       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11575   | Attribute (name, xs) ->
11576       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11577   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11578   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11579   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11580   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11581   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11582   | Value value -> "Value \"" ^ value ^ "\""
11583   | Text -> "Text"
11584
11585 and string_of_rng_list xs =
11586   String.concat ", " (List.map string_of_rng xs)
11587
11588 let rec parse_rng ?defines context = function
11589   | [] -> []
11590   | Xml.Element ("element", ["name", name], children) :: rest ->
11591       Element (name, parse_rng ?defines context children)
11592       :: parse_rng ?defines context rest
11593   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11594       Attribute (name, parse_rng ?defines context children)
11595       :: parse_rng ?defines context rest
11596   | Xml.Element ("interleave", [], children) :: rest ->
11597       Interleave (parse_rng ?defines context children)
11598       :: parse_rng ?defines context rest
11599   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11600       let rng = parse_rng ?defines context [child] in
11601       (match rng with
11602        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11603        | _ ->
11604            failwithf "%s: <zeroOrMore> contains more than one child element"
11605              context
11606       )
11607   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11608       let rng = parse_rng ?defines context [child] in
11609       (match rng with
11610        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11611        | _ ->
11612            failwithf "%s: <oneOrMore> contains more than one child element"
11613              context
11614       )
11615   | Xml.Element ("optional", [], [child]) :: rest ->
11616       let rng = parse_rng ?defines context [child] in
11617       (match rng with
11618        | [child] -> Optional child :: parse_rng ?defines context rest
11619        | _ ->
11620            failwithf "%s: <optional> contains more than one child element"
11621              context
11622       )
11623   | Xml.Element ("choice", [], children) :: rest ->
11624       let values = List.map (
11625         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11626         | _ ->
11627             failwithf "%s: can't handle anything except <value> in <choice>"
11628               context
11629       ) children in
11630       Choice values
11631       :: parse_rng ?defines context rest
11632   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11633       Value value :: parse_rng ?defines context rest
11634   | Xml.Element ("text", [], []) :: rest ->
11635       Text :: parse_rng ?defines context rest
11636   | Xml.Element ("ref", ["name", name], []) :: rest ->
11637       (* Look up the reference.  Because of limitations in this parser,
11638        * we can't handle arbitrarily nested <ref> yet.  You can only
11639        * use <ref> from inside <start>.
11640        *)
11641       (match defines with
11642        | None ->
11643            failwithf "%s: contains <ref>, but no refs are defined yet" context
11644        | Some map ->
11645            let rng = StringMap.find name map in
11646            rng @ parse_rng ?defines context rest
11647       )
11648   | x :: _ ->
11649       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11650
11651 let grammar =
11652   let xml = Xml.parse_file rng_input in
11653   match xml with
11654   | Xml.Element ("grammar", _,
11655                  Xml.Element ("start", _, gram) :: defines) ->
11656       (* The <define/> elements are referenced in the <start> section,
11657        * so build a map of those first.
11658        *)
11659       let defines = List.fold_left (
11660         fun map ->
11661           function Xml.Element ("define", ["name", name], defn) ->
11662             StringMap.add name defn map
11663           | _ ->
11664               failwithf "%s: expected <define name=name/>" rng_input
11665       ) StringMap.empty defines in
11666       let defines = StringMap.mapi parse_rng defines in
11667
11668       (* Parse the <start> clause, passing the defines. *)
11669       parse_rng ~defines "<start>" gram
11670   | _ ->
11671       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11672         rng_input
11673
11674 let name_of_field = function
11675   | Element (name, _) | Attribute (name, _)
11676   | ZeroOrMore (Element (name, _))
11677   | OneOrMore (Element (name, _))
11678   | Optional (Element (name, _)) -> name
11679   | Optional (Attribute (name, _)) -> name
11680   | Text -> (* an unnamed field in an element *)
11681       "data"
11682   | rng ->
11683       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11684
11685 (* At the moment this function only generates OCaml types.  However we
11686  * should parameterize it later so it can generate types/structs in a
11687  * variety of languages.
11688  *)
11689 let generate_types xs =
11690   (* A simple type is one that can be printed out directly, eg.
11691    * "string option".  A complex type is one which has a name and has
11692    * to be defined via another toplevel definition, eg. a struct.
11693    *
11694    * generate_type generates code for either simple or complex types.
11695    * In the simple case, it returns the string ("string option").  In
11696    * the complex case, it returns the name ("mountpoint").  In the
11697    * complex case it has to print out the definition before returning,
11698    * so it should only be called when we are at the beginning of a
11699    * new line (BOL context).
11700    *)
11701   let rec generate_type = function
11702     | Text ->                                (* string *)
11703         "string", true
11704     | Choice values ->                        (* [`val1|`val2|...] *)
11705         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11706     | ZeroOrMore rng ->                        (* <rng> list *)
11707         let t, is_simple = generate_type rng in
11708         t ^ " list (* 0 or more *)", is_simple
11709     | OneOrMore rng ->                        (* <rng> list *)
11710         let t, is_simple = generate_type rng in
11711         t ^ " list (* 1 or more *)", is_simple
11712                                         (* virt-inspector hack: bool *)
11713     | Optional (Attribute (name, [Value "1"])) ->
11714         "bool", true
11715     | Optional rng ->                        (* <rng> list *)
11716         let t, is_simple = generate_type rng in
11717         t ^ " option", is_simple
11718                                         (* type name = { fields ... } *)
11719     | Element (name, fields) when is_attrs_interleave fields ->
11720         generate_type_struct name (get_attrs_interleave fields)
11721     | Element (name, [field])                (* type name = field *)
11722     | Attribute (name, [field]) ->
11723         let t, is_simple = generate_type field in
11724         if is_simple then (t, true)
11725         else (
11726           pr "type %s = %s\n" name t;
11727           name, false
11728         )
11729     | Element (name, fields) ->              (* type name = { fields ... } *)
11730         generate_type_struct name fields
11731     | rng ->
11732         failwithf "generate_type failed at: %s" (string_of_rng rng)
11733
11734   and is_attrs_interleave = function
11735     | [Interleave _] -> true
11736     | Attribute _ :: fields -> is_attrs_interleave fields
11737     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11738     | _ -> false
11739
11740   and get_attrs_interleave = function
11741     | [Interleave fields] -> fields
11742     | ((Attribute _) as field) :: fields
11743     | ((Optional (Attribute _)) as field) :: fields ->
11744         field :: get_attrs_interleave fields
11745     | _ -> assert false
11746
11747   and generate_types xs =
11748     List.iter (fun x -> ignore (generate_type x)) xs
11749
11750   and generate_type_struct name fields =
11751     (* Calculate the types of the fields first.  We have to do this
11752      * before printing anything so we are still in BOL context.
11753      *)
11754     let types = List.map fst (List.map generate_type fields) in
11755
11756     (* Special case of a struct containing just a string and another
11757      * field.  Turn it into an assoc list.
11758      *)
11759     match types with
11760     | ["string"; other] ->
11761         let fname1, fname2 =
11762           match fields with
11763           | [f1; f2] -> name_of_field f1, name_of_field f2
11764           | _ -> assert false in
11765         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11766         name, false
11767
11768     | types ->
11769         pr "type %s = {\n" name;
11770         List.iter (
11771           fun (field, ftype) ->
11772             let fname = name_of_field field in
11773             pr "  %s_%s : %s;\n" name fname ftype
11774         ) (List.combine fields types);
11775         pr "}\n";
11776         (* Return the name of this type, and
11777          * false because it's not a simple type.
11778          *)
11779         name, false
11780   in
11781
11782   generate_types xs
11783
11784 let generate_parsers xs =
11785   (* As for generate_type above, generate_parser makes a parser for
11786    * some type, and returns the name of the parser it has generated.
11787    * Because it (may) need to print something, it should always be
11788    * called in BOL context.
11789    *)
11790   let rec generate_parser = function
11791     | Text ->                                (* string *)
11792         "string_child_or_empty"
11793     | Choice values ->                        (* [`val1|`val2|...] *)
11794         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11795           (String.concat "|"
11796              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11797     | ZeroOrMore rng ->                        (* <rng> list *)
11798         let pa = generate_parser rng in
11799         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11800     | OneOrMore rng ->                        (* <rng> list *)
11801         let pa = generate_parser rng in
11802         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11803                                         (* virt-inspector hack: bool *)
11804     | Optional (Attribute (name, [Value "1"])) ->
11805         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11806     | Optional rng ->                        (* <rng> list *)
11807         let pa = generate_parser rng in
11808         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11809                                         (* type name = { fields ... } *)
11810     | Element (name, fields) when is_attrs_interleave fields ->
11811         generate_parser_struct name (get_attrs_interleave fields)
11812     | Element (name, [field]) ->        (* type name = field *)
11813         let pa = generate_parser field in
11814         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11815         pr "let %s =\n" parser_name;
11816         pr "  %s\n" pa;
11817         pr "let parse_%s = %s\n" name parser_name;
11818         parser_name
11819     | Attribute (name, [field]) ->
11820         let pa = generate_parser field in
11821         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11822         pr "let %s =\n" parser_name;
11823         pr "  %s\n" pa;
11824         pr "let parse_%s = %s\n" name parser_name;
11825         parser_name
11826     | Element (name, fields) ->              (* type name = { fields ... } *)
11827         generate_parser_struct name ([], fields)
11828     | rng ->
11829         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11830
11831   and is_attrs_interleave = function
11832     | [Interleave _] -> true
11833     | Attribute _ :: fields -> is_attrs_interleave fields
11834     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11835     | _ -> false
11836
11837   and get_attrs_interleave = function
11838     | [Interleave fields] -> [], fields
11839     | ((Attribute _) as field) :: fields
11840     | ((Optional (Attribute _)) as field) :: fields ->
11841         let attrs, interleaves = get_attrs_interleave fields in
11842         (field :: attrs), interleaves
11843     | _ -> assert false
11844
11845   and generate_parsers xs =
11846     List.iter (fun x -> ignore (generate_parser x)) xs
11847
11848   and generate_parser_struct name (attrs, interleaves) =
11849     (* Generate parsers for the fields first.  We have to do this
11850      * before printing anything so we are still in BOL context.
11851      *)
11852     let fields = attrs @ interleaves in
11853     let pas = List.map generate_parser fields in
11854
11855     (* Generate an intermediate tuple from all the fields first.
11856      * If the type is just a string + another field, then we will
11857      * return this directly, otherwise it is turned into a record.
11858      *
11859      * RELAX NG note: This code treats <interleave> and plain lists of
11860      * fields the same.  In other words, it doesn't bother enforcing
11861      * any ordering of fields in the XML.
11862      *)
11863     pr "let parse_%s x =\n" name;
11864     pr "  let t = (\n    ";
11865     let comma = ref false in
11866     List.iter (
11867       fun x ->
11868         if !comma then pr ",\n    ";
11869         comma := true;
11870         match x with
11871         | Optional (Attribute (fname, [field])), pa ->
11872             pr "%s x" pa
11873         | Optional (Element (fname, [field])), pa ->
11874             pr "%s (optional_child %S x)" pa fname
11875         | Attribute (fname, [Text]), _ ->
11876             pr "attribute %S x" fname
11877         | (ZeroOrMore _ | OneOrMore _), pa ->
11878             pr "%s x" pa
11879         | Text, pa ->
11880             pr "%s x" pa
11881         | (field, pa) ->
11882             let fname = name_of_field field in
11883             pr "%s (child %S x)" pa fname
11884     ) (List.combine fields pas);
11885     pr "\n  ) in\n";
11886
11887     (match fields with
11888      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11889          pr "  t\n"
11890
11891      | _ ->
11892          pr "  (Obj.magic t : %s)\n" name
11893 (*
11894          List.iter (
11895            function
11896            | (Optional (Attribute (fname, [field])), pa) ->
11897                pr "  %s_%s =\n" name fname;
11898                pr "    %s x;\n" pa
11899            | (Optional (Element (fname, [field])), pa) ->
11900                pr "  %s_%s =\n" name fname;
11901                pr "    (let x = optional_child %S x in\n" fname;
11902                pr "     %s x);\n" pa
11903            | (field, pa) ->
11904                let fname = name_of_field field in
11905                pr "  %s_%s =\n" name fname;
11906                pr "    (let x = child %S x in\n" fname;
11907                pr "     %s x);\n" pa
11908          ) (List.combine fields pas);
11909          pr "}\n"
11910 *)
11911     );
11912     sprintf "parse_%s" name
11913   in
11914
11915   generate_parsers xs
11916
11917 (* Generate ocaml/guestfs_inspector.mli. *)
11918 let generate_ocaml_inspector_mli () =
11919   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11920
11921   pr "\
11922 (** This is an OCaml language binding to the external [virt-inspector]
11923     program.
11924
11925     For more information, please read the man page [virt-inspector(1)].
11926 *)
11927
11928 ";
11929
11930   generate_types grammar;
11931   pr "(** The nested information returned from the {!inspect} function. *)\n";
11932   pr "\n";
11933
11934   pr "\
11935 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11936 (** To inspect a libvirt domain called [name], pass a singleton
11937     list: [inspect [name]].  When using libvirt only, you may
11938     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11939
11940     To inspect a disk image or images, pass a list of the filenames
11941     of the disk images: [inspect filenames]
11942
11943     This function inspects the given guest or disk images and
11944     returns a list of operating system(s) found and a large amount
11945     of information about them.  In the vast majority of cases,
11946     a virtual machine only contains a single operating system.
11947
11948     If the optional [~xml] parameter is given, then this function
11949     skips running the external virt-inspector program and just
11950     parses the given XML directly (which is expected to be XML
11951     produced from a previous run of virt-inspector).  The list of
11952     names and connect URI are ignored in this case.
11953
11954     This function can throw a wide variety of exceptions, for example
11955     if the external virt-inspector program cannot be found, or if
11956     it doesn't generate valid XML.
11957 *)
11958 "
11959
11960 (* Generate ocaml/guestfs_inspector.ml. *)
11961 let generate_ocaml_inspector_ml () =
11962   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11963
11964   pr "open Unix\n";
11965   pr "\n";
11966
11967   generate_types grammar;
11968   pr "\n";
11969
11970   pr "\
11971 (* Misc functions which are used by the parser code below. *)
11972 let first_child = function
11973   | Xml.Element (_, _, c::_) -> c
11974   | Xml.Element (name, _, []) ->
11975       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11976   | Xml.PCData str ->
11977       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11978
11979 let string_child_or_empty = function
11980   | Xml.Element (_, _, [Xml.PCData s]) -> s
11981   | Xml.Element (_, _, []) -> \"\"
11982   | Xml.Element (x, _, _) ->
11983       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11984                 x ^ \" instead\")
11985   | Xml.PCData str ->
11986       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11987
11988 let optional_child name xml =
11989   let children = Xml.children xml in
11990   try
11991     Some (List.find (function
11992                      | Xml.Element (n, _, _) when n = name -> true
11993                      | _ -> false) children)
11994   with
11995     Not_found -> None
11996
11997 let child name xml =
11998   match optional_child name xml with
11999   | Some c -> c
12000   | None ->
12001       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
12002
12003 let attribute name xml =
12004   try Xml.attrib xml name
12005   with Xml.No_attribute _ ->
12006     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
12007
12008 ";
12009
12010   generate_parsers grammar;
12011   pr "\n";
12012
12013   pr "\
12014 (* Run external virt-inspector, then use parser to parse the XML. *)
12015 let inspect ?connect ?xml names =
12016   let xml =
12017     match xml with
12018     | None ->
12019         if names = [] then invalid_arg \"inspect: no names given\";
12020         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
12021           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
12022           names in
12023         let cmd = List.map Filename.quote cmd in
12024         let cmd = String.concat \" \" cmd in
12025         let chan = open_process_in cmd in
12026         let xml = Xml.parse_in chan in
12027         (match close_process_in chan with
12028          | WEXITED 0 -> ()
12029          | WEXITED _ -> failwith \"external virt-inspector command failed\"
12030          | WSIGNALED i | WSTOPPED i ->
12031              failwith (\"external virt-inspector command died or stopped on sig \" ^
12032                        string_of_int i)
12033         );
12034         xml
12035     | Some doc ->
12036         Xml.parse_string doc in
12037   parse_operatingsystems xml
12038 "
12039
12040 and generate_max_proc_nr () =
12041   pr "%d\n" max_proc_nr
12042
12043 let output_to filename k =
12044   let filename_new = filename ^ ".new" in
12045   chan := open_out filename_new;
12046   k ();
12047   close_out !chan;
12048   chan := Pervasives.stdout;
12049
12050   (* Is the new file different from the current file? *)
12051   if Sys.file_exists filename && files_equal filename filename_new then
12052     unlink filename_new                 (* same, so skip it *)
12053   else (
12054     (* different, overwrite old one *)
12055     (try chmod filename 0o644 with Unix_error _ -> ());
12056     rename filename_new filename;
12057     chmod filename 0o444;
12058     printf "written %s\n%!" filename;
12059   )
12060
12061 let perror msg = function
12062   | Unix_error (err, _, _) ->
12063       eprintf "%s: %s\n" msg (error_message err)
12064   | exn ->
12065       eprintf "%s: %s\n" msg (Printexc.to_string exn)
12066
12067 (* Main program. *)
12068 let () =
12069   let lock_fd =
12070     try openfile "HACKING" [O_RDWR] 0
12071     with
12072     | Unix_error (ENOENT, _, _) ->
12073         eprintf "\
12074 You are probably running this from the wrong directory.
12075 Run it from the top source directory using the command
12076   src/generator.ml
12077 ";
12078         exit 1
12079     | exn ->
12080         perror "open: HACKING" exn;
12081         exit 1 in
12082
12083   (* Acquire a lock so parallel builds won't try to run the generator
12084    * twice at the same time.  Subsequent builds will wait for the first
12085    * one to finish.  Note the lock is released implicitly when the
12086    * program exits.
12087    *)
12088   (try lockf lock_fd F_LOCK 1
12089    with exn ->
12090      perror "lock: HACKING" exn;
12091      exit 1);
12092
12093   check_functions ();
12094
12095   output_to "src/guestfs_protocol.x" generate_xdr;
12096   output_to "src/guestfs-structs.h" generate_structs_h;
12097   output_to "src/guestfs-actions.h" generate_actions_h;
12098   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12099   output_to "src/guestfs-actions.c" generate_client_actions;
12100   output_to "src/guestfs-bindtests.c" generate_bindtests;
12101   output_to "src/guestfs-structs.pod" generate_structs_pod;
12102   output_to "src/guestfs-actions.pod" generate_actions_pod;
12103   output_to "src/guestfs-availability.pod" generate_availability_pod;
12104   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12105   output_to "src/libguestfs.syms" generate_linker_script;
12106   output_to "daemon/actions.h" generate_daemon_actions_h;
12107   output_to "daemon/stubs.c" generate_daemon_actions;
12108   output_to "daemon/names.c" generate_daemon_names;
12109   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12110   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12111   output_to "capitests/tests.c" generate_tests;
12112   output_to "fish/cmds.c" generate_fish_cmds;
12113   output_to "fish/completion.c" generate_fish_completion;
12114   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12115   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12116   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12117   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12118   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12119   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12120   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12121   output_to "perl/Guestfs.xs" generate_perl_xs;
12122   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12123   output_to "perl/bindtests.pl" generate_perl_bindtests;
12124   output_to "python/guestfs-py.c" generate_python_c;
12125   output_to "python/guestfs.py" generate_python_py;
12126   output_to "python/bindtests.py" generate_python_bindtests;
12127   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12128   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12129   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12130
12131   List.iter (
12132     fun (typ, jtyp) ->
12133       let cols = cols_of_struct typ in
12134       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12135       output_to filename (generate_java_struct jtyp cols);
12136   ) java_structs;
12137
12138   output_to "java/Makefile.inc" generate_java_makefile_inc;
12139   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12140   output_to "java/Bindtests.java" generate_java_bindtests;
12141   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12142   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12143   output_to "csharp/Libguestfs.cs" generate_csharp;
12144
12145   (* Always generate this file last, and unconditionally.  It's used
12146    * by the Makefile to know when we must re-run the generator.
12147    *)
12148   let chan = open_out "src/stamp-generator" in
12149   fprintf chan "1\n";
12150   close_out chan;
12151
12152   printf "generated %d lines of code\n" !lines