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