Rename guestfs-{actions,bindtests}.c to {actions,bindtests}.c
[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,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 Note that this call checks for the existence of C<filename>.  This
562 stops you from specifying other types of drive which are supported
563 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
564 the general C<guestfs_config> call instead.");
565
566   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
567    [],
568    "add qemu parameters",
569    "\
570 This can be used to add arbitrary qemu command line parameters
571 of the form C<-param value>.  Actually it's not quite arbitrary - we
572 prevent you from setting some parameters which would interfere with
573 parameters that we use.
574
575 The first character of C<param> string must be a C<-> (dash).
576
577 C<value> can be NULL.");
578
579   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
580    [],
581    "set the qemu binary",
582    "\
583 Set the qemu binary that we will use.
584
585 The default is chosen when the library was compiled by the
586 configure script.
587
588 You can also override this by setting the C<LIBGUESTFS_QEMU>
589 environment variable.
590
591 Setting C<qemu> to C<NULL> restores the default qemu binary.
592
593 Note that you should call this function as early as possible
594 after creating the handle.  This is because some pre-launch
595 operations depend on testing qemu features (by running C<qemu -help>).
596 If the qemu binary changes, we don't retest features, and
597 so you might see inconsistent results.  Using the environment
598 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
599 the qemu binary at the same time as the handle is created.");
600
601   ("get_qemu", (RConstString "qemu", []), -1, [],
602    [InitNone, Always, TestRun (
603       [["get_qemu"]])],
604    "get the qemu binary",
605    "\
606 Return the current qemu binary.
607
608 This is always non-NULL.  If it wasn't set already, then this will
609 return the default qemu binary name.");
610
611   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
612    [],
613    "set the search path",
614    "\
615 Set the path that libguestfs searches for kernel and initrd.img.
616
617 The default is C<$libdir/guestfs> unless overridden by setting
618 C<LIBGUESTFS_PATH> environment variable.
619
620 Setting C<path> to C<NULL> restores the default path.");
621
622   ("get_path", (RConstString "path", []), -1, [],
623    [InitNone, Always, TestRun (
624       [["get_path"]])],
625    "get the search path",
626    "\
627 Return the current search path.
628
629 This is always non-NULL.  If it wasn't set already, then this will
630 return the default path.");
631
632   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
633    [],
634    "add options to kernel command line",
635    "\
636 This function is used to add additional options to the
637 guest kernel command line.
638
639 The default is C<NULL> unless overridden by setting
640 C<LIBGUESTFS_APPEND> environment variable.
641
642 Setting C<append> to C<NULL> means I<no> additional options
643 are passed (libguestfs always adds a few of its own).");
644
645   ("get_append", (RConstOptString "append", []), -1, [],
646    (* This cannot be tested with the current framework.  The
647     * function can return NULL in normal operations, which the
648     * test framework interprets as an error.
649     *)
650    [],
651    "get the additional kernel options",
652    "\
653 Return the additional kernel options which are added to the
654 guest kernel command line.
655
656 If C<NULL> then no options are added.");
657
658   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
659    [],
660    "set autosync mode",
661    "\
662 If C<autosync> is true, this enables autosync.  Libguestfs will make a
663 best effort attempt to run C<guestfs_umount_all> followed by
664 C<guestfs_sync> when the handle is closed
665 (also if the program exits without closing handles).
666
667 This is disabled by default (except in guestfish where it is
668 enabled by default).");
669
670   ("get_autosync", (RBool "autosync", []), -1, [],
671    [InitNone, Always, TestRun (
672       [["get_autosync"]])],
673    "get autosync mode",
674    "\
675 Get the autosync flag.");
676
677   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
678    [],
679    "set verbose mode",
680    "\
681 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
682
683 Verbose messages are disabled unless the environment variable
684 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
685
686   ("get_verbose", (RBool "verbose", []), -1, [],
687    [],
688    "get verbose mode",
689    "\
690 This returns the verbose messages flag.");
691
692   ("is_ready", (RBool "ready", []), -1, [],
693    [InitNone, Always, TestOutputTrue (
694       [["is_ready"]])],
695    "is ready to accept commands",
696    "\
697 This returns true iff this handle is ready to accept commands
698 (in the C<READY> state).
699
700 For more information on states, see L<guestfs(3)>.");
701
702   ("is_config", (RBool "config", []), -1, [],
703    [InitNone, Always, TestOutputFalse (
704       [["is_config"]])],
705    "is in configuration state",
706    "\
707 This returns true iff this handle is being configured
708 (in the C<CONFIG> state).
709
710 For more information on states, see L<guestfs(3)>.");
711
712   ("is_launching", (RBool "launching", []), -1, [],
713    [InitNone, Always, TestOutputFalse (
714       [["is_launching"]])],
715    "is launching subprocess",
716    "\
717 This returns true iff this handle is launching the subprocess
718 (in the C<LAUNCHING> state).
719
720 For more information on states, see L<guestfs(3)>.");
721
722   ("is_busy", (RBool "busy", []), -1, [],
723    [InitNone, Always, TestOutputFalse (
724       [["is_busy"]])],
725    "is busy processing a command",
726    "\
727 This returns true iff this handle is busy processing a command
728 (in the C<BUSY> state).
729
730 For more information on states, see L<guestfs(3)>.");
731
732   ("get_state", (RInt "state", []), -1, [],
733    [],
734    "get the current state",
735    "\
736 This returns the current state as an opaque integer.  This is
737 only useful for printing debug and internal error messages.
738
739 For more information on states, see L<guestfs(3)>.");
740
741   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
742    [InitNone, Always, TestOutputInt (
743       [["set_memsize"; "500"];
744        ["get_memsize"]], 500)],
745    "set memory allocated to the qemu subprocess",
746    "\
747 This sets the memory size in megabytes allocated to the
748 qemu subprocess.  This only has any effect if called before
749 C<guestfs_launch>.
750
751 You can also change this by setting the environment
752 variable C<LIBGUESTFS_MEMSIZE> before the handle is
753 created.
754
755 For more information on the architecture of libguestfs,
756 see L<guestfs(3)>.");
757
758   ("get_memsize", (RInt "memsize", []), -1, [],
759    [InitNone, Always, TestOutputIntOp (
760       [["get_memsize"]], ">=", 256)],
761    "get memory allocated to the qemu subprocess",
762    "\
763 This gets the memory size in megabytes allocated to the
764 qemu subprocess.
765
766 If C<guestfs_set_memsize> was not called
767 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
768 then this returns the compiled-in default value for memsize.
769
770 For more information on the architecture of libguestfs,
771 see L<guestfs(3)>.");
772
773   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
774    [InitNone, Always, TestOutputIntOp (
775       [["get_pid"]], ">=", 1)],
776    "get PID of qemu subprocess",
777    "\
778 Return the process ID of the qemu subprocess.  If there is no
779 qemu subprocess, then this will return an error.
780
781 This is an internal call used for debugging and testing.");
782
783   ("version", (RStruct ("version", "version"), []), -1, [],
784    [InitNone, Always, TestOutputStruct (
785       [["version"]], [CompareWithInt ("major", 1)])],
786    "get the library version number",
787    "\
788 Return the libguestfs version number that the program is linked
789 against.
790
791 Note that because of dynamic linking this is not necessarily
792 the version of libguestfs that you compiled against.  You can
793 compile the program, and then at runtime dynamically link
794 against a completely different C<libguestfs.so> library.
795
796 This call was added in version C<1.0.58>.  In previous
797 versions of libguestfs there was no way to get the version
798 number.  From C code you can use dynamic linker functions
799 to find out if this symbol exists (if it doesn't, then
800 it's an earlier version).
801
802 The call returns a structure with four elements.  The first
803 three (C<major>, C<minor> and C<release>) are numbers and
804 correspond to the usual version triplet.  The fourth element
805 (C<extra>) is a string and is normally empty, but may be
806 used for distro-specific information.
807
808 To construct the original version string:
809 C<$major.$minor.$release$extra>
810
811 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
812
813 I<Note:> Don't use this call to test for availability
814 of features.  In enterprise distributions we backport
815 features from later versions into earlier versions,
816 making this an unreliable way to test for features.
817 Use C<guestfs_available> instead.");
818
819   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
820    [InitNone, Always, TestOutputTrue (
821       [["set_selinux"; "true"];
822        ["get_selinux"]])],
823    "set SELinux enabled or disabled at appliance boot",
824    "\
825 This sets the selinux flag that is passed to the appliance
826 at boot time.  The default is C<selinux=0> (disabled).
827
828 Note that if SELinux is enabled, it is always in
829 Permissive mode (C<enforcing=0>).
830
831 For more information on the architecture of libguestfs,
832 see L<guestfs(3)>.");
833
834   ("get_selinux", (RBool "selinux", []), -1, [],
835    [],
836    "get SELinux enabled flag",
837    "\
838 This returns the current setting of the selinux flag which
839 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
840
841 For more information on the architecture of libguestfs,
842 see L<guestfs(3)>.");
843
844   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
845    [InitNone, Always, TestOutputFalse (
846       [["set_trace"; "false"];
847        ["get_trace"]])],
848    "enable or disable command traces",
849    "\
850 If the command trace flag is set to 1, then commands are
851 printed on stdout before they are executed in a format
852 which is very similar to the one used by guestfish.  In
853 other words, you can run a program with this enabled, and
854 you will get out a script which you can feed to guestfish
855 to perform the same set of actions.
856
857 If you want to trace C API calls into libguestfs (and
858 other libraries) then possibly a better way is to use
859 the external ltrace(1) command.
860
861 Command traces are disabled unless the environment variable
862 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
863
864   ("get_trace", (RBool "trace", []), -1, [],
865    [],
866    "get command trace enabled flag",
867    "\
868 Return the command trace flag.");
869
870   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
871    [InitNone, Always, TestOutputFalse (
872       [["set_direct"; "false"];
873        ["get_direct"]])],
874    "enable or disable direct appliance mode",
875    "\
876 If the direct appliance mode flag is enabled, then stdin and
877 stdout are passed directly through to the appliance once it
878 is launched.
879
880 One consequence of this is that log messages aren't caught
881 by the library and handled by C<guestfs_set_log_message_callback>,
882 but go straight to stdout.
883
884 You probably don't want to use this unless you know what you
885 are doing.
886
887 The default is disabled.");
888
889   ("get_direct", (RBool "direct", []), -1, [],
890    [],
891    "get direct appliance mode flag",
892    "\
893 Return the direct appliance mode flag.");
894
895   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
896    [InitNone, Always, TestOutputTrue (
897       [["set_recovery_proc"; "true"];
898        ["get_recovery_proc"]])],
899    "enable or disable the recovery process",
900    "\
901 If this is called with the parameter C<false> then
902 C<guestfs_launch> does not create a recovery process.  The
903 purpose of the recovery process is to stop runaway qemu
904 processes in the case where the main program aborts abruptly.
905
906 This only has any effect if called before C<guestfs_launch>,
907 and the default is true.
908
909 About the only time when you would want to disable this is
910 if the main process will fork itself into the background
911 (\"daemonize\" itself).  In this case the recovery process
912 thinks that the main program has disappeared and so kills
913 qemu, which is not very helpful.");
914
915   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
916    [],
917    "get recovery process enabled flag",
918    "\
919 Return the recovery process enabled flag.");
920
921   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
922    [],
923    "add a drive specifying the QEMU block emulation to use",
924    "\
925 This is the same as C<guestfs_add_drive> but it allows you
926 to specify the QEMU interface emulation to use at run time.");
927
928   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
929    [],
930    "add a drive read-only specifying the QEMU block emulation to use",
931    "\
932 This is the same as C<guestfs_add_drive_ro> but it allows you
933 to specify the QEMU interface emulation to use at run time.");
934
935 ]
936
937 (* daemon_functions are any functions which cause some action
938  * to take place in the daemon.
939  *)
940
941 let daemon_functions = [
942   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
943    [InitEmpty, Always, TestOutput (
944       [["part_disk"; "/dev/sda"; "mbr"];
945        ["mkfs"; "ext2"; "/dev/sda1"];
946        ["mount"; "/dev/sda1"; "/"];
947        ["write"; "/new"; "new file contents"];
948        ["cat"; "/new"]], "new file contents")],
949    "mount a guest disk at a position in the filesystem",
950    "\
951 Mount a guest disk at a position in the filesystem.  Block devices
952 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
953 the guest.  If those block devices contain partitions, they will have
954 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
955 names can be used.
956
957 The rules are the same as for L<mount(2)>:  A filesystem must
958 first be mounted on C</> before others can be mounted.  Other
959 filesystems can only be mounted on directories which already
960 exist.
961
962 The mounted filesystem is writable, if we have sufficient permissions
963 on the underlying device.
964
965 B<Important note:>
966 When you use this call, the filesystem options C<sync> and C<noatime>
967 are set implicitly.  This was originally done because we thought it
968 would improve reliability, but it turns out that I<-o sync> has a
969 very large negative performance impact and negligible effect on
970 reliability.  Therefore we recommend that you avoid using
971 C<guestfs_mount> in any code that needs performance, and instead
972 use C<guestfs_mount_options> (use an empty string for the first
973 parameter if you don't want any options).");
974
975   ("sync", (RErr, []), 2, [],
976    [ InitEmpty, Always, TestRun [["sync"]]],
977    "sync disks, writes are flushed through to the disk image",
978    "\
979 This syncs the disk, so that any writes are flushed through to the
980 underlying disk image.
981
982 You should always call this if you have modified a disk image, before
983 closing the handle.");
984
985   ("touch", (RErr, [Pathname "path"]), 3, [],
986    [InitBasicFS, Always, TestOutputTrue (
987       [["touch"; "/new"];
988        ["exists"; "/new"]])],
989    "update file timestamps or create a new file",
990    "\
991 Touch acts like the L<touch(1)> command.  It can be used to
992 update the timestamps on a file, or, if the file does not exist,
993 to create a new zero-length file.
994
995 This command only works on regular files, and will fail on other
996 file types such as directories, symbolic links, block special etc.");
997
998   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
999    [InitISOFS, Always, TestOutput (
1000       [["cat"; "/known-2"]], "abcdef\n")],
1001    "list the contents of a file",
1002    "\
1003 Return the contents of the file named C<path>.
1004
1005 Note that this function cannot correctly handle binary files
1006 (specifically, files containing C<\\0> character which is treated
1007 as end of string).  For those you need to use the C<guestfs_read_file>
1008 or C<guestfs_download> functions which have a more complex interface.");
1009
1010   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1011    [], (* XXX Tricky to test because it depends on the exact format
1012         * of the 'ls -l' command, which changes between F10 and F11.
1013         *)
1014    "list the files in a directory (long format)",
1015    "\
1016 List the files in C<directory> (relative to the root directory,
1017 there is no cwd) in the format of 'ls -la'.
1018
1019 This command is mostly useful for interactive sessions.  It
1020 is I<not> intended that you try to parse the output string.");
1021
1022   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1023    [InitBasicFS, Always, TestOutputList (
1024       [["touch"; "/new"];
1025        ["touch"; "/newer"];
1026        ["touch"; "/newest"];
1027        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1028    "list the files in a directory",
1029    "\
1030 List the files in C<directory> (relative to the root directory,
1031 there is no cwd).  The '.' and '..' entries are not returned, but
1032 hidden files are shown.
1033
1034 This command is mostly useful for interactive sessions.  Programs
1035 should probably use C<guestfs_readdir> instead.");
1036
1037   ("list_devices", (RStringList "devices", []), 7, [],
1038    [InitEmpty, Always, TestOutputListOfDevices (
1039       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1040    "list the block devices",
1041    "\
1042 List all the block devices.
1043
1044 The full block device names are returned, eg. C</dev/sda>");
1045
1046   ("list_partitions", (RStringList "partitions", []), 8, [],
1047    [InitBasicFS, Always, TestOutputListOfDevices (
1048       [["list_partitions"]], ["/dev/sda1"]);
1049     InitEmpty, Always, TestOutputListOfDevices (
1050       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1051        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1052    "list the partitions",
1053    "\
1054 List all the partitions detected on all block devices.
1055
1056 The full partition device names are returned, eg. C</dev/sda1>
1057
1058 This does not return logical volumes.  For that you will need to
1059 call C<guestfs_lvs>.");
1060
1061   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1062    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1063       [["pvs"]], ["/dev/sda1"]);
1064     InitEmpty, Always, TestOutputListOfDevices (
1065       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066        ["pvcreate"; "/dev/sda1"];
1067        ["pvcreate"; "/dev/sda2"];
1068        ["pvcreate"; "/dev/sda3"];
1069        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1070    "list the LVM physical volumes (PVs)",
1071    "\
1072 List all the physical volumes detected.  This is the equivalent
1073 of the L<pvs(8)> command.
1074
1075 This returns a list of just the device names that contain
1076 PVs (eg. C</dev/sda2>).
1077
1078 See also C<guestfs_pvs_full>.");
1079
1080   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1081    [InitBasicFSonLVM, Always, TestOutputList (
1082       [["vgs"]], ["VG"]);
1083     InitEmpty, Always, TestOutputList (
1084       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1085        ["pvcreate"; "/dev/sda1"];
1086        ["pvcreate"; "/dev/sda2"];
1087        ["pvcreate"; "/dev/sda3"];
1088        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1089        ["vgcreate"; "VG2"; "/dev/sda3"];
1090        ["vgs"]], ["VG1"; "VG2"])],
1091    "list the LVM volume groups (VGs)",
1092    "\
1093 List all the volumes groups detected.  This is the equivalent
1094 of the L<vgs(8)> command.
1095
1096 This returns a list of just the volume group names that were
1097 detected (eg. C<VolGroup00>).
1098
1099 See also C<guestfs_vgs_full>.");
1100
1101   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1102    [InitBasicFSonLVM, Always, TestOutputList (
1103       [["lvs"]], ["/dev/VG/LV"]);
1104     InitEmpty, Always, TestOutputList (
1105       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1106        ["pvcreate"; "/dev/sda1"];
1107        ["pvcreate"; "/dev/sda2"];
1108        ["pvcreate"; "/dev/sda3"];
1109        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1110        ["vgcreate"; "VG2"; "/dev/sda3"];
1111        ["lvcreate"; "LV1"; "VG1"; "50"];
1112        ["lvcreate"; "LV2"; "VG1"; "50"];
1113        ["lvcreate"; "LV3"; "VG2"; "50"];
1114        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1115    "list the LVM logical volumes (LVs)",
1116    "\
1117 List all the logical volumes detected.  This is the equivalent
1118 of the L<lvs(8)> command.
1119
1120 This returns a list of the logical volume device names
1121 (eg. C</dev/VolGroup00/LogVol00>).
1122
1123 See also C<guestfs_lvs_full>.");
1124
1125   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM physical volumes (PVs)",
1128    "\
1129 List all the physical volumes detected.  This is the equivalent
1130 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1133    [], (* XXX how to test? *)
1134    "list the LVM volume groups (VGs)",
1135    "\
1136 List all the volumes groups detected.  This is the equivalent
1137 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1138
1139   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1140    [], (* XXX how to test? *)
1141    "list the LVM logical volumes (LVs)",
1142    "\
1143 List all the logical volumes detected.  This is the equivalent
1144 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1145
1146   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1147    [InitISOFS, Always, TestOutputList (
1148       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1149     InitISOFS, Always, TestOutputList (
1150       [["read_lines"; "/empty"]], [])],
1151    "read file as lines",
1152    "\
1153 Return the contents of the file named C<path>.
1154
1155 The file contents are returned as a list of lines.  Trailing
1156 C<LF> and C<CRLF> character sequences are I<not> returned.
1157
1158 Note that this function cannot correctly handle binary files
1159 (specifically, files containing C<\\0> character which is treated
1160 as end of line).  For those you need to use the C<guestfs_read_file>
1161 function which has a more complex interface.");
1162
1163   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1164    [], (* XXX Augeas code needs tests. *)
1165    "create a new Augeas handle",
1166    "\
1167 Create a new Augeas handle for editing configuration files.
1168 If there was any previous Augeas handle associated with this
1169 guestfs session, then it is closed.
1170
1171 You must call this before using any other C<guestfs_aug_*>
1172 commands.
1173
1174 C<root> is the filesystem root.  C<root> must not be NULL,
1175 use C</> instead.
1176
1177 The flags are the same as the flags defined in
1178 E<lt>augeas.hE<gt>, the logical I<or> of the following
1179 integers:
1180
1181 =over 4
1182
1183 =item C<AUG_SAVE_BACKUP> = 1
1184
1185 Keep the original file with a C<.augsave> extension.
1186
1187 =item C<AUG_SAVE_NEWFILE> = 2
1188
1189 Save changes into a file with extension C<.augnew>, and
1190 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1191
1192 =item C<AUG_TYPE_CHECK> = 4
1193
1194 Typecheck lenses (can be expensive).
1195
1196 =item C<AUG_NO_STDINC> = 8
1197
1198 Do not use standard load path for modules.
1199
1200 =item C<AUG_SAVE_NOOP> = 16
1201
1202 Make save a no-op, just record what would have been changed.
1203
1204 =item C<AUG_NO_LOAD> = 32
1205
1206 Do not load the tree in C<guestfs_aug_init>.
1207
1208 =back
1209
1210 To close the handle, you can call C<guestfs_aug_close>.
1211
1212 To find out more about Augeas, see L<http://augeas.net/>.");
1213
1214   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1215    [], (* XXX Augeas code needs tests. *)
1216    "close the current Augeas handle",
1217    "\
1218 Close the current Augeas handle and free up any resources
1219 used by it.  After calling this, you have to call
1220 C<guestfs_aug_init> again before you can use any other
1221 Augeas functions.");
1222
1223   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1224    [], (* XXX Augeas code needs tests. *)
1225    "define an Augeas variable",
1226    "\
1227 Defines an Augeas variable C<name> whose value is the result
1228 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1229 undefined.
1230
1231 On success this returns the number of nodes in C<expr>, or
1232 C<0> if C<expr> evaluates to something which is not a nodeset.");
1233
1234   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1235    [], (* XXX Augeas code needs tests. *)
1236    "define an Augeas node",
1237    "\
1238 Defines a variable C<name> whose value is the result of
1239 evaluating C<expr>.
1240
1241 If C<expr> evaluates to an empty nodeset, a node is created,
1242 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1243 C<name> will be the nodeset containing that single node.
1244
1245 On success this returns a pair containing the
1246 number of nodes in the nodeset, and a boolean flag
1247 if a node was created.");
1248
1249   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1250    [], (* XXX Augeas code needs tests. *)
1251    "look up the value of an Augeas path",
1252    "\
1253 Look up the value associated with C<path>.  If C<path>
1254 matches exactly one node, the C<value> is returned.");
1255
1256   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1257    [], (* XXX Augeas code needs tests. *)
1258    "set Augeas path to value",
1259    "\
1260 Set the value associated with C<path> to C<val>.
1261
1262 In the Augeas API, it is possible to clear a node by setting
1263 the value to NULL.  Due to an oversight in the libguestfs API
1264 you cannot do that with this call.  Instead you must use the
1265 C<guestfs_aug_clear> call.");
1266
1267   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1268    [], (* XXX Augeas code needs tests. *)
1269    "insert a sibling Augeas node",
1270    "\
1271 Create a new sibling C<label> for C<path>, inserting it into
1272 the tree before or after C<path> (depending on the boolean
1273 flag C<before>).
1274
1275 C<path> must match exactly one existing node in the tree, and
1276 C<label> must be a label, ie. not contain C</>, C<*> or end
1277 with a bracketed index C<[N]>.");
1278
1279   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1280    [], (* XXX Augeas code needs tests. *)
1281    "remove an Augeas path",
1282    "\
1283 Remove C<path> and all of its children.
1284
1285 On success this returns the number of entries which were removed.");
1286
1287   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "move Augeas node",
1290    "\
1291 Move the node C<src> to C<dest>.  C<src> must match exactly
1292 one node.  C<dest> is overwritten if it exists.");
1293
1294   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1295    [], (* XXX Augeas code needs tests. *)
1296    "return Augeas nodes which match augpath",
1297    "\
1298 Returns a list of paths which match the path expression C<path>.
1299 The returned paths are sufficiently qualified so that they match
1300 exactly one node in the current tree.");
1301
1302   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1303    [], (* XXX Augeas code needs tests. *)
1304    "write all pending Augeas changes to disk",
1305    "\
1306 This writes all pending changes to disk.
1307
1308 The flags which were passed to C<guestfs_aug_init> affect exactly
1309 how files are saved.");
1310
1311   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1312    [], (* XXX Augeas code needs tests. *)
1313    "load files into the tree",
1314    "\
1315 Load files into the tree.
1316
1317 See C<aug_load> in the Augeas documentation for the full gory
1318 details.");
1319
1320   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1321    [], (* XXX Augeas code needs tests. *)
1322    "list Augeas nodes under augpath",
1323    "\
1324 This is just a shortcut for listing C<guestfs_aug_match>
1325 C<path/*> and sorting the resulting nodes into alphabetical order.");
1326
1327   ("rm", (RErr, [Pathname "path"]), 29, [],
1328    [InitBasicFS, Always, TestRun
1329       [["touch"; "/new"];
1330        ["rm"; "/new"]];
1331     InitBasicFS, Always, TestLastFail
1332       [["rm"; "/new"]];
1333     InitBasicFS, Always, TestLastFail
1334       [["mkdir"; "/new"];
1335        ["rm"; "/new"]]],
1336    "remove a file",
1337    "\
1338 Remove the single file C<path>.");
1339
1340   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1341    [InitBasicFS, Always, TestRun
1342       [["mkdir"; "/new"];
1343        ["rmdir"; "/new"]];
1344     InitBasicFS, Always, TestLastFail
1345       [["rmdir"; "/new"]];
1346     InitBasicFS, Always, TestLastFail
1347       [["touch"; "/new"];
1348        ["rmdir"; "/new"]]],
1349    "remove a directory",
1350    "\
1351 Remove the single directory C<path>.");
1352
1353   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1354    [InitBasicFS, Always, TestOutputFalse
1355       [["mkdir"; "/new"];
1356        ["mkdir"; "/new/foo"];
1357        ["touch"; "/new/foo/bar"];
1358        ["rm_rf"; "/new"];
1359        ["exists"; "/new"]]],
1360    "remove a file or directory recursively",
1361    "\
1362 Remove the file or directory C<path>, recursively removing the
1363 contents if its a directory.  This is like the C<rm -rf> shell
1364 command.");
1365
1366   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1367    [InitBasicFS, Always, TestOutputTrue
1368       [["mkdir"; "/new"];
1369        ["is_dir"; "/new"]];
1370     InitBasicFS, Always, TestLastFail
1371       [["mkdir"; "/new/foo/bar"]]],
1372    "create a directory",
1373    "\
1374 Create a directory named C<path>.");
1375
1376   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1377    [InitBasicFS, Always, TestOutputTrue
1378       [["mkdir_p"; "/new/foo/bar"];
1379        ["is_dir"; "/new/foo/bar"]];
1380     InitBasicFS, Always, TestOutputTrue
1381       [["mkdir_p"; "/new/foo/bar"];
1382        ["is_dir"; "/new/foo"]];
1383     InitBasicFS, Always, TestOutputTrue
1384       [["mkdir_p"; "/new/foo/bar"];
1385        ["is_dir"; "/new"]];
1386     (* Regression tests for RHBZ#503133: *)
1387     InitBasicFS, Always, TestRun
1388       [["mkdir"; "/new"];
1389        ["mkdir_p"; "/new"]];
1390     InitBasicFS, Always, TestLastFail
1391       [["touch"; "/new"];
1392        ["mkdir_p"; "/new"]]],
1393    "create a directory and parents",
1394    "\
1395 Create a directory named C<path>, creating any parent directories
1396 as necessary.  This is like the C<mkdir -p> shell command.");
1397
1398   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1399    [], (* XXX Need stat command to test *)
1400    "change file mode",
1401    "\
1402 Change the mode (permissions) of C<path> to C<mode>.  Only
1403 numeric modes are supported.
1404
1405 I<Note>: When using this command from guestfish, C<mode>
1406 by default would be decimal, unless you prefix it with
1407 C<0> to get octal, ie. use C<0700> not C<700>.
1408
1409 The mode actually set is affected by the umask.");
1410
1411   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1412    [], (* XXX Need stat command to test *)
1413    "change file owner and group",
1414    "\
1415 Change the file owner to C<owner> and group to C<group>.
1416
1417 Only numeric uid and gid are supported.  If you want to use
1418 names, you will need to locate and parse the password file
1419 yourself (Augeas support makes this relatively easy).");
1420
1421   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1422    [InitISOFS, Always, TestOutputTrue (
1423       [["exists"; "/empty"]]);
1424     InitISOFS, Always, TestOutputTrue (
1425       [["exists"; "/directory"]])],
1426    "test if file or directory exists",
1427    "\
1428 This returns C<true> if and only if there is a file, directory
1429 (or anything) with the given C<path> name.
1430
1431 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1432
1433   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1434    [InitISOFS, Always, TestOutputTrue (
1435       [["is_file"; "/known-1"]]);
1436     InitISOFS, Always, TestOutputFalse (
1437       [["is_file"; "/directory"]])],
1438    "test if file exists",
1439    "\
1440 This returns C<true> if and only if there is a file
1441 with the given C<path> name.  Note that it returns false for
1442 other objects like directories.
1443
1444 See also C<guestfs_stat>.");
1445
1446   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1447    [InitISOFS, Always, TestOutputFalse (
1448       [["is_dir"; "/known-3"]]);
1449     InitISOFS, Always, TestOutputTrue (
1450       [["is_dir"; "/directory"]])],
1451    "test if file exists",
1452    "\
1453 This returns C<true> if and only if there is a directory
1454 with the given C<path> name.  Note that it returns false for
1455 other objects like files.
1456
1457 See also C<guestfs_stat>.");
1458
1459   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1460    [InitEmpty, Always, TestOutputListOfDevices (
1461       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1462        ["pvcreate"; "/dev/sda1"];
1463        ["pvcreate"; "/dev/sda2"];
1464        ["pvcreate"; "/dev/sda3"];
1465        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1466    "create an LVM physical volume",
1467    "\
1468 This creates an LVM physical volume on the named C<device>,
1469 where C<device> should usually be a partition name such
1470 as C</dev/sda1>.");
1471
1472   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1473    [InitEmpty, Always, TestOutputList (
1474       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1475        ["pvcreate"; "/dev/sda1"];
1476        ["pvcreate"; "/dev/sda2"];
1477        ["pvcreate"; "/dev/sda3"];
1478        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1479        ["vgcreate"; "VG2"; "/dev/sda3"];
1480        ["vgs"]], ["VG1"; "VG2"])],
1481    "create an LVM volume group",
1482    "\
1483 This creates an LVM volume group called C<volgroup>
1484 from the non-empty list of physical volumes C<physvols>.");
1485
1486   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1487    [InitEmpty, Always, TestOutputList (
1488       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1489        ["pvcreate"; "/dev/sda1"];
1490        ["pvcreate"; "/dev/sda2"];
1491        ["pvcreate"; "/dev/sda3"];
1492        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1493        ["vgcreate"; "VG2"; "/dev/sda3"];
1494        ["lvcreate"; "LV1"; "VG1"; "50"];
1495        ["lvcreate"; "LV2"; "VG1"; "50"];
1496        ["lvcreate"; "LV3"; "VG2"; "50"];
1497        ["lvcreate"; "LV4"; "VG2"; "50"];
1498        ["lvcreate"; "LV5"; "VG2"; "50"];
1499        ["lvs"]],
1500       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1501        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1502    "create an LVM logical volume",
1503    "\
1504 This creates an LVM logical volume called C<logvol>
1505 on the volume group C<volgroup>, with C<size> megabytes.");
1506
1507   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1508    [InitEmpty, Always, TestOutput (
1509       [["part_disk"; "/dev/sda"; "mbr"];
1510        ["mkfs"; "ext2"; "/dev/sda1"];
1511        ["mount_options"; ""; "/dev/sda1"; "/"];
1512        ["write"; "/new"; "new file contents"];
1513        ["cat"; "/new"]], "new file contents")],
1514    "make a filesystem",
1515    "\
1516 This creates a filesystem on C<device> (usually a partition
1517 or LVM logical volume).  The filesystem type is C<fstype>, for
1518 example C<ext3>.");
1519
1520   ("sfdisk", (RErr, [Device "device";
1521                      Int "cyls"; Int "heads"; Int "sectors";
1522                      StringList "lines"]), 43, [DangerWillRobinson],
1523    [],
1524    "create partitions on a block device",
1525    "\
1526 This is a direct interface to the L<sfdisk(8)> program for creating
1527 partitions on block devices.
1528
1529 C<device> should be a block device, for example C</dev/sda>.
1530
1531 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1532 and sectors on the device, which are passed directly to sfdisk as
1533 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1534 of these, then the corresponding parameter is omitted.  Usually for
1535 'large' disks, you can just pass C<0> for these, but for small
1536 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1537 out the right geometry and you will need to tell it.
1538
1539 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1540 information refer to the L<sfdisk(8)> manpage.
1541
1542 To create a single partition occupying the whole disk, you would
1543 pass C<lines> as a single element list, when the single element being
1544 the string C<,> (comma).
1545
1546 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1547 C<guestfs_part_init>");
1548
1549   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1550    (* Regression test for RHBZ#597135. *)
1551    [InitBasicFS, Always, TestLastFail
1552       [["write_file"; "/new"; "abc"; "10000"]]],
1553    "create a file",
1554    "\
1555 This call creates a file called C<path>.  The contents of the
1556 file is the string C<content> (which can contain any 8 bit data),
1557 with length C<size>.
1558
1559 As a special case, if C<size> is C<0>
1560 then the length is calculated using C<strlen> (so in this case
1561 the content cannot contain embedded ASCII NULs).
1562
1563 I<NB.> Owing to a bug, writing content containing ASCII NUL
1564 characters does I<not> work, even if the length is specified.");
1565
1566   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1567    [InitEmpty, Always, TestOutputListOfDevices (
1568       [["part_disk"; "/dev/sda"; "mbr"];
1569        ["mkfs"; "ext2"; "/dev/sda1"];
1570        ["mount_options"; ""; "/dev/sda1"; "/"];
1571        ["mounts"]], ["/dev/sda1"]);
1572     InitEmpty, Always, TestOutputList (
1573       [["part_disk"; "/dev/sda"; "mbr"];
1574        ["mkfs"; "ext2"; "/dev/sda1"];
1575        ["mount_options"; ""; "/dev/sda1"; "/"];
1576        ["umount"; "/"];
1577        ["mounts"]], [])],
1578    "unmount a filesystem",
1579    "\
1580 This unmounts the given filesystem.  The filesystem may be
1581 specified either by its mountpoint (path) or the device which
1582 contains the filesystem.");
1583
1584   ("mounts", (RStringList "devices", []), 46, [],
1585    [InitBasicFS, Always, TestOutputListOfDevices (
1586       [["mounts"]], ["/dev/sda1"])],
1587    "show mounted filesystems",
1588    "\
1589 This returns the list of currently mounted filesystems.  It returns
1590 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1591
1592 Some internal mounts are not shown.
1593
1594 See also: C<guestfs_mountpoints>");
1595
1596   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1597    [InitBasicFS, Always, TestOutputList (
1598       [["umount_all"];
1599        ["mounts"]], []);
1600     (* check that umount_all can unmount nested mounts correctly: *)
1601     InitEmpty, Always, TestOutputList (
1602       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1603        ["mkfs"; "ext2"; "/dev/sda1"];
1604        ["mkfs"; "ext2"; "/dev/sda2"];
1605        ["mkfs"; "ext2"; "/dev/sda3"];
1606        ["mount_options"; ""; "/dev/sda1"; "/"];
1607        ["mkdir"; "/mp1"];
1608        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1609        ["mkdir"; "/mp1/mp2"];
1610        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1611        ["mkdir"; "/mp1/mp2/mp3"];
1612        ["umount_all"];
1613        ["mounts"]], [])],
1614    "unmount all filesystems",
1615    "\
1616 This unmounts all mounted filesystems.
1617
1618 Some internal mounts are not unmounted by this call.");
1619
1620   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1621    [],
1622    "remove all LVM LVs, VGs and PVs",
1623    "\
1624 This command removes all LVM logical volumes, volume groups
1625 and physical volumes.");
1626
1627   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1628    [InitISOFS, Always, TestOutput (
1629       [["file"; "/empty"]], "empty");
1630     InitISOFS, Always, TestOutput (
1631       [["file"; "/known-1"]], "ASCII text");
1632     InitISOFS, Always, TestLastFail (
1633       [["file"; "/notexists"]]);
1634     InitISOFS, Always, TestOutput (
1635       [["file"; "/abssymlink"]], "symbolic link");
1636     InitISOFS, Always, TestOutput (
1637       [["file"; "/directory"]], "directory")],
1638    "determine file type",
1639    "\
1640 This call uses the standard L<file(1)> command to determine
1641 the type or contents of the file.
1642
1643 This call will also transparently look inside various types
1644 of compressed file.
1645
1646 The exact command which runs is C<file -zb path>.  Note in
1647 particular that the filename is not prepended to the output
1648 (the C<-b> option).
1649
1650 This command can also be used on C</dev/> devices
1651 (and partitions, LV names).  You can for example use this
1652 to determine if a device contains a filesystem, although
1653 it's usually better to use C<guestfs_vfs_type>.
1654
1655 If the C<path> does not begin with C</dev/> then
1656 this command only works for the content of regular files.
1657 For other file types (directory, symbolic link etc) it
1658 will just return the string C<directory> etc.");
1659
1660   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1661    [InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 1"]], "Result1");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 2"]], "Result2\n");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 3"]], "\nResult3");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 4"]], "\nResult4\n");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 5"]], "\nResult5\n\n");
1681     InitBasicFS, Always, TestOutput (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1685     InitBasicFS, Always, TestOutput (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command"; "/test-command 7"]], "");
1689     InitBasicFS, Always, TestOutput (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command"; "/test-command 8"]], "\n");
1693     InitBasicFS, Always, TestOutput (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command"; "/test-command 9"]], "\n\n");
1697     InitBasicFS, Always, TestOutput (
1698       [["upload"; "test-command"; "/test-command"];
1699        ["chmod"; "0o755"; "/test-command"];
1700        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1701     InitBasicFS, Always, TestOutput (
1702       [["upload"; "test-command"; "/test-command"];
1703        ["chmod"; "0o755"; "/test-command"];
1704        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1705     InitBasicFS, Always, TestLastFail (
1706       [["upload"; "test-command"; "/test-command"];
1707        ["chmod"; "0o755"; "/test-command"];
1708        ["command"; "/test-command"]])],
1709    "run a command from the guest filesystem",
1710    "\
1711 This call runs a command from the guest filesystem.  The
1712 filesystem must be mounted, and must contain a compatible
1713 operating system (ie. something Linux, with the same
1714 or compatible processor architecture).
1715
1716 The single parameter is an argv-style list of arguments.
1717 The first element is the name of the program to run.
1718 Subsequent elements are parameters.  The list must be
1719 non-empty (ie. must contain a program name).  Note that
1720 the command runs directly, and is I<not> invoked via
1721 the shell (see C<guestfs_sh>).
1722
1723 The return value is anything printed to I<stdout> by
1724 the command.
1725
1726 If the command returns a non-zero exit status, then
1727 this function returns an error message.  The error message
1728 string is the content of I<stderr> from the command.
1729
1730 The C<$PATH> environment variable will contain at least
1731 C</usr/bin> and C</bin>.  If you require a program from
1732 another location, you should provide the full path in the
1733 first parameter.
1734
1735 Shared libraries and data files required by the program
1736 must be available on filesystems which are mounted in the
1737 correct places.  It is the caller's responsibility to ensure
1738 all filesystems that are needed are mounted at the right
1739 locations.");
1740
1741   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1742    [InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 1"]], ["Result1"]);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 2"]], ["Result2"]);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1762     InitBasicFS, Always, TestOutputList (
1763       [["upload"; "test-command"; "/test-command"];
1764        ["chmod"; "0o755"; "/test-command"];
1765        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1766     InitBasicFS, Always, TestOutputList (
1767       [["upload"; "test-command"; "/test-command"];
1768        ["chmod"; "0o755"; "/test-command"];
1769        ["command_lines"; "/test-command 7"]], []);
1770     InitBasicFS, Always, TestOutputList (
1771       [["upload"; "test-command"; "/test-command"];
1772        ["chmod"; "0o755"; "/test-command"];
1773        ["command_lines"; "/test-command 8"]], [""]);
1774     InitBasicFS, Always, TestOutputList (
1775       [["upload"; "test-command"; "/test-command"];
1776        ["chmod"; "0o755"; "/test-command"];
1777        ["command_lines"; "/test-command 9"]], ["";""]);
1778     InitBasicFS, Always, TestOutputList (
1779       [["upload"; "test-command"; "/test-command"];
1780        ["chmod"; "0o755"; "/test-command"];
1781        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1782     InitBasicFS, Always, TestOutputList (
1783       [["upload"; "test-command"; "/test-command"];
1784        ["chmod"; "0o755"; "/test-command"];
1785        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1786    "run a command, returning lines",
1787    "\
1788 This is the same as C<guestfs_command>, but splits the
1789 result into a list of lines.
1790
1791 See also: C<guestfs_sh_lines>");
1792
1793   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1794    [InitISOFS, Always, TestOutputStruct (
1795       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1796    "get file information",
1797    "\
1798 Returns file information for the given C<path>.
1799
1800 This is the same as the C<stat(2)> system call.");
1801
1802   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1803    [InitISOFS, Always, TestOutputStruct (
1804       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1805    "get file information for a symbolic link",
1806    "\
1807 Returns file information for the given C<path>.
1808
1809 This is the same as C<guestfs_stat> except that if C<path>
1810 is a symbolic link, then the link is stat-ed, not the file it
1811 refers to.
1812
1813 This is the same as the C<lstat(2)> system call.");
1814
1815   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1816    [InitISOFS, Always, TestOutputStruct (
1817       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1818    "get file system statistics",
1819    "\
1820 Returns file system statistics for any mounted file system.
1821 C<path> should be a file or directory in the mounted file system
1822 (typically it is the mount point itself, but it doesn't need to be).
1823
1824 This is the same as the C<statvfs(2)> system call.");
1825
1826   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1827    [], (* XXX test *)
1828    "get ext2/ext3/ext4 superblock details",
1829    "\
1830 This returns the contents of the ext2, ext3 or ext4 filesystem
1831 superblock on C<device>.
1832
1833 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1834 manpage for more details.  The list of fields returned isn't
1835 clearly defined, and depends on both the version of C<tune2fs>
1836 that libguestfs was built against, and the filesystem itself.");
1837
1838   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1839    [InitEmpty, Always, TestOutputTrue (
1840       [["blockdev_setro"; "/dev/sda"];
1841        ["blockdev_getro"; "/dev/sda"]])],
1842    "set block device to read-only",
1843    "\
1844 Sets the block device named C<device> to read-only.
1845
1846 This uses the L<blockdev(8)> command.");
1847
1848   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1849    [InitEmpty, Always, TestOutputFalse (
1850       [["blockdev_setrw"; "/dev/sda"];
1851        ["blockdev_getro"; "/dev/sda"]])],
1852    "set block device to read-write",
1853    "\
1854 Sets the block device named C<device> to read-write.
1855
1856 This uses the L<blockdev(8)> command.");
1857
1858   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1859    [InitEmpty, Always, TestOutputTrue (
1860       [["blockdev_setro"; "/dev/sda"];
1861        ["blockdev_getro"; "/dev/sda"]])],
1862    "is block device set to read-only",
1863    "\
1864 Returns a boolean indicating if the block device is read-only
1865 (true if read-only, false if not).
1866
1867 This uses the L<blockdev(8)> command.");
1868
1869   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1870    [InitEmpty, Always, TestOutputInt (
1871       [["blockdev_getss"; "/dev/sda"]], 512)],
1872    "get sectorsize of block device",
1873    "\
1874 This returns the size of sectors on a block device.
1875 Usually 512, but can be larger for modern devices.
1876
1877 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1878 for that).
1879
1880 This uses the L<blockdev(8)> command.");
1881
1882   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1883    [InitEmpty, Always, TestOutputInt (
1884       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1885    "get blocksize of block device",
1886    "\
1887 This returns the block size of a device.
1888
1889 (Note this is different from both I<size in blocks> and
1890 I<filesystem block size>).
1891
1892 This uses the L<blockdev(8)> command.");
1893
1894   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1895    [], (* XXX test *)
1896    "set blocksize of block device",
1897    "\
1898 This sets the block size of a device.
1899
1900 (Note this is different from both I<size in blocks> and
1901 I<filesystem block size>).
1902
1903 This uses the L<blockdev(8)> command.");
1904
1905   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1906    [InitEmpty, Always, TestOutputInt (
1907       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1908    "get total size of device in 512-byte sectors",
1909    "\
1910 This returns the size of the device in units of 512-byte sectors
1911 (even if the sectorsize isn't 512 bytes ... weird).
1912
1913 See also C<guestfs_blockdev_getss> for the real sector size of
1914 the device, and C<guestfs_blockdev_getsize64> for the more
1915 useful I<size in bytes>.
1916
1917 This uses the L<blockdev(8)> command.");
1918
1919   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1920    [InitEmpty, Always, TestOutputInt (
1921       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1922    "get total size of device in bytes",
1923    "\
1924 This returns the size of the device in bytes.
1925
1926 See also C<guestfs_blockdev_getsz>.
1927
1928 This uses the L<blockdev(8)> command.");
1929
1930   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1931    [InitEmpty, Always, TestRun
1932       [["blockdev_flushbufs"; "/dev/sda"]]],
1933    "flush device buffers",
1934    "\
1935 This tells the kernel to flush internal buffers associated
1936 with C<device>.
1937
1938 This uses the L<blockdev(8)> command.");
1939
1940   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1941    [InitEmpty, Always, TestRun
1942       [["blockdev_rereadpt"; "/dev/sda"]]],
1943    "reread partition table",
1944    "\
1945 Reread the partition table on C<device>.
1946
1947 This uses the L<blockdev(8)> command.");
1948
1949   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1950    [InitBasicFS, Always, TestOutput (
1951       (* Pick a file from cwd which isn't likely to change. *)
1952       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1953        ["checksum"; "md5"; "/COPYING.LIB"]],
1954       Digest.to_hex (Digest.file "COPYING.LIB"))],
1955    "upload a file from the local machine",
1956    "\
1957 Upload local file C<filename> to C<remotefilename> on the
1958 filesystem.
1959
1960 C<filename> can also be a named pipe.
1961
1962 See also C<guestfs_download>.");
1963
1964   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1965    [InitBasicFS, Always, TestOutput (
1966       (* Pick a file from cwd which isn't likely to change. *)
1967       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1968        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1969        ["upload"; "testdownload.tmp"; "/upload"];
1970        ["checksum"; "md5"; "/upload"]],
1971       Digest.to_hex (Digest.file "COPYING.LIB"))],
1972    "download a file to the local machine",
1973    "\
1974 Download file C<remotefilename> and save it as C<filename>
1975 on the local machine.
1976
1977 C<filename> can also be a named pipe.
1978
1979 See also C<guestfs_upload>, C<guestfs_cat>.");
1980
1981   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1982    [InitISOFS, Always, TestOutput (
1983       [["checksum"; "crc"; "/known-3"]], "2891671662");
1984     InitISOFS, Always, TestLastFail (
1985       [["checksum"; "crc"; "/notexists"]]);
1986     InitISOFS, Always, TestOutput (
1987       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1988     InitISOFS, Always, TestOutput (
1989       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1990     InitISOFS, Always, TestOutput (
1991       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1992     InitISOFS, Always, TestOutput (
1993       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1994     InitISOFS, Always, TestOutput (
1995       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1996     InitISOFS, Always, TestOutput (
1997       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1998     (* Test for RHBZ#579608, absolute symbolic links. *)
1999     InitISOFS, Always, TestOutput (
2000       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
2001    "compute MD5, SHAx or CRC checksum of file",
2002    "\
2003 This call computes the MD5, SHAx or CRC checksum of the
2004 file named C<path>.
2005
2006 The type of checksum to compute is given by the C<csumtype>
2007 parameter which must have one of the following values:
2008
2009 =over 4
2010
2011 =item C<crc>
2012
2013 Compute the cyclic redundancy check (CRC) specified by POSIX
2014 for the C<cksum> command.
2015
2016 =item C<md5>
2017
2018 Compute the MD5 hash (using the C<md5sum> program).
2019
2020 =item C<sha1>
2021
2022 Compute the SHA1 hash (using the C<sha1sum> program).
2023
2024 =item C<sha224>
2025
2026 Compute the SHA224 hash (using the C<sha224sum> program).
2027
2028 =item C<sha256>
2029
2030 Compute the SHA256 hash (using the C<sha256sum> program).
2031
2032 =item C<sha384>
2033
2034 Compute the SHA384 hash (using the C<sha384sum> program).
2035
2036 =item C<sha512>
2037
2038 Compute the SHA512 hash (using the C<sha512sum> program).
2039
2040 =back
2041
2042 The checksum is returned as a printable string.
2043
2044 To get the checksum for a device, use C<guestfs_checksum_device>.
2045
2046 To get the checksums for many files, use C<guestfs_checksums_out>.");
2047
2048   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2049    [InitBasicFS, Always, TestOutput (
2050       [["tar_in"; "../images/helloworld.tar"; "/"];
2051        ["cat"; "/hello"]], "hello\n")],
2052    "unpack tarfile to directory",
2053    "\
2054 This command uploads and unpacks local file C<tarfile> (an
2055 I<uncompressed> tar file) into C<directory>.
2056
2057 To upload a compressed tarball, use C<guestfs_tgz_in>
2058 or C<guestfs_txz_in>.");
2059
2060   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2061    [],
2062    "pack directory into tarfile",
2063    "\
2064 This command packs the contents of C<directory> and downloads
2065 it to local file C<tarfile>.
2066
2067 To download a compressed tarball, use C<guestfs_tgz_out>
2068 or C<guestfs_txz_out>.");
2069
2070   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2071    [InitBasicFS, Always, TestOutput (
2072       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2073        ["cat"; "/hello"]], "hello\n")],
2074    "unpack compressed tarball to directory",
2075    "\
2076 This command uploads and unpacks local file C<tarball> (a
2077 I<gzip compressed> tar file) into C<directory>.
2078
2079 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2080
2081   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2082    [],
2083    "pack directory into compressed tarball",
2084    "\
2085 This command packs the contents of C<directory> and downloads
2086 it to local file C<tarball>.
2087
2088 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2089
2090   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2091    [InitBasicFS, Always, TestLastFail (
2092       [["umount"; "/"];
2093        ["mount_ro"; "/dev/sda1"; "/"];
2094        ["touch"; "/new"]]);
2095     InitBasicFS, Always, TestOutput (
2096       [["write"; "/new"; "data"];
2097        ["umount"; "/"];
2098        ["mount_ro"; "/dev/sda1"; "/"];
2099        ["cat"; "/new"]], "data")],
2100    "mount a guest disk, read-only",
2101    "\
2102 This is the same as the C<guestfs_mount> command, but it
2103 mounts the filesystem with the read-only (I<-o ro>) flag.");
2104
2105   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2106    [],
2107    "mount a guest disk with mount options",
2108    "\
2109 This is the same as the C<guestfs_mount> command, but it
2110 allows you to set the mount options as for the
2111 L<mount(8)> I<-o> flag.
2112
2113 If the C<options> parameter is an empty string, then
2114 no options are passed (all options default to whatever
2115 the filesystem uses).");
2116
2117   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2118    [],
2119    "mount a guest disk with mount options and vfstype",
2120    "\
2121 This is the same as the C<guestfs_mount> command, but it
2122 allows you to set both the mount options and the vfstype
2123 as for the L<mount(8)> I<-o> and I<-t> flags.");
2124
2125   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2126    [],
2127    "debugging and internals",
2128    "\
2129 The C<guestfs_debug> command exposes some internals of
2130 C<guestfsd> (the guestfs daemon) that runs inside the
2131 qemu subprocess.
2132
2133 There is no comprehensive help for this command.  You have
2134 to look at the file C<daemon/debug.c> in the libguestfs source
2135 to find out what you can do.");
2136
2137   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2138    [InitEmpty, Always, TestOutputList (
2139       [["part_disk"; "/dev/sda"; "mbr"];
2140        ["pvcreate"; "/dev/sda1"];
2141        ["vgcreate"; "VG"; "/dev/sda1"];
2142        ["lvcreate"; "LV1"; "VG"; "50"];
2143        ["lvcreate"; "LV2"; "VG"; "50"];
2144        ["lvremove"; "/dev/VG/LV1"];
2145        ["lvs"]], ["/dev/VG/LV2"]);
2146     InitEmpty, Always, TestOutputList (
2147       [["part_disk"; "/dev/sda"; "mbr"];
2148        ["pvcreate"; "/dev/sda1"];
2149        ["vgcreate"; "VG"; "/dev/sda1"];
2150        ["lvcreate"; "LV1"; "VG"; "50"];
2151        ["lvcreate"; "LV2"; "VG"; "50"];
2152        ["lvremove"; "/dev/VG"];
2153        ["lvs"]], []);
2154     InitEmpty, Always, TestOutputList (
2155       [["part_disk"; "/dev/sda"; "mbr"];
2156        ["pvcreate"; "/dev/sda1"];
2157        ["vgcreate"; "VG"; "/dev/sda1"];
2158        ["lvcreate"; "LV1"; "VG"; "50"];
2159        ["lvcreate"; "LV2"; "VG"; "50"];
2160        ["lvremove"; "/dev/VG"];
2161        ["vgs"]], ["VG"])],
2162    "remove an LVM logical volume",
2163    "\
2164 Remove an LVM logical volume C<device>, where C<device> is
2165 the path to the LV, such as C</dev/VG/LV>.
2166
2167 You can also remove all LVs in a volume group by specifying
2168 the VG name, C</dev/VG>.");
2169
2170   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2171    [InitEmpty, Always, TestOutputList (
2172       [["part_disk"; "/dev/sda"; "mbr"];
2173        ["pvcreate"; "/dev/sda1"];
2174        ["vgcreate"; "VG"; "/dev/sda1"];
2175        ["lvcreate"; "LV1"; "VG"; "50"];
2176        ["lvcreate"; "LV2"; "VG"; "50"];
2177        ["vgremove"; "VG"];
2178        ["lvs"]], []);
2179     InitEmpty, Always, TestOutputList (
2180       [["part_disk"; "/dev/sda"; "mbr"];
2181        ["pvcreate"; "/dev/sda1"];
2182        ["vgcreate"; "VG"; "/dev/sda1"];
2183        ["lvcreate"; "LV1"; "VG"; "50"];
2184        ["lvcreate"; "LV2"; "VG"; "50"];
2185        ["vgremove"; "VG"];
2186        ["vgs"]], [])],
2187    "remove an LVM volume group",
2188    "\
2189 Remove an LVM volume group C<vgname>, (for example C<VG>).
2190
2191 This also forcibly removes all logical volumes in the volume
2192 group (if any).");
2193
2194   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2195    [InitEmpty, Always, TestOutputListOfDevices (
2196       [["part_disk"; "/dev/sda"; "mbr"];
2197        ["pvcreate"; "/dev/sda1"];
2198        ["vgcreate"; "VG"; "/dev/sda1"];
2199        ["lvcreate"; "LV1"; "VG"; "50"];
2200        ["lvcreate"; "LV2"; "VG"; "50"];
2201        ["vgremove"; "VG"];
2202        ["pvremove"; "/dev/sda1"];
2203        ["lvs"]], []);
2204     InitEmpty, Always, TestOutputListOfDevices (
2205       [["part_disk"; "/dev/sda"; "mbr"];
2206        ["pvcreate"; "/dev/sda1"];
2207        ["vgcreate"; "VG"; "/dev/sda1"];
2208        ["lvcreate"; "LV1"; "VG"; "50"];
2209        ["lvcreate"; "LV2"; "VG"; "50"];
2210        ["vgremove"; "VG"];
2211        ["pvremove"; "/dev/sda1"];
2212        ["vgs"]], []);
2213     InitEmpty, Always, TestOutputListOfDevices (
2214       [["part_disk"; "/dev/sda"; "mbr"];
2215        ["pvcreate"; "/dev/sda1"];
2216        ["vgcreate"; "VG"; "/dev/sda1"];
2217        ["lvcreate"; "LV1"; "VG"; "50"];
2218        ["lvcreate"; "LV2"; "VG"; "50"];
2219        ["vgremove"; "VG"];
2220        ["pvremove"; "/dev/sda1"];
2221        ["pvs"]], [])],
2222    "remove an LVM physical volume",
2223    "\
2224 This wipes a physical volume C<device> so that LVM will no longer
2225 recognise it.
2226
2227 The implementation uses the C<pvremove> command which refuses to
2228 wipe physical volumes that contain any volume groups, so you have
2229 to remove those first.");
2230
2231   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2232    [InitBasicFS, Always, TestOutput (
2233       [["set_e2label"; "/dev/sda1"; "testlabel"];
2234        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2235    "set the ext2/3/4 filesystem label",
2236    "\
2237 This sets the ext2/3/4 filesystem label of the filesystem on
2238 C<device> to C<label>.  Filesystem labels are limited to
2239 16 characters.
2240
2241 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2242 to return the existing label on a filesystem.");
2243
2244   ("get_e2label", (RString "label", [Device "device"]), 81, [DeprecatedBy "vfs_label"],
2245    [],
2246    "get the ext2/3/4 filesystem label",
2247    "\
2248 This returns the ext2/3/4 filesystem label of the filesystem on
2249 C<device>.");
2250
2251   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2252    (let uuid = uuidgen () in
2253     [InitBasicFS, Always, TestOutput (
2254        [["set_e2uuid"; "/dev/sda1"; uuid];
2255         ["get_e2uuid"; "/dev/sda1"]], uuid);
2256      InitBasicFS, Always, TestOutput (
2257        [["set_e2uuid"; "/dev/sda1"; "clear"];
2258         ["get_e2uuid"; "/dev/sda1"]], "");
2259      (* We can't predict what UUIDs will be, so just check the commands run. *)
2260      InitBasicFS, Always, TestRun (
2261        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2262      InitBasicFS, Always, TestRun (
2263        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2264    "set the ext2/3/4 filesystem UUID",
2265    "\
2266 This sets the ext2/3/4 filesystem UUID of the filesystem on
2267 C<device> to C<uuid>.  The format of the UUID and alternatives
2268 such as C<clear>, C<random> and C<time> are described in the
2269 L<tune2fs(8)> manpage.
2270
2271 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2272 to return the existing UUID of a filesystem.");
2273
2274   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [DeprecatedBy "vfs_uuid"],
2275    (* Regression test for RHBZ#597112. *)
2276    (let uuid = uuidgen () in
2277     [InitBasicFS, Always, TestOutput (
2278        [["mke2journal"; "1024"; "/dev/sdb"];
2279         ["set_e2uuid"; "/dev/sdb"; uuid];
2280         ["get_e2uuid"; "/dev/sdb"]], uuid)]),
2281    "get the ext2/3/4 filesystem UUID",
2282    "\
2283 This returns the ext2/3/4 filesystem UUID of the filesystem on
2284 C<device>.");
2285
2286   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2287    [InitBasicFS, Always, TestOutputInt (
2288       [["umount"; "/dev/sda1"];
2289        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2290     InitBasicFS, Always, TestOutputInt (
2291       [["umount"; "/dev/sda1"];
2292        ["zero"; "/dev/sda1"];
2293        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2294    "run the filesystem checker",
2295    "\
2296 This runs the filesystem checker (fsck) on C<device> which
2297 should have filesystem type C<fstype>.
2298
2299 The returned integer is the status.  See L<fsck(8)> for the
2300 list of status codes from C<fsck>.
2301
2302 Notes:
2303
2304 =over 4
2305
2306 =item *
2307
2308 Multiple status codes can be summed together.
2309
2310 =item *
2311
2312 A non-zero return code can mean \"success\", for example if
2313 errors have been corrected on the filesystem.
2314
2315 =item *
2316
2317 Checking or repairing NTFS volumes is not supported
2318 (by linux-ntfs).
2319
2320 =back
2321
2322 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2323
2324   ("zero", (RErr, [Device "device"]), 85, [],
2325    [InitBasicFS, Always, TestOutput (
2326       [["umount"; "/dev/sda1"];
2327        ["zero"; "/dev/sda1"];
2328        ["file"; "/dev/sda1"]], "data")],
2329    "write zeroes to the device",
2330    "\
2331 This command writes zeroes over the first few blocks of C<device>.
2332
2333 How many blocks are zeroed isn't specified (but it's I<not> enough
2334 to securely wipe the device).  It should be sufficient to remove
2335 any partition tables, filesystem superblocks and so on.
2336
2337 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2338
2339   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2340    (* See:
2341     * https://bugzilla.redhat.com/show_bug.cgi?id=484986
2342     * https://bugzilla.redhat.com/show_bug.cgi?id=479760
2343     *)
2344    [InitBasicFS, Always, TestOutputTrue (
2345       [["mkdir_p"; "/boot/grub"];
2346        ["write"; "/boot/grub/device.map"; "(hd0) /dev/vda"];
2347        ["grub_install"; "/"; "/dev/vda"];
2348        ["is_dir"; "/boot"]])],
2349    "install GRUB",
2350    "\
2351 This command installs GRUB (the Grand Unified Bootloader) on
2352 C<device>, with the root directory being C<root>.
2353
2354 Note: If grub-install reports the error
2355 \"No suitable drive was found in the generated device map.\"
2356 it may be that you need to create a C</boot/grub/device.map>
2357 file first that contains the mapping between grub device names
2358 and Linux device names.  It is usually sufficient to create
2359 a file containing:
2360
2361  (hd0) /dev/vda
2362
2363 replacing C</dev/vda> with the name of the installation device.");
2364
2365   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2366    [InitBasicFS, Always, TestOutput (
2367       [["write"; "/old"; "file content"];
2368        ["cp"; "/old"; "/new"];
2369        ["cat"; "/new"]], "file content");
2370     InitBasicFS, Always, TestOutputTrue (
2371       [["write"; "/old"; "file content"];
2372        ["cp"; "/old"; "/new"];
2373        ["is_file"; "/old"]]);
2374     InitBasicFS, Always, TestOutput (
2375       [["write"; "/old"; "file content"];
2376        ["mkdir"; "/dir"];
2377        ["cp"; "/old"; "/dir/new"];
2378        ["cat"; "/dir/new"]], "file content")],
2379    "copy a file",
2380    "\
2381 This copies a file from C<src> to C<dest> where C<dest> is
2382 either a destination filename or destination directory.");
2383
2384   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2385    [InitBasicFS, Always, TestOutput (
2386       [["mkdir"; "/olddir"];
2387        ["mkdir"; "/newdir"];
2388        ["write"; "/olddir/file"; "file content"];
2389        ["cp_a"; "/olddir"; "/newdir"];
2390        ["cat"; "/newdir/olddir/file"]], "file content")],
2391    "copy a file or directory recursively",
2392    "\
2393 This copies a file or directory from C<src> to C<dest>
2394 recursively using the C<cp -a> command.");
2395
2396   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2397    [InitBasicFS, Always, TestOutput (
2398       [["write"; "/old"; "file content"];
2399        ["mv"; "/old"; "/new"];
2400        ["cat"; "/new"]], "file content");
2401     InitBasicFS, Always, TestOutputFalse (
2402       [["write"; "/old"; "file content"];
2403        ["mv"; "/old"; "/new"];
2404        ["is_file"; "/old"]])],
2405    "move a file",
2406    "\
2407 This moves a file from C<src> to C<dest> where C<dest> is
2408 either a destination filename or destination directory.");
2409
2410   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2411    [InitEmpty, Always, TestRun (
2412       [["drop_caches"; "3"]])],
2413    "drop kernel page cache, dentries and inodes",
2414    "\
2415 This instructs the guest kernel to drop its page cache,
2416 and/or dentries and inode caches.  The parameter C<whattodrop>
2417 tells the kernel what precisely to drop, see
2418 L<http://linux-mm.org/Drop_Caches>
2419
2420 Setting C<whattodrop> to 3 should drop everything.
2421
2422 This automatically calls L<sync(2)> before the operation,
2423 so that the maximum guest memory is freed.");
2424
2425   ("dmesg", (RString "kmsgs", []), 91, [],
2426    [InitEmpty, Always, TestRun (
2427       [["dmesg"]])],
2428    "return kernel messages",
2429    "\
2430 This returns the kernel messages (C<dmesg> output) from
2431 the guest kernel.  This is sometimes useful for extended
2432 debugging of problems.
2433
2434 Another way to get the same information is to enable
2435 verbose messages with C<guestfs_set_verbose> or by setting
2436 the environment variable C<LIBGUESTFS_DEBUG=1> before
2437 running the program.");
2438
2439   ("ping_daemon", (RErr, []), 92, [],
2440    [InitEmpty, Always, TestRun (
2441       [["ping_daemon"]])],
2442    "ping the guest daemon",
2443    "\
2444 This is a test probe into the guestfs daemon running inside
2445 the qemu subprocess.  Calling this function checks that the
2446 daemon responds to the ping message, without affecting the daemon
2447 or attached block device(s) in any other way.");
2448
2449   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2450    [InitBasicFS, Always, TestOutputTrue (
2451       [["write"; "/file1"; "contents of a file"];
2452        ["cp"; "/file1"; "/file2"];
2453        ["equal"; "/file1"; "/file2"]]);
2454     InitBasicFS, Always, TestOutputFalse (
2455       [["write"; "/file1"; "contents of a file"];
2456        ["write"; "/file2"; "contents of another file"];
2457        ["equal"; "/file1"; "/file2"]]);
2458     InitBasicFS, Always, TestLastFail (
2459       [["equal"; "/file1"; "/file2"]])],
2460    "test if two files have equal contents",
2461    "\
2462 This compares the two files C<file1> and C<file2> and returns
2463 true if their content is exactly equal, or false otherwise.
2464
2465 The external L<cmp(1)> program is used for the comparison.");
2466
2467   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2468    [InitISOFS, Always, TestOutputList (
2469       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2470     InitISOFS, Always, TestOutputList (
2471       [["strings"; "/empty"]], []);
2472     (* Test for RHBZ#579608, absolute symbolic links. *)
2473     InitISOFS, Always, TestRun (
2474       [["strings"; "/abssymlink"]])],
2475    "print the printable strings in a file",
2476    "\
2477 This runs the L<strings(1)> command on a file and returns
2478 the list of printable strings found.");
2479
2480   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2481    [InitISOFS, Always, TestOutputList (
2482       [["strings_e"; "b"; "/known-5"]], []);
2483     InitBasicFS, Always, TestOutputList (
2484       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2485        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2486    "print the printable strings in a file",
2487    "\
2488 This is like the C<guestfs_strings> command, but allows you to
2489 specify the encoding of strings that are looked for in
2490 the source file C<path>.
2491
2492 Allowed encodings are:
2493
2494 =over 4
2495
2496 =item s
2497
2498 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2499 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2500
2501 =item S
2502
2503 Single 8-bit-byte characters.
2504
2505 =item b
2506
2507 16-bit big endian strings such as those encoded in
2508 UTF-16BE or UCS-2BE.
2509
2510 =item l (lower case letter L)
2511
2512 16-bit little endian such as UTF-16LE and UCS-2LE.
2513 This is useful for examining binaries in Windows guests.
2514
2515 =item B
2516
2517 32-bit big endian such as UCS-4BE.
2518
2519 =item L
2520
2521 32-bit little endian such as UCS-4LE.
2522
2523 =back
2524
2525 The returned strings are transcoded to UTF-8.");
2526
2527   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2528    [InitISOFS, Always, TestOutput (
2529       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2530     (* Test for RHBZ#501888c2 regression which caused large hexdump
2531      * commands to segfault.
2532      *)
2533     InitISOFS, Always, TestRun (
2534       [["hexdump"; "/100krandom"]]);
2535     (* Test for RHBZ#579608, absolute symbolic links. *)
2536     InitISOFS, Always, TestRun (
2537       [["hexdump"; "/abssymlink"]])],
2538    "dump a file in hexadecimal",
2539    "\
2540 This runs C<hexdump -C> on the given C<path>.  The result is
2541 the human-readable, canonical hex dump of the file.");
2542
2543   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2544    [InitNone, Always, TestOutput (
2545       [["part_disk"; "/dev/sda"; "mbr"];
2546        ["mkfs"; "ext3"; "/dev/sda1"];
2547        ["mount_options"; ""; "/dev/sda1"; "/"];
2548        ["write"; "/new"; "test file"];
2549        ["umount"; "/dev/sda1"];
2550        ["zerofree"; "/dev/sda1"];
2551        ["mount_options"; ""; "/dev/sda1"; "/"];
2552        ["cat"; "/new"]], "test file")],
2553    "zero unused inodes and disk blocks on ext2/3 filesystem",
2554    "\
2555 This runs the I<zerofree> program on C<device>.  This program
2556 claims to zero unused inodes and disk blocks on an ext2/3
2557 filesystem, thus making it possible to compress the filesystem
2558 more effectively.
2559
2560 You should B<not> run this program if the filesystem is
2561 mounted.
2562
2563 It is possible that using this program can damage the filesystem
2564 or data on the filesystem.");
2565
2566   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2567    [],
2568    "resize an LVM physical volume",
2569    "\
2570 This resizes (expands or shrinks) an existing LVM physical
2571 volume to match the new size of the underlying device.");
2572
2573   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2574                        Int "cyls"; Int "heads"; Int "sectors";
2575                        String "line"]), 99, [DangerWillRobinson],
2576    [],
2577    "modify a single partition on a block device",
2578    "\
2579 This runs L<sfdisk(8)> option to modify just the single
2580 partition C<n> (note: C<n> counts from 1).
2581
2582 For other parameters, see C<guestfs_sfdisk>.  You should usually
2583 pass C<0> for the cyls/heads/sectors parameters.
2584
2585 See also: C<guestfs_part_add>");
2586
2587   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2588    [],
2589    "display the partition table",
2590    "\
2591 This displays the partition table on C<device>, in the
2592 human-readable output of the L<sfdisk(8)> command.  It is
2593 not intended to be parsed.
2594
2595 See also: C<guestfs_part_list>");
2596
2597   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2598    [],
2599    "display the kernel geometry",
2600    "\
2601 This displays the kernel's idea of the geometry of C<device>.
2602
2603 The result is in human-readable format, and not designed to
2604 be parsed.");
2605
2606   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2607    [],
2608    "display the disk geometry from the partition table",
2609    "\
2610 This displays the disk geometry of C<device> read from the
2611 partition table.  Especially in the case where the underlying
2612 block device has been resized, this can be different from the
2613 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2614
2615 The result is in human-readable format, and not designed to
2616 be parsed.");
2617
2618   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2619    [],
2620    "activate or deactivate all volume groups",
2621    "\
2622 This command activates or (if C<activate> is false) deactivates
2623 all logical volumes in all volume groups.
2624 If activated, then they are made known to the
2625 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2626 then those devices disappear.
2627
2628 This command is the same as running C<vgchange -a y|n>");
2629
2630   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2631    [],
2632    "activate or deactivate some volume groups",
2633    "\
2634 This command activates or (if C<activate> is false) deactivates
2635 all logical volumes in the listed volume groups C<volgroups>.
2636 If activated, then they are made known to the
2637 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2638 then those devices disappear.
2639
2640 This command is the same as running C<vgchange -a y|n volgroups...>
2641
2642 Note that if C<volgroups> is an empty list then B<all> volume groups
2643 are activated or deactivated.");
2644
2645   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2646    [InitNone, Always, TestOutput (
2647       [["part_disk"; "/dev/sda"; "mbr"];
2648        ["pvcreate"; "/dev/sda1"];
2649        ["vgcreate"; "VG"; "/dev/sda1"];
2650        ["lvcreate"; "LV"; "VG"; "10"];
2651        ["mkfs"; "ext2"; "/dev/VG/LV"];
2652        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2653        ["write"; "/new"; "test content"];
2654        ["umount"; "/"];
2655        ["lvresize"; "/dev/VG/LV"; "20"];
2656        ["e2fsck_f"; "/dev/VG/LV"];
2657        ["resize2fs"; "/dev/VG/LV"];
2658        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2659        ["cat"; "/new"]], "test content");
2660     InitNone, Always, TestRun (
2661       (* Make an LV smaller to test RHBZ#587484. *)
2662       [["part_disk"; "/dev/sda"; "mbr"];
2663        ["pvcreate"; "/dev/sda1"];
2664        ["vgcreate"; "VG"; "/dev/sda1"];
2665        ["lvcreate"; "LV"; "VG"; "20"];
2666        ["lvresize"; "/dev/VG/LV"; "10"]])],
2667    "resize an LVM logical volume",
2668    "\
2669 This resizes (expands or shrinks) an existing LVM logical
2670 volume to C<mbytes>.  When reducing, data in the reduced part
2671 is lost.");
2672
2673   ("resize2fs", (RErr, [Device "device"]), 106, [],
2674    [], (* lvresize tests this *)
2675    "resize an ext2, ext3 or ext4 filesystem",
2676    "\
2677 This resizes an ext2, ext3 or ext4 filesystem to match the size of
2678 the underlying device.
2679
2680 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2681 on the C<device> before calling this command.  For unknown reasons
2682 C<resize2fs> sometimes gives an error about this and sometimes not.
2683 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2684 calling this function.");
2685
2686   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2687    [InitBasicFS, Always, TestOutputList (
2688       [["find"; "/"]], ["lost+found"]);
2689     InitBasicFS, Always, TestOutputList (
2690       [["touch"; "/a"];
2691        ["mkdir"; "/b"];
2692        ["touch"; "/b/c"];
2693        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2694     InitBasicFS, Always, TestOutputList (
2695       [["mkdir_p"; "/a/b/c"];
2696        ["touch"; "/a/b/c/d"];
2697        ["find"; "/a/b/"]], ["c"; "c/d"])],
2698    "find all files and directories",
2699    "\
2700 This command lists out all files and directories, recursively,
2701 starting at C<directory>.  It is essentially equivalent to
2702 running the shell command C<find directory -print> but some
2703 post-processing happens on the output, described below.
2704
2705 This returns a list of strings I<without any prefix>.  Thus
2706 if the directory structure was:
2707
2708  /tmp/a
2709  /tmp/b
2710  /tmp/c/d
2711
2712 then the returned list from C<guestfs_find> C</tmp> would be
2713 4 elements:
2714
2715  a
2716  b
2717  c
2718  c/d
2719
2720 If C<directory> is not a directory, then this command returns
2721 an error.
2722
2723 The returned list is sorted.
2724
2725 See also C<guestfs_find0>.");
2726
2727   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2728    [], (* lvresize tests this *)
2729    "check an ext2/ext3 filesystem",
2730    "\
2731 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2732 filesystem checker on C<device>, noninteractively (C<-p>),
2733 even if the filesystem appears to be clean (C<-f>).
2734
2735 This command is only needed because of C<guestfs_resize2fs>
2736 (q.v.).  Normally you should use C<guestfs_fsck>.");
2737
2738   ("sleep", (RErr, [Int "secs"]), 109, [],
2739    [InitNone, Always, TestRun (
2740       [["sleep"; "1"]])],
2741    "sleep for some seconds",
2742    "\
2743 Sleep for C<secs> seconds.");
2744
2745   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2746    [InitNone, Always, TestOutputInt (
2747       [["part_disk"; "/dev/sda"; "mbr"];
2748        ["mkfs"; "ntfs"; "/dev/sda1"];
2749        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2750     InitNone, Always, TestOutputInt (
2751       [["part_disk"; "/dev/sda"; "mbr"];
2752        ["mkfs"; "ext2"; "/dev/sda1"];
2753        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2754    "probe NTFS volume",
2755    "\
2756 This command runs the L<ntfs-3g.probe(8)> command which probes
2757 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2758 be mounted read-write, and some cannot be mounted at all).
2759
2760 C<rw> is a boolean flag.  Set it to true if you want to test
2761 if the volume can be mounted read-write.  Set it to false if
2762 you want to test if the volume can be mounted read-only.
2763
2764 The return value is an integer which C<0> if the operation
2765 would succeed, or some non-zero value documented in the
2766 L<ntfs-3g.probe(8)> manual page.");
2767
2768   ("sh", (RString "output", [String "command"]), 111, [],
2769    [], (* XXX needs tests *)
2770    "run a command via the shell",
2771    "\
2772 This call runs a command from the guest filesystem via the
2773 guest's C</bin/sh>.
2774
2775 This is like C<guestfs_command>, but passes the command to:
2776
2777  /bin/sh -c \"command\"
2778
2779 Depending on the guest's shell, this usually results in
2780 wildcards being expanded, shell expressions being interpolated
2781 and so on.
2782
2783 All the provisos about C<guestfs_command> apply to this call.");
2784
2785   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2786    [], (* XXX needs tests *)
2787    "run a command via the shell returning lines",
2788    "\
2789 This is the same as C<guestfs_sh>, but splits the result
2790 into a list of lines.
2791
2792 See also: C<guestfs_command_lines>");
2793
2794   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2795    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2796     * code in stubs.c, since all valid glob patterns must start with "/".
2797     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2798     *)
2799    [InitBasicFS, Always, TestOutputList (
2800       [["mkdir_p"; "/a/b/c"];
2801        ["touch"; "/a/b/c/d"];
2802        ["touch"; "/a/b/c/e"];
2803        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2804     InitBasicFS, Always, TestOutputList (
2805       [["mkdir_p"; "/a/b/c"];
2806        ["touch"; "/a/b/c/d"];
2807        ["touch"; "/a/b/c/e"];
2808        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2809     InitBasicFS, Always, TestOutputList (
2810       [["mkdir_p"; "/a/b/c"];
2811        ["touch"; "/a/b/c/d"];
2812        ["touch"; "/a/b/c/e"];
2813        ["glob_expand"; "/a/*/x/*"]], [])],
2814    "expand a wildcard path",
2815    "\
2816 This command searches for all the pathnames matching
2817 C<pattern> according to the wildcard expansion rules
2818 used by the shell.
2819
2820 If no paths match, then this returns an empty list
2821 (note: not an error).
2822
2823 It is just a wrapper around the C L<glob(3)> function
2824 with flags C<GLOB_MARK|GLOB_BRACE>.
2825 See that manual page for more details.");
2826
2827   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2828    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2829       [["scrub_device"; "/dev/sdc"]])],
2830    "scrub (securely wipe) a device",
2831    "\
2832 This command writes patterns over C<device> to make data retrieval
2833 more difficult.
2834
2835 It is an interface to the L<scrub(1)> program.  See that
2836 manual page for more details.");
2837
2838   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2839    [InitBasicFS, Always, TestRun (
2840       [["write"; "/file"; "content"];
2841        ["scrub_file"; "/file"]])],
2842    "scrub (securely wipe) a file",
2843    "\
2844 This command writes patterns over a file to make data retrieval
2845 more difficult.
2846
2847 The file is I<removed> after scrubbing.
2848
2849 It is an interface to the L<scrub(1)> program.  See that
2850 manual page for more details.");
2851
2852   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2853    [], (* XXX needs testing *)
2854    "scrub (securely wipe) free space",
2855    "\
2856 This command creates the directory C<dir> and then fills it
2857 with files until the filesystem is full, and scrubs the files
2858 as for C<guestfs_scrub_file>, and deletes them.
2859 The intention is to scrub any free space on the partition
2860 containing C<dir>.
2861
2862 It is an interface to the L<scrub(1)> program.  See that
2863 manual page for more details.");
2864
2865   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2866    [InitBasicFS, Always, TestRun (
2867       [["mkdir"; "/tmp"];
2868        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2869    "create a temporary directory",
2870    "\
2871 This command creates a temporary directory.  The
2872 C<template> parameter should be a full pathname for the
2873 temporary directory name with the final six characters being
2874 \"XXXXXX\".
2875
2876 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2877 the second one being suitable for Windows filesystems.
2878
2879 The name of the temporary directory that was created
2880 is returned.
2881
2882 The temporary directory is created with mode 0700
2883 and is owned by root.
2884
2885 The caller is responsible for deleting the temporary
2886 directory and its contents after use.
2887
2888 See also: L<mkdtemp(3)>");
2889
2890   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2891    [InitISOFS, Always, TestOutputInt (
2892       [["wc_l"; "/10klines"]], 10000);
2893     (* Test for RHBZ#579608, absolute symbolic links. *)
2894     InitISOFS, Always, TestOutputInt (
2895       [["wc_l"; "/abssymlink"]], 10000)],
2896    "count lines in a file",
2897    "\
2898 This command counts the lines in a file, using the
2899 C<wc -l> external command.");
2900
2901   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2902    [InitISOFS, Always, TestOutputInt (
2903       [["wc_w"; "/10klines"]], 10000)],
2904    "count words in a file",
2905    "\
2906 This command counts the words in a file, using the
2907 C<wc -w> external command.");
2908
2909   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2910    [InitISOFS, Always, TestOutputInt (
2911       [["wc_c"; "/100kallspaces"]], 102400)],
2912    "count characters in a file",
2913    "\
2914 This command counts the characters in a file, using the
2915 C<wc -c> external command.");
2916
2917   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2918    [InitISOFS, Always, TestOutputList (
2919       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2920     (* Test for RHBZ#579608, absolute symbolic links. *)
2921     InitISOFS, Always, TestOutputList (
2922       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2923    "return first 10 lines of a file",
2924    "\
2925 This command returns up to the first 10 lines of a file as
2926 a list of strings.");
2927
2928   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2929    [InitISOFS, Always, TestOutputList (
2930       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2931     InitISOFS, Always, TestOutputList (
2932       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2933     InitISOFS, Always, TestOutputList (
2934       [["head_n"; "0"; "/10klines"]], [])],
2935    "return first N lines of a file",
2936    "\
2937 If the parameter C<nrlines> is a positive number, this returns the first
2938 C<nrlines> lines of the file C<path>.
2939
2940 If the parameter C<nrlines> is a negative number, this returns lines
2941 from the file C<path>, excluding the last C<nrlines> lines.
2942
2943 If the parameter C<nrlines> is zero, this returns an empty list.");
2944
2945   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2946    [InitISOFS, Always, TestOutputList (
2947       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2948    "return last 10 lines of a file",
2949    "\
2950 This command returns up to the last 10 lines of a file as
2951 a list of strings.");
2952
2953   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2954    [InitISOFS, Always, TestOutputList (
2955       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2956     InitISOFS, Always, TestOutputList (
2957       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2958     InitISOFS, Always, TestOutputList (
2959       [["tail_n"; "0"; "/10klines"]], [])],
2960    "return last N lines of a file",
2961    "\
2962 If the parameter C<nrlines> is a positive number, this returns the last
2963 C<nrlines> lines of the file C<path>.
2964
2965 If the parameter C<nrlines> is a negative number, this returns lines
2966 from the file C<path>, starting with the C<-nrlines>th line.
2967
2968 If the parameter C<nrlines> is zero, this returns an empty list.");
2969
2970   ("df", (RString "output", []), 125, [],
2971    [], (* XXX Tricky to test because it depends on the exact format
2972         * of the 'df' command and other imponderables.
2973         *)
2974    "report file system disk space usage",
2975    "\
2976 This command runs the C<df> command to report disk space used.
2977
2978 This command is mostly useful for interactive sessions.  It
2979 is I<not> intended that you try to parse the output string.
2980 Use C<statvfs> from programs.");
2981
2982   ("df_h", (RString "output", []), 126, [],
2983    [], (* XXX Tricky to test because it depends on the exact format
2984         * of the 'df' command and other imponderables.
2985         *)
2986    "report file system disk space usage (human readable)",
2987    "\
2988 This command runs the C<df -h> command to report disk space used
2989 in human-readable format.
2990
2991 This command is mostly useful for interactive sessions.  It
2992 is I<not> intended that you try to parse the output string.
2993 Use C<statvfs> from programs.");
2994
2995   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2996    [InitISOFS, Always, TestOutputInt (
2997       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2998    "estimate file space usage",
2999    "\
3000 This command runs the C<du -s> command to estimate file space
3001 usage for C<path>.
3002
3003 C<path> can be a file or a directory.  If C<path> is a directory
3004 then the estimate includes the contents of the directory and all
3005 subdirectories (recursively).
3006
3007 The result is the estimated size in I<kilobytes>
3008 (ie. units of 1024 bytes).");
3009
3010   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
3011    [InitISOFS, Always, TestOutputList (
3012       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
3013    "list files in an initrd",
3014    "\
3015 This command lists out files contained in an initrd.
3016
3017 The files are listed without any initial C</> character.  The
3018 files are listed in the order they appear (not necessarily
3019 alphabetical).  Directory names are listed as separate items.
3020
3021 Old Linux kernels (2.4 and earlier) used a compressed ext2
3022 filesystem as initrd.  We I<only> support the newer initramfs
3023 format (compressed cpio files).");
3024
3025   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3026    [],
3027    "mount a file using the loop device",
3028    "\
3029 This command lets you mount C<file> (a filesystem image
3030 in a file) on a mount point.  It is entirely equivalent to
3031 the command C<mount -o loop file mountpoint>.");
3032
3033   ("mkswap", (RErr, [Device "device"]), 130, [],
3034    [InitEmpty, Always, TestRun (
3035       [["part_disk"; "/dev/sda"; "mbr"];
3036        ["mkswap"; "/dev/sda1"]])],
3037    "create a swap partition",
3038    "\
3039 Create a swap partition on C<device>.");
3040
3041   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3042    [InitEmpty, Always, TestRun (
3043       [["part_disk"; "/dev/sda"; "mbr"];
3044        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3045    "create a swap partition with a label",
3046    "\
3047 Create a swap partition on C<device> with label C<label>.
3048
3049 Note that you cannot attach a swap label to a block device
3050 (eg. C</dev/sda>), just to a partition.  This appears to be
3051 a limitation of the kernel or swap tools.");
3052
3053   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3054    (let uuid = uuidgen () in
3055     [InitEmpty, Always, TestRun (
3056        [["part_disk"; "/dev/sda"; "mbr"];
3057         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3058    "create a swap partition with an explicit UUID",
3059    "\
3060 Create a swap partition on C<device> with UUID C<uuid>.");
3061
3062   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3063    [InitBasicFS, Always, TestOutputStruct (
3064       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3065        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3066        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3067     InitBasicFS, Always, TestOutputStruct (
3068       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3069        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3070    "make block, character or FIFO devices",
3071    "\
3072 This call creates block or character special devices, or
3073 named pipes (FIFOs).
3074
3075 The C<mode> parameter should be the mode, using the standard
3076 constants.  C<devmajor> and C<devminor> are the
3077 device major and minor numbers, only used when creating block
3078 and character special devices.
3079
3080 Note that, just like L<mknod(2)>, the mode must be bitwise
3081 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3082 just creates a regular file).  These constants are
3083 available in the standard Linux header files, or you can use
3084 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3085 which are wrappers around this command which bitwise OR
3086 in the appropriate constant for you.
3087
3088 The mode actually set is affected by the umask.");
3089
3090   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3091    [InitBasicFS, Always, TestOutputStruct (
3092       [["mkfifo"; "0o777"; "/node"];
3093        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3094    "make FIFO (named pipe)",
3095    "\
3096 This call creates a FIFO (named pipe) called C<path> with
3097 mode C<mode>.  It is just a convenient wrapper around
3098 C<guestfs_mknod>.
3099
3100 The mode actually set is affected by the umask.");
3101
3102   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3103    [InitBasicFS, Always, TestOutputStruct (
3104       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3105        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3106    "make block device node",
3107    "\
3108 This call creates a block device node called C<path> with
3109 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3110 It is just a convenient wrapper around C<guestfs_mknod>.
3111
3112 The mode actually set is affected by the umask.");
3113
3114   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3115    [InitBasicFS, Always, TestOutputStruct (
3116       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3117        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3118    "make char device node",
3119    "\
3120 This call creates a char device node called C<path> with
3121 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3122 It is just a convenient wrapper around C<guestfs_mknod>.
3123
3124 The mode actually set is affected by the umask.");
3125
3126   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3127    [InitEmpty, Always, TestOutputInt (
3128       [["umask"; "0o22"]], 0o22)],
3129    "set file mode creation mask (umask)",
3130    "\
3131 This function sets the mask used for creating new files and
3132 device nodes to C<mask & 0777>.
3133
3134 Typical umask values would be C<022> which creates new files
3135 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3136 C<002> which creates new files with permissions like
3137 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3138
3139 The default umask is C<022>.  This is important because it
3140 means that directories and device nodes will be created with
3141 C<0644> or C<0755> mode even if you specify C<0777>.
3142
3143 See also C<guestfs_get_umask>,
3144 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3145
3146 This call returns the previous umask.");
3147
3148   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3149    [],
3150    "read directories entries",
3151    "\
3152 This returns the list of directory entries in directory C<dir>.
3153
3154 All entries in the directory are returned, including C<.> and
3155 C<..>.  The entries are I<not> sorted, but returned in the same
3156 order as the underlying filesystem.
3157
3158 Also this call returns basic file type information about each
3159 file.  The C<ftyp> field will contain one of the following characters:
3160
3161 =over 4
3162
3163 =item 'b'
3164
3165 Block special
3166
3167 =item 'c'
3168
3169 Char special
3170
3171 =item 'd'
3172
3173 Directory
3174
3175 =item 'f'
3176
3177 FIFO (named pipe)
3178
3179 =item 'l'
3180
3181 Symbolic link
3182
3183 =item 'r'
3184
3185 Regular file
3186
3187 =item 's'
3188
3189 Socket
3190
3191 =item 'u'
3192
3193 Unknown file type
3194
3195 =item '?'
3196
3197 The L<readdir(3)> call returned a C<d_type> field with an
3198 unexpected value
3199
3200 =back
3201
3202 This function is primarily intended for use by programs.  To
3203 get a simple list of names, use C<guestfs_ls>.  To get a printable
3204 directory for human consumption, use C<guestfs_ll>.");
3205
3206   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3207    [],
3208    "create partitions on a block device",
3209    "\
3210 This is a simplified interface to the C<guestfs_sfdisk>
3211 command, where partition sizes are specified in megabytes
3212 only (rounded to the nearest cylinder) and you don't need
3213 to specify the cyls, heads and sectors parameters which
3214 were rarely if ever used anyway.
3215
3216 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3217 and C<guestfs_part_disk>");
3218
3219   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3220    [],
3221    "determine file type inside a compressed file",
3222    "\
3223 This command runs C<file> after first decompressing C<path>
3224 using C<method>.
3225
3226 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3227
3228 Since 1.0.63, use C<guestfs_file> instead which can now
3229 process compressed files.");
3230
3231   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3232    [],
3233    "list extended attributes of a file or directory",
3234    "\
3235 This call lists the extended attributes of the file or directory
3236 C<path>.
3237
3238 At the system call level, this is a combination of the
3239 L<listxattr(2)> and L<getxattr(2)> calls.
3240
3241 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3242
3243   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3244    [],
3245    "list extended attributes of a file or directory",
3246    "\
3247 This is the same as C<guestfs_getxattrs>, but if C<path>
3248 is a symbolic link, then it returns the extended attributes
3249 of the link itself.");
3250
3251   ("setxattr", (RErr, [String "xattr";
3252                        String "val"; Int "vallen"; (* will be BufferIn *)
3253                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3254    [],
3255    "set extended attribute of a file or directory",
3256    "\
3257 This call sets the extended attribute named C<xattr>
3258 of the file C<path> to the value C<val> (of length C<vallen>).
3259 The value is arbitrary 8 bit data.
3260
3261 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3262
3263   ("lsetxattr", (RErr, [String "xattr";
3264                         String "val"; Int "vallen"; (* will be BufferIn *)
3265                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3266    [],
3267    "set extended attribute of a file or directory",
3268    "\
3269 This is the same as C<guestfs_setxattr>, but if C<path>
3270 is a symbolic link, then it sets an extended attribute
3271 of the link itself.");
3272
3273   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3274    [],
3275    "remove extended attribute of a file or directory",
3276    "\
3277 This call removes the extended attribute named C<xattr>
3278 of the file C<path>.
3279
3280 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3281
3282   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3283    [],
3284    "remove extended attribute of a file or directory",
3285    "\
3286 This is the same as C<guestfs_removexattr>, but if C<path>
3287 is a symbolic link, then it removes an extended attribute
3288 of the link itself.");
3289
3290   ("mountpoints", (RHashtable "mps", []), 147, [],
3291    [],
3292    "show mountpoints",
3293    "\
3294 This call is similar to C<guestfs_mounts>.  That call returns
3295 a list of devices.  This one returns a hash table (map) of
3296 device name to directory where the device is mounted.");
3297
3298   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3299    (* This is a special case: while you would expect a parameter
3300     * of type "Pathname", that doesn't work, because it implies
3301     * NEED_ROOT in the generated calling code in stubs.c, and
3302     * this function cannot use NEED_ROOT.
3303     *)
3304    [],
3305    "create a mountpoint",
3306    "\
3307 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3308 specialized calls that can be used to create extra mountpoints
3309 before mounting the first filesystem.
3310
3311 These calls are I<only> necessary in some very limited circumstances,
3312 mainly the case where you want to mount a mix of unrelated and/or
3313 read-only filesystems together.
3314
3315 For example, live CDs often contain a \"Russian doll\" nest of
3316 filesystems, an ISO outer layer, with a squashfs image inside, with
3317 an ext2/3 image inside that.  You can unpack this as follows
3318 in guestfish:
3319
3320  add-ro Fedora-11-i686-Live.iso
3321  run
3322  mkmountpoint /cd
3323  mkmountpoint /squash
3324  mkmountpoint /ext3
3325  mount /dev/sda /cd
3326  mount-loop /cd/LiveOS/squashfs.img /squash
3327  mount-loop /squash/LiveOS/ext3fs.img /ext3
3328
3329 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3330
3331   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3332    [],
3333    "remove a mountpoint",
3334    "\
3335 This calls removes a mountpoint that was previously created
3336 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3337 for full details.");
3338
3339   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3340    [InitISOFS, Always, TestOutputBuffer (
3341       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3342     (* Test various near large, large and too large files (RHBZ#589039). *)
3343     InitBasicFS, Always, TestLastFail (
3344       [["touch"; "/a"];
3345        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3346        ["read_file"; "/a"]]);
3347     InitBasicFS, Always, TestLastFail (
3348       [["touch"; "/a"];
3349        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3350        ["read_file"; "/a"]]);
3351     InitBasicFS, Always, TestLastFail (
3352       [["touch"; "/a"];
3353        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3354        ["read_file"; "/a"]])],
3355    "read a file",
3356    "\
3357 This calls returns the contents of the file C<path> as a
3358 buffer.
3359
3360 Unlike C<guestfs_cat>, this function can correctly
3361 handle files that contain embedded ASCII NUL characters.
3362 However unlike C<guestfs_download>, this function is limited
3363 in the total size of file that can be handled.");
3364
3365   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3366    [InitISOFS, Always, TestOutputList (
3367       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3368     InitISOFS, Always, TestOutputList (
3369       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3370     (* Test for RHBZ#579608, absolute symbolic links. *)
3371     InitISOFS, Always, TestOutputList (
3372       [["grep"; "nomatch"; "/abssymlink"]], [])],
3373    "return lines matching a pattern",
3374    "\
3375 This calls the external C<grep> program and returns the
3376 matching lines.");
3377
3378   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3379    [InitISOFS, Always, TestOutputList (
3380       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3381    "return lines matching a pattern",
3382    "\
3383 This calls the external C<egrep> program and returns the
3384 matching lines.");
3385
3386   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3387    [InitISOFS, Always, TestOutputList (
3388       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3389    "return lines matching a pattern",
3390    "\
3391 This calls the external C<fgrep> program and returns the
3392 matching lines.");
3393
3394   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3395    [InitISOFS, Always, TestOutputList (
3396       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3397    "return lines matching a pattern",
3398    "\
3399 This calls the external C<grep -i> program and returns the
3400 matching lines.");
3401
3402   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3403    [InitISOFS, Always, TestOutputList (
3404       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3405    "return lines matching a pattern",
3406    "\
3407 This calls the external C<egrep -i> program and returns the
3408 matching lines.");
3409
3410   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3411    [InitISOFS, Always, TestOutputList (
3412       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3413    "return lines matching a pattern",
3414    "\
3415 This calls the external C<fgrep -i> program and returns the
3416 matching lines.");
3417
3418   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3419    [InitISOFS, Always, TestOutputList (
3420       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3421    "return lines matching a pattern",
3422    "\
3423 This calls the external C<zgrep> program and returns the
3424 matching lines.");
3425
3426   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3427    [InitISOFS, Always, TestOutputList (
3428       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3429    "return lines matching a pattern",
3430    "\
3431 This calls the external C<zegrep> program and returns the
3432 matching lines.");
3433
3434   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3435    [InitISOFS, Always, TestOutputList (
3436       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3437    "return lines matching a pattern",
3438    "\
3439 This calls the external C<zfgrep> program and returns the
3440 matching lines.");
3441
3442   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3443    [InitISOFS, Always, TestOutputList (
3444       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3445    "return lines matching a pattern",
3446    "\
3447 This calls the external C<zgrep -i> program and returns the
3448 matching lines.");
3449
3450   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3451    [InitISOFS, Always, TestOutputList (
3452       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3453    "return lines matching a pattern",
3454    "\
3455 This calls the external C<zegrep -i> program and returns the
3456 matching lines.");
3457
3458   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3459    [InitISOFS, Always, TestOutputList (
3460       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3461    "return lines matching a pattern",
3462    "\
3463 This calls the external C<zfgrep -i> program and returns the
3464 matching lines.");
3465
3466   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3467    [InitISOFS, Always, TestOutput (
3468       [["realpath"; "/../directory"]], "/directory")],
3469    "canonicalized absolute pathname",
3470    "\
3471 Return the canonicalized absolute pathname of C<path>.  The
3472 returned path has no C<.>, C<..> or symbolic link path elements.");
3473
3474   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3475    [InitBasicFS, Always, TestOutputStruct (
3476       [["touch"; "/a"];
3477        ["ln"; "/a"; "/b"];
3478        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3479    "create a hard link",
3480    "\
3481 This command creates a hard link using the C<ln> command.");
3482
3483   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3484    [InitBasicFS, Always, TestOutputStruct (
3485       [["touch"; "/a"];
3486        ["touch"; "/b"];
3487        ["ln_f"; "/a"; "/b"];
3488        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3489    "create a hard link",
3490    "\
3491 This command creates a hard link using the C<ln -f> command.
3492 The C<-f> option removes the link (C<linkname>) if it exists already.");
3493
3494   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3495    [InitBasicFS, Always, TestOutputStruct (
3496       [["touch"; "/a"];
3497        ["ln_s"; "a"; "/b"];
3498        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3499    "create a symbolic link",
3500    "\
3501 This command creates a symbolic link using the C<ln -s> command.");
3502
3503   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3504    [InitBasicFS, Always, TestOutput (
3505       [["mkdir_p"; "/a/b"];
3506        ["touch"; "/a/b/c"];
3507        ["ln_sf"; "../d"; "/a/b/c"];
3508        ["readlink"; "/a/b/c"]], "../d")],
3509    "create a symbolic link",
3510    "\
3511 This command creates a symbolic link using the C<ln -sf> command,
3512 The C<-f> option removes the link (C<linkname>) if it exists already.");
3513
3514   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3515    [] (* XXX tested above *),
3516    "read the target of a symbolic link",
3517    "\
3518 This command reads the target of a symbolic link.");
3519
3520   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3521    [InitBasicFS, Always, TestOutputStruct (
3522       [["fallocate"; "/a"; "1000000"];
3523        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3524    "preallocate a file in the guest filesystem",
3525    "\
3526 This command preallocates a file (containing zero bytes) named
3527 C<path> of size C<len> bytes.  If the file exists already, it
3528 is overwritten.
3529
3530 Do not confuse this with the guestfish-specific
3531 C<alloc> command which allocates a file in the host and
3532 attaches it as a device.");
3533
3534   ("swapon_device", (RErr, [Device "device"]), 170, [],
3535    [InitPartition, Always, TestRun (
3536       [["mkswap"; "/dev/sda1"];
3537        ["swapon_device"; "/dev/sda1"];
3538        ["swapoff_device"; "/dev/sda1"]])],
3539    "enable swap on device",
3540    "\
3541 This command enables the libguestfs appliance to use the
3542 swap device or partition named C<device>.  The increased
3543 memory is made available for all commands, for example
3544 those run using C<guestfs_command> or C<guestfs_sh>.
3545
3546 Note that you should not swap to existing guest swap
3547 partitions unless you know what you are doing.  They may
3548 contain hibernation information, or other information that
3549 the guest doesn't want you to trash.  You also risk leaking
3550 information about the host to the guest this way.  Instead,
3551 attach a new host device to the guest and swap on that.");
3552
3553   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3554    [], (* XXX tested by swapon_device *)
3555    "disable swap on device",
3556    "\
3557 This command disables the libguestfs appliance swap
3558 device or partition named C<device>.
3559 See C<guestfs_swapon_device>.");
3560
3561   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3562    [InitBasicFS, Always, TestRun (
3563       [["fallocate"; "/swap"; "8388608"];
3564        ["mkswap_file"; "/swap"];
3565        ["swapon_file"; "/swap"];
3566        ["swapoff_file"; "/swap"]])],
3567    "enable swap on file",
3568    "\
3569 This command enables swap to a file.
3570 See C<guestfs_swapon_device> for other notes.");
3571
3572   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3573    [], (* XXX tested by swapon_file *)
3574    "disable swap on file",
3575    "\
3576 This command disables the libguestfs appliance swap on file.");
3577
3578   ("swapon_label", (RErr, [String "label"]), 174, [],
3579    [InitEmpty, Always, TestRun (
3580       [["part_disk"; "/dev/sdb"; "mbr"];
3581        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3582        ["swapon_label"; "swapit"];
3583        ["swapoff_label"; "swapit"];
3584        ["zero"; "/dev/sdb"];
3585        ["blockdev_rereadpt"; "/dev/sdb"]])],
3586    "enable swap on labeled swap partition",
3587    "\
3588 This command enables swap to a labeled swap partition.
3589 See C<guestfs_swapon_device> for other notes.");
3590
3591   ("swapoff_label", (RErr, [String "label"]), 175, [],
3592    [], (* XXX tested by swapon_label *)
3593    "disable swap on labeled swap partition",
3594    "\
3595 This command disables the libguestfs appliance swap on
3596 labeled swap partition.");
3597
3598   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3599    (let uuid = uuidgen () in
3600     [InitEmpty, Always, TestRun (
3601        [["mkswap_U"; uuid; "/dev/sdb"];
3602         ["swapon_uuid"; uuid];
3603         ["swapoff_uuid"; uuid]])]),
3604    "enable swap on swap partition by UUID",
3605    "\
3606 This command enables swap to a swap partition with the given UUID.
3607 See C<guestfs_swapon_device> for other notes.");
3608
3609   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3610    [], (* XXX tested by swapon_uuid *)
3611    "disable swap on swap partition by UUID",
3612    "\
3613 This command disables the libguestfs appliance swap partition
3614 with the given UUID.");
3615
3616   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3617    [InitBasicFS, Always, TestRun (
3618       [["fallocate"; "/swap"; "8388608"];
3619        ["mkswap_file"; "/swap"]])],
3620    "create a swap file",
3621    "\
3622 Create a swap file.
3623
3624 This command just writes a swap file signature to an existing
3625 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3626
3627   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3628    [InitISOFS, Always, TestRun (
3629       [["inotify_init"; "0"]])],
3630    "create an inotify handle",
3631    "\
3632 This command creates a new inotify handle.
3633 The inotify subsystem can be used to notify events which happen to
3634 objects in the guest filesystem.
3635
3636 C<maxevents> is the maximum number of events which will be
3637 queued up between calls to C<guestfs_inotify_read> or
3638 C<guestfs_inotify_files>.
3639 If this is passed as C<0>, then the kernel (or previously set)
3640 default is used.  For Linux 2.6.29 the default was 16384 events.
3641 Beyond this limit, the kernel throws away events, but records
3642 the fact that it threw them away by setting a flag
3643 C<IN_Q_OVERFLOW> in the returned structure list (see
3644 C<guestfs_inotify_read>).
3645
3646 Before any events are generated, you have to add some
3647 watches to the internal watch list.  See:
3648 C<guestfs_inotify_add_watch>,
3649 C<guestfs_inotify_rm_watch> and
3650 C<guestfs_inotify_watch_all>.
3651
3652 Queued up events should be read periodically by calling
3653 C<guestfs_inotify_read>
3654 (or C<guestfs_inotify_files> which is just a helpful
3655 wrapper around C<guestfs_inotify_read>).  If you don't
3656 read the events out often enough then you risk the internal
3657 queue overflowing.
3658
3659 The handle should be closed after use by calling
3660 C<guestfs_inotify_close>.  This also removes any
3661 watches automatically.
3662
3663 See also L<inotify(7)> for an overview of the inotify interface
3664 as exposed by the Linux kernel, which is roughly what we expose
3665 via libguestfs.  Note that there is one global inotify handle
3666 per libguestfs instance.");
3667
3668   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3669    [InitBasicFS, Always, TestOutputList (
3670       [["inotify_init"; "0"];
3671        ["inotify_add_watch"; "/"; "1073741823"];
3672        ["touch"; "/a"];
3673        ["touch"; "/b"];
3674        ["inotify_files"]], ["a"; "b"])],
3675    "add an inotify watch",
3676    "\
3677 Watch C<path> for the events listed in C<mask>.
3678
3679 Note that if C<path> is a directory then events within that
3680 directory are watched, but this does I<not> happen recursively
3681 (in subdirectories).
3682
3683 Note for non-C or non-Linux callers: the inotify events are
3684 defined by the Linux kernel ABI and are listed in
3685 C</usr/include/sys/inotify.h>.");
3686
3687   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3688    [],
3689    "remove an inotify watch",
3690    "\
3691 Remove a previously defined inotify watch.
3692 See C<guestfs_inotify_add_watch>.");
3693
3694   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3695    [],
3696    "return list of inotify events",
3697    "\
3698 Return the complete queue of events that have happened
3699 since the previous read call.
3700
3701 If no events have happened, this returns an empty list.
3702
3703 I<Note>: In order to make sure that all events have been
3704 read, you must call this function repeatedly until it
3705 returns an empty list.  The reason is that the call will
3706 read events up to the maximum appliance-to-host message
3707 size and leave remaining events in the queue.");
3708
3709   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3710    [],
3711    "return list of watched files that had events",
3712    "\
3713 This function is a helpful wrapper around C<guestfs_inotify_read>
3714 which just returns a list of pathnames of objects that were
3715 touched.  The returned pathnames are sorted and deduplicated.");
3716
3717   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3718    [],
3719    "close the inotify handle",
3720    "\
3721 This closes the inotify handle which was previously
3722 opened by inotify_init.  It removes all watches, throws
3723 away any pending events, and deallocates all resources.");
3724
3725   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3726    [],
3727    "set SELinux security context",
3728    "\
3729 This sets the SELinux security context of the daemon
3730 to the string C<context>.
3731
3732 See the documentation about SELINUX in L<guestfs(3)>.");
3733
3734   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3735    [],
3736    "get SELinux security context",
3737    "\
3738 This gets the SELinux security context of the daemon.
3739
3740 See the documentation about SELINUX in L<guestfs(3)>,
3741 and C<guestfs_setcon>");
3742
3743   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3744    [InitEmpty, Always, TestOutput (
3745       [["part_disk"; "/dev/sda"; "mbr"];
3746        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3747        ["mount_options"; ""; "/dev/sda1"; "/"];
3748        ["write"; "/new"; "new file contents"];
3749        ["cat"; "/new"]], "new file contents");
3750     InitEmpty, Always, TestRun (
3751       [["part_disk"; "/dev/sda"; "mbr"];
3752        ["mkfs_b"; "vfat"; "32768"; "/dev/sda1"]]);
3753     InitEmpty, Always, TestLastFail (
3754       [["part_disk"; "/dev/sda"; "mbr"];
3755        ["mkfs_b"; "vfat"; "32769"; "/dev/sda1"]]);
3756     InitEmpty, Always, TestLastFail (
3757       [["part_disk"; "/dev/sda"; "mbr"];
3758        ["mkfs_b"; "vfat"; "33280"; "/dev/sda1"]]);
3759     InitEmpty, IfAvailable "ntfsprogs", TestRun (
3760       [["part_disk"; "/dev/sda"; "mbr"];
3761        ["mkfs_b"; "ntfs"; "32768"; "/dev/sda1"]])],
3762    "make a filesystem with block size",
3763    "\
3764 This call is similar to C<guestfs_mkfs>, but it allows you to
3765 control the block size of the resulting filesystem.  Supported
3766 block sizes depend on the filesystem type, but typically they
3767 are C<1024>, C<2048> or C<4096> only.
3768
3769 For VFAT and NTFS the C<blocksize> parameter is treated as
3770 the requested cluster size.");
3771
3772   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3773    [InitEmpty, Always, TestOutput (
3774       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3775        ["mke2journal"; "4096"; "/dev/sda1"];
3776        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3777        ["mount_options"; ""; "/dev/sda2"; "/"];
3778        ["write"; "/new"; "new file contents"];
3779        ["cat"; "/new"]], "new file contents")],
3780    "make ext2/3/4 external journal",
3781    "\
3782 This creates an ext2 external journal on C<device>.  It is equivalent
3783 to the command:
3784
3785  mke2fs -O journal_dev -b blocksize device");
3786
3787   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3788    [InitEmpty, Always, TestOutput (
3789       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3790        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3791        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3792        ["mount_options"; ""; "/dev/sda2"; "/"];
3793        ["write"; "/new"; "new file contents"];
3794        ["cat"; "/new"]], "new file contents")],
3795    "make ext2/3/4 external journal with label",
3796    "\
3797 This creates an ext2 external journal on C<device> with label C<label>.");
3798
3799   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3800    (let uuid = uuidgen () in
3801     [InitEmpty, Always, TestOutput (
3802        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3803         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3804         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3805         ["mount_options"; ""; "/dev/sda2"; "/"];
3806         ["write"; "/new"; "new file contents"];
3807         ["cat"; "/new"]], "new file contents")]),
3808    "make ext2/3/4 external journal with UUID",
3809    "\
3810 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3811
3812   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3813    [],
3814    "make ext2/3/4 filesystem with external journal",
3815    "\
3816 This creates an ext2/3/4 filesystem on C<device> with
3817 an external journal on C<journal>.  It is equivalent
3818 to the command:
3819
3820  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3821
3822 See also C<guestfs_mke2journal>.");
3823
3824   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3825    [],
3826    "make ext2/3/4 filesystem with external journal",
3827    "\
3828 This creates an ext2/3/4 filesystem on C<device> with
3829 an external journal on the journal labeled C<label>.
3830
3831 See also C<guestfs_mke2journal_L>.");
3832
3833   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3834    [],
3835    "make ext2/3/4 filesystem with external journal",
3836    "\
3837 This creates an ext2/3/4 filesystem on C<device> with
3838 an external journal on the journal with UUID C<uuid>.
3839
3840 See also C<guestfs_mke2journal_U>.");
3841
3842   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3843    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3844    "load a kernel module",
3845    "\
3846 This loads a kernel module in the appliance.
3847
3848 The kernel module must have been whitelisted when libguestfs
3849 was built (see C<appliance/kmod.whitelist.in> in the source).");
3850
3851   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3852    [InitNone, Always, TestOutput (
3853       [["echo_daemon"; "This is a test"]], "This is a test"
3854     )],
3855    "echo arguments back to the client",
3856    "\
3857 This command concatenates the list of C<words> passed with single spaces
3858 between them and returns the resulting string.
3859
3860 You can use this command to test the connection through to the daemon.
3861
3862 See also C<guestfs_ping_daemon>.");
3863
3864   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3865    [], (* There is a regression test for this. *)
3866    "find all files and directories, returning NUL-separated list",
3867    "\
3868 This command lists out all files and directories, recursively,
3869 starting at C<directory>, placing the resulting list in the
3870 external file called C<files>.
3871
3872 This command works the same way as C<guestfs_find> with the
3873 following exceptions:
3874
3875 =over 4
3876
3877 =item *
3878
3879 The resulting list is written to an external file.
3880
3881 =item *
3882
3883 Items (filenames) in the result are separated
3884 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3885
3886 =item *
3887
3888 This command is not limited in the number of names that it
3889 can return.
3890
3891 =item *
3892
3893 The result list is not sorted.
3894
3895 =back");
3896
3897   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3898    [InitISOFS, Always, TestOutput (
3899       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3900     InitISOFS, Always, TestOutput (
3901       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3902     InitISOFS, Always, TestOutput (
3903       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3904     InitISOFS, Always, TestLastFail (
3905       [["case_sensitive_path"; "/Known-1/"]]);
3906     InitBasicFS, Always, TestOutput (
3907       [["mkdir"; "/a"];
3908        ["mkdir"; "/a/bbb"];
3909        ["touch"; "/a/bbb/c"];
3910        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3911     InitBasicFS, Always, TestOutput (
3912       [["mkdir"; "/a"];
3913        ["mkdir"; "/a/bbb"];
3914        ["touch"; "/a/bbb/c"];
3915        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3916     InitBasicFS, Always, TestLastFail (
3917       [["mkdir"; "/a"];
3918        ["mkdir"; "/a/bbb"];
3919        ["touch"; "/a/bbb/c"];
3920        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3921    "return true path on case-insensitive filesystem",
3922    "\
3923 This can be used to resolve case insensitive paths on
3924 a filesystem which is case sensitive.  The use case is
3925 to resolve paths which you have read from Windows configuration
3926 files or the Windows Registry, to the true path.
3927
3928 The command handles a peculiarity of the Linux ntfs-3g
3929 filesystem driver (and probably others), which is that although
3930 the underlying filesystem is case-insensitive, the driver
3931 exports the filesystem to Linux as case-sensitive.
3932
3933 One consequence of this is that special directories such
3934 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3935 (or other things) depending on the precise details of how
3936 they were created.  In Windows itself this would not be
3937 a problem.
3938
3939 Bug or feature?  You decide:
3940 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3941
3942 This function resolves the true case of each element in the
3943 path and returns the case-sensitive path.
3944
3945 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3946 might return C<\"/WINDOWS/system32\"> (the exact return value
3947 would depend on details of how the directories were originally
3948 created under Windows).
3949
3950 I<Note>:
3951 This function does not handle drive names, backslashes etc.
3952
3953 See also C<guestfs_realpath>.");
3954
3955   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3956    [InitBasicFS, Always, TestOutput (
3957       [["vfs_type"; "/dev/sda1"]], "ext2")],
3958    "get the Linux VFS type corresponding to a mounted device",
3959    "\
3960 This command gets the filesystem type corresponding to
3961 the filesystem on C<device>.
3962
3963 For most filesystems, the result is the name of the Linux
3964 VFS module which would be used to mount this filesystem
3965 if you mounted it without specifying the filesystem type.
3966 For example a string such as C<ext3> or C<ntfs>.");
3967
3968   ("truncate", (RErr, [Pathname "path"]), 199, [],
3969    [InitBasicFS, Always, TestOutputStruct (
3970       [["write"; "/test"; "some stuff so size is not zero"];
3971        ["truncate"; "/test"];
3972        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3973    "truncate a file to zero size",
3974    "\
3975 This command truncates C<path> to a zero-length file.  The
3976 file must exist already.");
3977
3978   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3979    [InitBasicFS, Always, TestOutputStruct (
3980       [["touch"; "/test"];
3981        ["truncate_size"; "/test"; "1000"];
3982        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3983    "truncate a file to a particular size",
3984    "\
3985 This command truncates C<path> to size C<size> bytes.  The file
3986 must exist already.
3987
3988 If the current file size is less than C<size> then
3989 the file is extended to the required size with zero bytes.
3990 This creates a sparse file (ie. disk blocks are not allocated
3991 for the file until you write to it).  To create a non-sparse
3992 file of zeroes, use C<guestfs_fallocate64> instead.");
3993
3994   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3995    [InitBasicFS, Always, TestOutputStruct (
3996       [["touch"; "/test"];
3997        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3998        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3999    "set timestamp of a file with nanosecond precision",
4000    "\
4001 This command sets the timestamps of a file with nanosecond
4002 precision.
4003
4004 C<atsecs, atnsecs> are the last access time (atime) in secs and
4005 nanoseconds from the epoch.
4006
4007 C<mtsecs, mtnsecs> are the last modification time (mtime) in
4008 secs and nanoseconds from the epoch.
4009
4010 If the C<*nsecs> field contains the special value C<-1> then
4011 the corresponding timestamp is set to the current time.  (The
4012 C<*secs> field is ignored in this case).
4013
4014 If the C<*nsecs> field contains the special value C<-2> then
4015 the corresponding timestamp is left unchanged.  (The
4016 C<*secs> field is ignored in this case).");
4017
4018   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
4019    [InitBasicFS, Always, TestOutputStruct (
4020       [["mkdir_mode"; "/test"; "0o111"];
4021        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
4022    "create a directory with a particular mode",
4023    "\
4024 This command creates a directory, setting the initial permissions
4025 of the directory to C<mode>.
4026
4027 For common Linux filesystems, the actual mode which is set will
4028 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
4029 interpret the mode in other ways.
4030
4031 See also C<guestfs_mkdir>, C<guestfs_umask>");
4032
4033   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
4034    [], (* XXX *)
4035    "change file owner and group",
4036    "\
4037 Change the file owner to C<owner> and group to C<group>.
4038 This is like C<guestfs_chown> but if C<path> is a symlink then
4039 the link itself is changed, not the target.
4040
4041 Only numeric uid and gid are supported.  If you want to use
4042 names, you will need to locate and parse the password file
4043 yourself (Augeas support makes this relatively easy).");
4044
4045   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4046    [], (* XXX *)
4047    "lstat on multiple files",
4048    "\
4049 This call allows you to perform the C<guestfs_lstat> operation
4050 on multiple files, where all files are in the directory C<path>.
4051 C<names> is the list of files from this directory.
4052
4053 On return you get a list of stat structs, with a one-to-one
4054 correspondence to the C<names> list.  If any name did not exist
4055 or could not be lstat'd, then the C<ino> field of that structure
4056 is set to C<-1>.
4057
4058 This call is intended for programs that want to efficiently
4059 list a directory contents without making many round-trips.
4060 See also C<guestfs_lxattrlist> for a similarly efficient call
4061 for getting extended attributes.  Very long directory listings
4062 might cause the protocol message size to be exceeded, causing
4063 this call to fail.  The caller must split up such requests
4064 into smaller groups of names.");
4065
4066   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4067    [], (* XXX *)
4068    "lgetxattr on multiple files",
4069    "\
4070 This call allows you to get the extended attributes
4071 of multiple files, where all files are in the directory C<path>.
4072 C<names> is the list of files from this directory.
4073
4074 On return you get a flat list of xattr structs which must be
4075 interpreted sequentially.  The first xattr struct always has a zero-length
4076 C<attrname>.  C<attrval> in this struct is zero-length
4077 to indicate there was an error doing C<lgetxattr> for this
4078 file, I<or> is a C string which is a decimal number
4079 (the number of following attributes for this file, which could
4080 be C<\"0\">).  Then after the first xattr struct are the
4081 zero or more attributes for the first named file.
4082 This repeats for the second and subsequent files.
4083
4084 This call is intended for programs that want to efficiently
4085 list a directory contents without making many round-trips.
4086 See also C<guestfs_lstatlist> for a similarly efficient call
4087 for getting standard stats.  Very long directory listings
4088 might cause the protocol message size to be exceeded, causing
4089 this call to fail.  The caller must split up such requests
4090 into smaller groups of names.");
4091
4092   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4093    [], (* XXX *)
4094    "readlink on multiple files",
4095    "\
4096 This call allows you to do a C<readlink> operation
4097 on multiple files, where all files are in the directory C<path>.
4098 C<names> is the list of files from this directory.
4099
4100 On return you get a list of strings, with a one-to-one
4101 correspondence to the C<names> list.  Each string is the
4102 value of the symbolic link.
4103
4104 If the C<readlink(2)> operation fails on any name, then
4105 the corresponding result string is the empty string C<\"\">.
4106 However the whole operation is completed even if there
4107 were C<readlink(2)> errors, and so you can call this
4108 function with names where you don't know if they are
4109 symbolic links already (albeit slightly less efficient).
4110
4111 This call is intended for programs that want to efficiently
4112 list a directory contents without making many round-trips.
4113 Very long directory listings might cause the protocol
4114 message size to be exceeded, causing
4115 this call to fail.  The caller must split up such requests
4116 into smaller groups of names.");
4117
4118   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4119    [InitISOFS, Always, TestOutputBuffer (
4120       [["pread"; "/known-4"; "1"; "3"]], "\n");
4121     InitISOFS, Always, TestOutputBuffer (
4122       [["pread"; "/empty"; "0"; "100"]], "")],
4123    "read part of a file",
4124    "\
4125 This command lets you read part of a file.  It reads C<count>
4126 bytes of the file, starting at C<offset>, from file C<path>.
4127
4128 This may read fewer bytes than requested.  For further details
4129 see the L<pread(2)> system call.
4130
4131 See also C<guestfs_pwrite>.");
4132
4133   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4134    [InitEmpty, Always, TestRun (
4135       [["part_init"; "/dev/sda"; "gpt"]])],
4136    "create an empty partition table",
4137    "\
4138 This creates an empty partition table on C<device> of one of the
4139 partition types listed below.  Usually C<parttype> should be
4140 either C<msdos> or C<gpt> (for large disks).
4141
4142 Initially there are no partitions.  Following this, you should
4143 call C<guestfs_part_add> for each partition required.
4144
4145 Possible values for C<parttype> are:
4146
4147 =over 4
4148
4149 =item B<efi> | B<gpt>
4150
4151 Intel EFI / GPT partition table.
4152
4153 This is recommended for >= 2 TB partitions that will be accessed
4154 from Linux and Intel-based Mac OS X.  It also has limited backwards
4155 compatibility with the C<mbr> format.
4156
4157 =item B<mbr> | B<msdos>
4158
4159 The standard PC \"Master Boot Record\" (MBR) format used
4160 by MS-DOS and Windows.  This partition type will B<only> work
4161 for device sizes up to 2 TB.  For large disks we recommend
4162 using C<gpt>.
4163
4164 =back
4165
4166 Other partition table types that may work but are not
4167 supported include:
4168
4169 =over 4
4170
4171 =item B<aix>
4172
4173 AIX disk labels.
4174
4175 =item B<amiga> | B<rdb>
4176
4177 Amiga \"Rigid Disk Block\" format.
4178
4179 =item B<bsd>
4180
4181 BSD disk labels.
4182
4183 =item B<dasd>
4184
4185 DASD, used on IBM mainframes.
4186
4187 =item B<dvh>
4188
4189 MIPS/SGI volumes.
4190
4191 =item B<mac>
4192
4193 Old Mac partition format.  Modern Macs use C<gpt>.
4194
4195 =item B<pc98>
4196
4197 NEC PC-98 format, common in Japan apparently.
4198
4199 =item B<sun>
4200
4201 Sun disk labels.
4202
4203 =back");
4204
4205   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4206    [InitEmpty, Always, TestRun (
4207       [["part_init"; "/dev/sda"; "mbr"];
4208        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4209     InitEmpty, Always, TestRun (
4210       [["part_init"; "/dev/sda"; "gpt"];
4211        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4212        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4213     InitEmpty, Always, TestRun (
4214       [["part_init"; "/dev/sda"; "mbr"];
4215        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4216        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4217        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4218        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4219    "add a partition to the device",
4220    "\
4221 This command adds a partition to C<device>.  If there is no partition
4222 table on the device, call C<guestfs_part_init> first.
4223
4224 The C<prlogex> parameter is the type of partition.  Normally you
4225 should pass C<p> or C<primary> here, but MBR partition tables also
4226 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4227 types.
4228
4229 C<startsect> and C<endsect> are the start and end of the partition
4230 in I<sectors>.  C<endsect> may be negative, which means it counts
4231 backwards from the end of the disk (C<-1> is the last sector).
4232
4233 Creating a partition which covers the whole disk is not so easy.
4234 Use C<guestfs_part_disk> to do that.");
4235
4236   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4237    [InitEmpty, Always, TestRun (
4238       [["part_disk"; "/dev/sda"; "mbr"]]);
4239     InitEmpty, Always, TestRun (
4240       [["part_disk"; "/dev/sda"; "gpt"]])],
4241    "partition whole disk with a single primary partition",
4242    "\
4243 This command is simply a combination of C<guestfs_part_init>
4244 followed by C<guestfs_part_add> to create a single primary partition
4245 covering the whole disk.
4246
4247 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4248 but other possible values are described in C<guestfs_part_init>.");
4249
4250   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4251    [InitEmpty, Always, TestRun (
4252       [["part_disk"; "/dev/sda"; "mbr"];
4253        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4254    "make a partition bootable",
4255    "\
4256 This sets the bootable flag on partition numbered C<partnum> on
4257 device C<device>.  Note that partitions are numbered from 1.
4258
4259 The bootable flag is used by some operating systems (notably
4260 Windows) to determine which partition to boot from.  It is by
4261 no means universally recognized.");
4262
4263   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4264    [InitEmpty, Always, TestRun (
4265       [["part_disk"; "/dev/sda"; "gpt"];
4266        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4267    "set partition name",
4268    "\
4269 This sets the partition name on partition numbered C<partnum> on
4270 device C<device>.  Note that partitions are numbered from 1.
4271
4272 The partition name can only be set on certain types of partition
4273 table.  This works on C<gpt> but not on C<mbr> partitions.");
4274
4275   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4276    [], (* XXX Add a regression test for this. *)
4277    "list partitions on a device",
4278    "\
4279 This command parses the partition table on C<device> and
4280 returns the list of partitions found.
4281
4282 The fields in the returned structure are:
4283
4284 =over 4
4285
4286 =item B<part_num>
4287
4288 Partition number, counting from 1.
4289
4290 =item B<part_start>
4291
4292 Start of the partition I<in bytes>.  To get sectors you have to
4293 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4294
4295 =item B<part_end>
4296
4297 End of the partition in bytes.
4298
4299 =item B<part_size>
4300
4301 Size of the partition in bytes.
4302
4303 =back");
4304
4305   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4306    [InitEmpty, Always, TestOutput (
4307       [["part_disk"; "/dev/sda"; "gpt"];
4308        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4309    "get the partition table type",
4310    "\
4311 This command examines the partition table on C<device> and
4312 returns the partition table type (format) being used.
4313
4314 Common return values include: C<msdos> (a DOS/Windows style MBR
4315 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4316 values are possible, although unusual.  See C<guestfs_part_init>
4317 for a full list.");
4318
4319   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4320    [InitBasicFS, Always, TestOutputBuffer (
4321       [["fill"; "0x63"; "10"; "/test"];
4322        ["read_file"; "/test"]], "cccccccccc")],
4323    "fill a file with octets",
4324    "\
4325 This command creates a new file called C<path>.  The initial
4326 content of the file is C<len> octets of C<c>, where C<c>
4327 must be a number in the range C<[0..255]>.
4328
4329 To fill a file with zero bytes (sparsely), it is
4330 much more efficient to use C<guestfs_truncate_size>.
4331 To create a file with a pattern of repeating bytes
4332 use C<guestfs_fill_pattern>.");
4333
4334   ("available", (RErr, [StringList "groups"]), 216, [],
4335    [InitNone, Always, TestRun [["available"; ""]]],
4336    "test availability of some parts of the API",
4337    "\
4338 This command is used to check the availability of some
4339 groups of functionality in the appliance, which not all builds of
4340 the libguestfs appliance will be able to provide.
4341
4342 The libguestfs groups, and the functions that those
4343 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4344 You can also fetch this list at runtime by calling
4345 C<guestfs_available_all_groups>.
4346
4347 The argument C<groups> is a list of group names, eg:
4348 C<[\"inotify\", \"augeas\"]> would check for the availability of
4349 the Linux inotify functions and Augeas (configuration file
4350 editing) functions.
4351
4352 The command returns no error if I<all> requested groups are available.
4353
4354 It fails with an error if one or more of the requested
4355 groups is unavailable in the appliance.
4356
4357 If an unknown group name is included in the
4358 list of groups then an error is always returned.
4359
4360 I<Notes:>
4361
4362 =over 4
4363
4364 =item *
4365
4366 You must call C<guestfs_launch> before calling this function.
4367
4368 The reason is because we don't know what groups are
4369 supported by the appliance/daemon until it is running and can
4370 be queried.
4371
4372 =item *
4373
4374 If a group of functions is available, this does not necessarily
4375 mean that they will work.  You still have to check for errors
4376 when calling individual API functions even if they are
4377 available.
4378
4379 =item *
4380
4381 It is usually the job of distro packagers to build
4382 complete functionality into the libguestfs appliance.
4383 Upstream libguestfs, if built from source with all
4384 requirements satisfied, will support everything.
4385
4386 =item *
4387
4388 This call was added in version C<1.0.80>.  In previous
4389 versions of libguestfs all you could do would be to speculatively
4390 execute a command to find out if the daemon implemented it.
4391 See also C<guestfs_version>.
4392
4393 =back");
4394
4395   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4396    [InitBasicFS, Always, TestOutputBuffer (
4397       [["write"; "/src"; "hello, world"];
4398        ["dd"; "/src"; "/dest"];
4399        ["read_file"; "/dest"]], "hello, world")],
4400    "copy from source to destination using dd",
4401    "\
4402 This command copies from one source device or file C<src>
4403 to another destination device or file C<dest>.  Normally you
4404 would use this to copy to or from a device or partition, for
4405 example to duplicate a filesystem.
4406
4407 If the destination is a device, it must be as large or larger
4408 than the source file or device, otherwise the copy will fail.
4409 This command cannot do partial copies (see C<guestfs_copy_size>).");
4410
4411   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4412    [InitBasicFS, Always, TestOutputInt (
4413       [["write"; "/file"; "hello, world"];
4414        ["filesize"; "/file"]], 12)],
4415    "return the size of the file in bytes",
4416    "\
4417 This command returns the size of C<file> in bytes.
4418
4419 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4420 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4421 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4422
4423   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4424    [InitBasicFSonLVM, Always, TestOutputList (
4425       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4426        ["lvs"]], ["/dev/VG/LV2"])],
4427    "rename an LVM logical volume",
4428    "\
4429 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4430
4431   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4432    [InitBasicFSonLVM, Always, TestOutputList (
4433       [["umount"; "/"];
4434        ["vg_activate"; "false"; "VG"];
4435        ["vgrename"; "VG"; "VG2"];
4436        ["vg_activate"; "true"; "VG2"];
4437        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4438        ["vgs"]], ["VG2"])],
4439    "rename an LVM volume group",
4440    "\
4441 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4442
4443   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4444    [InitISOFS, Always, TestOutputBuffer (
4445       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4446    "list the contents of a single file in an initrd",
4447    "\
4448 This command unpacks the file C<filename> from the initrd file
4449 called C<initrdpath>.  The filename must be given I<without> the
4450 initial C</> character.
4451
4452 For example, in guestfish you could use the following command
4453 to examine the boot script (usually called C</init>)
4454 contained in a Linux initrd or initramfs image:
4455
4456  initrd-cat /boot/initrd-<version>.img init
4457
4458 See also C<guestfs_initrd_list>.");
4459
4460   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4461    [],
4462    "get the UUID of a physical volume",
4463    "\
4464 This command returns the UUID of the LVM PV C<device>.");
4465
4466   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4467    [],
4468    "get the UUID of a volume group",
4469    "\
4470 This command returns the UUID of the LVM VG named C<vgname>.");
4471
4472   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4473    [],
4474    "get the UUID of a logical volume",
4475    "\
4476 This command returns the UUID of the LVM LV C<device>.");
4477
4478   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4479    [],
4480    "get the PV UUIDs containing the volume group",
4481    "\
4482 Given a VG called C<vgname>, this returns the UUIDs of all
4483 the physical volumes that this volume group resides on.
4484
4485 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4486 calls to associate physical volumes and volume groups.
4487
4488 See also C<guestfs_vglvuuids>.");
4489
4490   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4491    [],
4492    "get the LV UUIDs of all LVs in the volume group",
4493    "\
4494 Given a VG called C<vgname>, this returns the UUIDs of all
4495 the logical volumes created in this volume group.
4496
4497 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4498 calls to associate logical volumes and volume groups.
4499
4500 See also C<guestfs_vgpvuuids>.");
4501
4502   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4503    [InitBasicFS, Always, TestOutputBuffer (
4504       [["write"; "/src"; "hello, world"];
4505        ["copy_size"; "/src"; "/dest"; "5"];
4506        ["read_file"; "/dest"]], "hello")],
4507    "copy size bytes from source to destination using dd",
4508    "\
4509 This command copies exactly C<size> bytes from one source device
4510 or file C<src> to another destination device or file C<dest>.
4511
4512 Note this will fail if the source is too short or if the destination
4513 is not large enough.");
4514
4515   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4516    [InitBasicFSonLVM, Always, TestRun (
4517       [["zero_device"; "/dev/VG/LV"]])],
4518    "write zeroes to an entire device",
4519    "\
4520 This command writes zeroes over the entire C<device>.  Compare
4521 with C<guestfs_zero> which just zeroes the first few blocks of
4522 a device.");
4523
4524   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4525    [InitBasicFS, Always, TestOutput (
4526       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4527        ["cat"; "/hello"]], "hello\n")],
4528    "unpack compressed tarball to directory",
4529    "\
4530 This command uploads and unpacks local file C<tarball> (an
4531 I<xz compressed> tar file) into C<directory>.");
4532
4533   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4534    [],
4535    "pack directory into compressed tarball",
4536    "\
4537 This command packs the contents of C<directory> and downloads
4538 it to local file C<tarball> (as an xz compressed tar archive).");
4539
4540   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4541    [],
4542    "resize an NTFS filesystem",
4543    "\
4544 This command resizes an NTFS filesystem, expanding or
4545 shrinking it to the size of the underlying device.
4546 See also L<ntfsresize(8)>.");
4547
4548   ("vgscan", (RErr, []), 232, [],
4549    [InitEmpty, Always, TestRun (
4550       [["vgscan"]])],
4551    "rescan for LVM physical volumes, volume groups and logical volumes",
4552    "\
4553 This rescans all block devices and rebuilds the list of LVM
4554 physical volumes, volume groups and logical volumes.");
4555
4556   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4557    [InitEmpty, Always, TestRun (
4558       [["part_init"; "/dev/sda"; "mbr"];
4559        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4560        ["part_del"; "/dev/sda"; "1"]])],
4561    "delete a partition",
4562    "\
4563 This command deletes the partition numbered C<partnum> on C<device>.
4564
4565 Note that in the case of MBR partitioning, deleting an
4566 extended partition also deletes any logical partitions
4567 it contains.");
4568
4569   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4570    [InitEmpty, Always, TestOutputTrue (
4571       [["part_init"; "/dev/sda"; "mbr"];
4572        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4573        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4574        ["part_get_bootable"; "/dev/sda"; "1"]])],
4575    "return true if a partition is bootable",
4576    "\
4577 This command returns true if the partition C<partnum> on
4578 C<device> has the bootable flag set.
4579
4580 See also C<guestfs_part_set_bootable>.");
4581
4582   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4583    [InitEmpty, Always, TestOutputInt (
4584       [["part_init"; "/dev/sda"; "mbr"];
4585        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4586        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4587        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4588    "get the MBR type byte (ID byte) from a partition",
4589    "\
4590 Returns the MBR type byte (also known as the ID byte) from
4591 the numbered partition C<partnum>.
4592
4593 Note that only MBR (old DOS-style) partitions have type bytes.
4594 You will get undefined results for other partition table
4595 types (see C<guestfs_part_get_parttype>).");
4596
4597   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4598    [], (* tested by part_get_mbr_id *)
4599    "set the MBR type byte (ID byte) of a partition",
4600    "\
4601 Sets the MBR type byte (also known as the ID byte) of
4602 the numbered partition C<partnum> to C<idbyte>.  Note
4603 that the type bytes quoted in most documentation are
4604 in fact hexadecimal numbers, but usually documented
4605 without any leading \"0x\" which might be confusing.
4606
4607 Note that only MBR (old DOS-style) partitions have type bytes.
4608 You will get undefined results for other partition table
4609 types (see C<guestfs_part_get_parttype>).");
4610
4611   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4612    [InitISOFS, Always, TestOutput (
4613       [["checksum_device"; "md5"; "/dev/sdd"]],
4614       (Digest.to_hex (Digest.file "images/test.iso")))],
4615    "compute MD5, SHAx or CRC checksum of the contents of a device",
4616    "\
4617 This call computes the MD5, SHAx or CRC checksum of the
4618 contents of the device named C<device>.  For the types of
4619 checksums supported see the C<guestfs_checksum> command.");
4620
4621   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4622    [InitNone, Always, TestRun (
4623       [["part_disk"; "/dev/sda"; "mbr"];
4624        ["pvcreate"; "/dev/sda1"];
4625        ["vgcreate"; "VG"; "/dev/sda1"];
4626        ["lvcreate"; "LV"; "VG"; "10"];
4627        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4628    "expand an LV to fill free space",
4629    "\
4630 This expands an existing logical volume C<lv> so that it fills
4631 C<pc>% of the remaining free space in the volume group.  Commonly
4632 you would call this with pc = 100 which expands the logical volume
4633 as much as possible, using all remaining free space in the volume
4634 group.");
4635
4636   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4637    [], (* XXX Augeas code needs tests. *)
4638    "clear Augeas path",
4639    "\
4640 Set the value associated with C<path> to C<NULL>.  This
4641 is the same as the L<augtool(1)> C<clear> command.");
4642
4643   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4644    [InitEmpty, Always, TestOutputInt (
4645       [["get_umask"]], 0o22)],
4646    "get the current umask",
4647    "\
4648 Return the current umask.  By default the umask is C<022>
4649 unless it has been set by calling C<guestfs_umask>.");
4650
4651   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4652    [],
4653    "upload a file to the appliance (internal use only)",
4654    "\
4655 The C<guestfs_debug_upload> command uploads a file to
4656 the libguestfs appliance.
4657
4658 There is no comprehensive help for this command.  You have
4659 to look at the file C<daemon/debug.c> in the libguestfs source
4660 to find out what it is for.");
4661
4662   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4663    [InitBasicFS, Always, TestOutput (
4664       [["base64_in"; "../images/hello.b64"; "/hello"];
4665        ["cat"; "/hello"]], "hello\n")],
4666    "upload base64-encoded data to file",
4667    "\
4668 This command uploads base64-encoded data from C<base64file>
4669 to C<filename>.");
4670
4671   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4672    [],
4673    "download file and encode as base64",
4674    "\
4675 This command downloads the contents of C<filename>, writing
4676 it out to local file C<base64file> encoded as base64.");
4677
4678   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4679    [],
4680    "compute MD5, SHAx or CRC checksum of files in a directory",
4681    "\
4682 This command computes the checksums of all regular files in
4683 C<directory> and then emits a list of those checksums to
4684 the local output file C<sumsfile>.
4685
4686 This can be used for verifying the integrity of a virtual
4687 machine.  However to be properly secure you should pay
4688 attention to the output of the checksum command (it uses
4689 the ones from GNU coreutils).  In particular when the
4690 filename is not printable, coreutils uses a special
4691 backslash syntax.  For more information, see the GNU
4692 coreutils info file.");
4693
4694   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4695    [InitBasicFS, Always, TestOutputBuffer (
4696       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4697        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4698    "fill a file with a repeating pattern of bytes",
4699    "\
4700 This function is like C<guestfs_fill> except that it creates
4701 a new file of length C<len> containing the repeating pattern
4702 of bytes in C<pattern>.  The pattern is truncated if necessary
4703 to ensure the length of the file is exactly C<len> bytes.");
4704
4705   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4706    [InitBasicFS, Always, TestOutput (
4707       [["write"; "/new"; "new file contents"];
4708        ["cat"; "/new"]], "new file contents");
4709     InitBasicFS, Always, TestOutput (
4710       [["write"; "/new"; "\nnew file contents\n"];
4711        ["cat"; "/new"]], "\nnew file contents\n");
4712     InitBasicFS, Always, TestOutput (
4713       [["write"; "/new"; "\n\n"];
4714        ["cat"; "/new"]], "\n\n");
4715     InitBasicFS, Always, TestOutput (
4716       [["write"; "/new"; ""];
4717        ["cat"; "/new"]], "");
4718     InitBasicFS, Always, TestOutput (
4719       [["write"; "/new"; "\n\n\n"];
4720        ["cat"; "/new"]], "\n\n\n");
4721     InitBasicFS, Always, TestOutput (
4722       [["write"; "/new"; "\n"];
4723        ["cat"; "/new"]], "\n")],
4724    "create a new file",
4725    "\
4726 This call creates a file called C<path>.  The content of the
4727 file is the string C<content> (which can contain any 8 bit data).");
4728
4729   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4730    [InitBasicFS, Always, TestOutput (
4731       [["write"; "/new"; "new file contents"];
4732        ["pwrite"; "/new"; "data"; "4"];
4733        ["cat"; "/new"]], "new data contents");
4734     InitBasicFS, Always, TestOutput (
4735       [["write"; "/new"; "new file contents"];
4736        ["pwrite"; "/new"; "is extended"; "9"];
4737        ["cat"; "/new"]], "new file is extended");
4738     InitBasicFS, Always, TestOutput (
4739       [["write"; "/new"; "new file contents"];
4740        ["pwrite"; "/new"; ""; "4"];
4741        ["cat"; "/new"]], "new file contents")],
4742    "write to part of a file",
4743    "\
4744 This command writes to part of a file.  It writes the data
4745 buffer C<content> to the file C<path> starting at offset C<offset>.
4746
4747 This command implements the L<pwrite(2)> system call, and like
4748 that system call it may not write the full data requested.  The
4749 return value is the number of bytes that were actually written
4750 to the file.  This could even be 0, although short writes are
4751 unlikely for regular files in ordinary circumstances.
4752
4753 See also C<guestfs_pread>.");
4754
4755   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4756    [],
4757    "resize an ext2, ext3 or ext4 filesystem (with size)",
4758    "\
4759 This command is the same as C<guestfs_resize2fs> except that it
4760 allows you to specify the new size (in bytes) explicitly.");
4761
4762   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4763    [],
4764    "resize an LVM physical volume (with size)",
4765    "\
4766 This command is the same as C<guestfs_pvresize> except that it
4767 allows you to specify the new size (in bytes) explicitly.");
4768
4769   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4770    [],
4771    "resize an NTFS filesystem (with size)",
4772    "\
4773 This command is the same as C<guestfs_ntfsresize> except that it
4774 allows you to specify the new size (in bytes) explicitly.");
4775
4776   ("available_all_groups", (RStringList "groups", []), 251, [],
4777    [InitNone, Always, TestRun [["available_all_groups"]]],
4778    "return a list of all optional groups",
4779    "\
4780 This command returns a list of all optional groups that this
4781 daemon knows about.  Note this returns both supported and unsupported
4782 groups.  To find out which ones the daemon can actually support
4783 you have to call C<guestfs_available> on each member of the
4784 returned list.
4785
4786 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4787
4788   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4789    [InitBasicFS, Always, TestOutputStruct (
4790       [["fallocate64"; "/a"; "1000000"];
4791        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4792    "preallocate a file in the guest filesystem",
4793    "\
4794 This command preallocates a file (containing zero bytes) named
4795 C<path> of size C<len> bytes.  If the file exists already, it
4796 is overwritten.
4797
4798 Note that this call allocates disk blocks for the file.
4799 To create a sparse file use C<guestfs_truncate_size> instead.
4800
4801 The deprecated call C<guestfs_fallocate> does the same,
4802 but owing to an oversight it only allowed 30 bit lengths
4803 to be specified, effectively limiting the maximum size
4804 of files created through that call to 1GB.
4805
4806 Do not confuse this with the guestfish-specific
4807 C<alloc> and C<sparse> commands which create
4808 a file in the host and attach it as a device.");
4809
4810   ("vfs_label", (RString "label", [Device "device"]), 253, [],
4811    [InitBasicFS, Always, TestOutput (
4812        [["set_e2label"; "/dev/sda1"; "LTEST"];
4813         ["vfs_label"; "/dev/sda1"]], "LTEST")],
4814    "get the filesystem label",
4815    "\
4816 This returns the filesystem label of the filesystem on
4817 C<device>.
4818
4819 If the filesystem is unlabeled, this returns the empty string.");
4820
4821   ("vfs_uuid", (RString "uuid", [Device "device"]), 254, [],
4822    (let uuid = uuidgen () in
4823     [InitBasicFS, Always, TestOutput (
4824        [["set_e2uuid"; "/dev/sda1"; uuid];
4825         ["vfs_uuid"; "/dev/sda1"]], uuid)]),
4826    "get the filesystem UUID",
4827    "\
4828 This returns the filesystem UUID of the filesystem on
4829 C<device>.
4830
4831 If the filesystem does not have a UUID, this returns the empty string.");
4832
4833 ]
4834
4835 let all_functions = non_daemon_functions @ daemon_functions
4836
4837 (* In some places we want the functions to be displayed sorted
4838  * alphabetically, so this is useful:
4839  *)
4840 let all_functions_sorted =
4841   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4842                compare n1 n2) all_functions
4843
4844 (* This is used to generate the src/MAX_PROC_NR file which
4845  * contains the maximum procedure number, a surrogate for the
4846  * ABI version number.  See src/Makefile.am for the details.
4847  *)
4848 let max_proc_nr =
4849   let proc_nrs = List.map (
4850     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4851   ) daemon_functions in
4852   List.fold_left max 0 proc_nrs
4853
4854 (* Field types for structures. *)
4855 type field =
4856   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4857   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4858   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4859   | FUInt32
4860   | FInt32
4861   | FUInt64
4862   | FInt64
4863   | FBytes                      (* Any int measure that counts bytes. *)
4864   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4865   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4866
4867 (* Because we generate extra parsing code for LVM command line tools,
4868  * we have to pull out the LVM columns separately here.
4869  *)
4870 let lvm_pv_cols = [
4871   "pv_name", FString;
4872   "pv_uuid", FUUID;
4873   "pv_fmt", FString;
4874   "pv_size", FBytes;
4875   "dev_size", FBytes;
4876   "pv_free", FBytes;
4877   "pv_used", FBytes;
4878   "pv_attr", FString (* XXX *);
4879   "pv_pe_count", FInt64;
4880   "pv_pe_alloc_count", FInt64;
4881   "pv_tags", FString;
4882   "pe_start", FBytes;
4883   "pv_mda_count", FInt64;
4884   "pv_mda_free", FBytes;
4885   (* Not in Fedora 10:
4886      "pv_mda_size", FBytes;
4887   *)
4888 ]
4889 let lvm_vg_cols = [
4890   "vg_name", FString;
4891   "vg_uuid", FUUID;
4892   "vg_fmt", FString;
4893   "vg_attr", FString (* XXX *);
4894   "vg_size", FBytes;
4895   "vg_free", FBytes;
4896   "vg_sysid", FString;
4897   "vg_extent_size", FBytes;
4898   "vg_extent_count", FInt64;
4899   "vg_free_count", FInt64;
4900   "max_lv", FInt64;
4901   "max_pv", FInt64;
4902   "pv_count", FInt64;
4903   "lv_count", FInt64;
4904   "snap_count", FInt64;
4905   "vg_seqno", FInt64;
4906   "vg_tags", FString;
4907   "vg_mda_count", FInt64;
4908   "vg_mda_free", FBytes;
4909   (* Not in Fedora 10:
4910      "vg_mda_size", FBytes;
4911   *)
4912 ]
4913 let lvm_lv_cols = [
4914   "lv_name", FString;
4915   "lv_uuid", FUUID;
4916   "lv_attr", FString (* XXX *);
4917   "lv_major", FInt64;
4918   "lv_minor", FInt64;
4919   "lv_kernel_major", FInt64;
4920   "lv_kernel_minor", FInt64;
4921   "lv_size", FBytes;
4922   "seg_count", FInt64;
4923   "origin", FString;
4924   "snap_percent", FOptPercent;
4925   "copy_percent", FOptPercent;
4926   "move_pv", FString;
4927   "lv_tags", FString;
4928   "mirror_log", FString;
4929   "modules", FString;
4930 ]
4931
4932 (* Names and fields in all structures (in RStruct and RStructList)
4933  * that we support.
4934  *)
4935 let structs = [
4936   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4937    * not use this struct in any new code.
4938    *)
4939   "int_bool", [
4940     "i", FInt32;                (* for historical compatibility *)
4941     "b", FInt32;                (* for historical compatibility *)
4942   ];
4943
4944   (* LVM PVs, VGs, LVs. *)
4945   "lvm_pv", lvm_pv_cols;
4946   "lvm_vg", lvm_vg_cols;
4947   "lvm_lv", lvm_lv_cols;
4948
4949   (* Column names and types from stat structures.
4950    * NB. Can't use things like 'st_atime' because glibc header files
4951    * define some of these as macros.  Ugh.
4952    *)
4953   "stat", [
4954     "dev", FInt64;
4955     "ino", FInt64;
4956     "mode", FInt64;
4957     "nlink", FInt64;
4958     "uid", FInt64;
4959     "gid", FInt64;
4960     "rdev", FInt64;
4961     "size", FInt64;
4962     "blksize", FInt64;
4963     "blocks", FInt64;
4964     "atime", FInt64;
4965     "mtime", FInt64;
4966     "ctime", FInt64;
4967   ];
4968   "statvfs", [
4969     "bsize", FInt64;
4970     "frsize", FInt64;
4971     "blocks", FInt64;
4972     "bfree", FInt64;
4973     "bavail", FInt64;
4974     "files", FInt64;
4975     "ffree", FInt64;
4976     "favail", FInt64;
4977     "fsid", FInt64;
4978     "flag", FInt64;
4979     "namemax", FInt64;
4980   ];
4981
4982   (* Column names in dirent structure. *)
4983   "dirent", [
4984     "ino", FInt64;
4985     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4986     "ftyp", FChar;
4987     "name", FString;
4988   ];
4989
4990   (* Version numbers. *)
4991   "version", [
4992     "major", FInt64;
4993     "minor", FInt64;
4994     "release", FInt64;
4995     "extra", FString;
4996   ];
4997
4998   (* Extended attribute. *)
4999   "xattr", [
5000     "attrname", FString;
5001     "attrval", FBuffer;
5002   ];
5003
5004   (* Inotify events. *)
5005   "inotify_event", [
5006     "in_wd", FInt64;
5007     "in_mask", FUInt32;
5008     "in_cookie", FUInt32;
5009     "in_name", FString;
5010   ];
5011
5012   (* Partition table entry. *)
5013   "partition", [
5014     "part_num", FInt32;
5015     "part_start", FBytes;
5016     "part_end", FBytes;
5017     "part_size", FBytes;
5018   ];
5019 ] (* end of structs *)
5020
5021 (* Ugh, Java has to be different ..
5022  * These names are also used by the Haskell bindings.
5023  *)
5024 let java_structs = [
5025   "int_bool", "IntBool";
5026   "lvm_pv", "PV";
5027   "lvm_vg", "VG";
5028   "lvm_lv", "LV";
5029   "stat", "Stat";
5030   "statvfs", "StatVFS";
5031   "dirent", "Dirent";
5032   "version", "Version";
5033   "xattr", "XAttr";
5034   "inotify_event", "INotifyEvent";
5035   "partition", "Partition";
5036 ]
5037
5038 (* What structs are actually returned. *)
5039 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
5040
5041 (* Returns a list of RStruct/RStructList structs that are returned
5042  * by any function.  Each element of returned list is a pair:
5043  *
5044  * (structname, RStructOnly)
5045  *    == there exists function which returns RStruct (_, structname)
5046  * (structname, RStructListOnly)
5047  *    == there exists function which returns RStructList (_, structname)
5048  * (structname, RStructAndList)
5049  *    == there are functions returning both RStruct (_, structname)
5050  *                                      and RStructList (_, structname)
5051  *)
5052 let rstructs_used_by functions =
5053   (* ||| is a "logical OR" for rstructs_used_t *)
5054   let (|||) a b =
5055     match a, b with
5056     | RStructAndList, _
5057     | _, RStructAndList -> RStructAndList
5058     | RStructOnly, RStructListOnly
5059     | RStructListOnly, RStructOnly -> RStructAndList
5060     | RStructOnly, RStructOnly -> RStructOnly
5061     | RStructListOnly, RStructListOnly -> RStructListOnly
5062   in
5063
5064   let h = Hashtbl.create 13 in
5065
5066   (* if elem->oldv exists, update entry using ||| operator,
5067    * else just add elem->newv to the hash
5068    *)
5069   let update elem newv =
5070     try  let oldv = Hashtbl.find h elem in
5071          Hashtbl.replace h elem (newv ||| oldv)
5072     with Not_found -> Hashtbl.add h elem newv
5073   in
5074
5075   List.iter (
5076     fun (_, style, _, _, _, _, _) ->
5077       match fst style with
5078       | RStruct (_, structname) -> update structname RStructOnly
5079       | RStructList (_, structname) -> update structname RStructListOnly
5080       | _ -> ()
5081   ) functions;
5082
5083   (* return key->values as a list of (key,value) *)
5084   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5085
5086 (* Used for testing language bindings. *)
5087 type callt =
5088   | CallString of string
5089   | CallOptString of string option
5090   | CallStringList of string list
5091   | CallInt of int
5092   | CallInt64 of int64
5093   | CallBool of bool
5094   | CallBuffer of string
5095
5096 (* Used to memoize the result of pod2text. *)
5097 let pod2text_memo_filename = "src/.pod2text.data"
5098 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5099   try
5100     let chan = open_in pod2text_memo_filename in
5101     let v = input_value chan in
5102     close_in chan;
5103     v
5104   with
5105     _ -> Hashtbl.create 13
5106 let pod2text_memo_updated () =
5107   let chan = open_out pod2text_memo_filename in
5108   output_value chan pod2text_memo;
5109   close_out chan
5110
5111 (* Useful functions.
5112  * Note we don't want to use any external OCaml libraries which
5113  * makes this a bit harder than it should be.
5114  *)
5115 module StringMap = Map.Make (String)
5116
5117 let failwithf fs = ksprintf failwith fs
5118
5119 let unique = let i = ref 0 in fun () -> incr i; !i
5120
5121 let replace_char s c1 c2 =
5122   let s2 = String.copy s in
5123   let r = ref false in
5124   for i = 0 to String.length s2 - 1 do
5125     if String.unsafe_get s2 i = c1 then (
5126       String.unsafe_set s2 i c2;
5127       r := true
5128     )
5129   done;
5130   if not !r then s else s2
5131
5132 let isspace c =
5133   c = ' '
5134   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5135
5136 let triml ?(test = isspace) str =
5137   let i = ref 0 in
5138   let n = ref (String.length str) in
5139   while !n > 0 && test str.[!i]; do
5140     decr n;
5141     incr i
5142   done;
5143   if !i = 0 then str
5144   else String.sub str !i !n
5145
5146 let trimr ?(test = isspace) str =
5147   let n = ref (String.length str) in
5148   while !n > 0 && test str.[!n-1]; do
5149     decr n
5150   done;
5151   if !n = String.length str then str
5152   else String.sub str 0 !n
5153
5154 let trim ?(test = isspace) str =
5155   trimr ~test (triml ~test str)
5156
5157 let rec find s sub =
5158   let len = String.length s in
5159   let sublen = String.length sub in
5160   let rec loop i =
5161     if i <= len-sublen then (
5162       let rec loop2 j =
5163         if j < sublen then (
5164           if s.[i+j] = sub.[j] then loop2 (j+1)
5165           else -1
5166         ) else
5167           i (* found *)
5168       in
5169       let r = loop2 0 in
5170       if r = -1 then loop (i+1) else r
5171     ) else
5172       -1 (* not found *)
5173   in
5174   loop 0
5175
5176 let rec replace_str s s1 s2 =
5177   let len = String.length s in
5178   let sublen = String.length s1 in
5179   let i = find s s1 in
5180   if i = -1 then s
5181   else (
5182     let s' = String.sub s 0 i in
5183     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5184     s' ^ s2 ^ replace_str s'' s1 s2
5185   )
5186
5187 let rec string_split sep str =
5188   let len = String.length str in
5189   let seplen = String.length sep in
5190   let i = find str sep in
5191   if i = -1 then [str]
5192   else (
5193     let s' = String.sub str 0 i in
5194     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5195     s' :: string_split sep s''
5196   )
5197
5198 let files_equal n1 n2 =
5199   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5200   match Sys.command cmd with
5201   | 0 -> true
5202   | 1 -> false
5203   | i -> failwithf "%s: failed with error code %d" cmd i
5204
5205 let rec filter_map f = function
5206   | [] -> []
5207   | x :: xs ->
5208       match f x with
5209       | Some y -> y :: filter_map f xs
5210       | None -> filter_map f xs
5211
5212 let rec find_map f = function
5213   | [] -> raise Not_found
5214   | x :: xs ->
5215       match f x with
5216       | Some y -> y
5217       | None -> find_map f xs
5218
5219 let iteri f xs =
5220   let rec loop i = function
5221     | [] -> ()
5222     | x :: xs -> f i x; loop (i+1) xs
5223   in
5224   loop 0 xs
5225
5226 let mapi f xs =
5227   let rec loop i = function
5228     | [] -> []
5229     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5230   in
5231   loop 0 xs
5232
5233 let count_chars c str =
5234   let count = ref 0 in
5235   for i = 0 to String.length str - 1 do
5236     if c = String.unsafe_get str i then incr count
5237   done;
5238   !count
5239
5240 let explode str =
5241   let r = ref [] in
5242   for i = 0 to String.length str - 1 do
5243     let c = String.unsafe_get str i in
5244     r := c :: !r;
5245   done;
5246   List.rev !r
5247
5248 let map_chars f str =
5249   List.map f (explode str)
5250
5251 let name_of_argt = function
5252   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5253   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5254   | FileIn n | FileOut n | BufferIn n -> n
5255
5256 let java_name_of_struct typ =
5257   try List.assoc typ java_structs
5258   with Not_found ->
5259     failwithf
5260       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5261
5262 let cols_of_struct typ =
5263   try List.assoc typ structs
5264   with Not_found ->
5265     failwithf "cols_of_struct: unknown struct %s" typ
5266
5267 let seq_of_test = function
5268   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5269   | TestOutputListOfDevices (s, _)
5270   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5271   | TestOutputTrue s | TestOutputFalse s
5272   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5273   | TestOutputStruct (s, _)
5274   | TestLastFail s -> s
5275
5276 (* Handling for function flags. *)
5277 let protocol_limit_warning =
5278   "Because of the message protocol, there is a transfer limit
5279 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5280
5281 let danger_will_robinson =
5282   "B<This command is dangerous.  Without careful use you
5283 can easily destroy all your data>."
5284
5285 let deprecation_notice flags =
5286   try
5287     let alt =
5288       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5289     let txt =
5290       sprintf "This function is deprecated.
5291 In new code, use the C<%s> call instead.
5292
5293 Deprecated functions will not be removed from the API, but the
5294 fact that they are deprecated indicates that there are problems
5295 with correct use of these functions." alt in
5296     Some txt
5297   with
5298     Not_found -> None
5299
5300 (* Create list of optional groups. *)
5301 let optgroups =
5302   let h = Hashtbl.create 13 in
5303   List.iter (
5304     fun (name, _, _, flags, _, _, _) ->
5305       List.iter (
5306         function
5307         | Optional group ->
5308             let names = try Hashtbl.find h group with Not_found -> [] in
5309             Hashtbl.replace h group (name :: names)
5310         | _ -> ()
5311       ) flags
5312   ) daemon_functions;
5313   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5314   let groups =
5315     List.map (
5316       fun group -> group, List.sort compare (Hashtbl.find h group)
5317     ) groups in
5318   List.sort (fun x y -> compare (fst x) (fst y)) groups
5319
5320 (* Check function names etc. for consistency. *)
5321 let check_functions () =
5322   let contains_uppercase str =
5323     let len = String.length str in
5324     let rec loop i =
5325       if i >= len then false
5326       else (
5327         let c = str.[i] in
5328         if c >= 'A' && c <= 'Z' then true
5329         else loop (i+1)
5330       )
5331     in
5332     loop 0
5333   in
5334
5335   (* Check function names. *)
5336   List.iter (
5337     fun (name, _, _, _, _, _, _) ->
5338       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5339         failwithf "function name %s does not need 'guestfs' prefix" name;
5340       if name = "" then
5341         failwithf "function name is empty";
5342       if name.[0] < 'a' || name.[0] > 'z' then
5343         failwithf "function name %s must start with lowercase a-z" name;
5344       if String.contains name '-' then
5345         failwithf "function name %s should not contain '-', use '_' instead."
5346           name
5347   ) all_functions;
5348
5349   (* Check function parameter/return names. *)
5350   List.iter (
5351     fun (name, style, _, _, _, _, _) ->
5352       let check_arg_ret_name n =
5353         if contains_uppercase n then
5354           failwithf "%s param/ret %s should not contain uppercase chars"
5355             name n;
5356         if String.contains n '-' || String.contains n '_' then
5357           failwithf "%s param/ret %s should not contain '-' or '_'"
5358             name n;
5359         if n = "value" then
5360           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;
5361         if n = "int" || n = "char" || n = "short" || n = "long" then
5362           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5363         if n = "i" || n = "n" then
5364           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5365         if n = "argv" || n = "args" then
5366           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5367
5368         (* List Haskell, OCaml and C keywords here.
5369          * http://www.haskell.org/haskellwiki/Keywords
5370          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5371          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5372          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5373          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5374          * Omitting _-containing words, since they're handled above.
5375          * Omitting the OCaml reserved word, "val", is ok,
5376          * and saves us from renaming several parameters.
5377          *)
5378         let reserved = [
5379           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5380           "char"; "class"; "const"; "constraint"; "continue"; "data";
5381           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5382           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5383           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5384           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5385           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5386           "interface";
5387           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5388           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5389           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5390           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5391           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5392           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5393           "volatile"; "when"; "where"; "while";
5394           ] in
5395         if List.mem n reserved then
5396           failwithf "%s has param/ret using reserved word %s" name n;
5397       in
5398
5399       (match fst style with
5400        | RErr -> ()
5401        | RInt n | RInt64 n | RBool n
5402        | RConstString n | RConstOptString n | RString n
5403        | RStringList n | RStruct (n, _) | RStructList (n, _)
5404        | RHashtable n | RBufferOut n ->
5405            check_arg_ret_name n
5406       );
5407       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5408   ) all_functions;
5409
5410   (* Check short descriptions. *)
5411   List.iter (
5412     fun (name, _, _, _, _, shortdesc, _) ->
5413       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5414         failwithf "short description of %s should begin with lowercase." name;
5415       let c = shortdesc.[String.length shortdesc-1] in
5416       if c = '\n' || c = '.' then
5417         failwithf "short description of %s should not end with . or \\n." name
5418   ) all_functions;
5419
5420   (* Check long descriptions. *)
5421   List.iter (
5422     fun (name, _, _, _, _, _, longdesc) ->
5423       if longdesc.[String.length longdesc-1] = '\n' then
5424         failwithf "long description of %s should not end with \\n." name
5425   ) all_functions;
5426
5427   (* Check proc_nrs. *)
5428   List.iter (
5429     fun (name, _, proc_nr, _, _, _, _) ->
5430       if proc_nr <= 0 then
5431         failwithf "daemon function %s should have proc_nr > 0" name
5432   ) daemon_functions;
5433
5434   List.iter (
5435     fun (name, _, proc_nr, _, _, _, _) ->
5436       if proc_nr <> -1 then
5437         failwithf "non-daemon function %s should have proc_nr -1" name
5438   ) non_daemon_functions;
5439
5440   let proc_nrs =
5441     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5442       daemon_functions in
5443   let proc_nrs =
5444     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5445   let rec loop = function
5446     | [] -> ()
5447     | [_] -> ()
5448     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5449         loop rest
5450     | (name1,nr1) :: (name2,nr2) :: _ ->
5451         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5452           name1 name2 nr1 nr2
5453   in
5454   loop proc_nrs;
5455
5456   (* Check tests. *)
5457   List.iter (
5458     function
5459       (* Ignore functions that have no tests.  We generate a
5460        * warning when the user does 'make check' instead.
5461        *)
5462     | name, _, _, _, [], _, _ -> ()
5463     | name, _, _, _, tests, _, _ ->
5464         let funcs =
5465           List.map (
5466             fun (_, _, test) ->
5467               match seq_of_test test with
5468               | [] ->
5469                   failwithf "%s has a test containing an empty sequence" name
5470               | cmds -> List.map List.hd cmds
5471           ) tests in
5472         let funcs = List.flatten funcs in
5473
5474         let tested = List.mem name funcs in
5475
5476         if not tested then
5477           failwithf "function %s has tests but does not test itself" name
5478   ) all_functions
5479
5480 (* 'pr' prints to the current output file. *)
5481 let chan = ref Pervasives.stdout
5482 let lines = ref 0
5483 let pr fs =
5484   ksprintf
5485     (fun str ->
5486        let i = count_chars '\n' str in
5487        lines := !lines + i;
5488        output_string !chan str
5489     ) fs
5490
5491 let copyright_years =
5492   let this_year = 1900 + (localtime (time ())).tm_year in
5493   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5494
5495 (* Generate a header block in a number of standard styles. *)
5496 type comment_style =
5497     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5498 type license = GPLv2plus | LGPLv2plus
5499
5500 let generate_header ?(extra_inputs = []) comment license =
5501   let inputs = "src/generator.ml" :: extra_inputs in
5502   let c = match comment with
5503     | CStyle ->         pr "/* "; " *"
5504     | CPlusPlusStyle -> pr "// "; "//"
5505     | HashStyle ->      pr "# ";  "#"
5506     | OCamlStyle ->     pr "(* "; " *"
5507     | HaskellStyle ->   pr "{- "; "  " in
5508   pr "libguestfs generated file\n";
5509   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5510   List.iter (pr "%s   %s\n" c) inputs;
5511   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5512   pr "%s\n" c;
5513   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5514   pr "%s\n" c;
5515   (match license with
5516    | GPLv2plus ->
5517        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5518        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5519        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5520        pr "%s (at your option) any later version.\n" c;
5521        pr "%s\n" c;
5522        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5523        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5524        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5525        pr "%s GNU General Public License for more details.\n" c;
5526        pr "%s\n" c;
5527        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5528        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5529        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5530
5531    | LGPLv2plus ->
5532        pr "%s This library is free software; you can redistribute it and/or\n" c;
5533        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5534        pr "%s License as published by the Free Software Foundation; either\n" c;
5535        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5536        pr "%s\n" c;
5537        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5538        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5539        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5540        pr "%s Lesser General Public License for more details.\n" c;
5541        pr "%s\n" c;
5542        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5543        pr "%s License along with this library; if not, write to the Free Software\n" c;
5544        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5545   );
5546   (match comment with
5547    | CStyle -> pr " */\n"
5548    | CPlusPlusStyle
5549    | HashStyle -> ()
5550    | OCamlStyle -> pr " *)\n"
5551    | HaskellStyle -> pr "-}\n"
5552   );
5553   pr "\n"
5554
5555 (* Start of main code generation functions below this line. *)
5556
5557 (* Generate the pod documentation for the C API. *)
5558 let rec generate_actions_pod () =
5559   List.iter (
5560     fun (shortname, style, _, flags, _, _, longdesc) ->
5561       if not (List.mem NotInDocs flags) then (
5562         let name = "guestfs_" ^ shortname in
5563         pr "=head2 %s\n\n" name;
5564         pr " ";
5565         generate_prototype ~extern:false ~handle:"g" name style;
5566         pr "\n\n";
5567         pr "%s\n\n" longdesc;
5568         (match fst style with
5569          | RErr ->
5570              pr "This function returns 0 on success or -1 on error.\n\n"
5571          | RInt _ ->
5572              pr "On error this function returns -1.\n\n"
5573          | RInt64 _ ->
5574              pr "On error this function returns -1.\n\n"
5575          | RBool _ ->
5576              pr "This function returns a C truth value on success or -1 on error.\n\n"
5577          | RConstString _ ->
5578              pr "This function returns a string, or NULL on error.
5579 The string is owned by the guest handle and must I<not> be freed.\n\n"
5580          | RConstOptString _ ->
5581              pr "This function returns a string which may be NULL.
5582 There is way to return an error from this function.
5583 The string is owned by the guest handle and must I<not> be freed.\n\n"
5584          | RString _ ->
5585              pr "This function returns a string, or NULL on error.
5586 I<The caller must free the returned string after use>.\n\n"
5587          | RStringList _ ->
5588              pr "This function returns a NULL-terminated array of strings
5589 (like L<environ(3)>), or NULL if there was an error.
5590 I<The caller must free the strings and the array after use>.\n\n"
5591          | RStruct (_, typ) ->
5592              pr "This function returns a C<struct guestfs_%s *>,
5593 or NULL if there was an error.
5594 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5595          | RStructList (_, typ) ->
5596              pr "This function returns a C<struct guestfs_%s_list *>
5597 (see E<lt>guestfs-structs.hE<gt>),
5598 or NULL if there was an error.
5599 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5600          | RHashtable _ ->
5601              pr "This function returns a NULL-terminated array of
5602 strings, or NULL if there was an error.
5603 The array of strings will always have length C<2n+1>, where
5604 C<n> keys and values alternate, followed by the trailing NULL entry.
5605 I<The caller must free the strings and the array after use>.\n\n"
5606          | RBufferOut _ ->
5607              pr "This function returns a buffer, or NULL on error.
5608 The size of the returned buffer is written to C<*size_r>.
5609 I<The caller must free the returned buffer after use>.\n\n"
5610         );
5611         if List.mem ProtocolLimitWarning flags then
5612           pr "%s\n\n" protocol_limit_warning;
5613         if List.mem DangerWillRobinson flags then
5614           pr "%s\n\n" danger_will_robinson;
5615         match deprecation_notice flags with
5616         | None -> ()
5617         | Some txt -> pr "%s\n\n" txt
5618       )
5619   ) all_functions_sorted
5620
5621 and generate_structs_pod () =
5622   (* Structs documentation. *)
5623   List.iter (
5624     fun (typ, cols) ->
5625       pr "=head2 guestfs_%s\n" typ;
5626       pr "\n";
5627       pr " struct guestfs_%s {\n" typ;
5628       List.iter (
5629         function
5630         | name, FChar -> pr "   char %s;\n" name
5631         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5632         | name, FInt32 -> pr "   int32_t %s;\n" name
5633         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5634         | name, FInt64 -> pr "   int64_t %s;\n" name
5635         | name, FString -> pr "   char *%s;\n" name
5636         | name, FBuffer ->
5637             pr "   /* The next two fields describe a byte array. */\n";
5638             pr "   uint32_t %s_len;\n" name;
5639             pr "   char *%s;\n" name
5640         | name, FUUID ->
5641             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5642             pr "   char %s[32];\n" name
5643         | name, FOptPercent ->
5644             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5645             pr "   float %s;\n" name
5646       ) cols;
5647       pr " };\n";
5648       pr " \n";
5649       pr " struct guestfs_%s_list {\n" typ;
5650       pr "   uint32_t len; /* Number of elements in list. */\n";
5651       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5652       pr " };\n";
5653       pr " \n";
5654       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5655       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5656         typ typ;
5657       pr "\n"
5658   ) structs
5659
5660 and generate_availability_pod () =
5661   (* Availability documentation. *)
5662   pr "=over 4\n";
5663   pr "\n";
5664   List.iter (
5665     fun (group, functions) ->
5666       pr "=item B<%s>\n" group;
5667       pr "\n";
5668       pr "The following functions:\n";
5669       List.iter (pr "L</guestfs_%s>\n") functions;
5670       pr "\n"
5671   ) optgroups;
5672   pr "=back\n";
5673   pr "\n"
5674
5675 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5676  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5677  *
5678  * We have to use an underscore instead of a dash because otherwise
5679  * rpcgen generates incorrect code.
5680  *
5681  * This header is NOT exported to clients, but see also generate_structs_h.
5682  *)
5683 and generate_xdr () =
5684   generate_header CStyle LGPLv2plus;
5685
5686   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5687   pr "typedef string str<>;\n";
5688   pr "\n";
5689
5690   (* Internal structures. *)
5691   List.iter (
5692     function
5693     | typ, cols ->
5694         pr "struct guestfs_int_%s {\n" typ;
5695         List.iter (function
5696                    | name, FChar -> pr "  char %s;\n" name
5697                    | name, FString -> pr "  string %s<>;\n" name
5698                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5699                    | name, FUUID -> pr "  opaque %s[32];\n" name
5700                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5701                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5702                    | name, FOptPercent -> pr "  float %s;\n" name
5703                   ) cols;
5704         pr "};\n";
5705         pr "\n";
5706         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5707         pr "\n";
5708   ) structs;
5709
5710   List.iter (
5711     fun (shortname, style, _, _, _, _, _) ->
5712       let name = "guestfs_" ^ shortname in
5713
5714       (match snd style with
5715        | [] -> ()
5716        | args ->
5717            pr "struct %s_args {\n" name;
5718            List.iter (
5719              function
5720              | Pathname n | Device n | Dev_or_Path n | String n ->
5721                  pr "  string %s<>;\n" n
5722              | OptString n -> pr "  str *%s;\n" n
5723              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5724              | Bool n -> pr "  bool %s;\n" n
5725              | Int n -> pr "  int %s;\n" n
5726              | Int64 n -> pr "  hyper %s;\n" n
5727              | BufferIn n ->
5728                  pr "  opaque %s<>;\n" n
5729              | FileIn _ | FileOut _ -> ()
5730            ) args;
5731            pr "};\n\n"
5732       );
5733       (match fst style with
5734        | RErr -> ()
5735        | RInt n ->
5736            pr "struct %s_ret {\n" name;
5737            pr "  int %s;\n" n;
5738            pr "};\n\n"
5739        | RInt64 n ->
5740            pr "struct %s_ret {\n" name;
5741            pr "  hyper %s;\n" n;
5742            pr "};\n\n"
5743        | RBool n ->
5744            pr "struct %s_ret {\n" name;
5745            pr "  bool %s;\n" n;
5746            pr "};\n\n"
5747        | RConstString _ | RConstOptString _ ->
5748            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5749        | RString n ->
5750            pr "struct %s_ret {\n" name;
5751            pr "  string %s<>;\n" n;
5752            pr "};\n\n"
5753        | RStringList n ->
5754            pr "struct %s_ret {\n" name;
5755            pr "  str %s<>;\n" n;
5756            pr "};\n\n"
5757        | RStruct (n, typ) ->
5758            pr "struct %s_ret {\n" name;
5759            pr "  guestfs_int_%s %s;\n" typ n;
5760            pr "};\n\n"
5761        | RStructList (n, typ) ->
5762            pr "struct %s_ret {\n" name;
5763            pr "  guestfs_int_%s_list %s;\n" typ n;
5764            pr "};\n\n"
5765        | RHashtable n ->
5766            pr "struct %s_ret {\n" name;
5767            pr "  str %s<>;\n" n;
5768            pr "};\n\n"
5769        | RBufferOut n ->
5770            pr "struct %s_ret {\n" name;
5771            pr "  opaque %s<>;\n" n;
5772            pr "};\n\n"
5773       );
5774   ) daemon_functions;
5775
5776   (* Table of procedure numbers. *)
5777   pr "enum guestfs_procedure {\n";
5778   List.iter (
5779     fun (shortname, _, proc_nr, _, _, _, _) ->
5780       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5781   ) daemon_functions;
5782   pr "  GUESTFS_PROC_NR_PROCS\n";
5783   pr "};\n";
5784   pr "\n";
5785
5786   (* Having to choose a maximum message size is annoying for several
5787    * reasons (it limits what we can do in the API), but it (a) makes
5788    * the protocol a lot simpler, and (b) provides a bound on the size
5789    * of the daemon which operates in limited memory space.
5790    *)
5791   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5792   pr "\n";
5793
5794   (* Message header, etc. *)
5795   pr "\
5796 /* The communication protocol is now documented in the guestfs(3)
5797  * manpage.
5798  */
5799
5800 const GUESTFS_PROGRAM = 0x2000F5F5;
5801 const GUESTFS_PROTOCOL_VERSION = 1;
5802
5803 /* These constants must be larger than any possible message length. */
5804 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5805 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5806
5807 enum guestfs_message_direction {
5808   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5809   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5810 };
5811
5812 enum guestfs_message_status {
5813   GUESTFS_STATUS_OK = 0,
5814   GUESTFS_STATUS_ERROR = 1
5815 };
5816
5817 const GUESTFS_ERROR_LEN = 256;
5818
5819 struct guestfs_message_error {
5820   string error_message<GUESTFS_ERROR_LEN>;
5821 };
5822
5823 struct guestfs_message_header {
5824   unsigned prog;                     /* GUESTFS_PROGRAM */
5825   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5826   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5827   guestfs_message_direction direction;
5828   unsigned serial;                   /* message serial number */
5829   guestfs_message_status status;
5830 };
5831
5832 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5833
5834 struct guestfs_chunk {
5835   int cancel;                        /* if non-zero, transfer is cancelled */
5836   /* data size is 0 bytes if the transfer has finished successfully */
5837   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5838 };
5839 "
5840
5841 (* Generate the guestfs-structs.h file. *)
5842 and generate_structs_h () =
5843   generate_header CStyle LGPLv2plus;
5844
5845   (* This is a public exported header file containing various
5846    * structures.  The structures are carefully written to have
5847    * exactly the same in-memory format as the XDR structures that
5848    * we use on the wire to the daemon.  The reason for creating
5849    * copies of these structures here is just so we don't have to
5850    * export the whole of guestfs_protocol.h (which includes much
5851    * unrelated and XDR-dependent stuff that we don't want to be
5852    * public, or required by clients).
5853    *
5854    * To reiterate, we will pass these structures to and from the
5855    * client with a simple assignment or memcpy, so the format
5856    * must be identical to what rpcgen / the RFC defines.
5857    *)
5858
5859   (* Public structures. *)
5860   List.iter (
5861     fun (typ, cols) ->
5862       pr "struct guestfs_%s {\n" typ;
5863       List.iter (
5864         function
5865         | name, FChar -> pr "  char %s;\n" name
5866         | name, FString -> pr "  char *%s;\n" name
5867         | name, FBuffer ->
5868             pr "  uint32_t %s_len;\n" name;
5869             pr "  char *%s;\n" name
5870         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5871         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5872         | name, FInt32 -> pr "  int32_t %s;\n" name
5873         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5874         | name, FInt64 -> pr "  int64_t %s;\n" name
5875         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5876       ) cols;
5877       pr "};\n";
5878       pr "\n";
5879       pr "struct guestfs_%s_list {\n" typ;
5880       pr "  uint32_t len;\n";
5881       pr "  struct guestfs_%s *val;\n" typ;
5882       pr "};\n";
5883       pr "\n";
5884       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5885       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5886       pr "\n"
5887   ) structs
5888
5889 (* Generate the guestfs-actions.h file. *)
5890 and generate_actions_h () =
5891   generate_header CStyle LGPLv2plus;
5892   List.iter (
5893     fun (shortname, style, _, _, _, _, _) ->
5894       let name = "guestfs_" ^ shortname in
5895       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5896         name style
5897   ) all_functions
5898
5899 (* Generate the guestfs-internal-actions.h file. *)
5900 and generate_internal_actions_h () =
5901   generate_header CStyle LGPLv2plus;
5902   List.iter (
5903     fun (shortname, style, _, _, _, _, _) ->
5904       let name = "guestfs__" ^ shortname in
5905       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5906         name style
5907   ) non_daemon_functions
5908
5909 (* Generate the client-side dispatch stubs. *)
5910 and generate_client_actions () =
5911   generate_header CStyle LGPLv2plus;
5912
5913   pr "\
5914 #include <stdio.h>
5915 #include <stdlib.h>
5916 #include <stdint.h>
5917 #include <string.h>
5918 #include <inttypes.h>
5919
5920 #include \"guestfs.h\"
5921 #include \"guestfs-internal.h\"
5922 #include \"guestfs-internal-actions.h\"
5923 #include \"guestfs_protocol.h\"
5924
5925 #define error guestfs_error
5926 //#define perrorf guestfs_perrorf
5927 #define safe_malloc guestfs_safe_malloc
5928 #define safe_realloc guestfs_safe_realloc
5929 //#define safe_strdup guestfs_safe_strdup
5930 #define safe_memdup guestfs_safe_memdup
5931
5932 /* Check the return message from a call for validity. */
5933 static int
5934 check_reply_header (guestfs_h *g,
5935                     const struct guestfs_message_header *hdr,
5936                     unsigned int proc_nr, unsigned int serial)
5937 {
5938   if (hdr->prog != GUESTFS_PROGRAM) {
5939     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5940     return -1;
5941   }
5942   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5943     error (g, \"wrong protocol version (%%d/%%d)\",
5944            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5945     return -1;
5946   }
5947   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5948     error (g, \"unexpected message direction (%%d/%%d)\",
5949            hdr->direction, GUESTFS_DIRECTION_REPLY);
5950     return -1;
5951   }
5952   if (hdr->proc != proc_nr) {
5953     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5954     return -1;
5955   }
5956   if (hdr->serial != serial) {
5957     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5958     return -1;
5959   }
5960
5961   return 0;
5962 }
5963
5964 /* Check we are in the right state to run a high-level action. */
5965 static int
5966 check_state (guestfs_h *g, const char *caller)
5967 {
5968   if (!guestfs__is_ready (g)) {
5969     if (guestfs__is_config (g) || guestfs__is_launching (g))
5970       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5971         caller);
5972     else
5973       error (g, \"%%s called from the wrong state, %%d != READY\",
5974         caller, guestfs__get_state (g));
5975     return -1;
5976   }
5977   return 0;
5978 }
5979
5980 ";
5981
5982   let error_code_of = function
5983     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5984     | RConstString _ | RConstOptString _
5985     | RString _ | RStringList _
5986     | RStruct _ | RStructList _
5987     | RHashtable _ | RBufferOut _ -> "NULL"
5988   in
5989
5990   (* Generate code to check String-like parameters are not passed in
5991    * as NULL (returning an error if they are).
5992    *)
5993   let check_null_strings shortname style =
5994     let pr_newline = ref false in
5995     List.iter (
5996       function
5997       (* parameters which should not be NULL *)
5998       | String n
5999       | Device n
6000       | Pathname n
6001       | Dev_or_Path n
6002       | FileIn n
6003       | FileOut n
6004       | BufferIn n
6005       | StringList n
6006       | DeviceList n ->
6007           pr "  if (%s == NULL) {\n" n;
6008           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
6009           pr "           \"%s\", \"%s\");\n" shortname n;
6010           pr "    return %s;\n" (error_code_of (fst style));
6011           pr "  }\n";
6012           pr_newline := true
6013
6014       (* can be NULL *)
6015       | OptString _
6016
6017       (* not applicable *)
6018       | Bool _
6019       | Int _
6020       | Int64 _ -> ()
6021     ) (snd style);
6022
6023     if !pr_newline then pr "\n";
6024   in
6025
6026   (* Generate code to generate guestfish call traces. *)
6027   let trace_call shortname style =
6028     pr "  if (guestfs__get_trace (g)) {\n";
6029
6030     let needs_i =
6031       List.exists (function
6032                    | StringList _ | DeviceList _ -> true
6033                    | _ -> false) (snd style) in
6034     if needs_i then (
6035       pr "    size_t i;\n";
6036       pr "\n"
6037     );
6038
6039     pr "    printf (\"%s\");\n" shortname;
6040     List.iter (
6041       function
6042       | String n                        (* strings *)
6043       | Device n
6044       | Pathname n
6045       | Dev_or_Path n
6046       | FileIn n
6047       | FileOut n
6048       | BufferIn n ->
6049           (* guestfish doesn't support string escaping, so neither do we *)
6050           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
6051       | OptString n ->                  (* string option *)
6052           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
6053           pr "    else printf (\" null\");\n"
6054       | StringList n
6055       | DeviceList n ->                 (* string list *)
6056           pr "    putchar (' ');\n";
6057           pr "    putchar ('\"');\n";
6058           pr "    for (i = 0; %s[i]; ++i) {\n" n;
6059           pr "      if (i > 0) putchar (' ');\n";
6060           pr "      fputs (%s[i], stdout);\n" n;
6061           pr "    }\n";
6062           pr "    putchar ('\"');\n";
6063       | Bool n ->                       (* boolean *)
6064           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
6065       | Int n ->                        (* int *)
6066           pr "    printf (\" %%d\", %s);\n" n
6067       | Int64 n ->
6068           pr "    printf (\" %%\" PRIi64, %s);\n" n
6069     ) (snd style);
6070     pr "    putchar ('\\n');\n";
6071     pr "  }\n";
6072     pr "\n";
6073   in
6074
6075   (* For non-daemon functions, generate a wrapper around each function. *)
6076   List.iter (
6077     fun (shortname, style, _, _, _, _, _) ->
6078       let name = "guestfs_" ^ shortname in
6079
6080       generate_prototype ~extern:false ~semicolon:false ~newline:true
6081         ~handle:"g" name style;
6082       pr "{\n";
6083       check_null_strings shortname style;
6084       trace_call shortname style;
6085       pr "  return guestfs__%s " shortname;
6086       generate_c_call_args ~handle:"g" style;
6087       pr ";\n";
6088       pr "}\n";
6089       pr "\n"
6090   ) non_daemon_functions;
6091
6092   (* Client-side stubs for each function. *)
6093   List.iter (
6094     fun (shortname, style, _, _, _, _, _) ->
6095       let name = "guestfs_" ^ shortname in
6096       let error_code = error_code_of (fst style) in
6097
6098       (* Generate the action stub. *)
6099       generate_prototype ~extern:false ~semicolon:false ~newline:true
6100         ~handle:"g" name style;
6101
6102       pr "{\n";
6103
6104       (match snd style with
6105        | [] -> ()
6106        | _ -> pr "  struct %s_args args;\n" name
6107       );
6108
6109       pr "  guestfs_message_header hdr;\n";
6110       pr "  guestfs_message_error err;\n";
6111       let has_ret =
6112         match fst style with
6113         | RErr -> false
6114         | RConstString _ | RConstOptString _ ->
6115             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6116         | RInt _ | RInt64 _
6117         | RBool _ | RString _ | RStringList _
6118         | RStruct _ | RStructList _
6119         | RHashtable _ | RBufferOut _ ->
6120             pr "  struct %s_ret ret;\n" name;
6121             true in
6122
6123       pr "  int serial;\n";
6124       pr "  int r;\n";
6125       pr "\n";
6126       check_null_strings shortname style;
6127       trace_call shortname style;
6128       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6129         shortname error_code;
6130       pr "  guestfs___set_busy (g);\n";
6131       pr "\n";
6132
6133       (* Send the main header and arguments. *)
6134       (match snd style with
6135        | [] ->
6136            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6137              (String.uppercase shortname)
6138        | args ->
6139            List.iter (
6140              function
6141              | Pathname n | Device n | Dev_or_Path n | String n ->
6142                  pr "  args.%s = (char *) %s;\n" n n
6143              | OptString n ->
6144                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6145              | StringList n | DeviceList n ->
6146                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6147                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6148              | Bool n ->
6149                  pr "  args.%s = %s;\n" n n
6150              | Int n ->
6151                  pr "  args.%s = %s;\n" n n
6152              | Int64 n ->
6153                  pr "  args.%s = %s;\n" n n
6154              | FileIn _ | FileOut _ -> ()
6155              | BufferIn n ->
6156                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6157                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6158                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6159                    shortname;
6160                  pr "    guestfs___end_busy (g);\n";
6161                  pr "    return %s;\n" error_code;
6162                  pr "  }\n";
6163                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6164                  pr "  args.%s.%s_len = %s_size;\n" n n n
6165            ) args;
6166            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6167              (String.uppercase shortname);
6168            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6169              name;
6170       );
6171       pr "  if (serial == -1) {\n";
6172       pr "    guestfs___end_busy (g);\n";
6173       pr "    return %s;\n" error_code;
6174       pr "  }\n";
6175       pr "\n";
6176
6177       (* Send any additional files (FileIn) requested. *)
6178       let need_read_reply_label = ref false in
6179       List.iter (
6180         function
6181         | FileIn n ->
6182             pr "  r = guestfs___send_file (g, %s);\n" n;
6183             pr "  if (r == -1) {\n";
6184             pr "    guestfs___end_busy (g);\n";
6185             pr "    return %s;\n" error_code;
6186             pr "  }\n";
6187             pr "  if (r == -2) /* daemon cancelled */\n";
6188             pr "    goto read_reply;\n";
6189             need_read_reply_label := true;
6190             pr "\n";
6191         | _ -> ()
6192       ) (snd style);
6193
6194       (* Wait for the reply from the remote end. *)
6195       if !need_read_reply_label then pr " read_reply:\n";
6196       pr "  memset (&hdr, 0, sizeof hdr);\n";
6197       pr "  memset (&err, 0, sizeof err);\n";
6198       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6199       pr "\n";
6200       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6201       if not has_ret then
6202         pr "NULL, NULL"
6203       else
6204         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6205       pr ");\n";
6206
6207       pr "  if (r == -1) {\n";
6208       pr "    guestfs___end_busy (g);\n";
6209       pr "    return %s;\n" error_code;
6210       pr "  }\n";
6211       pr "\n";
6212
6213       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6214         (String.uppercase shortname);
6215       pr "    guestfs___end_busy (g);\n";
6216       pr "    return %s;\n" error_code;
6217       pr "  }\n";
6218       pr "\n";
6219
6220       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6221       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6222       pr "    free (err.error_message);\n";
6223       pr "    guestfs___end_busy (g);\n";
6224       pr "    return %s;\n" error_code;
6225       pr "  }\n";
6226       pr "\n";
6227
6228       (* Expecting to receive further files (FileOut)? *)
6229       List.iter (
6230         function
6231         | FileOut n ->
6232             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6233             pr "    guestfs___end_busy (g);\n";
6234             pr "    return %s;\n" error_code;
6235             pr "  }\n";
6236             pr "\n";
6237         | _ -> ()
6238       ) (snd style);
6239
6240       pr "  guestfs___end_busy (g);\n";
6241
6242       (match fst style with
6243        | RErr -> pr "  return 0;\n"
6244        | RInt n | RInt64 n | RBool n ->
6245            pr "  return ret.%s;\n" n
6246        | RConstString _ | RConstOptString _ ->
6247            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6248        | RString n ->
6249            pr "  return ret.%s; /* caller will free */\n" n
6250        | RStringList n | RHashtable n ->
6251            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6252            pr "  ret.%s.%s_val =\n" n n;
6253            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6254            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6255              n n;
6256            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6257            pr "  return ret.%s.%s_val;\n" n n
6258        | RStruct (n, _) ->
6259            pr "  /* caller will free this */\n";
6260            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6261        | RStructList (n, _) ->
6262            pr "  /* caller will free this */\n";
6263            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6264        | RBufferOut n ->
6265            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6266            pr "   * _val might be NULL here.  To make the API saner for\n";
6267            pr "   * callers, we turn this case into a unique pointer (using\n";
6268            pr "   * malloc(1)).\n";
6269            pr "   */\n";
6270            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6271            pr "    *size_r = ret.%s.%s_len;\n" n n;
6272            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6273            pr "  } else {\n";
6274            pr "    free (ret.%s.%s_val);\n" n n;
6275            pr "    char *p = safe_malloc (g, 1);\n";
6276            pr "    *size_r = ret.%s.%s_len;\n" n n;
6277            pr "    return p;\n";
6278            pr "  }\n";
6279       );
6280
6281       pr "}\n\n"
6282   ) daemon_functions;
6283
6284   (* Functions to free structures. *)
6285   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6286   pr " * structure format is identical to the XDR format.  See note in\n";
6287   pr " * generator.ml.\n";
6288   pr " */\n";
6289   pr "\n";
6290
6291   List.iter (
6292     fun (typ, _) ->
6293       pr "void\n";
6294       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6295       pr "{\n";
6296       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6297       pr "  free (x);\n";
6298       pr "}\n";
6299       pr "\n";
6300
6301       pr "void\n";
6302       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6303       pr "{\n";
6304       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6305       pr "  free (x);\n";
6306       pr "}\n";
6307       pr "\n";
6308
6309   ) structs;
6310
6311 (* Generate daemon/actions.h. *)
6312 and generate_daemon_actions_h () =
6313   generate_header CStyle GPLv2plus;
6314
6315   pr "#include \"../src/guestfs_protocol.h\"\n";
6316   pr "\n";
6317
6318   List.iter (
6319     fun (name, style, _, _, _, _, _) ->
6320       generate_prototype
6321         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6322         name style;
6323   ) daemon_functions
6324
6325 (* Generate the linker script which controls the visibility of
6326  * symbols in the public ABI and ensures no other symbols get
6327  * exported accidentally.
6328  *)
6329 and generate_linker_script () =
6330   generate_header HashStyle GPLv2plus;
6331
6332   let globals = [
6333     "guestfs_create";
6334     "guestfs_close";
6335     "guestfs_get_error_handler";
6336     "guestfs_get_out_of_memory_handler";
6337     "guestfs_last_error";
6338     "guestfs_set_close_callback";
6339     "guestfs_set_error_handler";
6340     "guestfs_set_launch_done_callback";
6341     "guestfs_set_log_message_callback";
6342     "guestfs_set_out_of_memory_handler";
6343     "guestfs_set_subprocess_quit_callback";
6344
6345     (* Unofficial parts of the API: the bindings code use these
6346      * functions, so it is useful to export them.
6347      *)
6348     "guestfs_safe_calloc";
6349     "guestfs_safe_malloc";
6350     "guestfs_safe_strdup";
6351     "guestfs_safe_memdup";
6352   ] in
6353   let functions =
6354     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6355       all_functions in
6356   let structs =
6357     List.concat (
6358       List.map (fun (typ, _) ->
6359                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6360         structs
6361     ) in
6362   let globals = List.sort compare (globals @ functions @ structs) in
6363
6364   pr "{\n";
6365   pr "    global:\n";
6366   List.iter (pr "        %s;\n") globals;
6367   pr "\n";
6368
6369   pr "    local:\n";
6370   pr "        *;\n";
6371   pr "};\n"
6372
6373 (* Generate the server-side stubs. *)
6374 and generate_daemon_actions () =
6375   generate_header CStyle GPLv2plus;
6376
6377   pr "#include <config.h>\n";
6378   pr "\n";
6379   pr "#include <stdio.h>\n";
6380   pr "#include <stdlib.h>\n";
6381   pr "#include <string.h>\n";
6382   pr "#include <inttypes.h>\n";
6383   pr "#include <rpc/types.h>\n";
6384   pr "#include <rpc/xdr.h>\n";
6385   pr "\n";
6386   pr "#include \"daemon.h\"\n";
6387   pr "#include \"c-ctype.h\"\n";
6388   pr "#include \"../src/guestfs_protocol.h\"\n";
6389   pr "#include \"actions.h\"\n";
6390   pr "\n";
6391
6392   List.iter (
6393     fun (name, style, _, _, _, _, _) ->
6394       (* Generate server-side stubs. *)
6395       pr "static void %s_stub (XDR *xdr_in)\n" name;
6396       pr "{\n";
6397       let error_code =
6398         match fst style with
6399         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6400         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6401         | RBool _ -> pr "  int r;\n"; "-1"
6402         | RConstString _ | RConstOptString _ ->
6403             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6404         | RString _ -> pr "  char *r;\n"; "NULL"
6405         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6406         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6407         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6408         | RBufferOut _ ->
6409             pr "  size_t size = 1;\n";
6410             pr "  char *r;\n";
6411             "NULL" in
6412
6413       (match snd style with
6414        | [] -> ()
6415        | args ->
6416            pr "  struct guestfs_%s_args args;\n" name;
6417            List.iter (
6418              function
6419              | Device n | Dev_or_Path n
6420              | Pathname n
6421              | String n -> ()
6422              | OptString n -> pr "  char *%s;\n" n
6423              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6424              | Bool n -> pr "  int %s;\n" n
6425              | Int n -> pr "  int %s;\n" n
6426              | Int64 n -> pr "  int64_t %s;\n" n
6427              | FileIn _ | FileOut _ -> ()
6428              | BufferIn n ->
6429                  pr "  const char *%s;\n" n;
6430                  pr "  size_t %s_size;\n" n
6431            ) args
6432       );
6433       pr "\n";
6434
6435       let is_filein =
6436         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6437
6438       (match snd style with
6439        | [] -> ()
6440        | args ->
6441            pr "  memset (&args, 0, sizeof args);\n";
6442            pr "\n";
6443            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6444            if is_filein then
6445              pr "    if (cancel_receive () != -2)\n";
6446            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6447            pr "    goto done;\n";
6448            pr "  }\n";
6449            let pr_args n =
6450              pr "  char *%s = args.%s;\n" n n
6451            in
6452            let pr_list_handling_code n =
6453              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6454              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6455              pr "  if (%s == NULL) {\n" n;
6456              if is_filein then
6457                pr "    if (cancel_receive () != -2)\n";
6458              pr "      reply_with_perror (\"realloc\");\n";
6459              pr "    goto done;\n";
6460              pr "  }\n";
6461              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6462              pr "  args.%s.%s_val = %s;\n" n n n;
6463            in
6464            List.iter (
6465              function
6466              | Pathname n ->
6467                  pr_args n;
6468                  pr "  ABS_PATH (%s, %s, goto done);\n"
6469                    n (if is_filein then "cancel_receive ()" else "0");
6470              | Device n ->
6471                  pr_args n;
6472                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6473                    n (if is_filein then "cancel_receive ()" else "0");
6474              | Dev_or_Path n ->
6475                  pr_args n;
6476                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6477                    n (if is_filein then "cancel_receive ()" else "0");
6478              | String n -> pr_args n
6479              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6480              | StringList n ->
6481                  pr_list_handling_code n;
6482              | DeviceList n ->
6483                  pr_list_handling_code n;
6484                  pr "  /* Ensure that each is a device,\n";
6485                  pr "   * and perform device name translation.\n";
6486                  pr "   */\n";
6487                  pr "  {\n";
6488                  pr "    size_t i;\n";
6489                  pr "    for (i = 0; %s[i] != NULL; ++i)\n" n;
6490                  pr "      RESOLVE_DEVICE (%s[i], %s, goto done);\n" n
6491                    (if is_filein then "cancel_receive ()" else "0");
6492                  pr "  }\n";
6493              | Bool n -> pr "  %s = args.%s;\n" n n
6494              | Int n -> pr "  %s = args.%s;\n" n n
6495              | Int64 n -> pr "  %s = args.%s;\n" n n
6496              | FileIn _ | FileOut _ -> ()
6497              | BufferIn n ->
6498                  pr "  %s = args.%s.%s_val;\n" n n n;
6499                  pr "  %s_size = args.%s.%s_len;\n" n n n
6500            ) args;
6501            pr "\n"
6502       );
6503
6504       (* this is used at least for do_equal *)
6505       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6506         (* Emit NEED_ROOT just once, even when there are two or
6507            more Pathname args *)
6508         pr "  NEED_ROOT (%s, goto done);\n"
6509           (if is_filein then "cancel_receive ()" else "0");
6510       );
6511
6512       (* Don't want to call the impl with any FileIn or FileOut
6513        * parameters, since these go "outside" the RPC protocol.
6514        *)
6515       let args' =
6516         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6517           (snd style) in
6518       pr "  r = do_%s " name;
6519       generate_c_call_args (fst style, args');
6520       pr ";\n";
6521
6522       (match fst style with
6523        | RErr | RInt _ | RInt64 _ | RBool _
6524        | RConstString _ | RConstOptString _
6525        | RString _ | RStringList _ | RHashtable _
6526        | RStruct (_, _) | RStructList (_, _) ->
6527            pr "  if (r == %s)\n" error_code;
6528            pr "    /* do_%s has already called reply_with_error */\n" name;
6529            pr "    goto done;\n";
6530            pr "\n"
6531        | RBufferOut _ ->
6532            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6533            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6534            pr "   */\n";
6535            pr "  if (size == 1 && r == %s)\n" error_code;
6536            pr "    /* do_%s has already called reply_with_error */\n" name;
6537            pr "    goto done;\n";
6538            pr "\n"
6539       );
6540
6541       (* If there are any FileOut parameters, then the impl must
6542        * send its own reply.
6543        *)
6544       let no_reply =
6545         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6546       if no_reply then
6547         pr "  /* do_%s has already sent a reply */\n" name
6548       else (
6549         match fst style with
6550         | RErr -> pr "  reply (NULL, NULL);\n"
6551         | RInt n | RInt64 n | RBool n ->
6552             pr "  struct guestfs_%s_ret ret;\n" name;
6553             pr "  ret.%s = r;\n" n;
6554             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6555               name
6556         | RConstString _ | RConstOptString _ ->
6557             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6558         | RString n ->
6559             pr "  struct guestfs_%s_ret ret;\n" name;
6560             pr "  ret.%s = r;\n" n;
6561             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6562               name;
6563             pr "  free (r);\n"
6564         | RStringList n | RHashtable n ->
6565             pr "  struct guestfs_%s_ret ret;\n" name;
6566             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6567             pr "  ret.%s.%s_val = r;\n" n n;
6568             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6569               name;
6570             pr "  free_strings (r);\n"
6571         | RStruct (n, _) ->
6572             pr "  struct guestfs_%s_ret ret;\n" name;
6573             pr "  ret.%s = *r;\n" n;
6574             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6575               name;
6576             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6577               name
6578         | RStructList (n, _) ->
6579             pr "  struct guestfs_%s_ret ret;\n" name;
6580             pr "  ret.%s = *r;\n" n;
6581             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6582               name;
6583             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6584               name
6585         | RBufferOut n ->
6586             pr "  struct guestfs_%s_ret ret;\n" name;
6587             pr "  ret.%s.%s_val = r;\n" n n;
6588             pr "  ret.%s.%s_len = size;\n" n n;
6589             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6590               name;
6591             pr "  free (r);\n"
6592       );
6593
6594       (* Free the args. *)
6595       pr "done:\n";
6596       (match snd style with
6597        | [] -> ()
6598        | _ ->
6599            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6600              name
6601       );
6602       pr "  return;\n";
6603       pr "}\n\n";
6604   ) daemon_functions;
6605
6606   (* Dispatch function. *)
6607   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6608   pr "{\n";
6609   pr "  switch (proc_nr) {\n";
6610
6611   List.iter (
6612     fun (name, style, _, _, _, _, _) ->
6613       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6614       pr "      %s_stub (xdr_in);\n" name;
6615       pr "      break;\n"
6616   ) daemon_functions;
6617
6618   pr "    default:\n";
6619   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";
6620   pr "  }\n";
6621   pr "}\n";
6622   pr "\n";
6623
6624   (* LVM columns and tokenization functions. *)
6625   (* XXX This generates crap code.  We should rethink how we
6626    * do this parsing.
6627    *)
6628   List.iter (
6629     function
6630     | typ, cols ->
6631         pr "static const char *lvm_%s_cols = \"%s\";\n"
6632           typ (String.concat "," (List.map fst cols));
6633         pr "\n";
6634
6635         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6636         pr "{\n";
6637         pr "  char *tok, *p, *next;\n";
6638         pr "  size_t i, j;\n";
6639         pr "\n";
6640         (*
6641           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6642           pr "\n";
6643         *)
6644         pr "  if (!str) {\n";
6645         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6646         pr "    return -1;\n";
6647         pr "  }\n";
6648         pr "  if (!*str || c_isspace (*str)) {\n";
6649         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6650         pr "    return -1;\n";
6651         pr "  }\n";
6652         pr "  tok = str;\n";
6653         List.iter (
6654           fun (name, coltype) ->
6655             pr "  if (!tok) {\n";
6656             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6657             pr "    return -1;\n";
6658             pr "  }\n";
6659             pr "  p = strchrnul (tok, ',');\n";
6660             pr "  if (*p) next = p+1; else next = NULL;\n";
6661             pr "  *p = '\\0';\n";
6662             (match coltype with
6663              | FString ->
6664                  pr "  r->%s = strdup (tok);\n" name;
6665                  pr "  if (r->%s == NULL) {\n" name;
6666                  pr "    perror (\"strdup\");\n";
6667                  pr "    return -1;\n";
6668                  pr "  }\n"
6669              | FUUID ->
6670                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6671                  pr "    if (tok[j] == '\\0') {\n";
6672                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6673                  pr "      return -1;\n";
6674                  pr "    } else if (tok[j] != '-')\n";
6675                  pr "      r->%s[i++] = tok[j];\n" name;
6676                  pr "  }\n";
6677              | FBytes ->
6678                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6679                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6680                  pr "    return -1;\n";
6681                  pr "  }\n";
6682              | FInt64 ->
6683                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6684                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6685                  pr "    return -1;\n";
6686                  pr "  }\n";
6687              | FOptPercent ->
6688                  pr "  if (tok[0] == '\\0')\n";
6689                  pr "    r->%s = -1;\n" name;
6690                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6691                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6692                  pr "    return -1;\n";
6693                  pr "  }\n";
6694              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6695                  assert false (* can never be an LVM column *)
6696             );
6697             pr "  tok = next;\n";
6698         ) cols;
6699
6700         pr "  if (tok != NULL) {\n";
6701         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6702         pr "    return -1;\n";
6703         pr "  }\n";
6704         pr "  return 0;\n";
6705         pr "}\n";
6706         pr "\n";
6707
6708         pr "guestfs_int_lvm_%s_list *\n" typ;
6709         pr "parse_command_line_%ss (void)\n" typ;
6710         pr "{\n";
6711         pr "  char *out, *err;\n";
6712         pr "  char *p, *pend;\n";
6713         pr "  int r, i;\n";
6714         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6715         pr "  void *newp;\n";
6716         pr "\n";
6717         pr "  ret = malloc (sizeof *ret);\n";
6718         pr "  if (!ret) {\n";
6719         pr "    reply_with_perror (\"malloc\");\n";
6720         pr "    return NULL;\n";
6721         pr "  }\n";
6722         pr "\n";
6723         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6724         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6725         pr "\n";
6726         pr "  r = command (&out, &err,\n";
6727         pr "           \"lvm\", \"%ss\",\n" typ;
6728         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6729         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6730         pr "  if (r == -1) {\n";
6731         pr "    reply_with_error (\"%%s\", err);\n";
6732         pr "    free (out);\n";
6733         pr "    free (err);\n";
6734         pr "    free (ret);\n";
6735         pr "    return NULL;\n";
6736         pr "  }\n";
6737         pr "\n";
6738         pr "  free (err);\n";
6739         pr "\n";
6740         pr "  /* Tokenize each line of the output. */\n";
6741         pr "  p = out;\n";
6742         pr "  i = 0;\n";
6743         pr "  while (p) {\n";
6744         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6745         pr "    if (pend) {\n";
6746         pr "      *pend = '\\0';\n";
6747         pr "      pend++;\n";
6748         pr "    }\n";
6749         pr "\n";
6750         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6751         pr "      p++;\n";
6752         pr "\n";
6753         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6754         pr "      p = pend;\n";
6755         pr "      continue;\n";
6756         pr "    }\n";
6757         pr "\n";
6758         pr "    /* Allocate some space to store this next entry. */\n";
6759         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6760         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6761         pr "    if (newp == NULL) {\n";
6762         pr "      reply_with_perror (\"realloc\");\n";
6763         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6764         pr "      free (ret);\n";
6765         pr "      free (out);\n";
6766         pr "      return NULL;\n";
6767         pr "    }\n";
6768         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6769         pr "\n";
6770         pr "    /* Tokenize the next entry. */\n";
6771         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6772         pr "    if (r == -1) {\n";
6773         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6774         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6775         pr "      free (ret);\n";
6776         pr "      free (out);\n";
6777         pr "      return NULL;\n";
6778         pr "    }\n";
6779         pr "\n";
6780         pr "    ++i;\n";
6781         pr "    p = pend;\n";
6782         pr "  }\n";
6783         pr "\n";
6784         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6785         pr "\n";
6786         pr "  free (out);\n";
6787         pr "  return ret;\n";
6788         pr "}\n"
6789
6790   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6791
6792 (* Generate a list of function names, for debugging in the daemon.. *)
6793 and generate_daemon_names () =
6794   generate_header CStyle GPLv2plus;
6795
6796   pr "#include <config.h>\n";
6797   pr "\n";
6798   pr "#include \"daemon.h\"\n";
6799   pr "\n";
6800
6801   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6802   pr "const char *function_names[] = {\n";
6803   List.iter (
6804     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6805   ) daemon_functions;
6806   pr "};\n";
6807
6808 (* Generate the optional groups for the daemon to implement
6809  * guestfs_available.
6810  *)
6811 and generate_daemon_optgroups_c () =
6812   generate_header CStyle GPLv2plus;
6813
6814   pr "#include <config.h>\n";
6815   pr "\n";
6816   pr "#include \"daemon.h\"\n";
6817   pr "#include \"optgroups.h\"\n";
6818   pr "\n";
6819
6820   pr "struct optgroup optgroups[] = {\n";
6821   List.iter (
6822     fun (group, _) ->
6823       pr "  { \"%s\", optgroup_%s_available },\n" group group
6824   ) optgroups;
6825   pr "  { NULL, NULL }\n";
6826   pr "};\n"
6827
6828 and generate_daemon_optgroups_h () =
6829   generate_header CStyle GPLv2plus;
6830
6831   List.iter (
6832     fun (group, _) ->
6833       pr "extern int optgroup_%s_available (void);\n" group
6834   ) optgroups
6835
6836 (* Generate the tests. *)
6837 and generate_tests () =
6838   generate_header CStyle GPLv2plus;
6839
6840   pr "\
6841 #include <stdio.h>
6842 #include <stdlib.h>
6843 #include <string.h>
6844 #include <unistd.h>
6845 #include <sys/types.h>
6846 #include <fcntl.h>
6847
6848 #include \"guestfs.h\"
6849 #include \"guestfs-internal.h\"
6850
6851 static guestfs_h *g;
6852 static int suppress_error = 0;
6853
6854 static void print_error (guestfs_h *g, void *data, const char *msg)
6855 {
6856   if (!suppress_error)
6857     fprintf (stderr, \"%%s\\n\", msg);
6858 }
6859
6860 /* FIXME: nearly identical code appears in fish.c */
6861 static void print_strings (char *const *argv)
6862 {
6863   size_t argc;
6864
6865   for (argc = 0; argv[argc] != NULL; ++argc)
6866     printf (\"\\t%%s\\n\", argv[argc]);
6867 }
6868
6869 /*
6870 static void print_table (char const *const *argv)
6871 {
6872   size_t i;
6873
6874   for (i = 0; argv[i] != NULL; i += 2)
6875     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6876 }
6877 */
6878
6879 static int
6880 is_available (const char *group)
6881 {
6882   const char *groups[] = { group, NULL };
6883   int r;
6884
6885   suppress_error = 1;
6886   r = guestfs_available (g, (char **) groups);
6887   suppress_error = 0;
6888
6889   return r == 0;
6890 }
6891
6892 static void
6893 incr (guestfs_h *g, void *iv)
6894 {
6895   int *i = (int *) iv;
6896   (*i)++;
6897 }
6898
6899 ";
6900
6901   (* Generate a list of commands which are not tested anywhere. *)
6902   pr "static void no_test_warnings (void)\n";
6903   pr "{\n";
6904
6905   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6906   List.iter (
6907     fun (_, _, _, _, tests, _, _) ->
6908       let tests = filter_map (
6909         function
6910         | (_, (Always|If _|Unless _|IfAvailable _), test) -> Some test
6911         | (_, Disabled, _) -> None
6912       ) tests in
6913       let seq = List.concat (List.map seq_of_test tests) in
6914       let cmds_tested = List.map List.hd seq in
6915       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6916   ) all_functions;
6917
6918   List.iter (
6919     fun (name, _, _, _, _, _, _) ->
6920       if not (Hashtbl.mem hash name) then
6921         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6922   ) all_functions;
6923
6924   pr "}\n";
6925   pr "\n";
6926
6927   (* Generate the actual tests.  Note that we generate the tests
6928    * in reverse order, deliberately, so that (in general) the
6929    * newest tests run first.  This makes it quicker and easier to
6930    * debug them.
6931    *)
6932   let test_names =
6933     List.map (
6934       fun (name, _, _, flags, tests, _, _) ->
6935         mapi (generate_one_test name flags) tests
6936     ) (List.rev all_functions) in
6937   let test_names = List.concat test_names in
6938   let nr_tests = List.length test_names in
6939
6940   pr "\
6941 int main (int argc, char *argv[])
6942 {
6943   char c = 0;
6944   unsigned long int n_failed = 0;
6945   const char *filename;
6946   int fd;
6947   int nr_tests, test_num = 0;
6948
6949   setbuf (stdout, NULL);
6950
6951   no_test_warnings ();
6952
6953   g = guestfs_create ();
6954   if (g == NULL) {
6955     printf (\"guestfs_create FAILED\\n\");
6956     exit (EXIT_FAILURE);
6957   }
6958
6959   guestfs_set_error_handler (g, print_error, NULL);
6960
6961   guestfs_set_path (g, \"../appliance\");
6962
6963   filename = \"test1.img\";
6964   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6965   if (fd == -1) {
6966     perror (filename);
6967     exit (EXIT_FAILURE);
6968   }
6969   if (lseek (fd, %d, SEEK_SET) == -1) {
6970     perror (\"lseek\");
6971     close (fd);
6972     unlink (filename);
6973     exit (EXIT_FAILURE);
6974   }
6975   if (write (fd, &c, 1) == -1) {
6976     perror (\"write\");
6977     close (fd);
6978     unlink (filename);
6979     exit (EXIT_FAILURE);
6980   }
6981   if (close (fd) == -1) {
6982     perror (filename);
6983     unlink (filename);
6984     exit (EXIT_FAILURE);
6985   }
6986   if (guestfs_add_drive (g, filename) == -1) {
6987     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6988     exit (EXIT_FAILURE);
6989   }
6990
6991   filename = \"test2.img\";
6992   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6993   if (fd == -1) {
6994     perror (filename);
6995     exit (EXIT_FAILURE);
6996   }
6997   if (lseek (fd, %d, SEEK_SET) == -1) {
6998     perror (\"lseek\");
6999     close (fd);
7000     unlink (filename);
7001     exit (EXIT_FAILURE);
7002   }
7003   if (write (fd, &c, 1) == -1) {
7004     perror (\"write\");
7005     close (fd);
7006     unlink (filename);
7007     exit (EXIT_FAILURE);
7008   }
7009   if (close (fd) == -1) {
7010     perror (filename);
7011     unlink (filename);
7012     exit (EXIT_FAILURE);
7013   }
7014   if (guestfs_add_drive (g, filename) == -1) {
7015     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7016     exit (EXIT_FAILURE);
7017   }
7018
7019   filename = \"test3.img\";
7020   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7021   if (fd == -1) {
7022     perror (filename);
7023     exit (EXIT_FAILURE);
7024   }
7025   if (lseek (fd, %d, SEEK_SET) == -1) {
7026     perror (\"lseek\");
7027     close (fd);
7028     unlink (filename);
7029     exit (EXIT_FAILURE);
7030   }
7031   if (write (fd, &c, 1) == -1) {
7032     perror (\"write\");
7033     close (fd);
7034     unlink (filename);
7035     exit (EXIT_FAILURE);
7036   }
7037   if (close (fd) == -1) {
7038     perror (filename);
7039     unlink (filename);
7040     exit (EXIT_FAILURE);
7041   }
7042   if (guestfs_add_drive (g, filename) == -1) {
7043     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7044     exit (EXIT_FAILURE);
7045   }
7046
7047   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
7048     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
7049     exit (EXIT_FAILURE);
7050   }
7051
7052   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
7053   alarm (600);
7054
7055   if (guestfs_launch (g) == -1) {
7056     printf (\"guestfs_launch FAILED\\n\");
7057     exit (EXIT_FAILURE);
7058   }
7059
7060   /* Cancel previous alarm. */
7061   alarm (0);
7062
7063   nr_tests = %d;
7064
7065 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
7066
7067   iteri (
7068     fun i test_name ->
7069       pr "  test_num++;\n";
7070       pr "  if (guestfs_get_verbose (g))\n";
7071       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
7072       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
7073       pr "  if (%s () == -1) {\n" test_name;
7074       pr "    printf (\"%s FAILED\\n\");\n" test_name;
7075       pr "    n_failed++;\n";
7076       pr "  }\n";
7077   ) test_names;
7078   pr "\n";
7079
7080   pr "  /* Check close callback is called. */
7081   int close_sentinel = 1;
7082   guestfs_set_close_callback (g, incr, &close_sentinel);
7083
7084   guestfs_close (g);
7085
7086   if (close_sentinel != 2) {
7087     fprintf (stderr, \"close callback was not called\\n\");
7088     exit (EXIT_FAILURE);
7089   }
7090
7091   unlink (\"test1.img\");
7092   unlink (\"test2.img\");
7093   unlink (\"test3.img\");
7094
7095 ";
7096
7097   pr "  if (n_failed > 0) {\n";
7098   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7099   pr "    exit (EXIT_FAILURE);\n";
7100   pr "  }\n";
7101   pr "\n";
7102
7103   pr "  exit (EXIT_SUCCESS);\n";
7104   pr "}\n"
7105
7106 and generate_one_test name flags i (init, prereq, test) =
7107   let test_name = sprintf "test_%s_%d" name i in
7108
7109   pr "\
7110 static int %s_skip (void)
7111 {
7112   const char *str;
7113
7114   str = getenv (\"TEST_ONLY\");
7115   if (str)
7116     return strstr (str, \"%s\") == NULL;
7117   str = getenv (\"SKIP_%s\");
7118   if (str && STREQ (str, \"1\")) return 1;
7119   str = getenv (\"SKIP_TEST_%s\");
7120   if (str && STREQ (str, \"1\")) return 1;
7121   return 0;
7122 }
7123
7124 " test_name name (String.uppercase test_name) (String.uppercase name);
7125
7126   (match prereq with
7127    | Disabled | Always | IfAvailable _ -> ()
7128    | If code | Unless code ->
7129        pr "static int %s_prereq (void)\n" test_name;
7130        pr "{\n";
7131        pr "  %s\n" code;
7132        pr "}\n";
7133        pr "\n";
7134   );
7135
7136   pr "\
7137 static int %s (void)
7138 {
7139   if (%s_skip ()) {
7140     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7141     return 0;
7142   }
7143
7144 " test_name test_name test_name;
7145
7146   (* Optional functions should only be tested if the relevant
7147    * support is available in the daemon.
7148    *)
7149   List.iter (
7150     function
7151     | Optional group ->
7152         pr "  if (!is_available (\"%s\")) {\n" group;
7153         pr "    printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", \"%s\");\n" test_name group;
7154         pr "    return 0;\n";
7155         pr "  }\n";
7156     | _ -> ()
7157   ) flags;
7158
7159   (match prereq with
7160    | Disabled ->
7161        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7162    | If _ ->
7163        pr "  if (! %s_prereq ()) {\n" test_name;
7164        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7165        pr "    return 0;\n";
7166        pr "  }\n";
7167        pr "\n";
7168        generate_one_test_body name i test_name init test;
7169    | Unless _ ->
7170        pr "  if (%s_prereq ()) {\n" test_name;
7171        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7172        pr "    return 0;\n";
7173        pr "  }\n";
7174        pr "\n";
7175        generate_one_test_body name i test_name init test;
7176    | IfAvailable group ->
7177        pr "  if (!is_available (\"%s\")) {\n" group;
7178        pr "    printf (\"        %%s skipped (reason: %%s not available)\\n\", \"%s\", \"%s\");\n" test_name group;
7179        pr "    return 0;\n";
7180        pr "  }\n";
7181        pr "\n";
7182        generate_one_test_body name i test_name init test;
7183    | Always ->
7184        generate_one_test_body name i test_name init test
7185   );
7186
7187   pr "  return 0;\n";
7188   pr "}\n";
7189   pr "\n";
7190   test_name
7191
7192 and generate_one_test_body name i test_name init test =
7193   (match init with
7194    | InitNone (* XXX at some point, InitNone and InitEmpty became
7195                * folded together as the same thing.  Really we should
7196                * make InitNone do nothing at all, but the tests may
7197                * need to be checked to make sure this is OK.
7198                *)
7199    | InitEmpty ->
7200        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7201        List.iter (generate_test_command_call test_name)
7202          [["blockdev_setrw"; "/dev/sda"];
7203           ["umount_all"];
7204           ["lvm_remove_all"]]
7205    | InitPartition ->
7206        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7207        List.iter (generate_test_command_call test_name)
7208          [["blockdev_setrw"; "/dev/sda"];
7209           ["umount_all"];
7210           ["lvm_remove_all"];
7211           ["part_disk"; "/dev/sda"; "mbr"]]
7212    | InitBasicFS ->
7213        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7214        List.iter (generate_test_command_call test_name)
7215          [["blockdev_setrw"; "/dev/sda"];
7216           ["umount_all"];
7217           ["lvm_remove_all"];
7218           ["part_disk"; "/dev/sda"; "mbr"];
7219           ["mkfs"; "ext2"; "/dev/sda1"];
7220           ["mount_options"; ""; "/dev/sda1"; "/"]]
7221    | InitBasicFSonLVM ->
7222        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7223          test_name;
7224        List.iter (generate_test_command_call test_name)
7225          [["blockdev_setrw"; "/dev/sda"];
7226           ["umount_all"];
7227           ["lvm_remove_all"];
7228           ["part_disk"; "/dev/sda"; "mbr"];
7229           ["pvcreate"; "/dev/sda1"];
7230           ["vgcreate"; "VG"; "/dev/sda1"];
7231           ["lvcreate"; "LV"; "VG"; "8"];
7232           ["mkfs"; "ext2"; "/dev/VG/LV"];
7233           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7234    | InitISOFS ->
7235        pr "  /* InitISOFS for %s */\n" test_name;
7236        List.iter (generate_test_command_call test_name)
7237          [["blockdev_setrw"; "/dev/sda"];
7238           ["umount_all"];
7239           ["lvm_remove_all"];
7240           ["mount_ro"; "/dev/sdd"; "/"]]
7241   );
7242
7243   let get_seq_last = function
7244     | [] ->
7245         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7246           test_name
7247     | seq ->
7248         let seq = List.rev seq in
7249         List.rev (List.tl seq), List.hd seq
7250   in
7251
7252   match test with
7253   | TestRun seq ->
7254       pr "  /* TestRun for %s (%d) */\n" name i;
7255       List.iter (generate_test_command_call test_name) seq
7256   | TestOutput (seq, expected) ->
7257       pr "  /* TestOutput for %s (%d) */\n" name i;
7258       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7259       let seq, last = get_seq_last seq in
7260       let test () =
7261         pr "    if (STRNEQ (r, expected)) {\n";
7262         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7263         pr "      return -1;\n";
7264         pr "    }\n"
7265       in
7266       List.iter (generate_test_command_call test_name) seq;
7267       generate_test_command_call ~test test_name last
7268   | TestOutputList (seq, expected) ->
7269       pr "  /* TestOutputList for %s (%d) */\n" name i;
7270       let seq, last = get_seq_last seq in
7271       let test () =
7272         iteri (
7273           fun i str ->
7274             pr "    if (!r[%d]) {\n" i;
7275             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7276             pr "      print_strings (r);\n";
7277             pr "      return -1;\n";
7278             pr "    }\n";
7279             pr "    {\n";
7280             pr "      const char *expected = \"%s\";\n" (c_quote str);
7281             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7282             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7283             pr "        return -1;\n";
7284             pr "      }\n";
7285             pr "    }\n"
7286         ) expected;
7287         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7288         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7289           test_name;
7290         pr "      print_strings (r);\n";
7291         pr "      return -1;\n";
7292         pr "    }\n"
7293       in
7294       List.iter (generate_test_command_call test_name) seq;
7295       generate_test_command_call ~test test_name last
7296   | TestOutputListOfDevices (seq, expected) ->
7297       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7298       let seq, last = get_seq_last seq in
7299       let test () =
7300         iteri (
7301           fun i str ->
7302             pr "    if (!r[%d]) {\n" i;
7303             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7304             pr "      print_strings (r);\n";
7305             pr "      return -1;\n";
7306             pr "    }\n";
7307             pr "    {\n";
7308             pr "      const char *expected = \"%s\";\n" (c_quote str);
7309             pr "      r[%d][5] = 's';\n" i;
7310             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7311             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7312             pr "        return -1;\n";
7313             pr "      }\n";
7314             pr "    }\n"
7315         ) expected;
7316         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7317         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7318           test_name;
7319         pr "      print_strings (r);\n";
7320         pr "      return -1;\n";
7321         pr "    }\n"
7322       in
7323       List.iter (generate_test_command_call test_name) seq;
7324       generate_test_command_call ~test test_name last
7325   | TestOutputInt (seq, expected) ->
7326       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7327       let seq, last = get_seq_last seq in
7328       let test () =
7329         pr "    if (r != %d) {\n" expected;
7330         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7331           test_name expected;
7332         pr "               (int) r);\n";
7333         pr "      return -1;\n";
7334         pr "    }\n"
7335       in
7336       List.iter (generate_test_command_call test_name) seq;
7337       generate_test_command_call ~test test_name last
7338   | TestOutputIntOp (seq, op, expected) ->
7339       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7340       let seq, last = get_seq_last seq in
7341       let test () =
7342         pr "    if (! (r %s %d)) {\n" op expected;
7343         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7344           test_name op expected;
7345         pr "               (int) r);\n";
7346         pr "      return -1;\n";
7347         pr "    }\n"
7348       in
7349       List.iter (generate_test_command_call test_name) seq;
7350       generate_test_command_call ~test test_name last
7351   | TestOutputTrue seq ->
7352       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7353       let seq, last = get_seq_last seq in
7354       let test () =
7355         pr "    if (!r) {\n";
7356         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7357           test_name;
7358         pr "      return -1;\n";
7359         pr "    }\n"
7360       in
7361       List.iter (generate_test_command_call test_name) seq;
7362       generate_test_command_call ~test test_name last
7363   | TestOutputFalse seq ->
7364       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7365       let seq, last = get_seq_last seq in
7366       let test () =
7367         pr "    if (r) {\n";
7368         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7369           test_name;
7370         pr "      return -1;\n";
7371         pr "    }\n"
7372       in
7373       List.iter (generate_test_command_call test_name) seq;
7374       generate_test_command_call ~test test_name last
7375   | TestOutputLength (seq, expected) ->
7376       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7377       let seq, last = get_seq_last seq in
7378       let test () =
7379         pr "    int j;\n";
7380         pr "    for (j = 0; j < %d; ++j)\n" expected;
7381         pr "      if (r[j] == NULL) {\n";
7382         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7383           test_name;
7384         pr "        print_strings (r);\n";
7385         pr "        return -1;\n";
7386         pr "      }\n";
7387         pr "    if (r[j] != NULL) {\n";
7388         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7389           test_name;
7390         pr "      print_strings (r);\n";
7391         pr "      return -1;\n";
7392         pr "    }\n"
7393       in
7394       List.iter (generate_test_command_call test_name) seq;
7395       generate_test_command_call ~test test_name last
7396   | TestOutputBuffer (seq, expected) ->
7397       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7398       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7399       let seq, last = get_seq_last seq in
7400       let len = String.length expected in
7401       let test () =
7402         pr "    if (size != %d) {\n" len;
7403         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7404         pr "      return -1;\n";
7405         pr "    }\n";
7406         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7407         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7408         pr "      return -1;\n";
7409         pr "    }\n"
7410       in
7411       List.iter (generate_test_command_call test_name) seq;
7412       generate_test_command_call ~test test_name last
7413   | TestOutputStruct (seq, checks) ->
7414       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7415       let seq, last = get_seq_last seq in
7416       let test () =
7417         List.iter (
7418           function
7419           | CompareWithInt (field, expected) ->
7420               pr "    if (r->%s != %d) {\n" field expected;
7421               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7422                 test_name field expected;
7423               pr "               (int) r->%s);\n" field;
7424               pr "      return -1;\n";
7425               pr "    }\n"
7426           | CompareWithIntOp (field, op, expected) ->
7427               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7428               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7429                 test_name field op expected;
7430               pr "               (int) r->%s);\n" field;
7431               pr "      return -1;\n";
7432               pr "    }\n"
7433           | CompareWithString (field, expected) ->
7434               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7435               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7436                 test_name field expected;
7437               pr "               r->%s);\n" field;
7438               pr "      return -1;\n";
7439               pr "    }\n"
7440           | CompareFieldsIntEq (field1, field2) ->
7441               pr "    if (r->%s != r->%s) {\n" field1 field2;
7442               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7443                 test_name field1 field2;
7444               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7445               pr "      return -1;\n";
7446               pr "    }\n"
7447           | CompareFieldsStrEq (field1, field2) ->
7448               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7449               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7450                 test_name field1 field2;
7451               pr "               r->%s, r->%s);\n" field1 field2;
7452               pr "      return -1;\n";
7453               pr "    }\n"
7454         ) checks
7455       in
7456       List.iter (generate_test_command_call test_name) seq;
7457       generate_test_command_call ~test test_name last
7458   | TestLastFail seq ->
7459       pr "  /* TestLastFail for %s (%d) */\n" name i;
7460       let seq, last = get_seq_last seq in
7461       List.iter (generate_test_command_call test_name) seq;
7462       generate_test_command_call test_name ~expect_error:true last
7463
7464 (* Generate the code to run a command, leaving the result in 'r'.
7465  * If you expect to get an error then you should set expect_error:true.
7466  *)
7467 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7468   match cmd with
7469   | [] -> assert false
7470   | name :: args ->
7471       (* Look up the command to find out what args/ret it has. *)
7472       let style =
7473         try
7474           let _, style, _, _, _, _, _ =
7475             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7476           style
7477         with Not_found ->
7478           failwithf "%s: in test, command %s was not found" test_name name in
7479
7480       if List.length (snd style) <> List.length args then
7481         failwithf "%s: in test, wrong number of args given to %s"
7482           test_name name;
7483
7484       pr "  {\n";
7485
7486       List.iter (
7487         function
7488         | OptString n, "NULL" -> ()
7489         | Pathname n, arg
7490         | Device n, arg
7491         | Dev_or_Path n, arg
7492         | String n, arg
7493         | OptString n, arg ->
7494             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7495         | BufferIn n, arg ->
7496             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7497             pr "    size_t %s_size = %d;\n" n (String.length arg)
7498         | Int _, _
7499         | Int64 _, _
7500         | Bool _, _
7501         | FileIn _, _ | FileOut _, _ -> ()
7502         | StringList n, "" | DeviceList n, "" ->
7503             pr "    const char *const %s[1] = { NULL };\n" n
7504         | StringList n, arg | DeviceList n, arg ->
7505             let strs = string_split " " arg in
7506             iteri (
7507               fun i str ->
7508                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7509             ) strs;
7510             pr "    const char *const %s[] = {\n" n;
7511             iteri (
7512               fun i _ -> pr "      %s_%d,\n" n i
7513             ) strs;
7514             pr "      NULL\n";
7515             pr "    };\n";
7516       ) (List.combine (snd style) args);
7517
7518       let error_code =
7519         match fst style with
7520         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7521         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7522         | RConstString _ | RConstOptString _ ->
7523             pr "    const char *r;\n"; "NULL"
7524         | RString _ -> pr "    char *r;\n"; "NULL"
7525         | RStringList _ | RHashtable _ ->
7526             pr "    char **r;\n";
7527             pr "    size_t i;\n";
7528             "NULL"
7529         | RStruct (_, typ) ->
7530             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7531         | RStructList (_, typ) ->
7532             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7533         | RBufferOut _ ->
7534             pr "    char *r;\n";
7535             pr "    size_t size;\n";
7536             "NULL" in
7537
7538       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7539       pr "    r = guestfs_%s (g" name;
7540
7541       (* Generate the parameters. *)
7542       List.iter (
7543         function
7544         | OptString _, "NULL" -> pr ", NULL"
7545         | Pathname n, _
7546         | Device n, _ | Dev_or_Path n, _
7547         | String n, _
7548         | OptString n, _ ->
7549             pr ", %s" n
7550         | BufferIn n, _ ->
7551             pr ", %s, %s_size" n n
7552         | FileIn _, arg | FileOut _, arg ->
7553             pr ", \"%s\"" (c_quote arg)
7554         | StringList n, _ | DeviceList n, _ ->
7555             pr ", (char **) %s" n
7556         | Int _, arg ->
7557             let i =
7558               try int_of_string arg
7559               with Failure "int_of_string" ->
7560                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7561             pr ", %d" i
7562         | Int64 _, arg ->
7563             let i =
7564               try Int64.of_string arg
7565               with Failure "int_of_string" ->
7566                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7567             pr ", %Ld" i
7568         | Bool _, arg ->
7569             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7570       ) (List.combine (snd style) args);
7571
7572       (match fst style with
7573        | RBufferOut _ -> pr ", &size"
7574        | _ -> ()
7575       );
7576
7577       pr ");\n";
7578
7579       if not expect_error then
7580         pr "    if (r == %s)\n" error_code
7581       else
7582         pr "    if (r != %s)\n" error_code;
7583       pr "      return -1;\n";
7584
7585       (* Insert the test code. *)
7586       (match test with
7587        | None -> ()
7588        | Some f -> f ()
7589       );
7590
7591       (match fst style with
7592        | RErr | RInt _ | RInt64 _ | RBool _
7593        | RConstString _ | RConstOptString _ -> ()
7594        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7595        | RStringList _ | RHashtable _ ->
7596            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7597            pr "      free (r[i]);\n";
7598            pr "    free (r);\n"
7599        | RStruct (_, typ) ->
7600            pr "    guestfs_free_%s (r);\n" typ
7601        | RStructList (_, typ) ->
7602            pr "    guestfs_free_%s_list (r);\n" typ
7603       );
7604
7605       pr "  }\n"
7606
7607 and c_quote str =
7608   let str = replace_str str "\r" "\\r" in
7609   let str = replace_str str "\n" "\\n" in
7610   let str = replace_str str "\t" "\\t" in
7611   let str = replace_str str "\000" "\\0" in
7612   str
7613
7614 (* Generate a lot of different functions for guestfish. *)
7615 and generate_fish_cmds () =
7616   generate_header CStyle GPLv2plus;
7617
7618   let all_functions =
7619     List.filter (
7620       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7621     ) all_functions in
7622   let all_functions_sorted =
7623     List.filter (
7624       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7625     ) all_functions_sorted in
7626
7627   pr "#include <config.h>\n";
7628   pr "\n";
7629   pr "#include <stdio.h>\n";
7630   pr "#include <stdlib.h>\n";
7631   pr "#include <string.h>\n";
7632   pr "#include <inttypes.h>\n";
7633   pr "\n";
7634   pr "#include <guestfs.h>\n";
7635   pr "#include \"c-ctype.h\"\n";
7636   pr "#include \"full-write.h\"\n";
7637   pr "#include \"xstrtol.h\"\n";
7638   pr "#include \"fish.h\"\n";
7639   pr "\n";
7640   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7641   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7642   pr "\n";
7643
7644   (* list_commands function, which implements guestfish -h *)
7645   pr "void list_commands (void)\n";
7646   pr "{\n";
7647   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7648   pr "  list_builtin_commands ();\n";
7649   List.iter (
7650     fun (name, _, _, flags, _, shortdesc, _) ->
7651       let name = replace_char name '_' '-' in
7652       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7653         name shortdesc
7654   ) all_functions_sorted;
7655   pr "  printf (\"    %%s\\n\",";
7656   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7657   pr "}\n";
7658   pr "\n";
7659
7660   (* display_command function, which implements guestfish -h cmd *)
7661   pr "int display_command (const char *cmd)\n";
7662   pr "{\n";
7663   List.iter (
7664     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7665       let name2 = replace_char name '_' '-' in
7666       let alias =
7667         try find_map (function FishAlias n -> Some n | _ -> None) flags
7668         with Not_found -> name in
7669       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7670       let synopsis =
7671         match snd style with
7672         | [] -> name2
7673         | args ->
7674             sprintf "%s %s"
7675               name2 (String.concat " " (List.map name_of_argt args)) in
7676
7677       let warnings =
7678         if List.mem ProtocolLimitWarning flags then
7679           ("\n\n" ^ protocol_limit_warning)
7680         else "" in
7681
7682       (* For DangerWillRobinson commands, we should probably have
7683        * guestfish prompt before allowing you to use them (especially
7684        * in interactive mode). XXX
7685        *)
7686       let warnings =
7687         warnings ^
7688           if List.mem DangerWillRobinson flags then
7689             ("\n\n" ^ danger_will_robinson)
7690           else "" in
7691
7692       let warnings =
7693         warnings ^
7694           match deprecation_notice flags with
7695           | None -> ""
7696           | Some txt -> "\n\n" ^ txt in
7697
7698       let describe_alias =
7699         if name <> alias then
7700           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7701         else "" in
7702
7703       pr "  if (";
7704       pr "STRCASEEQ (cmd, \"%s\")" name;
7705       if name <> name2 then
7706         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7707       if name <> alias then
7708         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7709       pr ") {\n";
7710       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7711         name2 shortdesc
7712         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7713          "=head1 DESCRIPTION\n\n" ^
7714          longdesc ^ warnings ^ describe_alias);
7715       pr "    return 0;\n";
7716       pr "  }\n";
7717       pr "  else\n"
7718   ) all_functions;
7719   pr "    return display_builtin_command (cmd);\n";
7720   pr "}\n";
7721   pr "\n";
7722
7723   let emit_print_list_function typ =
7724     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7725       typ typ typ;
7726     pr "{\n";
7727     pr "  unsigned int i;\n";
7728     pr "\n";
7729     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7730     pr "    printf (\"[%%d] = {\\n\", i);\n";
7731     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7732     pr "    printf (\"}\\n\");\n";
7733     pr "  }\n";
7734     pr "}\n";
7735     pr "\n";
7736   in
7737
7738   (* print_* functions *)
7739   List.iter (
7740     fun (typ, cols) ->
7741       let needs_i =
7742         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7743
7744       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7745       pr "{\n";
7746       if needs_i then (
7747         pr "  unsigned int i;\n";
7748         pr "\n"
7749       );
7750       List.iter (
7751         function
7752         | name, FString ->
7753             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7754         | name, FUUID ->
7755             pr "  printf (\"%%s%s: \", indent);\n" name;
7756             pr "  for (i = 0; i < 32; ++i)\n";
7757             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7758             pr "  printf (\"\\n\");\n"
7759         | name, FBuffer ->
7760             pr "  printf (\"%%s%s: \", indent);\n" name;
7761             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7762             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7763             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7764             pr "    else\n";
7765             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7766             pr "  printf (\"\\n\");\n"
7767         | name, (FUInt64|FBytes) ->
7768             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7769               name typ name
7770         | name, FInt64 ->
7771             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7772               name typ name
7773         | name, FUInt32 ->
7774             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7775               name typ name
7776         | name, FInt32 ->
7777             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7778               name typ name
7779         | name, FChar ->
7780             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7781               name typ name
7782         | name, FOptPercent ->
7783             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7784               typ name name typ name;
7785             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7786       ) cols;
7787       pr "}\n";
7788       pr "\n";
7789   ) structs;
7790
7791   (* Emit a print_TYPE_list function definition only if that function is used. *)
7792   List.iter (
7793     function
7794     | typ, (RStructListOnly | RStructAndList) ->
7795         (* generate the function for typ *)
7796         emit_print_list_function typ
7797     | typ, _ -> () (* empty *)
7798   ) (rstructs_used_by all_functions);
7799
7800   (* Emit a print_TYPE function definition only if that function is used. *)
7801   List.iter (
7802     function
7803     | typ, (RStructOnly | RStructAndList) ->
7804         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7805         pr "{\n";
7806         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7807         pr "}\n";
7808         pr "\n";
7809     | typ, _ -> () (* empty *)
7810   ) (rstructs_used_by all_functions);
7811
7812   (* run_<action> actions *)
7813   List.iter (
7814     fun (name, style, _, flags, _, _, _) ->
7815       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7816       pr "{\n";
7817       (match fst style with
7818        | RErr
7819        | RInt _
7820        | RBool _ -> pr "  int r;\n"
7821        | RInt64 _ -> pr "  int64_t r;\n"
7822        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7823        | RString _ -> pr "  char *r;\n"
7824        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7825        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7826        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7827        | RBufferOut _ ->
7828            pr "  char *r;\n";
7829            pr "  size_t size;\n";
7830       );
7831       List.iter (
7832         function
7833         | Device n
7834         | String n
7835         | OptString n -> pr "  const char *%s;\n" n
7836         | Pathname n
7837         | Dev_or_Path n
7838         | FileIn n
7839         | FileOut n -> pr "  char *%s;\n" n
7840         | BufferIn n ->
7841             pr "  const char *%s;\n" n;
7842             pr "  size_t %s_size;\n" n
7843         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7844         | Bool n -> pr "  int %s;\n" n
7845         | Int n -> pr "  int %s;\n" n
7846         | Int64 n -> pr "  int64_t %s;\n" n
7847       ) (snd style);
7848
7849       (* Check and convert parameters. *)
7850       let argc_expected = List.length (snd style) in
7851       pr "  if (argc != %d) {\n" argc_expected;
7852       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7853         argc_expected;
7854       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7855       pr "    return -1;\n";
7856       pr "  }\n";
7857
7858       let parse_integer fn fntyp rtyp range name i =
7859         pr "  {\n";
7860         pr "    strtol_error xerr;\n";
7861         pr "    %s r;\n" fntyp;
7862         pr "\n";
7863         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7864         pr "    if (xerr != LONGINT_OK) {\n";
7865         pr "      fprintf (stderr,\n";
7866         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7867         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7868         pr "      return -1;\n";
7869         pr "    }\n";
7870         (match range with
7871          | None -> ()
7872          | Some (min, max, comment) ->
7873              pr "    /* %s */\n" comment;
7874              pr "    if (r < %s || r > %s) {\n" min max;
7875              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7876                name;
7877              pr "      return -1;\n";
7878              pr "    }\n";
7879              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7880         );
7881         pr "    %s = r;\n" name;
7882         pr "  }\n";
7883       in
7884
7885       iteri (
7886         fun i ->
7887           function
7888           | Device name
7889           | String name ->
7890               pr "  %s = argv[%d];\n" name i
7891           | Pathname name
7892           | Dev_or_Path name ->
7893               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7894               pr "  if (%s == NULL) return -1;\n" name
7895           | OptString name ->
7896               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7897                 name i i
7898           | BufferIn name ->
7899               pr "  %s = argv[%d];\n" name i;
7900               pr "  %s_size = strlen (argv[%d]);\n" name i
7901           | FileIn name ->
7902               pr "  %s = file_in (argv[%d]);\n" name i;
7903               pr "  if (%s == NULL) return -1;\n" name
7904           | FileOut name ->
7905               pr "  %s = file_out (argv[%d]);\n" name i;
7906               pr "  if (%s == NULL) return -1;\n" name
7907           | StringList name | DeviceList name ->
7908               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7909               pr "  if (%s == NULL) return -1;\n" name;
7910           | Bool name ->
7911               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7912           | Int name ->
7913               let range =
7914                 let min = "(-(2LL<<30))"
7915                 and max = "((2LL<<30)-1)"
7916                 and comment =
7917                   "The Int type in the generator is a signed 31 bit int." in
7918                 Some (min, max, comment) in
7919               parse_integer "xstrtoll" "long long" "int" range name i
7920           | Int64 name ->
7921               parse_integer "xstrtoll" "long long" "int64_t" None name i
7922       ) (snd style);
7923
7924       (* Call C API function. *)
7925       pr "  r = guestfs_%s " name;
7926       generate_c_call_args ~handle:"g" style;
7927       pr ";\n";
7928
7929       List.iter (
7930         function
7931         | Device _ | String _
7932         | OptString _ | Bool _
7933         | Int _ | Int64 _
7934         | BufferIn _ -> ()
7935         | Pathname name | Dev_or_Path name | FileOut name ->
7936             pr "  free (%s);\n" name
7937         | FileIn name ->
7938             pr "  free_file_in (%s);\n" name
7939         | StringList name | DeviceList name ->
7940             pr "  free_strings (%s);\n" name
7941       ) (snd style);
7942
7943       (* Any output flags? *)
7944       let fish_output =
7945         let flags = filter_map (
7946           function FishOutput flag -> Some flag | _ -> None
7947         ) flags in
7948         match flags with
7949         | [] -> None
7950         | [f] -> Some f
7951         | _ ->
7952             failwithf "%s: more than one FishOutput flag is not allowed" name in
7953
7954       (* Check return value for errors and display command results. *)
7955       (match fst style with
7956        | RErr -> pr "  return r;\n"
7957        | RInt _ ->
7958            pr "  if (r == -1) return -1;\n";
7959            (match fish_output with
7960             | None ->
7961                 pr "  printf (\"%%d\\n\", r);\n";
7962             | Some FishOutputOctal ->
7963                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7964             | Some FishOutputHexadecimal ->
7965                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7966            pr "  return 0;\n"
7967        | RInt64 _ ->
7968            pr "  if (r == -1) return -1;\n";
7969            (match fish_output with
7970             | None ->
7971                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7972             | Some FishOutputOctal ->
7973                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7974             | Some FishOutputHexadecimal ->
7975                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7976            pr "  return 0;\n"
7977        | RBool _ ->
7978            pr "  if (r == -1) return -1;\n";
7979            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7980            pr "  return 0;\n"
7981        | RConstString _ ->
7982            pr "  if (r == NULL) return -1;\n";
7983            pr "  printf (\"%%s\\n\", r);\n";
7984            pr "  return 0;\n"
7985        | RConstOptString _ ->
7986            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7987            pr "  return 0;\n"
7988        | RString _ ->
7989            pr "  if (r == NULL) return -1;\n";
7990            pr "  printf (\"%%s\\n\", r);\n";
7991            pr "  free (r);\n";
7992            pr "  return 0;\n"
7993        | RStringList _ ->
7994            pr "  if (r == NULL) return -1;\n";
7995            pr "  print_strings (r);\n";
7996            pr "  free_strings (r);\n";
7997            pr "  return 0;\n"
7998        | RStruct (_, typ) ->
7999            pr "  if (r == NULL) return -1;\n";
8000            pr "  print_%s (r);\n" typ;
8001            pr "  guestfs_free_%s (r);\n" typ;
8002            pr "  return 0;\n"
8003        | RStructList (_, typ) ->
8004            pr "  if (r == NULL) return -1;\n";
8005            pr "  print_%s_list (r);\n" typ;
8006            pr "  guestfs_free_%s_list (r);\n" typ;
8007            pr "  return 0;\n"
8008        | RHashtable _ ->
8009            pr "  if (r == NULL) return -1;\n";
8010            pr "  print_table (r);\n";
8011            pr "  free_strings (r);\n";
8012            pr "  return 0;\n"
8013        | RBufferOut _ ->
8014            pr "  if (r == NULL) return -1;\n";
8015            pr "  if (full_write (1, r, size) != size) {\n";
8016            pr "    perror (\"write\");\n";
8017            pr "    free (r);\n";
8018            pr "    return -1;\n";
8019            pr "  }\n";
8020            pr "  free (r);\n";
8021            pr "  return 0;\n"
8022       );
8023       pr "}\n";
8024       pr "\n"
8025   ) all_functions;
8026
8027   (* run_action function *)
8028   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
8029   pr "{\n";
8030   List.iter (
8031     fun (name, _, _, flags, _, _, _) ->
8032       let name2 = replace_char name '_' '-' in
8033       let alias =
8034         try find_map (function FishAlias n -> Some n | _ -> None) flags
8035         with Not_found -> name in
8036       pr "  if (";
8037       pr "STRCASEEQ (cmd, \"%s\")" name;
8038       if name <> name2 then
8039         pr " || STRCASEEQ (cmd, \"%s\")" name2;
8040       if name <> alias then
8041         pr " || STRCASEEQ (cmd, \"%s\")" alias;
8042       pr ")\n";
8043       pr "    return run_%s (cmd, argc, argv);\n" name;
8044       pr "  else\n";
8045   ) all_functions;
8046   pr "    {\n";
8047   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
8048   pr "      if (command_num == 1)\n";
8049   pr "        extended_help_message ();\n";
8050   pr "      return -1;\n";
8051   pr "    }\n";
8052   pr "  return 0;\n";
8053   pr "}\n";
8054   pr "\n"
8055
8056 (* Readline completion for guestfish. *)
8057 and generate_fish_completion () =
8058   generate_header CStyle GPLv2plus;
8059
8060   let all_functions =
8061     List.filter (
8062       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
8063     ) all_functions in
8064
8065   pr "\
8066 #include <config.h>
8067
8068 #include <stdio.h>
8069 #include <stdlib.h>
8070 #include <string.h>
8071
8072 #ifdef HAVE_LIBREADLINE
8073 #include <readline/readline.h>
8074 #endif
8075
8076 #include \"fish.h\"
8077
8078 #ifdef HAVE_LIBREADLINE
8079
8080 static const char *const commands[] = {
8081   BUILTIN_COMMANDS_FOR_COMPLETION,
8082 ";
8083
8084   (* Get the commands, including the aliases.  They don't need to be
8085    * sorted - the generator() function just does a dumb linear search.
8086    *)
8087   let commands =
8088     List.map (
8089       fun (name, _, _, flags, _, _, _) ->
8090         let name2 = replace_char name '_' '-' in
8091         let alias =
8092           try find_map (function FishAlias n -> Some n | _ -> None) flags
8093           with Not_found -> name in
8094
8095         if name <> alias then [name2; alias] else [name2]
8096     ) all_functions in
8097   let commands = List.flatten commands in
8098
8099   List.iter (pr "  \"%s\",\n") commands;
8100
8101   pr "  NULL
8102 };
8103
8104 static char *
8105 generator (const char *text, int state)
8106 {
8107   static size_t index, len;
8108   const char *name;
8109
8110   if (!state) {
8111     index = 0;
8112     len = strlen (text);
8113   }
8114
8115   rl_attempted_completion_over = 1;
8116
8117   while ((name = commands[index]) != NULL) {
8118     index++;
8119     if (STRCASEEQLEN (name, text, len))
8120       return strdup (name);
8121   }
8122
8123   return NULL;
8124 }
8125
8126 #endif /* HAVE_LIBREADLINE */
8127
8128 #ifdef HAVE_RL_COMPLETION_MATCHES
8129 #define RL_COMPLETION_MATCHES rl_completion_matches
8130 #else
8131 #ifdef HAVE_COMPLETION_MATCHES
8132 #define RL_COMPLETION_MATCHES completion_matches
8133 #endif
8134 #endif /* else just fail if we don't have either symbol */
8135
8136 char **
8137 do_completion (const char *text, int start, int end)
8138 {
8139   char **matches = NULL;
8140
8141 #ifdef HAVE_LIBREADLINE
8142   rl_completion_append_character = ' ';
8143
8144   if (start == 0)
8145     matches = RL_COMPLETION_MATCHES (text, generator);
8146   else if (complete_dest_paths)
8147     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8148 #endif
8149
8150   return matches;
8151 }
8152 ";
8153
8154 (* Generate the POD documentation for guestfish. *)
8155 and generate_fish_actions_pod () =
8156   let all_functions_sorted =
8157     List.filter (
8158       fun (_, _, _, flags, _, _, _) ->
8159         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8160     ) all_functions_sorted in
8161
8162   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8163
8164   List.iter (
8165     fun (name, style, _, flags, _, _, longdesc) ->
8166       let longdesc =
8167         Str.global_substitute rex (
8168           fun s ->
8169             let sub =
8170               try Str.matched_group 1 s
8171               with Not_found ->
8172                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8173             "C<" ^ replace_char sub '_' '-' ^ ">"
8174         ) longdesc in
8175       let name = replace_char name '_' '-' in
8176       let alias =
8177         try find_map (function FishAlias n -> Some n | _ -> None) flags
8178         with Not_found -> name in
8179
8180       pr "=head2 %s" name;
8181       if name <> alias then
8182         pr " | %s" alias;
8183       pr "\n";
8184       pr "\n";
8185       pr " %s" name;
8186       List.iter (
8187         function
8188         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8189         | OptString n -> pr " %s" n
8190         | StringList n | DeviceList n -> pr " '%s ...'" n
8191         | Bool _ -> pr " true|false"
8192         | Int n -> pr " %s" n
8193         | Int64 n -> pr " %s" n
8194         | FileIn n | FileOut n -> pr " (%s|-)" n
8195         | BufferIn n -> pr " %s" n
8196       ) (snd style);
8197       pr "\n";
8198       pr "\n";
8199       pr "%s\n\n" longdesc;
8200
8201       if List.exists (function FileIn _ | FileOut _ -> true
8202                       | _ -> false) (snd style) then
8203         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8204
8205       if List.mem ProtocolLimitWarning flags then
8206         pr "%s\n\n" protocol_limit_warning;
8207
8208       if List.mem DangerWillRobinson flags then
8209         pr "%s\n\n" danger_will_robinson;
8210
8211       match deprecation_notice flags with
8212       | None -> ()
8213       | Some txt -> pr "%s\n\n" txt
8214   ) all_functions_sorted
8215
8216 (* Generate a C function prototype. *)
8217 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8218     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8219     ?(prefix = "")
8220     ?handle name style =
8221   if extern then pr "extern ";
8222   if static then pr "static ";
8223   (match fst style with
8224    | RErr -> pr "int "
8225    | RInt _ -> pr "int "
8226    | RInt64 _ -> pr "int64_t "
8227    | RBool _ -> pr "int "
8228    | RConstString _ | RConstOptString _ -> pr "const char *"
8229    | RString _ | RBufferOut _ -> pr "char *"
8230    | RStringList _ | RHashtable _ -> pr "char **"
8231    | RStruct (_, typ) ->
8232        if not in_daemon then pr "struct guestfs_%s *" typ
8233        else pr "guestfs_int_%s *" typ
8234    | RStructList (_, typ) ->
8235        if not in_daemon then pr "struct guestfs_%s_list *" typ
8236        else pr "guestfs_int_%s_list *" typ
8237   );
8238   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8239   pr "%s%s (" prefix name;
8240   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8241     pr "void"
8242   else (
8243     let comma = ref false in
8244     (match handle with
8245      | None -> ()
8246      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8247     );
8248     let next () =
8249       if !comma then (
8250         if single_line then pr ", " else pr ",\n\t\t"
8251       );
8252       comma := true
8253     in
8254     List.iter (
8255       function
8256       | Pathname n
8257       | Device n | Dev_or_Path n
8258       | String n
8259       | OptString n ->
8260           next ();
8261           pr "const char *%s" n
8262       | StringList n | DeviceList n ->
8263           next ();
8264           pr "char *const *%s" n
8265       | Bool n -> next (); pr "int %s" n
8266       | Int n -> next (); pr "int %s" n
8267       | Int64 n -> next (); pr "int64_t %s" n
8268       | FileIn n
8269       | FileOut n ->
8270           if not in_daemon then (next (); pr "const char *%s" n)
8271       | BufferIn n ->
8272           next ();
8273           pr "const char *%s" n;
8274           next ();
8275           pr "size_t %s_size" n
8276     ) (snd style);
8277     if is_RBufferOut then (next (); pr "size_t *size_r");
8278   );
8279   pr ")";
8280   if semicolon then pr ";";
8281   if newline then pr "\n"
8282
8283 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8284 and generate_c_call_args ?handle ?(decl = false) style =
8285   pr "(";
8286   let comma = ref false in
8287   let next () =
8288     if !comma then pr ", ";
8289     comma := true
8290   in
8291   (match handle with
8292    | None -> ()
8293    | Some handle -> pr "%s" handle; comma := true
8294   );
8295   List.iter (
8296     function
8297     | BufferIn n ->
8298         next ();
8299         pr "%s, %s_size" n n
8300     | arg ->
8301         next ();
8302         pr "%s" (name_of_argt arg)
8303   ) (snd style);
8304   (* For RBufferOut calls, add implicit &size parameter. *)
8305   if not decl then (
8306     match fst style with
8307     | RBufferOut _ ->
8308         next ();
8309         pr "&size"
8310     | _ -> ()
8311   );
8312   pr ")"
8313
8314 (* Generate the OCaml bindings interface. *)
8315 and generate_ocaml_mli () =
8316   generate_header OCamlStyle LGPLv2plus;
8317
8318   pr "\
8319 (** For API documentation you should refer to the C API
8320     in the guestfs(3) manual page.  The OCaml API uses almost
8321     exactly the same calls. *)
8322
8323 type t
8324 (** A [guestfs_h] handle. *)
8325
8326 exception Error of string
8327 (** This exception is raised when there is an error. *)
8328
8329 exception Handle_closed of string
8330 (** This exception is raised if you use a {!Guestfs.t} handle
8331     after calling {!close} on it.  The string is the name of
8332     the function. *)
8333
8334 val create : unit -> t
8335 (** Create a {!Guestfs.t} handle. *)
8336
8337 val close : t -> unit
8338 (** Close the {!Guestfs.t} handle and free up all resources used
8339     by it immediately.
8340
8341     Handles are closed by the garbage collector when they become
8342     unreferenced, but callers can call this in order to provide
8343     predictable cleanup. *)
8344
8345 ";
8346   generate_ocaml_structure_decls ();
8347
8348   (* The actions. *)
8349   List.iter (
8350     fun (name, style, _, _, _, shortdesc, _) ->
8351       generate_ocaml_prototype name style;
8352       pr "(** %s *)\n" shortdesc;
8353       pr "\n"
8354   ) all_functions_sorted
8355
8356 (* Generate the OCaml bindings implementation. *)
8357 and generate_ocaml_ml () =
8358   generate_header OCamlStyle LGPLv2plus;
8359
8360   pr "\
8361 type t
8362
8363 exception Error of string
8364 exception Handle_closed of string
8365
8366 external create : unit -> t = \"ocaml_guestfs_create\"
8367 external close : t -> unit = \"ocaml_guestfs_close\"
8368
8369 (* Give the exceptions names, so they can be raised from the C code. *)
8370 let () =
8371   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8372   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8373
8374 ";
8375
8376   generate_ocaml_structure_decls ();
8377
8378   (* The actions. *)
8379   List.iter (
8380     fun (name, style, _, _, _, shortdesc, _) ->
8381       generate_ocaml_prototype ~is_external:true name style;
8382   ) all_functions_sorted
8383
8384 (* Generate the OCaml bindings C implementation. *)
8385 and generate_ocaml_c () =
8386   generate_header CStyle LGPLv2plus;
8387
8388   pr "\
8389 #include <stdio.h>
8390 #include <stdlib.h>
8391 #include <string.h>
8392
8393 #include <caml/config.h>
8394 #include <caml/alloc.h>
8395 #include <caml/callback.h>
8396 #include <caml/fail.h>
8397 #include <caml/memory.h>
8398 #include <caml/mlvalues.h>
8399 #include <caml/signals.h>
8400
8401 #include \"guestfs.h\"
8402
8403 #include \"guestfs_c.h\"
8404
8405 /* Copy a hashtable of string pairs into an assoc-list.  We return
8406  * the list in reverse order, but hashtables aren't supposed to be
8407  * ordered anyway.
8408  */
8409 static CAMLprim value
8410 copy_table (char * const * argv)
8411 {
8412   CAMLparam0 ();
8413   CAMLlocal5 (rv, pairv, kv, vv, cons);
8414   size_t i;
8415
8416   rv = Val_int (0);
8417   for (i = 0; argv[i] != NULL; i += 2) {
8418     kv = caml_copy_string (argv[i]);
8419     vv = caml_copy_string (argv[i+1]);
8420     pairv = caml_alloc (2, 0);
8421     Store_field (pairv, 0, kv);
8422     Store_field (pairv, 1, vv);
8423     cons = caml_alloc (2, 0);
8424     Store_field (cons, 1, rv);
8425     rv = cons;
8426     Store_field (cons, 0, pairv);
8427   }
8428
8429   CAMLreturn (rv);
8430 }
8431
8432 ";
8433
8434   (* Struct copy functions. *)
8435
8436   let emit_ocaml_copy_list_function typ =
8437     pr "static CAMLprim value\n";
8438     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8439     pr "{\n";
8440     pr "  CAMLparam0 ();\n";
8441     pr "  CAMLlocal2 (rv, v);\n";
8442     pr "  unsigned int i;\n";
8443     pr "\n";
8444     pr "  if (%ss->len == 0)\n" typ;
8445     pr "    CAMLreturn (Atom (0));\n";
8446     pr "  else {\n";
8447     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8448     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8449     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8450     pr "      caml_modify (&Field (rv, i), v);\n";
8451     pr "    }\n";
8452     pr "    CAMLreturn (rv);\n";
8453     pr "  }\n";
8454     pr "}\n";
8455     pr "\n";
8456   in
8457
8458   List.iter (
8459     fun (typ, cols) ->
8460       let has_optpercent_col =
8461         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8462
8463       pr "static CAMLprim value\n";
8464       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8465       pr "{\n";
8466       pr "  CAMLparam0 ();\n";
8467       if has_optpercent_col then
8468         pr "  CAMLlocal3 (rv, v, v2);\n"
8469       else
8470         pr "  CAMLlocal2 (rv, v);\n";
8471       pr "\n";
8472       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8473       iteri (
8474         fun i col ->
8475           (match col with
8476            | name, FString ->
8477                pr "  v = caml_copy_string (%s->%s);\n" typ name
8478            | name, FBuffer ->
8479                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8480                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8481                  typ name typ name
8482            | name, FUUID ->
8483                pr "  v = caml_alloc_string (32);\n";
8484                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8485            | name, (FBytes|FInt64|FUInt64) ->
8486                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8487            | name, (FInt32|FUInt32) ->
8488                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8489            | name, FOptPercent ->
8490                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8491                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8492                pr "    v = caml_alloc (1, 0);\n";
8493                pr "    Store_field (v, 0, v2);\n";
8494                pr "  } else /* None */\n";
8495                pr "    v = Val_int (0);\n";
8496            | name, FChar ->
8497                pr "  v = Val_int (%s->%s);\n" typ name
8498           );
8499           pr "  Store_field (rv, %d, v);\n" i
8500       ) cols;
8501       pr "  CAMLreturn (rv);\n";
8502       pr "}\n";
8503       pr "\n";
8504   ) structs;
8505
8506   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8507   List.iter (
8508     function
8509     | typ, (RStructListOnly | RStructAndList) ->
8510         (* generate the function for typ *)
8511         emit_ocaml_copy_list_function typ
8512     | typ, _ -> () (* empty *)
8513   ) (rstructs_used_by all_functions);
8514
8515   (* The wrappers. *)
8516   List.iter (
8517     fun (name, style, _, _, _, _, _) ->
8518       pr "/* Automatically generated wrapper for function\n";
8519       pr " * ";
8520       generate_ocaml_prototype name style;
8521       pr " */\n";
8522       pr "\n";
8523
8524       let params =
8525         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8526
8527       let needs_extra_vs =
8528         match fst style with RConstOptString _ -> true | _ -> false in
8529
8530       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8531       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8532       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8533       pr "\n";
8534
8535       pr "CAMLprim value\n";
8536       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8537       List.iter (pr ", value %s") (List.tl params);
8538       pr ")\n";
8539       pr "{\n";
8540
8541       (match params with
8542        | [p1; p2; p3; p4; p5] ->
8543            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8544        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8545            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8546            pr "  CAMLxparam%d (%s);\n"
8547              (List.length rest) (String.concat ", " rest)
8548        | ps ->
8549            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8550       );
8551       if not needs_extra_vs then
8552         pr "  CAMLlocal1 (rv);\n"
8553       else
8554         pr "  CAMLlocal3 (rv, v, v2);\n";
8555       pr "\n";
8556
8557       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8558       pr "  if (g == NULL)\n";
8559       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8560       pr "\n";
8561
8562       List.iter (
8563         function
8564         | Pathname n
8565         | Device n | Dev_or_Path n
8566         | String n
8567         | FileIn n
8568         | FileOut n ->
8569             (* Copy strings in case the GC moves them: RHBZ#604691 *)
8570             pr "  char *%s = guestfs_safe_strdup (g, String_val (%sv));\n" n n
8571         | OptString n ->
8572             pr "  char *%s =\n" n;
8573             pr "    %sv != Val_int (0) ?" n;
8574             pr "      guestfs_safe_strdup (g, String_val (Field (%sv, 0))) : NULL;\n" n
8575         | BufferIn n ->
8576             pr "  size_t %s_size = caml_string_length (%sv);\n" n n;
8577             pr "  char *%s = guestfs_safe_memdup (g, String_val (%sv), %s_size);\n" n n n
8578         | StringList n | DeviceList n ->
8579             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8580         | Bool n ->
8581             pr "  int %s = Bool_val (%sv);\n" n n
8582         | Int n ->
8583             pr "  int %s = Int_val (%sv);\n" n n
8584         | Int64 n ->
8585             pr "  int64_t %s = Int64_val (%sv);\n" n n
8586       ) (snd style);
8587       let error_code =
8588         match fst style with
8589         | RErr -> pr "  int r;\n"; "-1"
8590         | RInt _ -> pr "  int r;\n"; "-1"
8591         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8592         | RBool _ -> pr "  int r;\n"; "-1"
8593         | RConstString _ | RConstOptString _ ->
8594             pr "  const char *r;\n"; "NULL"
8595         | RString _ -> pr "  char *r;\n"; "NULL"
8596         | RStringList _ ->
8597             pr "  size_t i;\n";
8598             pr "  char **r;\n";
8599             "NULL"
8600         | RStruct (_, typ) ->
8601             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8602         | RStructList (_, typ) ->
8603             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8604         | RHashtable _ ->
8605             pr "  size_t i;\n";
8606             pr "  char **r;\n";
8607             "NULL"
8608         | RBufferOut _ ->
8609             pr "  char *r;\n";
8610             pr "  size_t size;\n";
8611             "NULL" in
8612       pr "\n";
8613
8614       pr "  caml_enter_blocking_section ();\n";
8615       pr "  r = guestfs_%s " name;
8616       generate_c_call_args ~handle:"g" style;
8617       pr ";\n";
8618       pr "  caml_leave_blocking_section ();\n";
8619
8620       (* Free strings if we copied them above. *)
8621       List.iter (
8622         function
8623         | Pathname n | Device n | Dev_or_Path n | String n | OptString n
8624         | FileIn n | FileOut n | BufferIn n ->
8625             pr "  free (%s);\n" n
8626         | StringList n | DeviceList n ->
8627             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8628         | Bool _ | Int _ | Int64 _ -> ()
8629       ) (snd style);
8630
8631       pr "  if (r == %s)\n" error_code;
8632       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8633       pr "\n";
8634
8635       (match fst style with
8636        | RErr -> pr "  rv = Val_unit;\n"
8637        | RInt _ -> pr "  rv = Val_int (r);\n"
8638        | RInt64 _ ->
8639            pr "  rv = caml_copy_int64 (r);\n"
8640        | RBool _ -> pr "  rv = Val_bool (r);\n"
8641        | RConstString _ ->
8642            pr "  rv = caml_copy_string (r);\n"
8643        | RConstOptString _ ->
8644            pr "  if (r) { /* Some string */\n";
8645            pr "    v = caml_alloc (1, 0);\n";
8646            pr "    v2 = caml_copy_string (r);\n";
8647            pr "    Store_field (v, 0, v2);\n";
8648            pr "  } else /* None */\n";
8649            pr "    v = Val_int (0);\n";
8650        | RString _ ->
8651            pr "  rv = caml_copy_string (r);\n";
8652            pr "  free (r);\n"
8653        | RStringList _ ->
8654            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8655            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8656            pr "  free (r);\n"
8657        | RStruct (_, typ) ->
8658            pr "  rv = copy_%s (r);\n" typ;
8659            pr "  guestfs_free_%s (r);\n" typ;
8660        | RStructList (_, typ) ->
8661            pr "  rv = copy_%s_list (r);\n" typ;
8662            pr "  guestfs_free_%s_list (r);\n" typ;
8663        | RHashtable _ ->
8664            pr "  rv = copy_table (r);\n";
8665            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8666            pr "  free (r);\n";
8667        | RBufferOut _ ->
8668            pr "  rv = caml_alloc_string (size);\n";
8669            pr "  memcpy (String_val (rv), r, size);\n";
8670       );
8671
8672       pr "  CAMLreturn (rv);\n";
8673       pr "}\n";
8674       pr "\n";
8675
8676       if List.length params > 5 then (
8677         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8678         pr "CAMLprim value ";
8679         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8680         pr "CAMLprim value\n";
8681         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8682         pr "{\n";
8683         pr "  return ocaml_guestfs_%s (argv[0]" name;
8684         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8685         pr ");\n";
8686         pr "}\n";
8687         pr "\n"
8688       )
8689   ) all_functions_sorted
8690
8691 and generate_ocaml_structure_decls () =
8692   List.iter (
8693     fun (typ, cols) ->
8694       pr "type %s = {\n" typ;
8695       List.iter (
8696         function
8697         | name, FString -> pr "  %s : string;\n" name
8698         | name, FBuffer -> pr "  %s : string;\n" name
8699         | name, FUUID -> pr "  %s : string;\n" name
8700         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8701         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8702         | name, FChar -> pr "  %s : char;\n" name
8703         | name, FOptPercent -> pr "  %s : float option;\n" name
8704       ) cols;
8705       pr "}\n";
8706       pr "\n"
8707   ) structs
8708
8709 and generate_ocaml_prototype ?(is_external = false) name style =
8710   if is_external then pr "external " else pr "val ";
8711   pr "%s : t -> " name;
8712   List.iter (
8713     function
8714     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8715     | BufferIn _ -> pr "string -> "
8716     | OptString _ -> pr "string option -> "
8717     | StringList _ | DeviceList _ -> pr "string array -> "
8718     | Bool _ -> pr "bool -> "
8719     | Int _ -> pr "int -> "
8720     | Int64 _ -> pr "int64 -> "
8721   ) (snd style);
8722   (match fst style with
8723    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8724    | RInt _ -> pr "int"
8725    | RInt64 _ -> pr "int64"
8726    | RBool _ -> pr "bool"
8727    | RConstString _ -> pr "string"
8728    | RConstOptString _ -> pr "string option"
8729    | RString _ | RBufferOut _ -> pr "string"
8730    | RStringList _ -> pr "string array"
8731    | RStruct (_, typ) -> pr "%s" typ
8732    | RStructList (_, typ) -> pr "%s array" typ
8733    | RHashtable _ -> pr "(string * string) list"
8734   );
8735   if is_external then (
8736     pr " = ";
8737     if List.length (snd style) + 1 > 5 then
8738       pr "\"ocaml_guestfs_%s_byte\" " name;
8739     pr "\"ocaml_guestfs_%s\"" name
8740   );
8741   pr "\n"
8742
8743 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8744 and generate_perl_xs () =
8745   generate_header CStyle LGPLv2plus;
8746
8747   pr "\
8748 #include \"EXTERN.h\"
8749 #include \"perl.h\"
8750 #include \"XSUB.h\"
8751
8752 #include <guestfs.h>
8753
8754 #ifndef PRId64
8755 #define PRId64 \"lld\"
8756 #endif
8757
8758 static SV *
8759 my_newSVll(long long val) {
8760 #ifdef USE_64_BIT_ALL
8761   return newSViv(val);
8762 #else
8763   char buf[100];
8764   int len;
8765   len = snprintf(buf, 100, \"%%\" PRId64, val);
8766   return newSVpv(buf, len);
8767 #endif
8768 }
8769
8770 #ifndef PRIu64
8771 #define PRIu64 \"llu\"
8772 #endif
8773
8774 static SV *
8775 my_newSVull(unsigned long long val) {
8776 #ifdef USE_64_BIT_ALL
8777   return newSVuv(val);
8778 #else
8779   char buf[100];
8780   int len;
8781   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8782   return newSVpv(buf, len);
8783 #endif
8784 }
8785
8786 /* http://www.perlmonks.org/?node_id=680842 */
8787 static char **
8788 XS_unpack_charPtrPtr (SV *arg) {
8789   char **ret;
8790   AV *av;
8791   I32 i;
8792
8793   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8794     croak (\"array reference expected\");
8795
8796   av = (AV *)SvRV (arg);
8797   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8798   if (!ret)
8799     croak (\"malloc failed\");
8800
8801   for (i = 0; i <= av_len (av); i++) {
8802     SV **elem = av_fetch (av, i, 0);
8803
8804     if (!elem || !*elem)
8805       croak (\"missing element in list\");
8806
8807     ret[i] = SvPV_nolen (*elem);
8808   }
8809
8810   ret[i] = NULL;
8811
8812   return ret;
8813 }
8814
8815 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8816
8817 PROTOTYPES: ENABLE
8818
8819 guestfs_h *
8820 _create ()
8821    CODE:
8822       RETVAL = guestfs_create ();
8823       if (!RETVAL)
8824         croak (\"could not create guestfs handle\");
8825       guestfs_set_error_handler (RETVAL, NULL, NULL);
8826  OUTPUT:
8827       RETVAL
8828
8829 void
8830 DESTROY (sv)
8831       SV *sv;
8832  PPCODE:
8833       /* For the 'g' argument above we do the conversion explicitly and
8834        * don't rely on the typemap, because if the handle has been
8835        * explicitly closed we don't want the typemap conversion to
8836        * display an error.
8837        */
8838       HV *hv = (HV *) SvRV (sv);
8839       SV **svp = hv_fetch (hv, \"_g\", 2, 0);
8840       if (svp != NULL) {
8841         guestfs_h *g = (guestfs_h *) SvIV (*svp);
8842         assert (g != NULL);
8843         guestfs_close (g);
8844       }
8845
8846 void
8847 close (g)
8848       guestfs_h *g;
8849  PPCODE:
8850       guestfs_close (g);
8851       /* Avoid double-free in DESTROY method. */
8852       HV *hv = (HV *) SvRV (ST(0));
8853       (void) hv_delete (hv, \"_g\", 2, G_DISCARD);
8854
8855 ";
8856
8857   List.iter (
8858     fun (name, style, _, _, _, _, _) ->
8859       (match fst style with
8860        | RErr -> pr "void\n"
8861        | RInt _ -> pr "SV *\n"
8862        | RInt64 _ -> pr "SV *\n"
8863        | RBool _ -> pr "SV *\n"
8864        | RConstString _ -> pr "SV *\n"
8865        | RConstOptString _ -> pr "SV *\n"
8866        | RString _ -> pr "SV *\n"
8867        | RBufferOut _ -> pr "SV *\n"
8868        | RStringList _
8869        | RStruct _ | RStructList _
8870        | RHashtable _ ->
8871            pr "void\n" (* all lists returned implictly on the stack *)
8872       );
8873       (* Call and arguments. *)
8874       pr "%s (g" name;
8875       List.iter (
8876         fun arg -> pr ", %s" (name_of_argt arg)
8877       ) (snd style);
8878       pr ")\n";
8879       pr "      guestfs_h *g;\n";
8880       iteri (
8881         fun i ->
8882           function
8883           | Pathname n | Device n | Dev_or_Path n | String n
8884           | FileIn n | FileOut n ->
8885               pr "      char *%s;\n" n
8886           | BufferIn n ->
8887               pr "      char *%s;\n" n;
8888               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8889           | OptString n ->
8890               (* http://www.perlmonks.org/?node_id=554277
8891                * Note that the implicit handle argument means we have
8892                * to add 1 to the ST(x) operator.
8893                *)
8894               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8895           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8896           | Bool n -> pr "      int %s;\n" n
8897           | Int n -> pr "      int %s;\n" n
8898           | Int64 n -> pr "      int64_t %s;\n" n
8899       ) (snd style);
8900
8901       let do_cleanups () =
8902         List.iter (
8903           function
8904           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8905           | Bool _ | Int _ | Int64 _
8906           | FileIn _ | FileOut _
8907           | BufferIn _ -> ()
8908           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8909         ) (snd style)
8910       in
8911
8912       (* Code. *)
8913       (match fst style with
8914        | RErr ->
8915            pr "PREINIT:\n";
8916            pr "      int r;\n";
8917            pr " PPCODE:\n";
8918            pr "      r = guestfs_%s " name;
8919            generate_c_call_args ~handle:"g" style;
8920            pr ";\n";
8921            do_cleanups ();
8922            pr "      if (r == -1)\n";
8923            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8924        | RInt n
8925        | RBool n ->
8926            pr "PREINIT:\n";
8927            pr "      int %s;\n" n;
8928            pr "   CODE:\n";
8929            pr "      %s = guestfs_%s " n name;
8930            generate_c_call_args ~handle:"g" style;
8931            pr ";\n";
8932            do_cleanups ();
8933            pr "      if (%s == -1)\n" n;
8934            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8935            pr "      RETVAL = newSViv (%s);\n" n;
8936            pr " OUTPUT:\n";
8937            pr "      RETVAL\n"
8938        | RInt64 n ->
8939            pr "PREINIT:\n";
8940            pr "      int64_t %s;\n" n;
8941            pr "   CODE:\n";
8942            pr "      %s = guestfs_%s " n name;
8943            generate_c_call_args ~handle:"g" style;
8944            pr ";\n";
8945            do_cleanups ();
8946            pr "      if (%s == -1)\n" n;
8947            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8948            pr "      RETVAL = my_newSVll (%s);\n" n;
8949            pr " OUTPUT:\n";
8950            pr "      RETVAL\n"
8951        | RConstString n ->
8952            pr "PREINIT:\n";
8953            pr "      const char *%s;\n" n;
8954            pr "   CODE:\n";
8955            pr "      %s = guestfs_%s " n name;
8956            generate_c_call_args ~handle:"g" style;
8957            pr ";\n";
8958            do_cleanups ();
8959            pr "      if (%s == NULL)\n" n;
8960            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8961            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8962            pr " OUTPUT:\n";
8963            pr "      RETVAL\n"
8964        | RConstOptString n ->
8965            pr "PREINIT:\n";
8966            pr "      const char *%s;\n" n;
8967            pr "   CODE:\n";
8968            pr "      %s = guestfs_%s " n name;
8969            generate_c_call_args ~handle:"g" style;
8970            pr ";\n";
8971            do_cleanups ();
8972            pr "      if (%s == NULL)\n" n;
8973            pr "        RETVAL = &PL_sv_undef;\n";
8974            pr "      else\n";
8975            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8976            pr " OUTPUT:\n";
8977            pr "      RETVAL\n"
8978        | RString n ->
8979            pr "PREINIT:\n";
8980            pr "      char *%s;\n" n;
8981            pr "   CODE:\n";
8982            pr "      %s = guestfs_%s " n name;
8983            generate_c_call_args ~handle:"g" style;
8984            pr ";\n";
8985            do_cleanups ();
8986            pr "      if (%s == NULL)\n" n;
8987            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8988            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8989            pr "      free (%s);\n" n;
8990            pr " OUTPUT:\n";
8991            pr "      RETVAL\n"
8992        | RStringList n | RHashtable n ->
8993            pr "PREINIT:\n";
8994            pr "      char **%s;\n" n;
8995            pr "      size_t i, n;\n";
8996            pr " PPCODE:\n";
8997            pr "      %s = guestfs_%s " n name;
8998            generate_c_call_args ~handle:"g" style;
8999            pr ";\n";
9000            do_cleanups ();
9001            pr "      if (%s == NULL)\n" n;
9002            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9003            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
9004            pr "      EXTEND (SP, n);\n";
9005            pr "      for (i = 0; i < n; ++i) {\n";
9006            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
9007            pr "        free (%s[i]);\n" n;
9008            pr "      }\n";
9009            pr "      free (%s);\n" n;
9010        | RStruct (n, typ) ->
9011            let cols = cols_of_struct typ in
9012            generate_perl_struct_code typ cols name style n do_cleanups
9013        | RStructList (n, typ) ->
9014            let cols = cols_of_struct typ in
9015            generate_perl_struct_list_code typ cols name style n do_cleanups
9016        | RBufferOut n ->
9017            pr "PREINIT:\n";
9018            pr "      char *%s;\n" n;
9019            pr "      size_t size;\n";
9020            pr "   CODE:\n";
9021            pr "      %s = guestfs_%s " n name;
9022            generate_c_call_args ~handle:"g" style;
9023            pr ";\n";
9024            do_cleanups ();
9025            pr "      if (%s == NULL)\n" n;
9026            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9027            pr "      RETVAL = newSVpvn (%s, size);\n" n;
9028            pr "      free (%s);\n" n;
9029            pr " OUTPUT:\n";
9030            pr "      RETVAL\n"
9031       );
9032
9033       pr "\n"
9034   ) all_functions
9035
9036 and generate_perl_struct_list_code typ cols name style n do_cleanups =
9037   pr "PREINIT:\n";
9038   pr "      struct guestfs_%s_list *%s;\n" typ n;
9039   pr "      size_t i;\n";
9040   pr "      HV *hv;\n";
9041   pr " PPCODE:\n";
9042   pr "      %s = guestfs_%s " n name;
9043   generate_c_call_args ~handle:"g" style;
9044   pr ";\n";
9045   do_cleanups ();
9046   pr "      if (%s == NULL)\n" n;
9047   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9048   pr "      EXTEND (SP, %s->len);\n" n;
9049   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
9050   pr "        hv = newHV ();\n";
9051   List.iter (
9052     function
9053     | name, FString ->
9054         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
9055           name (String.length name) n name
9056     | name, FUUID ->
9057         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
9058           name (String.length name) n name
9059     | name, FBuffer ->
9060         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
9061           name (String.length name) n name n name
9062     | name, (FBytes|FUInt64) ->
9063         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
9064           name (String.length name) n name
9065     | name, FInt64 ->
9066         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
9067           name (String.length name) n name
9068     | name, (FInt32|FUInt32) ->
9069         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9070           name (String.length name) n name
9071     | name, FChar ->
9072         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
9073           name (String.length name) n name
9074     | name, FOptPercent ->
9075         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9076           name (String.length name) n name
9077   ) cols;
9078   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
9079   pr "      }\n";
9080   pr "      guestfs_free_%s_list (%s);\n" typ n
9081
9082 and generate_perl_struct_code typ cols name style n do_cleanups =
9083   pr "PREINIT:\n";
9084   pr "      struct guestfs_%s *%s;\n" typ n;
9085   pr " PPCODE:\n";
9086   pr "      %s = guestfs_%s " n name;
9087   generate_c_call_args ~handle:"g" style;
9088   pr ";\n";
9089   do_cleanups ();
9090   pr "      if (%s == NULL)\n" n;
9091   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9092   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
9093   List.iter (
9094     fun ((name, _) as col) ->
9095       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
9096
9097       match col with
9098       | name, FString ->
9099           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
9100             n name
9101       | name, FBuffer ->
9102           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
9103             n name n name
9104       | name, FUUID ->
9105           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
9106             n name
9107       | name, (FBytes|FUInt64) ->
9108           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
9109             n name
9110       | name, FInt64 ->
9111           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
9112             n name
9113       | name, (FInt32|FUInt32) ->
9114           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9115             n name
9116       | name, FChar ->
9117           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9118             n name
9119       | name, FOptPercent ->
9120           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9121             n name
9122   ) cols;
9123   pr "      free (%s);\n" n
9124
9125 (* Generate Sys/Guestfs.pm. *)
9126 and generate_perl_pm () =
9127   generate_header HashStyle LGPLv2plus;
9128
9129   pr "\
9130 =pod
9131
9132 =head1 NAME
9133
9134 Sys::Guestfs - Perl bindings for libguestfs
9135
9136 =head1 SYNOPSIS
9137
9138  use Sys::Guestfs;
9139
9140  my $h = Sys::Guestfs->new ();
9141  $h->add_drive ('guest.img');
9142  $h->launch ();
9143  $h->mount ('/dev/sda1', '/');
9144  $h->touch ('/hello');
9145  $h->sync ();
9146
9147 =head1 DESCRIPTION
9148
9149 The C<Sys::Guestfs> module provides a Perl XS binding to the
9150 libguestfs API for examining and modifying virtual machine
9151 disk images.
9152
9153 Amongst the things this is good for: making batch configuration
9154 changes to guests, getting disk used/free statistics (see also:
9155 virt-df), migrating between virtualization systems (see also:
9156 virt-p2v), performing partial backups, performing partial guest
9157 clones, cloning guests and changing registry/UUID/hostname info, and
9158 much else besides.
9159
9160 Libguestfs uses Linux kernel and qemu code, and can access any type of
9161 guest filesystem that Linux and qemu can, including but not limited
9162 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9163 schemes, qcow, qcow2, vmdk.
9164
9165 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9166 LVs, what filesystem is in each LV, etc.).  It can also run commands
9167 in the context of the guest.  Also you can access filesystems over
9168 FUSE.
9169
9170 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9171 functions for using libguestfs from Perl, including integration
9172 with libvirt.
9173
9174 =head1 ERRORS
9175
9176 All errors turn into calls to C<croak> (see L<Carp(3)>).
9177
9178 =head1 METHODS
9179
9180 =over 4
9181
9182 =cut
9183
9184 package Sys::Guestfs;
9185
9186 use strict;
9187 use warnings;
9188
9189 # This version number changes whenever a new function
9190 # is added to the libguestfs API.  It is not directly
9191 # related to the libguestfs version number.
9192 use vars qw($VERSION);
9193 $VERSION = '0.%d';
9194
9195 require XSLoader;
9196 XSLoader::load ('Sys::Guestfs');
9197
9198 =item $h = Sys::Guestfs->new ();
9199
9200 Create a new guestfs handle.
9201
9202 =cut
9203
9204 sub new {
9205   my $proto = shift;
9206   my $class = ref ($proto) || $proto;
9207
9208   my $g = Sys::Guestfs::_create ();
9209   my $self = { _g => $g };
9210   bless $self, $class;
9211   return $self;
9212 }
9213
9214 =item $h->close ();
9215
9216 Explicitly close the guestfs handle.
9217
9218 B<Note:> You should not usually call this function.  The handle will
9219 be closed implicitly when its reference count goes to zero (eg.
9220 when it goes out of scope or the program ends).  This call is
9221 only required in some exceptional cases, such as where the program
9222 may contain cached references to the handle 'somewhere' and you
9223 really have to have the close happen right away.  After calling
9224 C<close> the program must not call any method (including C<close>)
9225 on the handle (but the implicit call to C<DESTROY> that happens
9226 when the final reference is cleaned up is OK).
9227
9228 =cut
9229
9230 " max_proc_nr;
9231
9232   (* Actions.  We only need to print documentation for these as
9233    * they are pulled in from the XS code automatically.
9234    *)
9235   List.iter (
9236     fun (name, style, _, flags, _, _, longdesc) ->
9237       if not (List.mem NotInDocs flags) then (
9238         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9239         pr "=item ";
9240         generate_perl_prototype name style;
9241         pr "\n\n";
9242         pr "%s\n\n" longdesc;
9243         if List.mem ProtocolLimitWarning flags then
9244           pr "%s\n\n" protocol_limit_warning;
9245         if List.mem DangerWillRobinson flags then
9246           pr "%s\n\n" danger_will_robinson;
9247         match deprecation_notice flags with
9248         | None -> ()
9249         | Some txt -> pr "%s\n\n" txt
9250       )
9251   ) all_functions_sorted;
9252
9253   (* End of file. *)
9254   pr "\
9255 =cut
9256
9257 1;
9258
9259 =back
9260
9261 =head1 COPYRIGHT
9262
9263 Copyright (C) %s Red Hat Inc.
9264
9265 =head1 LICENSE
9266
9267 Please see the file COPYING.LIB for the full license.
9268
9269 =head1 SEE ALSO
9270
9271 L<guestfs(3)>,
9272 L<guestfish(1)>,
9273 L<http://libguestfs.org>,
9274 L<Sys::Guestfs::Lib(3)>.
9275
9276 =cut
9277 " copyright_years
9278
9279 and generate_perl_prototype name style =
9280   (match fst style with
9281    | RErr -> ()
9282    | RBool n
9283    | RInt n
9284    | RInt64 n
9285    | RConstString n
9286    | RConstOptString n
9287    | RString n
9288    | RBufferOut n -> pr "$%s = " n
9289    | RStruct (n,_)
9290    | RHashtable n -> pr "%%%s = " n
9291    | RStringList n
9292    | RStructList (n,_) -> pr "@%s = " n
9293   );
9294   pr "$h->%s (" name;
9295   let comma = ref false in
9296   List.iter (
9297     fun arg ->
9298       if !comma then pr ", ";
9299       comma := true;
9300       match arg with
9301       | Pathname n | Device n | Dev_or_Path n | String n
9302       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9303       | BufferIn n ->
9304           pr "$%s" n
9305       | StringList n | DeviceList n ->
9306           pr "\\@%s" n
9307   ) (snd style);
9308   pr ");"
9309
9310 (* Generate Python C module. *)
9311 and generate_python_c () =
9312   generate_header CStyle LGPLv2plus;
9313
9314   pr "\
9315 #define PY_SSIZE_T_CLEAN 1
9316 #include <Python.h>
9317
9318 #if PY_VERSION_HEX < 0x02050000
9319 typedef int Py_ssize_t;
9320 #define PY_SSIZE_T_MAX INT_MAX
9321 #define PY_SSIZE_T_MIN INT_MIN
9322 #endif
9323
9324 #include <stdio.h>
9325 #include <stdlib.h>
9326 #include <assert.h>
9327
9328 #include \"guestfs.h\"
9329
9330 typedef struct {
9331   PyObject_HEAD
9332   guestfs_h *g;
9333 } Pyguestfs_Object;
9334
9335 static guestfs_h *
9336 get_handle (PyObject *obj)
9337 {
9338   assert (obj);
9339   assert (obj != Py_None);
9340   return ((Pyguestfs_Object *) obj)->g;
9341 }
9342
9343 static PyObject *
9344 put_handle (guestfs_h *g)
9345 {
9346   assert (g);
9347   return
9348     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9349 }
9350
9351 /* This list should be freed (but not the strings) after use. */
9352 static char **
9353 get_string_list (PyObject *obj)
9354 {
9355   size_t i, len;
9356   char **r;
9357
9358   assert (obj);
9359
9360   if (!PyList_Check (obj)) {
9361     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9362     return NULL;
9363   }
9364
9365   Py_ssize_t slen = PyList_Size (obj);
9366   if (slen == -1) {
9367     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
9368     return NULL;
9369   }
9370   len = (size_t) slen;
9371   r = malloc (sizeof (char *) * (len+1));
9372   if (r == NULL) {
9373     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9374     return NULL;
9375   }
9376
9377   for (i = 0; i < len; ++i)
9378     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9379   r[len] = NULL;
9380
9381   return r;
9382 }
9383
9384 static PyObject *
9385 put_string_list (char * const * const argv)
9386 {
9387   PyObject *list;
9388   int argc, i;
9389
9390   for (argc = 0; argv[argc] != NULL; ++argc)
9391     ;
9392
9393   list = PyList_New (argc);
9394   for (i = 0; i < argc; ++i)
9395     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9396
9397   return list;
9398 }
9399
9400 static PyObject *
9401 put_table (char * const * const argv)
9402 {
9403   PyObject *list, *item;
9404   int argc, i;
9405
9406   for (argc = 0; argv[argc] != NULL; ++argc)
9407     ;
9408
9409   list = PyList_New (argc >> 1);
9410   for (i = 0; i < argc; i += 2) {
9411     item = PyTuple_New (2);
9412     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9413     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9414     PyList_SetItem (list, i >> 1, item);
9415   }
9416
9417   return list;
9418 }
9419
9420 static void
9421 free_strings (char **argv)
9422 {
9423   int argc;
9424
9425   for (argc = 0; argv[argc] != NULL; ++argc)
9426     free (argv[argc]);
9427   free (argv);
9428 }
9429
9430 static PyObject *
9431 py_guestfs_create (PyObject *self, PyObject *args)
9432 {
9433   guestfs_h *g;
9434
9435   g = guestfs_create ();
9436   if (g == NULL) {
9437     PyErr_SetString (PyExc_RuntimeError,
9438                      \"guestfs.create: failed to allocate handle\");
9439     return NULL;
9440   }
9441   guestfs_set_error_handler (g, NULL, NULL);
9442   return put_handle (g);
9443 }
9444
9445 static PyObject *
9446 py_guestfs_close (PyObject *self, PyObject *args)
9447 {
9448   PyObject *py_g;
9449   guestfs_h *g;
9450
9451   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9452     return NULL;
9453   g = get_handle (py_g);
9454
9455   guestfs_close (g);
9456
9457   Py_INCREF (Py_None);
9458   return Py_None;
9459 }
9460
9461 ";
9462
9463   let emit_put_list_function typ =
9464     pr "static PyObject *\n";
9465     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9466     pr "{\n";
9467     pr "  PyObject *list;\n";
9468     pr "  size_t i;\n";
9469     pr "\n";
9470     pr "  list = PyList_New (%ss->len);\n" typ;
9471     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9472     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9473     pr "  return list;\n";
9474     pr "};\n";
9475     pr "\n"
9476   in
9477
9478   (* Structures, turned into Python dictionaries. *)
9479   List.iter (
9480     fun (typ, cols) ->
9481       pr "static PyObject *\n";
9482       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9483       pr "{\n";
9484       pr "  PyObject *dict;\n";
9485       pr "\n";
9486       pr "  dict = PyDict_New ();\n";
9487       List.iter (
9488         function
9489         | name, FString ->
9490             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9491             pr "                        PyString_FromString (%s->%s));\n"
9492               typ name
9493         | name, FBuffer ->
9494             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9495             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9496               typ name typ name
9497         | name, FUUID ->
9498             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9499             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9500               typ name
9501         | name, (FBytes|FUInt64) ->
9502             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9503             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9504               typ name
9505         | name, FInt64 ->
9506             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9507             pr "                        PyLong_FromLongLong (%s->%s));\n"
9508               typ name
9509         | name, FUInt32 ->
9510             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9511             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9512               typ name
9513         | name, FInt32 ->
9514             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9515             pr "                        PyLong_FromLong (%s->%s));\n"
9516               typ name
9517         | name, FOptPercent ->
9518             pr "  if (%s->%s >= 0)\n" typ name;
9519             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9520             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9521               typ name;
9522             pr "  else {\n";
9523             pr "    Py_INCREF (Py_None);\n";
9524             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9525             pr "  }\n"
9526         | name, FChar ->
9527             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9528             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9529       ) cols;
9530       pr "  return dict;\n";
9531       pr "};\n";
9532       pr "\n";
9533
9534   ) structs;
9535
9536   (* Emit a put_TYPE_list function definition only if that function is used. *)
9537   List.iter (
9538     function
9539     | typ, (RStructListOnly | RStructAndList) ->
9540         (* generate the function for typ *)
9541         emit_put_list_function typ
9542     | typ, _ -> () (* empty *)
9543   ) (rstructs_used_by all_functions);
9544
9545   (* Python wrapper functions. *)
9546   List.iter (
9547     fun (name, style, _, _, _, _, _) ->
9548       pr "static PyObject *\n";
9549       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9550       pr "{\n";
9551
9552       pr "  PyObject *py_g;\n";
9553       pr "  guestfs_h *g;\n";
9554       pr "  PyObject *py_r;\n";
9555
9556       let error_code =
9557         match fst style with
9558         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9559         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9560         | RConstString _ | RConstOptString _ ->
9561             pr "  const char *r;\n"; "NULL"
9562         | RString _ -> pr "  char *r;\n"; "NULL"
9563         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9564         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9565         | RStructList (_, typ) ->
9566             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9567         | RBufferOut _ ->
9568             pr "  char *r;\n";
9569             pr "  size_t size;\n";
9570             "NULL" in
9571
9572       List.iter (
9573         function
9574         | Pathname n | Device n | Dev_or_Path n | String n
9575         | FileIn n | FileOut n ->
9576             pr "  const char *%s;\n" n
9577         | OptString n -> pr "  const char *%s;\n" n
9578         | BufferIn n ->
9579             pr "  const char *%s;\n" n;
9580             pr "  Py_ssize_t %s_size;\n" n
9581         | StringList n | DeviceList n ->
9582             pr "  PyObject *py_%s;\n" n;
9583             pr "  char **%s;\n" n
9584         | Bool n -> pr "  int %s;\n" n
9585         | Int n -> pr "  int %s;\n" n
9586         | Int64 n -> pr "  long long %s;\n" n
9587       ) (snd style);
9588
9589       pr "\n";
9590
9591       (* Convert the parameters. *)
9592       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9593       List.iter (
9594         function
9595         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9596         | OptString _ -> pr "z"
9597         | StringList _ | DeviceList _ -> pr "O"
9598         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9599         | Int _ -> pr "i"
9600         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9601                              * emulate C's int/long/long long in Python?
9602                              *)
9603         | BufferIn _ -> pr "s#"
9604       ) (snd style);
9605       pr ":guestfs_%s\",\n" name;
9606       pr "                         &py_g";
9607       List.iter (
9608         function
9609         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9610         | OptString n -> pr ", &%s" n
9611         | StringList n | DeviceList n -> pr ", &py_%s" n
9612         | Bool n -> pr ", &%s" n
9613         | Int n -> pr ", &%s" n
9614         | Int64 n -> pr ", &%s" n
9615         | BufferIn n -> pr ", &%s, &%s_size" n n
9616       ) (snd style);
9617
9618       pr "))\n";
9619       pr "    return NULL;\n";
9620
9621       pr "  g = get_handle (py_g);\n";
9622       List.iter (
9623         function
9624         | Pathname _ | Device _ | Dev_or_Path _ | String _
9625         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9626         | BufferIn _ -> ()
9627         | StringList n | DeviceList n ->
9628             pr "  %s = get_string_list (py_%s);\n" n n;
9629             pr "  if (!%s) return NULL;\n" n
9630       ) (snd style);
9631
9632       pr "\n";
9633
9634       pr "  r = guestfs_%s " name;
9635       generate_c_call_args ~handle:"g" style;
9636       pr ";\n";
9637
9638       List.iter (
9639         function
9640         | Pathname _ | Device _ | Dev_or_Path _ | String _
9641         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9642         | BufferIn _ -> ()
9643         | StringList n | DeviceList n ->
9644             pr "  free (%s);\n" n
9645       ) (snd style);
9646
9647       pr "  if (r == %s) {\n" error_code;
9648       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9649       pr "    return NULL;\n";
9650       pr "  }\n";
9651       pr "\n";
9652
9653       (match fst style with
9654        | RErr ->
9655            pr "  Py_INCREF (Py_None);\n";
9656            pr "  py_r = Py_None;\n"
9657        | RInt _
9658        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9659        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9660        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9661        | RConstOptString _ ->
9662            pr "  if (r)\n";
9663            pr "    py_r = PyString_FromString (r);\n";
9664            pr "  else {\n";
9665            pr "    Py_INCREF (Py_None);\n";
9666            pr "    py_r = Py_None;\n";
9667            pr "  }\n"
9668        | RString _ ->
9669            pr "  py_r = PyString_FromString (r);\n";
9670            pr "  free (r);\n"
9671        | RStringList _ ->
9672            pr "  py_r = put_string_list (r);\n";
9673            pr "  free_strings (r);\n"
9674        | RStruct (_, typ) ->
9675            pr "  py_r = put_%s (r);\n" typ;
9676            pr "  guestfs_free_%s (r);\n" typ
9677        | RStructList (_, typ) ->
9678            pr "  py_r = put_%s_list (r);\n" typ;
9679            pr "  guestfs_free_%s_list (r);\n" typ
9680        | RHashtable n ->
9681            pr "  py_r = put_table (r);\n";
9682            pr "  free_strings (r);\n"
9683        | RBufferOut _ ->
9684            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9685            pr "  free (r);\n"
9686       );
9687
9688       pr "  return py_r;\n";
9689       pr "}\n";
9690       pr "\n"
9691   ) all_functions;
9692
9693   (* Table of functions. *)
9694   pr "static PyMethodDef methods[] = {\n";
9695   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9696   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9697   List.iter (
9698     fun (name, _, _, _, _, _, _) ->
9699       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9700         name name
9701   ) all_functions;
9702   pr "  { NULL, NULL, 0, NULL }\n";
9703   pr "};\n";
9704   pr "\n";
9705
9706   (* Init function. *)
9707   pr "\
9708 void
9709 initlibguestfsmod (void)
9710 {
9711   static int initialized = 0;
9712
9713   if (initialized) return;
9714   Py_InitModule ((char *) \"libguestfsmod\", methods);
9715   initialized = 1;
9716 }
9717 "
9718
9719 (* Generate Python module. *)
9720 and generate_python_py () =
9721   generate_header HashStyle LGPLv2plus;
9722
9723   pr "\
9724 u\"\"\"Python bindings for libguestfs
9725
9726 import guestfs
9727 g = guestfs.GuestFS ()
9728 g.add_drive (\"guest.img\")
9729 g.launch ()
9730 parts = g.list_partitions ()
9731
9732 The guestfs module provides a Python binding to the libguestfs API
9733 for examining and modifying virtual machine disk images.
9734
9735 Amongst the things this is good for: making batch configuration
9736 changes to guests, getting disk used/free statistics (see also:
9737 virt-df), migrating between virtualization systems (see also:
9738 virt-p2v), performing partial backups, performing partial guest
9739 clones, cloning guests and changing registry/UUID/hostname info, and
9740 much else besides.
9741
9742 Libguestfs uses Linux kernel and qemu code, and can access any type of
9743 guest filesystem that Linux and qemu can, including but not limited
9744 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9745 schemes, qcow, qcow2, vmdk.
9746
9747 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9748 LVs, what filesystem is in each LV, etc.).  It can also run commands
9749 in the context of the guest.  Also you can access filesystems over
9750 FUSE.
9751
9752 Errors which happen while using the API are turned into Python
9753 RuntimeError exceptions.
9754
9755 To create a guestfs handle you usually have to perform the following
9756 sequence of calls:
9757
9758 # Create the handle, call add_drive at least once, and possibly
9759 # several times if the guest has multiple block devices:
9760 g = guestfs.GuestFS ()
9761 g.add_drive (\"guest.img\")
9762
9763 # Launch the qemu subprocess and wait for it to become ready:
9764 g.launch ()
9765
9766 # Now you can issue commands, for example:
9767 logvols = g.lvs ()
9768
9769 \"\"\"
9770
9771 import libguestfsmod
9772
9773 class GuestFS:
9774     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9775
9776     def __init__ (self):
9777         \"\"\"Create a new libguestfs handle.\"\"\"
9778         self._o = libguestfsmod.create ()
9779
9780     def __del__ (self):
9781         libguestfsmod.close (self._o)
9782
9783 ";
9784
9785   List.iter (
9786     fun (name, style, _, flags, _, _, longdesc) ->
9787       pr "    def %s " name;
9788       generate_py_call_args ~handle:"self" (snd style);
9789       pr ":\n";
9790
9791       if not (List.mem NotInDocs flags) then (
9792         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9793         let doc =
9794           match fst style with
9795           | RErr | RInt _ | RInt64 _ | RBool _
9796           | RConstOptString _ | RConstString _
9797           | RString _ | RBufferOut _ -> doc
9798           | RStringList _ ->
9799               doc ^ "\n\nThis function returns a list of strings."
9800           | RStruct (_, typ) ->
9801               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9802           | RStructList (_, typ) ->
9803               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9804           | RHashtable _ ->
9805               doc ^ "\n\nThis function returns a dictionary." in
9806         let doc =
9807           if List.mem ProtocolLimitWarning flags then
9808             doc ^ "\n\n" ^ protocol_limit_warning
9809           else doc in
9810         let doc =
9811           if List.mem DangerWillRobinson flags then
9812             doc ^ "\n\n" ^ danger_will_robinson
9813           else doc in
9814         let doc =
9815           match deprecation_notice flags with
9816           | None -> doc
9817           | Some txt -> doc ^ "\n\n" ^ txt in
9818         let doc = pod2text ~width:60 name doc in
9819         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9820         let doc = String.concat "\n        " doc in
9821         pr "        u\"\"\"%s\"\"\"\n" doc;
9822       );
9823       pr "        return libguestfsmod.%s " name;
9824       generate_py_call_args ~handle:"self._o" (snd style);
9825       pr "\n";
9826       pr "\n";
9827   ) all_functions
9828
9829 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9830 and generate_py_call_args ~handle args =
9831   pr "(%s" handle;
9832   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9833   pr ")"
9834
9835 (* Useful if you need the longdesc POD text as plain text.  Returns a
9836  * list of lines.
9837  *
9838  * Because this is very slow (the slowest part of autogeneration),
9839  * we memoize the results.
9840  *)
9841 and pod2text ~width name longdesc =
9842   let key = width, name, longdesc in
9843   try Hashtbl.find pod2text_memo key
9844   with Not_found ->
9845     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9846     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9847     close_out chan;
9848     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9849     let chan = open_process_in cmd in
9850     let lines = ref [] in
9851     let rec loop i =
9852       let line = input_line chan in
9853       if i = 1 then             (* discard the first line of output *)
9854         loop (i+1)
9855       else (
9856         let line = triml line in
9857         lines := line :: !lines;
9858         loop (i+1)
9859       ) in
9860     let lines = try loop 1 with End_of_file -> List.rev !lines in
9861     unlink filename;
9862     (match close_process_in chan with
9863      | WEXITED 0 -> ()
9864      | WEXITED i ->
9865          failwithf "pod2text: process exited with non-zero status (%d)" i
9866      | WSIGNALED i | WSTOPPED i ->
9867          failwithf "pod2text: process signalled or stopped by signal %d" i
9868     );
9869     Hashtbl.add pod2text_memo key lines;
9870     pod2text_memo_updated ();
9871     lines
9872
9873 (* Generate ruby bindings. *)
9874 and generate_ruby_c () =
9875   generate_header CStyle LGPLv2plus;
9876
9877   pr "\
9878 #include <stdio.h>
9879 #include <stdlib.h>
9880
9881 #include <ruby.h>
9882
9883 #include \"guestfs.h\"
9884
9885 #include \"extconf.h\"
9886
9887 /* For Ruby < 1.9 */
9888 #ifndef RARRAY_LEN
9889 #define RARRAY_LEN(r) (RARRAY((r))->len)
9890 #endif
9891
9892 static VALUE m_guestfs;                 /* guestfs module */
9893 static VALUE c_guestfs;                 /* guestfs_h handle */
9894 static VALUE e_Error;                   /* used for all errors */
9895
9896 static void ruby_guestfs_free (void *p)
9897 {
9898   if (!p) return;
9899   guestfs_close ((guestfs_h *) p);
9900 }
9901
9902 static VALUE ruby_guestfs_create (VALUE m)
9903 {
9904   guestfs_h *g;
9905
9906   g = guestfs_create ();
9907   if (!g)
9908     rb_raise (e_Error, \"failed to create guestfs handle\");
9909
9910   /* Don't print error messages to stderr by default. */
9911   guestfs_set_error_handler (g, NULL, NULL);
9912
9913   /* Wrap it, and make sure the close function is called when the
9914    * handle goes away.
9915    */
9916   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9917 }
9918
9919 static VALUE ruby_guestfs_close (VALUE gv)
9920 {
9921   guestfs_h *g;
9922   Data_Get_Struct (gv, guestfs_h, g);
9923
9924   ruby_guestfs_free (g);
9925   DATA_PTR (gv) = NULL;
9926
9927   return Qnil;
9928 }
9929
9930 ";
9931
9932   List.iter (
9933     fun (name, style, _, _, _, _, _) ->
9934       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9935       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9936       pr ")\n";
9937       pr "{\n";
9938       pr "  guestfs_h *g;\n";
9939       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9940       pr "  if (!g)\n";
9941       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9942         name;
9943       pr "\n";
9944
9945       List.iter (
9946         function
9947         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9948             pr "  Check_Type (%sv, T_STRING);\n" n;
9949             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9950             pr "  if (!%s)\n" n;
9951             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9952             pr "              \"%s\", \"%s\");\n" n name
9953         | BufferIn n ->
9954             pr "  Check_Type (%sv, T_STRING);\n" n;
9955             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9956             pr "  if (!%s)\n" n;
9957             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9958             pr "              \"%s\", \"%s\");\n" n name;
9959             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9960         | OptString n ->
9961             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9962         | StringList n | DeviceList n ->
9963             pr "  char **%s;\n" n;
9964             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9965             pr "  {\n";
9966             pr "    size_t i, len;\n";
9967             pr "    len = RARRAY_LEN (%sv);\n" n;
9968             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9969               n;
9970             pr "    for (i = 0; i < len; ++i) {\n";
9971             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9972             pr "      %s[i] = StringValueCStr (v);\n" n;
9973             pr "    }\n";
9974             pr "    %s[len] = NULL;\n" n;
9975             pr "  }\n";
9976         | Bool n ->
9977             pr "  int %s = RTEST (%sv);\n" n n
9978         | Int n ->
9979             pr "  int %s = NUM2INT (%sv);\n" n n
9980         | Int64 n ->
9981             pr "  long long %s = NUM2LL (%sv);\n" n n
9982       ) (snd style);
9983       pr "\n";
9984
9985       let error_code =
9986         match fst style with
9987         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9988         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9989         | RConstString _ | RConstOptString _ ->
9990             pr "  const char *r;\n"; "NULL"
9991         | RString _ -> pr "  char *r;\n"; "NULL"
9992         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9993         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9994         | RStructList (_, typ) ->
9995             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9996         | RBufferOut _ ->
9997             pr "  char *r;\n";
9998             pr "  size_t size;\n";
9999             "NULL" in
10000       pr "\n";
10001
10002       pr "  r = guestfs_%s " name;
10003       generate_c_call_args ~handle:"g" style;
10004       pr ";\n";
10005
10006       List.iter (
10007         function
10008         | Pathname _ | Device _ | Dev_or_Path _ | String _
10009         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
10010         | BufferIn _ -> ()
10011         | StringList n | DeviceList n ->
10012             pr "  free (%s);\n" n
10013       ) (snd style);
10014
10015       pr "  if (r == %s)\n" error_code;
10016       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
10017       pr "\n";
10018
10019       (match fst style with
10020        | RErr ->
10021            pr "  return Qnil;\n"
10022        | RInt _ | RBool _ ->
10023            pr "  return INT2NUM (r);\n"
10024        | RInt64 _ ->
10025            pr "  return ULL2NUM (r);\n"
10026        | RConstString _ ->
10027            pr "  return rb_str_new2 (r);\n";
10028        | RConstOptString _ ->
10029            pr "  if (r)\n";
10030            pr "    return rb_str_new2 (r);\n";
10031            pr "  else\n";
10032            pr "    return Qnil;\n";
10033        | RString _ ->
10034            pr "  VALUE rv = rb_str_new2 (r);\n";
10035            pr "  free (r);\n";
10036            pr "  return rv;\n";
10037        | RStringList _ ->
10038            pr "  size_t i, len = 0;\n";
10039            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
10040            pr "  VALUE rv = rb_ary_new2 (len);\n";
10041            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
10042            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
10043            pr "    free (r[i]);\n";
10044            pr "  }\n";
10045            pr "  free (r);\n";
10046            pr "  return rv;\n"
10047        | RStruct (_, typ) ->
10048            let cols = cols_of_struct typ in
10049            generate_ruby_struct_code typ cols
10050        | RStructList (_, typ) ->
10051            let cols = cols_of_struct typ in
10052            generate_ruby_struct_list_code typ cols
10053        | RHashtable _ ->
10054            pr "  VALUE rv = rb_hash_new ();\n";
10055            pr "  size_t i;\n";
10056            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
10057            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
10058            pr "    free (r[i]);\n";
10059            pr "    free (r[i+1]);\n";
10060            pr "  }\n";
10061            pr "  free (r);\n";
10062            pr "  return rv;\n"
10063        | RBufferOut _ ->
10064            pr "  VALUE rv = rb_str_new (r, size);\n";
10065            pr "  free (r);\n";
10066            pr "  return rv;\n";
10067       );
10068
10069       pr "}\n";
10070       pr "\n"
10071   ) all_functions;
10072
10073   pr "\
10074 /* Initialize the module. */
10075 void Init__guestfs ()
10076 {
10077   m_guestfs = rb_define_module (\"Guestfs\");
10078   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
10079   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
10080
10081   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
10082   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
10083
10084 ";
10085   (* Define the rest of the methods. *)
10086   List.iter (
10087     fun (name, style, _, _, _, _, _) ->
10088       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
10089       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
10090   ) all_functions;
10091
10092   pr "}\n"
10093
10094 (* Ruby code to return a struct. *)
10095 and generate_ruby_struct_code typ cols =
10096   pr "  VALUE rv = rb_hash_new ();\n";
10097   List.iter (
10098     function
10099     | name, FString ->
10100         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
10101     | name, FBuffer ->
10102         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
10103     | name, FUUID ->
10104         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
10105     | name, (FBytes|FUInt64) ->
10106         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10107     | name, FInt64 ->
10108         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
10109     | name, FUInt32 ->
10110         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
10111     | name, FInt32 ->
10112         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
10113     | name, FOptPercent ->
10114         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
10115     | name, FChar -> (* XXX wrong? *)
10116         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10117   ) cols;
10118   pr "  guestfs_free_%s (r);\n" typ;
10119   pr "  return rv;\n"
10120
10121 (* Ruby code to return a struct list. *)
10122 and generate_ruby_struct_list_code typ cols =
10123   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
10124   pr "  size_t i;\n";
10125   pr "  for (i = 0; i < r->len; ++i) {\n";
10126   pr "    VALUE hv = rb_hash_new ();\n";
10127   List.iter (
10128     function
10129     | name, FString ->
10130         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
10131     | name, FBuffer ->
10132         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
10133     | name, FUUID ->
10134         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
10135     | name, (FBytes|FUInt64) ->
10136         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10137     | name, FInt64 ->
10138         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10139     | name, FUInt32 ->
10140         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10141     | name, FInt32 ->
10142         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10143     | name, FOptPercent ->
10144         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10145     | name, FChar -> (* XXX wrong? *)
10146         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10147   ) cols;
10148   pr "    rb_ary_push (rv, hv);\n";
10149   pr "  }\n";
10150   pr "  guestfs_free_%s_list (r);\n" typ;
10151   pr "  return rv;\n"
10152
10153 (* Generate Java bindings GuestFS.java file. *)
10154 and generate_java_java () =
10155   generate_header CStyle LGPLv2plus;
10156
10157   pr "\
10158 package com.redhat.et.libguestfs;
10159
10160 import java.util.HashMap;
10161 import com.redhat.et.libguestfs.LibGuestFSException;
10162 import com.redhat.et.libguestfs.PV;
10163 import com.redhat.et.libguestfs.VG;
10164 import com.redhat.et.libguestfs.LV;
10165 import com.redhat.et.libguestfs.Stat;
10166 import com.redhat.et.libguestfs.StatVFS;
10167 import com.redhat.et.libguestfs.IntBool;
10168 import com.redhat.et.libguestfs.Dirent;
10169
10170 /**
10171  * The GuestFS object is a libguestfs handle.
10172  *
10173  * @author rjones
10174  */
10175 public class GuestFS {
10176   // Load the native code.
10177   static {
10178     System.loadLibrary (\"guestfs_jni\");
10179   }
10180
10181   /**
10182    * The native guestfs_h pointer.
10183    */
10184   long g;
10185
10186   /**
10187    * Create a libguestfs handle.
10188    *
10189    * @throws LibGuestFSException
10190    */
10191   public GuestFS () throws LibGuestFSException
10192   {
10193     g = _create ();
10194   }
10195   private native long _create () throws LibGuestFSException;
10196
10197   /**
10198    * Close a libguestfs handle.
10199    *
10200    * You can also leave handles to be collected by the garbage
10201    * collector, but this method ensures that the resources used
10202    * by the handle are freed up immediately.  If you call any
10203    * other methods after closing the handle, you will get an
10204    * exception.
10205    *
10206    * @throws LibGuestFSException
10207    */
10208   public void close () throws LibGuestFSException
10209   {
10210     if (g != 0)
10211       _close (g);
10212     g = 0;
10213   }
10214   private native void _close (long g) throws LibGuestFSException;
10215
10216   public void finalize () throws LibGuestFSException
10217   {
10218     close ();
10219   }
10220
10221 ";
10222
10223   List.iter (
10224     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10225       if not (List.mem NotInDocs flags); then (
10226         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10227         let doc =
10228           if List.mem ProtocolLimitWarning flags then
10229             doc ^ "\n\n" ^ protocol_limit_warning
10230           else doc in
10231         let doc =
10232           if List.mem DangerWillRobinson flags then
10233             doc ^ "\n\n" ^ danger_will_robinson
10234           else doc in
10235         let doc =
10236           match deprecation_notice flags with
10237           | None -> doc
10238           | Some txt -> doc ^ "\n\n" ^ txt in
10239         let doc = pod2text ~width:60 name doc in
10240         let doc = List.map (            (* RHBZ#501883 *)
10241           function
10242           | "" -> "<p>"
10243           | nonempty -> nonempty
10244         ) doc in
10245         let doc = String.concat "\n   * " doc in
10246
10247         pr "  /**\n";
10248         pr "   * %s\n" shortdesc;
10249         pr "   * <p>\n";
10250         pr "   * %s\n" doc;
10251         pr "   * @throws LibGuestFSException\n";
10252         pr "   */\n";
10253         pr "  ";
10254       );
10255       generate_java_prototype ~public:true ~semicolon:false name style;
10256       pr "\n";
10257       pr "  {\n";
10258       pr "    if (g == 0)\n";
10259       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10260         name;
10261       pr "    ";
10262       if fst style <> RErr then pr "return ";
10263       pr "_%s " name;
10264       generate_java_call_args ~handle:"g" (snd style);
10265       pr ";\n";
10266       pr "  }\n";
10267       pr "  ";
10268       generate_java_prototype ~privat:true ~native:true name style;
10269       pr "\n";
10270       pr "\n";
10271   ) all_functions;
10272
10273   pr "}\n"
10274
10275 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10276 and generate_java_call_args ~handle args =
10277   pr "(%s" handle;
10278   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10279   pr ")"
10280
10281 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10282     ?(semicolon=true) name style =
10283   if privat then pr "private ";
10284   if public then pr "public ";
10285   if native then pr "native ";
10286
10287   (* return type *)
10288   (match fst style with
10289    | RErr -> pr "void ";
10290    | RInt _ -> pr "int ";
10291    | RInt64 _ -> pr "long ";
10292    | RBool _ -> pr "boolean ";
10293    | RConstString _ | RConstOptString _ | RString _
10294    | RBufferOut _ -> pr "String ";
10295    | RStringList _ -> pr "String[] ";
10296    | RStruct (_, typ) ->
10297        let name = java_name_of_struct typ in
10298        pr "%s " name;
10299    | RStructList (_, typ) ->
10300        let name = java_name_of_struct typ in
10301        pr "%s[] " name;
10302    | RHashtable _ -> pr "HashMap<String,String> ";
10303   );
10304
10305   if native then pr "_%s " name else pr "%s " name;
10306   pr "(";
10307   let needs_comma = ref false in
10308   if native then (
10309     pr "long g";
10310     needs_comma := true
10311   );
10312
10313   (* args *)
10314   List.iter (
10315     fun arg ->
10316       if !needs_comma then pr ", ";
10317       needs_comma := true;
10318
10319       match arg with
10320       | Pathname n
10321       | Device n | Dev_or_Path n
10322       | String n
10323       | OptString n
10324       | FileIn n
10325       | FileOut n ->
10326           pr "String %s" n
10327       | BufferIn n ->
10328           pr "byte[] %s" n
10329       | StringList n | DeviceList n ->
10330           pr "String[] %s" n
10331       | Bool n ->
10332           pr "boolean %s" n
10333       | Int n ->
10334           pr "int %s" n
10335       | Int64 n ->
10336           pr "long %s" n
10337   ) (snd style);
10338
10339   pr ")\n";
10340   pr "    throws LibGuestFSException";
10341   if semicolon then pr ";"
10342
10343 and generate_java_struct jtyp cols () =
10344   generate_header CStyle LGPLv2plus;
10345
10346   pr "\
10347 package com.redhat.et.libguestfs;
10348
10349 /**
10350  * Libguestfs %s structure.
10351  *
10352  * @author rjones
10353  * @see GuestFS
10354  */
10355 public class %s {
10356 " jtyp jtyp;
10357
10358   List.iter (
10359     function
10360     | name, FString
10361     | name, FUUID
10362     | name, FBuffer -> pr "  public String %s;\n" name
10363     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10364     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10365     | name, FChar -> pr "  public char %s;\n" name
10366     | name, FOptPercent ->
10367         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10368         pr "  public float %s;\n" name
10369   ) cols;
10370
10371   pr "}\n"
10372
10373 and generate_java_c () =
10374   generate_header CStyle LGPLv2plus;
10375
10376   pr "\
10377 #include <stdio.h>
10378 #include <stdlib.h>
10379 #include <string.h>
10380
10381 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10382 #include \"guestfs.h\"
10383
10384 /* Note that this function returns.  The exception is not thrown
10385  * until after the wrapper function returns.
10386  */
10387 static void
10388 throw_exception (JNIEnv *env, const char *msg)
10389 {
10390   jclass cl;
10391   cl = (*env)->FindClass (env,
10392                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10393   (*env)->ThrowNew (env, cl, msg);
10394 }
10395
10396 JNIEXPORT jlong JNICALL
10397 Java_com_redhat_et_libguestfs_GuestFS__1create
10398   (JNIEnv *env, jobject obj)
10399 {
10400   guestfs_h *g;
10401
10402   g = guestfs_create ();
10403   if (g == NULL) {
10404     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10405     return 0;
10406   }
10407   guestfs_set_error_handler (g, NULL, NULL);
10408   return (jlong) (long) g;
10409 }
10410
10411 JNIEXPORT void JNICALL
10412 Java_com_redhat_et_libguestfs_GuestFS__1close
10413   (JNIEnv *env, jobject obj, jlong jg)
10414 {
10415   guestfs_h *g = (guestfs_h *) (long) jg;
10416   guestfs_close (g);
10417 }
10418
10419 ";
10420
10421   List.iter (
10422     fun (name, style, _, _, _, _, _) ->
10423       pr "JNIEXPORT ";
10424       (match fst style with
10425        | RErr -> pr "void ";
10426        | RInt _ -> pr "jint ";
10427        | RInt64 _ -> pr "jlong ";
10428        | RBool _ -> pr "jboolean ";
10429        | RConstString _ | RConstOptString _ | RString _
10430        | RBufferOut _ -> pr "jstring ";
10431        | RStruct _ | RHashtable _ ->
10432            pr "jobject ";
10433        | RStringList _ | RStructList _ ->
10434            pr "jobjectArray ";
10435       );
10436       pr "JNICALL\n";
10437       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10438       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10439       pr "\n";
10440       pr "  (JNIEnv *env, jobject obj, jlong jg";
10441       List.iter (
10442         function
10443         | Pathname n
10444         | Device n | Dev_or_Path n
10445         | String n
10446         | OptString n
10447         | FileIn n
10448         | FileOut n ->
10449             pr ", jstring j%s" n
10450         | BufferIn n ->
10451             pr ", jbyteArray j%s" n
10452         | StringList n | DeviceList n ->
10453             pr ", jobjectArray j%s" n
10454         | Bool n ->
10455             pr ", jboolean j%s" n
10456         | Int n ->
10457             pr ", jint j%s" n
10458         | Int64 n ->
10459             pr ", jlong j%s" n
10460       ) (snd style);
10461       pr ")\n";
10462       pr "{\n";
10463       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10464       let error_code, no_ret =
10465         match fst style with
10466         | RErr -> pr "  int r;\n"; "-1", ""
10467         | RBool _
10468         | RInt _ -> pr "  int r;\n"; "-1", "0"
10469         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10470         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10471         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10472         | RString _ ->
10473             pr "  jstring jr;\n";
10474             pr "  char *r;\n"; "NULL", "NULL"
10475         | RStringList _ ->
10476             pr "  jobjectArray jr;\n";
10477             pr "  int r_len;\n";
10478             pr "  jclass cl;\n";
10479             pr "  jstring jstr;\n";
10480             pr "  char **r;\n"; "NULL", "NULL"
10481         | RStruct (_, typ) ->
10482             pr "  jobject jr;\n";
10483             pr "  jclass cl;\n";
10484             pr "  jfieldID fl;\n";
10485             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10486         | RStructList (_, typ) ->
10487             pr "  jobjectArray jr;\n";
10488             pr "  jclass cl;\n";
10489             pr "  jfieldID fl;\n";
10490             pr "  jobject jfl;\n";
10491             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10492         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10493         | RBufferOut _ ->
10494             pr "  jstring jr;\n";
10495             pr "  char *r;\n";
10496             pr "  size_t size;\n";
10497             "NULL", "NULL" in
10498       List.iter (
10499         function
10500         | Pathname n
10501         | Device n | Dev_or_Path n
10502         | String n
10503         | OptString n
10504         | FileIn n
10505         | FileOut n ->
10506             pr "  const char *%s;\n" n
10507         | BufferIn n ->
10508             pr "  jbyte *%s;\n" n;
10509             pr "  size_t %s_size;\n" n
10510         | StringList n | DeviceList n ->
10511             pr "  int %s_len;\n" n;
10512             pr "  const char **%s;\n" n
10513         | Bool n
10514         | Int n ->
10515             pr "  int %s;\n" n
10516         | Int64 n ->
10517             pr "  int64_t %s;\n" n
10518       ) (snd style);
10519
10520       let needs_i =
10521         (match fst style with
10522          | RStringList _ | RStructList _ -> true
10523          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10524          | RConstOptString _
10525          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10526           List.exists (function
10527                        | StringList _ -> true
10528                        | DeviceList _ -> true
10529                        | _ -> false) (snd style) in
10530       if needs_i then
10531         pr "  size_t i;\n";
10532
10533       pr "\n";
10534
10535       (* Get the parameters. *)
10536       List.iter (
10537         function
10538         | Pathname n
10539         | Device n | Dev_or_Path n
10540         | String n
10541         | FileIn n
10542         | FileOut n ->
10543             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10544         | OptString n ->
10545             (* This is completely undocumented, but Java null becomes
10546              * a NULL parameter.
10547              *)
10548             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10549         | BufferIn n ->
10550             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10551             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10552         | StringList n | DeviceList n ->
10553             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10554             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10555             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10556             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10557               n;
10558             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10559             pr "  }\n";
10560             pr "  %s[%s_len] = NULL;\n" n n;
10561         | Bool n
10562         | Int n
10563         | Int64 n ->
10564             pr "  %s = j%s;\n" n n
10565       ) (snd style);
10566
10567       (* Make the call. *)
10568       pr "  r = guestfs_%s " name;
10569       generate_c_call_args ~handle:"g" style;
10570       pr ";\n";
10571
10572       (* Release the parameters. *)
10573       List.iter (
10574         function
10575         | Pathname n
10576         | Device n | Dev_or_Path n
10577         | String n
10578         | FileIn n
10579         | FileOut n ->
10580             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10581         | OptString n ->
10582             pr "  if (j%s)\n" n;
10583             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10584         | BufferIn n ->
10585             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10586         | StringList n | DeviceList n ->
10587             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10588             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10589               n;
10590             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10591             pr "  }\n";
10592             pr "  free (%s);\n" n
10593         | Bool n
10594         | Int n
10595         | Int64 n -> ()
10596       ) (snd style);
10597
10598       (* Check for errors. *)
10599       pr "  if (r == %s) {\n" error_code;
10600       pr "    throw_exception (env, guestfs_last_error (g));\n";
10601       pr "    return %s;\n" no_ret;
10602       pr "  }\n";
10603
10604       (* Return value. *)
10605       (match fst style with
10606        | RErr -> ()
10607        | RInt _ -> pr "  return (jint) r;\n"
10608        | RBool _ -> pr "  return (jboolean) r;\n"
10609        | RInt64 _ -> pr "  return (jlong) r;\n"
10610        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10611        | RConstOptString _ ->
10612            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10613        | RString _ ->
10614            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10615            pr "  free (r);\n";
10616            pr "  return jr;\n"
10617        | RStringList _ ->
10618            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10619            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10620            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10621            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10622            pr "  for (i = 0; i < r_len; ++i) {\n";
10623            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10624            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10625            pr "    free (r[i]);\n";
10626            pr "  }\n";
10627            pr "  free (r);\n";
10628            pr "  return jr;\n"
10629        | RStruct (_, typ) ->
10630            let jtyp = java_name_of_struct typ in
10631            let cols = cols_of_struct typ in
10632            generate_java_struct_return typ jtyp cols
10633        | RStructList (_, typ) ->
10634            let jtyp = java_name_of_struct typ in
10635            let cols = cols_of_struct typ in
10636            generate_java_struct_list_return typ jtyp cols
10637        | RHashtable _ ->
10638            (* XXX *)
10639            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10640            pr "  return NULL;\n"
10641        | RBufferOut _ ->
10642            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10643            pr "  free (r);\n";
10644            pr "  return jr;\n"
10645       );
10646
10647       pr "}\n";
10648       pr "\n"
10649   ) all_functions
10650
10651 and generate_java_struct_return typ jtyp cols =
10652   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10653   pr "  jr = (*env)->AllocObject (env, cl);\n";
10654   List.iter (
10655     function
10656     | name, FString ->
10657         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10658         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10659     | name, FUUID ->
10660         pr "  {\n";
10661         pr "    char s[33];\n";
10662         pr "    memcpy (s, r->%s, 32);\n" name;
10663         pr "    s[32] = 0;\n";
10664         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10665         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10666         pr "  }\n";
10667     | name, FBuffer ->
10668         pr "  {\n";
10669         pr "    int len = r->%s_len;\n" name;
10670         pr "    char s[len+1];\n";
10671         pr "    memcpy (s, r->%s, len);\n" name;
10672         pr "    s[len] = 0;\n";
10673         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10674         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10675         pr "  }\n";
10676     | name, (FBytes|FUInt64|FInt64) ->
10677         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10678         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10679     | name, (FUInt32|FInt32) ->
10680         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10681         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10682     | name, FOptPercent ->
10683         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10684         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10685     | name, FChar ->
10686         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10687         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10688   ) cols;
10689   pr "  free (r);\n";
10690   pr "  return jr;\n"
10691
10692 and generate_java_struct_list_return typ jtyp cols =
10693   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10694   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10695   pr "  for (i = 0; i < r->len; ++i) {\n";
10696   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10697   List.iter (
10698     function
10699     | name, FString ->
10700         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10701         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10702     | name, FUUID ->
10703         pr "    {\n";
10704         pr "      char s[33];\n";
10705         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10706         pr "      s[32] = 0;\n";
10707         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10708         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10709         pr "    }\n";
10710     | name, FBuffer ->
10711         pr "    {\n";
10712         pr "      int len = r->val[i].%s_len;\n" name;
10713         pr "      char s[len+1];\n";
10714         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10715         pr "      s[len] = 0;\n";
10716         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10717         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10718         pr "    }\n";
10719     | name, (FBytes|FUInt64|FInt64) ->
10720         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10721         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10722     | name, (FUInt32|FInt32) ->
10723         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10724         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10725     | name, FOptPercent ->
10726         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10727         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10728     | name, FChar ->
10729         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10730         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10731   ) cols;
10732   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10733   pr "  }\n";
10734   pr "  guestfs_free_%s_list (r);\n" typ;
10735   pr "  return jr;\n"
10736
10737 and generate_java_makefile_inc () =
10738   generate_header HashStyle GPLv2plus;
10739
10740   pr "java_built_sources = \\\n";
10741   List.iter (
10742     fun (typ, jtyp) ->
10743         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10744   ) java_structs;
10745   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10746
10747 and generate_haskell_hs () =
10748   generate_header HaskellStyle LGPLv2plus;
10749
10750   (* XXX We only know how to generate partial FFI for Haskell
10751    * at the moment.  Please help out!
10752    *)
10753   let can_generate style =
10754     match style with
10755     | RErr, _
10756     | RInt _, _
10757     | RInt64 _, _ -> true
10758     | RBool _, _
10759     | RConstString _, _
10760     | RConstOptString _, _
10761     | RString _, _
10762     | RStringList _, _
10763     | RStruct _, _
10764     | RStructList _, _
10765     | RHashtable _, _
10766     | RBufferOut _, _ -> false in
10767
10768   pr "\
10769 {-# INCLUDE <guestfs.h> #-}
10770 {-# LANGUAGE ForeignFunctionInterface #-}
10771
10772 module Guestfs (
10773   create";
10774
10775   (* List out the names of the actions we want to export. *)
10776   List.iter (
10777     fun (name, style, _, _, _, _, _) ->
10778       if can_generate style then pr ",\n  %s" name
10779   ) all_functions;
10780
10781   pr "
10782   ) where
10783
10784 -- Unfortunately some symbols duplicate ones already present
10785 -- in Prelude.  We don't know which, so we hard-code a list
10786 -- here.
10787 import Prelude hiding (truncate)
10788
10789 import Foreign
10790 import Foreign.C
10791 import Foreign.C.Types
10792 import IO
10793 import Control.Exception
10794 import Data.Typeable
10795
10796 data GuestfsS = GuestfsS            -- represents the opaque C struct
10797 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10798 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10799
10800 -- XXX define properly later XXX
10801 data PV = PV
10802 data VG = VG
10803 data LV = LV
10804 data IntBool = IntBool
10805 data Stat = Stat
10806 data StatVFS = StatVFS
10807 data Hashtable = Hashtable
10808
10809 foreign import ccall unsafe \"guestfs_create\" c_create
10810   :: IO GuestfsP
10811 foreign import ccall unsafe \"&guestfs_close\" c_close
10812   :: FunPtr (GuestfsP -> IO ())
10813 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10814   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10815
10816 create :: IO GuestfsH
10817 create = do
10818   p <- c_create
10819   c_set_error_handler p nullPtr nullPtr
10820   h <- newForeignPtr c_close p
10821   return h
10822
10823 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10824   :: GuestfsP -> IO CString
10825
10826 -- last_error :: GuestfsH -> IO (Maybe String)
10827 -- last_error h = do
10828 --   str <- withForeignPtr h (\\p -> c_last_error p)
10829 --   maybePeek peekCString str
10830
10831 last_error :: GuestfsH -> IO (String)
10832 last_error h = do
10833   str <- withForeignPtr h (\\p -> c_last_error p)
10834   if (str == nullPtr)
10835     then return \"no error\"
10836     else peekCString str
10837
10838 ";
10839
10840   (* Generate wrappers for each foreign function. *)
10841   List.iter (
10842     fun (name, style, _, _, _, _, _) ->
10843       if can_generate style then (
10844         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10845         pr "  :: ";
10846         generate_haskell_prototype ~handle:"GuestfsP" style;
10847         pr "\n";
10848         pr "\n";
10849         pr "%s :: " name;
10850         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10851         pr "\n";
10852         pr "%s %s = do\n" name
10853           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10854         pr "  r <- ";
10855         (* Convert pointer arguments using with* functions. *)
10856         List.iter (
10857           function
10858           | FileIn n
10859           | FileOut n
10860           | Pathname n | Device n | Dev_or_Path n | String n ->
10861               pr "withCString %s $ \\%s -> " n n
10862           | BufferIn n ->
10863               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10864           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10865           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10866           | Bool _ | Int _ | Int64 _ -> ()
10867         ) (snd style);
10868         (* Convert integer arguments. *)
10869         let args =
10870           List.map (
10871             function
10872             | Bool n -> sprintf "(fromBool %s)" n
10873             | Int n -> sprintf "(fromIntegral %s)" n
10874             | Int64 n -> sprintf "(fromIntegral %s)" n
10875             | FileIn n | FileOut n
10876             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10877             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10878           ) (snd style) in
10879         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10880           (String.concat " " ("p" :: args));
10881         (match fst style with
10882          | RErr | RInt _ | RInt64 _ | RBool _ ->
10883              pr "  if (r == -1)\n";
10884              pr "    then do\n";
10885              pr "      err <- last_error h\n";
10886              pr "      fail err\n";
10887          | RConstString _ | RConstOptString _ | RString _
10888          | RStringList _ | RStruct _
10889          | RStructList _ | RHashtable _ | RBufferOut _ ->
10890              pr "  if (r == nullPtr)\n";
10891              pr "    then do\n";
10892              pr "      err <- last_error h\n";
10893              pr "      fail err\n";
10894         );
10895         (match fst style with
10896          | RErr ->
10897              pr "    else return ()\n"
10898          | RInt _ ->
10899              pr "    else return (fromIntegral r)\n"
10900          | RInt64 _ ->
10901              pr "    else return (fromIntegral r)\n"
10902          | RBool _ ->
10903              pr "    else return (toBool r)\n"
10904          | RConstString _
10905          | RConstOptString _
10906          | RString _
10907          | RStringList _
10908          | RStruct _
10909          | RStructList _
10910          | RHashtable _
10911          | RBufferOut _ ->
10912              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10913         );
10914         pr "\n";
10915       )
10916   ) all_functions
10917
10918 and generate_haskell_prototype ~handle ?(hs = false) style =
10919   pr "%s -> " handle;
10920   let string = if hs then "String" else "CString" in
10921   let int = if hs then "Int" else "CInt" in
10922   let bool = if hs then "Bool" else "CInt" in
10923   let int64 = if hs then "Integer" else "Int64" in
10924   List.iter (
10925     fun arg ->
10926       (match arg with
10927        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10928        | BufferIn _ ->
10929            if hs then pr "String"
10930            else pr "CString -> CInt"
10931        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10932        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10933        | Bool _ -> pr "%s" bool
10934        | Int _ -> pr "%s" int
10935        | Int64 _ -> pr "%s" int
10936        | FileIn _ -> pr "%s" string
10937        | FileOut _ -> pr "%s" string
10938       );
10939       pr " -> ";
10940   ) (snd style);
10941   pr "IO (";
10942   (match fst style with
10943    | RErr -> if not hs then pr "CInt"
10944    | RInt _ -> pr "%s" int
10945    | RInt64 _ -> pr "%s" int64
10946    | RBool _ -> pr "%s" bool
10947    | RConstString _ -> pr "%s" string
10948    | RConstOptString _ -> pr "Maybe %s" string
10949    | RString _ -> pr "%s" string
10950    | RStringList _ -> pr "[%s]" string
10951    | RStruct (_, typ) ->
10952        let name = java_name_of_struct typ in
10953        pr "%s" name
10954    | RStructList (_, typ) ->
10955        let name = java_name_of_struct typ in
10956        pr "[%s]" name
10957    | RHashtable _ -> pr "Hashtable"
10958    | RBufferOut _ -> pr "%s" string
10959   );
10960   pr ")"
10961
10962 and generate_csharp () =
10963   generate_header CPlusPlusStyle LGPLv2plus;
10964
10965   (* XXX Make this configurable by the C# assembly users. *)
10966   let library = "libguestfs.so.0" in
10967
10968   pr "\
10969 // These C# bindings are highly experimental at present.
10970 //
10971 // Firstly they only work on Linux (ie. Mono).  In order to get them
10972 // to work on Windows (ie. .Net) you would need to port the library
10973 // itself to Windows first.
10974 //
10975 // The second issue is that some calls are known to be incorrect and
10976 // can cause Mono to segfault.  Particularly: calls which pass or
10977 // return string[], or return any structure value.  This is because
10978 // we haven't worked out the correct way to do this from C#.
10979 //
10980 // The third issue is that when compiling you get a lot of warnings.
10981 // We are not sure whether the warnings are important or not.
10982 //
10983 // Fourthly we do not routinely build or test these bindings as part
10984 // of the make && make check cycle, which means that regressions might
10985 // go unnoticed.
10986 //
10987 // Suggestions and patches are welcome.
10988
10989 // To compile:
10990 //
10991 // gmcs Libguestfs.cs
10992 // mono Libguestfs.exe
10993 //
10994 // (You'll probably want to add a Test class / static main function
10995 // otherwise this won't do anything useful).
10996
10997 using System;
10998 using System.IO;
10999 using System.Runtime.InteropServices;
11000 using System.Runtime.Serialization;
11001 using System.Collections;
11002
11003 namespace Guestfs
11004 {
11005   class Error : System.ApplicationException
11006   {
11007     public Error (string message) : base (message) {}
11008     protected Error (SerializationInfo info, StreamingContext context) {}
11009   }
11010
11011   class Guestfs
11012   {
11013     IntPtr _handle;
11014
11015     [DllImport (\"%s\")]
11016     static extern IntPtr guestfs_create ();
11017
11018     public Guestfs ()
11019     {
11020       _handle = guestfs_create ();
11021       if (_handle == IntPtr.Zero)
11022         throw new Error (\"could not create guestfs handle\");
11023     }
11024
11025     [DllImport (\"%s\")]
11026     static extern void guestfs_close (IntPtr h);
11027
11028     ~Guestfs ()
11029     {
11030       guestfs_close (_handle);
11031     }
11032
11033     [DllImport (\"%s\")]
11034     static extern string guestfs_last_error (IntPtr h);
11035
11036 " library library library;
11037
11038   (* Generate C# structure bindings.  We prefix struct names with
11039    * underscore because C# cannot have conflicting struct names and
11040    * method names (eg. "class stat" and "stat").
11041    *)
11042   List.iter (
11043     fun (typ, cols) ->
11044       pr "    [StructLayout (LayoutKind.Sequential)]\n";
11045       pr "    public class _%s {\n" typ;
11046       List.iter (
11047         function
11048         | name, FChar -> pr "      char %s;\n" name
11049         | name, FString -> pr "      string %s;\n" name
11050         | name, FBuffer ->
11051             pr "      uint %s_len;\n" name;
11052             pr "      string %s;\n" name
11053         | name, FUUID ->
11054             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
11055             pr "      string %s;\n" name
11056         | name, FUInt32 -> pr "      uint %s;\n" name
11057         | name, FInt32 -> pr "      int %s;\n" name
11058         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
11059         | name, FInt64 -> pr "      long %s;\n" name
11060         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
11061       ) cols;
11062       pr "    }\n";
11063       pr "\n"
11064   ) structs;
11065
11066   (* Generate C# function bindings. *)
11067   List.iter (
11068     fun (name, style, _, _, _, shortdesc, _) ->
11069       let rec csharp_return_type () =
11070         match fst style with
11071         | RErr -> "void"
11072         | RBool n -> "bool"
11073         | RInt n -> "int"
11074         | RInt64 n -> "long"
11075         | RConstString n
11076         | RConstOptString n
11077         | RString n
11078         | RBufferOut n -> "string"
11079         | RStruct (_,n) -> "_" ^ n
11080         | RHashtable n -> "Hashtable"
11081         | RStringList n -> "string[]"
11082         | RStructList (_,n) -> sprintf "_%s[]" n
11083
11084       and c_return_type () =
11085         match fst style with
11086         | RErr
11087         | RBool _
11088         | RInt _ -> "int"
11089         | RInt64 _ -> "long"
11090         | RConstString _
11091         | RConstOptString _
11092         | RString _
11093         | RBufferOut _ -> "string"
11094         | RStruct (_,n) -> "_" ^ n
11095         | RHashtable _
11096         | RStringList _ -> "string[]"
11097         | RStructList (_,n) -> sprintf "_%s[]" n
11098
11099       and c_error_comparison () =
11100         match fst style with
11101         | RErr
11102         | RBool _
11103         | RInt _
11104         | RInt64 _ -> "== -1"
11105         | RConstString _
11106         | RConstOptString _
11107         | RString _
11108         | RBufferOut _
11109         | RStruct (_,_)
11110         | RHashtable _
11111         | RStringList _
11112         | RStructList (_,_) -> "== null"
11113
11114       and generate_extern_prototype () =
11115         pr "    static extern %s guestfs_%s (IntPtr h"
11116           (c_return_type ()) name;
11117         List.iter (
11118           function
11119           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11120           | FileIn n | FileOut n
11121           | BufferIn n ->
11122               pr ", [In] string %s" n
11123           | StringList n | DeviceList n ->
11124               pr ", [In] string[] %s" n
11125           | Bool n ->
11126               pr ", bool %s" n
11127           | Int n ->
11128               pr ", int %s" n
11129           | Int64 n ->
11130               pr ", long %s" n
11131         ) (snd style);
11132         pr ");\n"
11133
11134       and generate_public_prototype () =
11135         pr "    public %s %s (" (csharp_return_type ()) name;
11136         let comma = ref false in
11137         let next () =
11138           if !comma then pr ", ";
11139           comma := true
11140         in
11141         List.iter (
11142           function
11143           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11144           | FileIn n | FileOut n
11145           | BufferIn n ->
11146               next (); pr "string %s" n
11147           | StringList n | DeviceList n ->
11148               next (); pr "string[] %s" n
11149           | Bool n ->
11150               next (); pr "bool %s" n
11151           | Int n ->
11152               next (); pr "int %s" n
11153           | Int64 n ->
11154               next (); pr "long %s" n
11155         ) (snd style);
11156         pr ")\n"
11157
11158       and generate_call () =
11159         pr "guestfs_%s (_handle" name;
11160         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11161         pr ");\n";
11162       in
11163
11164       pr "    [DllImport (\"%s\")]\n" library;
11165       generate_extern_prototype ();
11166       pr "\n";
11167       pr "    /// <summary>\n";
11168       pr "    /// %s\n" shortdesc;
11169       pr "    /// </summary>\n";
11170       generate_public_prototype ();
11171       pr "    {\n";
11172       pr "      %s r;\n" (c_return_type ());
11173       pr "      r = ";
11174       generate_call ();
11175       pr "      if (r %s)\n" (c_error_comparison ());
11176       pr "        throw new Error (guestfs_last_error (_handle));\n";
11177       (match fst style with
11178        | RErr -> ()
11179        | RBool _ ->
11180            pr "      return r != 0 ? true : false;\n"
11181        | RHashtable _ ->
11182            pr "      Hashtable rr = new Hashtable ();\n";
11183            pr "      for (size_t i = 0; i < r.Length; i += 2)\n";
11184            pr "        rr.Add (r[i], r[i+1]);\n";
11185            pr "      return rr;\n"
11186        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11187        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11188        | RStructList _ ->
11189            pr "      return r;\n"
11190       );
11191       pr "    }\n";
11192       pr "\n";
11193   ) all_functions_sorted;
11194
11195   pr "  }
11196 }
11197 "
11198
11199 and generate_bindtests () =
11200   generate_header CStyle LGPLv2plus;
11201
11202   pr "\
11203 #include <stdio.h>
11204 #include <stdlib.h>
11205 #include <inttypes.h>
11206 #include <string.h>
11207
11208 #include \"guestfs.h\"
11209 #include \"guestfs-internal.h\"
11210 #include \"guestfs-internal-actions.h\"
11211 #include \"guestfs_protocol.h\"
11212
11213 #define error guestfs_error
11214 #define safe_calloc guestfs_safe_calloc
11215 #define safe_malloc guestfs_safe_malloc
11216
11217 static void
11218 print_strings (char *const *argv)
11219 {
11220   size_t argc;
11221
11222   printf (\"[\");
11223   for (argc = 0; argv[argc] != NULL; ++argc) {
11224     if (argc > 0) printf (\", \");
11225     printf (\"\\\"%%s\\\"\", argv[argc]);
11226   }
11227   printf (\"]\\n\");
11228 }
11229
11230 /* The test0 function prints its parameters to stdout. */
11231 ";
11232
11233   let test0, tests =
11234     match test_functions with
11235     | [] -> assert false
11236     | test0 :: tests -> test0, tests in
11237
11238   let () =
11239     let (name, style, _, _, _, _, _) = test0 in
11240     generate_prototype ~extern:false ~semicolon:false ~newline:true
11241       ~handle:"g" ~prefix:"guestfs__" name style;
11242     pr "{\n";
11243     List.iter (
11244       function
11245       | Pathname n
11246       | Device n | Dev_or_Path n
11247       | String n
11248       | FileIn n
11249       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11250       | BufferIn n ->
11251           pr "  {\n";
11252           pr "    size_t i;\n";
11253           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11254           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11255           pr "    printf (\"\\n\");\n";
11256           pr "  }\n";
11257       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11258       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11259       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11260       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11261       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11262     ) (snd style);
11263     pr "  /* Java changes stdout line buffering so we need this: */\n";
11264     pr "  fflush (stdout);\n";
11265     pr "  return 0;\n";
11266     pr "}\n";
11267     pr "\n" in
11268
11269   List.iter (
11270     fun (name, style, _, _, _, _, _) ->
11271       if String.sub name (String.length name - 3) 3 <> "err" then (
11272         pr "/* Test normal return. */\n";
11273         generate_prototype ~extern:false ~semicolon:false ~newline:true
11274           ~handle:"g" ~prefix:"guestfs__" name style;
11275         pr "{\n";
11276         (match fst style with
11277          | RErr ->
11278              pr "  return 0;\n"
11279          | RInt _ ->
11280              pr "  int r;\n";
11281              pr "  sscanf (val, \"%%d\", &r);\n";
11282              pr "  return r;\n"
11283          | RInt64 _ ->
11284              pr "  int64_t r;\n";
11285              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11286              pr "  return r;\n"
11287          | RBool _ ->
11288              pr "  return STREQ (val, \"true\");\n"
11289          | RConstString _
11290          | RConstOptString _ ->
11291              (* Can't return the input string here.  Return a static
11292               * string so we ensure we get a segfault if the caller
11293               * tries to free it.
11294               *)
11295              pr "  return \"static string\";\n"
11296          | RString _ ->
11297              pr "  return strdup (val);\n"
11298          | RStringList _ ->
11299              pr "  char **strs;\n";
11300              pr "  int n, i;\n";
11301              pr "  sscanf (val, \"%%d\", &n);\n";
11302              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11303              pr "  for (i = 0; i < n; ++i) {\n";
11304              pr "    strs[i] = safe_malloc (g, 16);\n";
11305              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11306              pr "  }\n";
11307              pr "  strs[n] = NULL;\n";
11308              pr "  return strs;\n"
11309          | RStruct (_, typ) ->
11310              pr "  struct guestfs_%s *r;\n" typ;
11311              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11312              pr "  return r;\n"
11313          | RStructList (_, typ) ->
11314              pr "  struct guestfs_%s_list *r;\n" typ;
11315              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11316              pr "  sscanf (val, \"%%d\", &r->len);\n";
11317              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11318              pr "  return r;\n"
11319          | RHashtable _ ->
11320              pr "  char **strs;\n";
11321              pr "  int n, i;\n";
11322              pr "  sscanf (val, \"%%d\", &n);\n";
11323              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11324              pr "  for (i = 0; i < n; ++i) {\n";
11325              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11326              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11327              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11328              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11329              pr "  }\n";
11330              pr "  strs[n*2] = NULL;\n";
11331              pr "  return strs;\n"
11332          | RBufferOut _ ->
11333              pr "  return strdup (val);\n"
11334         );
11335         pr "}\n";
11336         pr "\n"
11337       ) else (
11338         pr "/* Test error return. */\n";
11339         generate_prototype ~extern:false ~semicolon:false ~newline:true
11340           ~handle:"g" ~prefix:"guestfs__" name style;
11341         pr "{\n";
11342         pr "  error (g, \"error\");\n";
11343         (match fst style with
11344          | RErr | RInt _ | RInt64 _ | RBool _ ->
11345              pr "  return -1;\n"
11346          | RConstString _ | RConstOptString _
11347          | RString _ | RStringList _ | RStruct _
11348          | RStructList _
11349          | RHashtable _
11350          | RBufferOut _ ->
11351              pr "  return NULL;\n"
11352         );
11353         pr "}\n";
11354         pr "\n"
11355       )
11356   ) tests
11357
11358 and generate_ocaml_bindtests () =
11359   generate_header OCamlStyle GPLv2plus;
11360
11361   pr "\
11362 let () =
11363   let g = Guestfs.create () in
11364 ";
11365
11366   let mkargs args =
11367     String.concat " " (
11368       List.map (
11369         function
11370         | CallString s -> "\"" ^ s ^ "\""
11371         | CallOptString None -> "None"
11372         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11373         | CallStringList xs ->
11374             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11375         | CallInt i when i >= 0 -> string_of_int i
11376         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11377         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11378         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11379         | CallBool b -> string_of_bool b
11380         | CallBuffer s -> sprintf "%S" s
11381       ) args
11382     )
11383   in
11384
11385   generate_lang_bindtests (
11386     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11387   );
11388
11389   pr "print_endline \"EOF\"\n"
11390
11391 and generate_perl_bindtests () =
11392   pr "#!/usr/bin/perl -w\n";
11393   generate_header HashStyle GPLv2plus;
11394
11395   pr "\
11396 use strict;
11397
11398 use Sys::Guestfs;
11399
11400 my $g = Sys::Guestfs->new ();
11401 ";
11402
11403   let mkargs args =
11404     String.concat ", " (
11405       List.map (
11406         function
11407         | CallString s -> "\"" ^ s ^ "\""
11408         | CallOptString None -> "undef"
11409         | CallOptString (Some s) -> sprintf "\"%s\"" s
11410         | CallStringList xs ->
11411             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11412         | CallInt i -> string_of_int i
11413         | CallInt64 i -> Int64.to_string i
11414         | CallBool b -> if b then "1" else "0"
11415         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11416       ) args
11417     )
11418   in
11419
11420   generate_lang_bindtests (
11421     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11422   );
11423
11424   pr "print \"EOF\\n\"\n"
11425
11426 and generate_python_bindtests () =
11427   generate_header HashStyle GPLv2plus;
11428
11429   pr "\
11430 import guestfs
11431
11432 g = guestfs.GuestFS ()
11433 ";
11434
11435   let mkargs args =
11436     String.concat ", " (
11437       List.map (
11438         function
11439         | CallString s -> "\"" ^ s ^ "\""
11440         | CallOptString None -> "None"
11441         | CallOptString (Some s) -> sprintf "\"%s\"" s
11442         | CallStringList xs ->
11443             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11444         | CallInt i -> string_of_int i
11445         | CallInt64 i -> Int64.to_string i
11446         | CallBool b -> if b then "1" else "0"
11447         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11448       ) args
11449     )
11450   in
11451
11452   generate_lang_bindtests (
11453     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11454   );
11455
11456   pr "print \"EOF\"\n"
11457
11458 and generate_ruby_bindtests () =
11459   generate_header HashStyle GPLv2plus;
11460
11461   pr "\
11462 require 'guestfs'
11463
11464 g = Guestfs::create()
11465 ";
11466
11467   let mkargs args =
11468     String.concat ", " (
11469       List.map (
11470         function
11471         | CallString s -> "\"" ^ s ^ "\""
11472         | CallOptString None -> "nil"
11473         | CallOptString (Some s) -> sprintf "\"%s\"" s
11474         | CallStringList xs ->
11475             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11476         | CallInt i -> string_of_int i
11477         | CallInt64 i -> Int64.to_string i
11478         | CallBool b -> string_of_bool b
11479         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11480       ) args
11481     )
11482   in
11483
11484   generate_lang_bindtests (
11485     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11486   );
11487
11488   pr "print \"EOF\\n\"\n"
11489
11490 and generate_java_bindtests () =
11491   generate_header CStyle GPLv2plus;
11492
11493   pr "\
11494 import com.redhat.et.libguestfs.*;
11495
11496 public class Bindtests {
11497     public static void main (String[] argv)
11498     {
11499         try {
11500             GuestFS g = new GuestFS ();
11501 ";
11502
11503   let mkargs args =
11504     String.concat ", " (
11505       List.map (
11506         function
11507         | CallString s -> "\"" ^ s ^ "\""
11508         | CallOptString None -> "null"
11509         | CallOptString (Some s) -> sprintf "\"%s\"" s
11510         | CallStringList xs ->
11511             "new String[]{" ^
11512               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11513         | CallInt i -> string_of_int i
11514         | CallInt64 i -> Int64.to_string i
11515         | CallBool b -> string_of_bool b
11516         | CallBuffer s ->
11517             "new byte[] { " ^ String.concat "," (
11518               map_chars (fun c -> string_of_int (Char.code c)) s
11519             ) ^ " }"
11520       ) args
11521     )
11522   in
11523
11524   generate_lang_bindtests (
11525     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11526   );
11527
11528   pr "
11529             System.out.println (\"EOF\");
11530         }
11531         catch (Exception exn) {
11532             System.err.println (exn);
11533             System.exit (1);
11534         }
11535     }
11536 }
11537 "
11538
11539 and generate_haskell_bindtests () =
11540   generate_header HaskellStyle GPLv2plus;
11541
11542   pr "\
11543 module Bindtests where
11544 import qualified Guestfs
11545
11546 main = do
11547   g <- Guestfs.create
11548 ";
11549
11550   let mkargs args =
11551     String.concat " " (
11552       List.map (
11553         function
11554         | CallString s -> "\"" ^ s ^ "\""
11555         | CallOptString None -> "Nothing"
11556         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11557         | CallStringList xs ->
11558             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11559         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11560         | CallInt i -> string_of_int i
11561         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11562         | CallInt64 i -> Int64.to_string i
11563         | CallBool true -> "True"
11564         | CallBool false -> "False"
11565         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11566       ) args
11567     )
11568   in
11569
11570   generate_lang_bindtests (
11571     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11572   );
11573
11574   pr "  putStrLn \"EOF\"\n"
11575
11576 (* Language-independent bindings tests - we do it this way to
11577  * ensure there is parity in testing bindings across all languages.
11578  *)
11579 and generate_lang_bindtests call =
11580   call "test0" [CallString "abc"; CallOptString (Some "def");
11581                 CallStringList []; CallBool false;
11582                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11583                 CallBuffer "abc\000abc"];
11584   call "test0" [CallString "abc"; CallOptString None;
11585                 CallStringList []; CallBool false;
11586                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11587                 CallBuffer "abc\000abc"];
11588   call "test0" [CallString ""; CallOptString (Some "def");
11589                 CallStringList []; CallBool false;
11590                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11591                 CallBuffer "abc\000abc"];
11592   call "test0" [CallString ""; CallOptString (Some "");
11593                 CallStringList []; CallBool false;
11594                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11595                 CallBuffer "abc\000abc"];
11596   call "test0" [CallString "abc"; CallOptString (Some "def");
11597                 CallStringList ["1"]; CallBool false;
11598                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11599                 CallBuffer "abc\000abc"];
11600   call "test0" [CallString "abc"; CallOptString (Some "def");
11601                 CallStringList ["1"; "2"]; CallBool false;
11602                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11603                 CallBuffer "abc\000abc"];
11604   call "test0" [CallString "abc"; CallOptString (Some "def");
11605                 CallStringList ["1"]; CallBool true;
11606                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11607                 CallBuffer "abc\000abc"];
11608   call "test0" [CallString "abc"; CallOptString (Some "def");
11609                 CallStringList ["1"]; CallBool false;
11610                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11611                 CallBuffer "abc\000abc"];
11612   call "test0" [CallString "abc"; CallOptString (Some "def");
11613                 CallStringList ["1"]; CallBool false;
11614                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11615                 CallBuffer "abc\000abc"];
11616   call "test0" [CallString "abc"; CallOptString (Some "def");
11617                 CallStringList ["1"]; CallBool false;
11618                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11619                 CallBuffer "abc\000abc"];
11620   call "test0" [CallString "abc"; CallOptString (Some "def");
11621                 CallStringList ["1"]; CallBool false;
11622                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11623                 CallBuffer "abc\000abc"];
11624   call "test0" [CallString "abc"; CallOptString (Some "def");
11625                 CallStringList ["1"]; CallBool false;
11626                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11627                 CallBuffer "abc\000abc"];
11628   call "test0" [CallString "abc"; CallOptString (Some "def");
11629                 CallStringList ["1"]; CallBool false;
11630                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11631                 CallBuffer "abc\000abc"]
11632
11633 (* XXX Add here tests of the return and error functions. *)
11634
11635 (* Code to generator bindings for virt-inspector.  Currently only
11636  * implemented for OCaml code (for virt-p2v 2.0).
11637  *)
11638 let rng_input = "inspector/virt-inspector.rng"
11639
11640 (* Read the input file and parse it into internal structures.  This is
11641  * by no means a complete RELAX NG parser, but is just enough to be
11642  * able to parse the specific input file.
11643  *)
11644 type rng =
11645   | Element of string * rng list        (* <element name=name/> *)
11646   | Attribute of string * rng list        (* <attribute name=name/> *)
11647   | Interleave of rng list                (* <interleave/> *)
11648   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11649   | OneOrMore of rng                        (* <oneOrMore/> *)
11650   | Optional of rng                        (* <optional/> *)
11651   | Choice of string list                (* <choice><value/>*</choice> *)
11652   | Value of string                        (* <value>str</value> *)
11653   | Text                                (* <text/> *)
11654
11655 let rec string_of_rng = function
11656   | Element (name, xs) ->
11657       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11658   | Attribute (name, xs) ->
11659       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11660   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11661   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11662   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11663   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11664   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11665   | Value value -> "Value \"" ^ value ^ "\""
11666   | Text -> "Text"
11667
11668 and string_of_rng_list xs =
11669   String.concat ", " (List.map string_of_rng xs)
11670
11671 let rec parse_rng ?defines context = function
11672   | [] -> []
11673   | Xml.Element ("element", ["name", name], children) :: rest ->
11674       Element (name, parse_rng ?defines context children)
11675       :: parse_rng ?defines context rest
11676   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11677       Attribute (name, parse_rng ?defines context children)
11678       :: parse_rng ?defines context rest
11679   | Xml.Element ("interleave", [], children) :: rest ->
11680       Interleave (parse_rng ?defines context children)
11681       :: parse_rng ?defines context rest
11682   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11683       let rng = parse_rng ?defines context [child] in
11684       (match rng with
11685        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11686        | _ ->
11687            failwithf "%s: <zeroOrMore> contains more than one child element"
11688              context
11689       )
11690   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11691       let rng = parse_rng ?defines context [child] in
11692       (match rng with
11693        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11694        | _ ->
11695            failwithf "%s: <oneOrMore> contains more than one child element"
11696              context
11697       )
11698   | Xml.Element ("optional", [], [child]) :: rest ->
11699       let rng = parse_rng ?defines context [child] in
11700       (match rng with
11701        | [child] -> Optional child :: parse_rng ?defines context rest
11702        | _ ->
11703            failwithf "%s: <optional> contains more than one child element"
11704              context
11705       )
11706   | Xml.Element ("choice", [], children) :: rest ->
11707       let values = List.map (
11708         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11709         | _ ->
11710             failwithf "%s: can't handle anything except <value> in <choice>"
11711               context
11712       ) children in
11713       Choice values
11714       :: parse_rng ?defines context rest
11715   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11716       Value value :: parse_rng ?defines context rest
11717   | Xml.Element ("text", [], []) :: rest ->
11718       Text :: parse_rng ?defines context rest
11719   | Xml.Element ("ref", ["name", name], []) :: rest ->
11720       (* Look up the reference.  Because of limitations in this parser,
11721        * we can't handle arbitrarily nested <ref> yet.  You can only
11722        * use <ref> from inside <start>.
11723        *)
11724       (match defines with
11725        | None ->
11726            failwithf "%s: contains <ref>, but no refs are defined yet" context
11727        | Some map ->
11728            let rng = StringMap.find name map in
11729            rng @ parse_rng ?defines context rest
11730       )
11731   | x :: _ ->
11732       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11733
11734 let grammar =
11735   let xml = Xml.parse_file rng_input in
11736   match xml with
11737   | Xml.Element ("grammar", _,
11738                  Xml.Element ("start", _, gram) :: defines) ->
11739       (* The <define/> elements are referenced in the <start> section,
11740        * so build a map of those first.
11741        *)
11742       let defines = List.fold_left (
11743         fun map ->
11744           function Xml.Element ("define", ["name", name], defn) ->
11745             StringMap.add name defn map
11746           | _ ->
11747               failwithf "%s: expected <define name=name/>" rng_input
11748       ) StringMap.empty defines in
11749       let defines = StringMap.mapi parse_rng defines in
11750
11751       (* Parse the <start> clause, passing the defines. *)
11752       parse_rng ~defines "<start>" gram
11753   | _ ->
11754       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11755         rng_input
11756
11757 let name_of_field = function
11758   | Element (name, _) | Attribute (name, _)
11759   | ZeroOrMore (Element (name, _))
11760   | OneOrMore (Element (name, _))
11761   | Optional (Element (name, _)) -> name
11762   | Optional (Attribute (name, _)) -> name
11763   | Text -> (* an unnamed field in an element *)
11764       "data"
11765   | rng ->
11766       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11767
11768 (* At the moment this function only generates OCaml types.  However we
11769  * should parameterize it later so it can generate types/structs in a
11770  * variety of languages.
11771  *)
11772 let generate_types xs =
11773   (* A simple type is one that can be printed out directly, eg.
11774    * "string option".  A complex type is one which has a name and has
11775    * to be defined via another toplevel definition, eg. a struct.
11776    *
11777    * generate_type generates code for either simple or complex types.
11778    * In the simple case, it returns the string ("string option").  In
11779    * the complex case, it returns the name ("mountpoint").  In the
11780    * complex case it has to print out the definition before returning,
11781    * so it should only be called when we are at the beginning of a
11782    * new line (BOL context).
11783    *)
11784   let rec generate_type = function
11785     | Text ->                                (* string *)
11786         "string", true
11787     | Choice values ->                        (* [`val1|`val2|...] *)
11788         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11789     | ZeroOrMore rng ->                        (* <rng> list *)
11790         let t, is_simple = generate_type rng in
11791         t ^ " list (* 0 or more *)", is_simple
11792     | OneOrMore rng ->                        (* <rng> list *)
11793         let t, is_simple = generate_type rng in
11794         t ^ " list (* 1 or more *)", is_simple
11795                                         (* virt-inspector hack: bool *)
11796     | Optional (Attribute (name, [Value "1"])) ->
11797         "bool", true
11798     | Optional rng ->                        (* <rng> list *)
11799         let t, is_simple = generate_type rng in
11800         t ^ " option", is_simple
11801                                         (* type name = { fields ... } *)
11802     | Element (name, fields) when is_attrs_interleave fields ->
11803         generate_type_struct name (get_attrs_interleave fields)
11804     | Element (name, [field])                (* type name = field *)
11805     | Attribute (name, [field]) ->
11806         let t, is_simple = generate_type field in
11807         if is_simple then (t, true)
11808         else (
11809           pr "type %s = %s\n" name t;
11810           name, false
11811         )
11812     | Element (name, fields) ->              (* type name = { fields ... } *)
11813         generate_type_struct name fields
11814     | rng ->
11815         failwithf "generate_type failed at: %s" (string_of_rng rng)
11816
11817   and is_attrs_interleave = function
11818     | [Interleave _] -> true
11819     | Attribute _ :: fields -> is_attrs_interleave fields
11820     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11821     | _ -> false
11822
11823   and get_attrs_interleave = function
11824     | [Interleave fields] -> fields
11825     | ((Attribute _) as field) :: fields
11826     | ((Optional (Attribute _)) as field) :: fields ->
11827         field :: get_attrs_interleave fields
11828     | _ -> assert false
11829
11830   and generate_types xs =
11831     List.iter (fun x -> ignore (generate_type x)) xs
11832
11833   and generate_type_struct name fields =
11834     (* Calculate the types of the fields first.  We have to do this
11835      * before printing anything so we are still in BOL context.
11836      *)
11837     let types = List.map fst (List.map generate_type fields) in
11838
11839     (* Special case of a struct containing just a string and another
11840      * field.  Turn it into an assoc list.
11841      *)
11842     match types with
11843     | ["string"; other] ->
11844         let fname1, fname2 =
11845           match fields with
11846           | [f1; f2] -> name_of_field f1, name_of_field f2
11847           | _ -> assert false in
11848         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11849         name, false
11850
11851     | types ->
11852         pr "type %s = {\n" name;
11853         List.iter (
11854           fun (field, ftype) ->
11855             let fname = name_of_field field in
11856             pr "  %s_%s : %s;\n" name fname ftype
11857         ) (List.combine fields types);
11858         pr "}\n";
11859         (* Return the name of this type, and
11860          * false because it's not a simple type.
11861          *)
11862         name, false
11863   in
11864
11865   generate_types xs
11866
11867 let generate_parsers xs =
11868   (* As for generate_type above, generate_parser makes a parser for
11869    * some type, and returns the name of the parser it has generated.
11870    * Because it (may) need to print something, it should always be
11871    * called in BOL context.
11872    *)
11873   let rec generate_parser = function
11874     | Text ->                                (* string *)
11875         "string_child_or_empty"
11876     | Choice values ->                        (* [`val1|`val2|...] *)
11877         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11878           (String.concat "|"
11879              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11880     | ZeroOrMore rng ->                        (* <rng> list *)
11881         let pa = generate_parser rng in
11882         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11883     | OneOrMore rng ->                        (* <rng> list *)
11884         let pa = generate_parser rng in
11885         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11886                                         (* virt-inspector hack: bool *)
11887     | Optional (Attribute (name, [Value "1"])) ->
11888         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11889     | Optional rng ->                        (* <rng> list *)
11890         let pa = generate_parser rng in
11891         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11892                                         (* type name = { fields ... } *)
11893     | Element (name, fields) when is_attrs_interleave fields ->
11894         generate_parser_struct name (get_attrs_interleave fields)
11895     | Element (name, [field]) ->        (* type name = field *)
11896         let pa = generate_parser field in
11897         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11898         pr "let %s =\n" parser_name;
11899         pr "  %s\n" pa;
11900         pr "let parse_%s = %s\n" name parser_name;
11901         parser_name
11902     | Attribute (name, [field]) ->
11903         let pa = generate_parser field in
11904         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11905         pr "let %s =\n" parser_name;
11906         pr "  %s\n" pa;
11907         pr "let parse_%s = %s\n" name parser_name;
11908         parser_name
11909     | Element (name, fields) ->              (* type name = { fields ... } *)
11910         generate_parser_struct name ([], fields)
11911     | rng ->
11912         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11913
11914   and is_attrs_interleave = function
11915     | [Interleave _] -> true
11916     | Attribute _ :: fields -> is_attrs_interleave fields
11917     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11918     | _ -> false
11919
11920   and get_attrs_interleave = function
11921     | [Interleave fields] -> [], fields
11922     | ((Attribute _) as field) :: fields
11923     | ((Optional (Attribute _)) as field) :: fields ->
11924         let attrs, interleaves = get_attrs_interleave fields in
11925         (field :: attrs), interleaves
11926     | _ -> assert false
11927
11928   and generate_parsers xs =
11929     List.iter (fun x -> ignore (generate_parser x)) xs
11930
11931   and generate_parser_struct name (attrs, interleaves) =
11932     (* Generate parsers for the fields first.  We have to do this
11933      * before printing anything so we are still in BOL context.
11934      *)
11935     let fields = attrs @ interleaves in
11936     let pas = List.map generate_parser fields in
11937
11938     (* Generate an intermediate tuple from all the fields first.
11939      * If the type is just a string + another field, then we will
11940      * return this directly, otherwise it is turned into a record.
11941      *
11942      * RELAX NG note: This code treats <interleave> and plain lists of
11943      * fields the same.  In other words, it doesn't bother enforcing
11944      * any ordering of fields in the XML.
11945      *)
11946     pr "let parse_%s x =\n" name;
11947     pr "  let t = (\n    ";
11948     let comma = ref false in
11949     List.iter (
11950       fun x ->
11951         if !comma then pr ",\n    ";
11952         comma := true;
11953         match x with
11954         | Optional (Attribute (fname, [field])), pa ->
11955             pr "%s x" pa
11956         | Optional (Element (fname, [field])), pa ->
11957             pr "%s (optional_child %S x)" pa fname
11958         | Attribute (fname, [Text]), _ ->
11959             pr "attribute %S x" fname
11960         | (ZeroOrMore _ | OneOrMore _), pa ->
11961             pr "%s x" pa
11962         | Text, pa ->
11963             pr "%s x" pa
11964         | (field, pa) ->
11965             let fname = name_of_field field in
11966             pr "%s (child %S x)" pa fname
11967     ) (List.combine fields pas);
11968     pr "\n  ) in\n";
11969
11970     (match fields with
11971      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11972          pr "  t\n"
11973
11974      | _ ->
11975          pr "  (Obj.magic t : %s)\n" name
11976 (*
11977          List.iter (
11978            function
11979            | (Optional (Attribute (fname, [field])), pa) ->
11980                pr "  %s_%s =\n" name fname;
11981                pr "    %s x;\n" pa
11982            | (Optional (Element (fname, [field])), pa) ->
11983                pr "  %s_%s =\n" name fname;
11984                pr "    (let x = optional_child %S x in\n" fname;
11985                pr "     %s x);\n" pa
11986            | (field, pa) ->
11987                let fname = name_of_field field in
11988                pr "  %s_%s =\n" name fname;
11989                pr "    (let x = child %S x in\n" fname;
11990                pr "     %s x);\n" pa
11991          ) (List.combine fields pas);
11992          pr "}\n"
11993 *)
11994     );
11995     sprintf "parse_%s" name
11996   in
11997
11998   generate_parsers xs
11999
12000 (* Generate ocaml/guestfs_inspector.mli. *)
12001 let generate_ocaml_inspector_mli () =
12002   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12003
12004   pr "\
12005 (** This is an OCaml language binding to the external [virt-inspector]
12006     program.
12007
12008     For more information, please read the man page [virt-inspector(1)].
12009 *)
12010
12011 ";
12012
12013   generate_types grammar;
12014   pr "(** The nested information returned from the {!inspect} function. *)\n";
12015   pr "\n";
12016
12017   pr "\
12018 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
12019 (** To inspect a libvirt domain called [name], pass a singleton
12020     list: [inspect [name]].  When using libvirt only, you may
12021     optionally pass a libvirt URI using [inspect ~connect:uri ...].
12022
12023     To inspect a disk image or images, pass a list of the filenames
12024     of the disk images: [inspect filenames]
12025
12026     This function inspects the given guest or disk images and
12027     returns a list of operating system(s) found and a large amount
12028     of information about them.  In the vast majority of cases,
12029     a virtual machine only contains a single operating system.
12030
12031     If the optional [~xml] parameter is given, then this function
12032     skips running the external virt-inspector program and just
12033     parses the given XML directly (which is expected to be XML
12034     produced from a previous run of virt-inspector).  The list of
12035     names and connect URI are ignored in this case.
12036
12037     This function can throw a wide variety of exceptions, for example
12038     if the external virt-inspector program cannot be found, or if
12039     it doesn't generate valid XML.
12040 *)
12041 "
12042
12043 (* Generate ocaml/guestfs_inspector.ml. *)
12044 let generate_ocaml_inspector_ml () =
12045   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12046
12047   pr "open Unix\n";
12048   pr "\n";
12049
12050   generate_types grammar;
12051   pr "\n";
12052
12053   pr "\
12054 (* Misc functions which are used by the parser code below. *)
12055 let first_child = function
12056   | Xml.Element (_, _, c::_) -> c
12057   | Xml.Element (name, _, []) ->
12058       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
12059   | Xml.PCData str ->
12060       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12061
12062 let string_child_or_empty = function
12063   | Xml.Element (_, _, [Xml.PCData s]) -> s
12064   | Xml.Element (_, _, []) -> \"\"
12065   | Xml.Element (x, _, _) ->
12066       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
12067                 x ^ \" instead\")
12068   | Xml.PCData str ->
12069       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12070
12071 let optional_child name xml =
12072   let children = Xml.children xml in
12073   try
12074     Some (List.find (function
12075                      | Xml.Element (n, _, _) when n = name -> true
12076                      | _ -> false) children)
12077   with
12078     Not_found -> None
12079
12080 let child name xml =
12081   match optional_child name xml with
12082   | Some c -> c
12083   | None ->
12084       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
12085
12086 let attribute name xml =
12087   try Xml.attrib xml name
12088   with Xml.No_attribute _ ->
12089     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
12090
12091 ";
12092
12093   generate_parsers grammar;
12094   pr "\n";
12095
12096   pr "\
12097 (* Run external virt-inspector, then use parser to parse the XML. *)
12098 let inspect ?connect ?xml names =
12099   let xml =
12100     match xml with
12101     | None ->
12102         if names = [] then invalid_arg \"inspect: no names given\";
12103         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
12104           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
12105           names in
12106         let cmd = List.map Filename.quote cmd in
12107         let cmd = String.concat \" \" cmd in
12108         let chan = open_process_in cmd in
12109         let xml = Xml.parse_in chan in
12110         (match close_process_in chan with
12111          | WEXITED 0 -> ()
12112          | WEXITED _ -> failwith \"external virt-inspector command failed\"
12113          | WSIGNALED i | WSTOPPED i ->
12114              failwith (\"external virt-inspector command died or stopped on sig \" ^
12115                        string_of_int i)
12116         );
12117         xml
12118     | Some doc ->
12119         Xml.parse_string doc in
12120   parse_operatingsystems xml
12121 "
12122
12123 and generate_max_proc_nr () =
12124   pr "%d\n" max_proc_nr
12125
12126 let output_to filename k =
12127   let filename_new = filename ^ ".new" in
12128   chan := open_out filename_new;
12129   k ();
12130   close_out !chan;
12131   chan := Pervasives.stdout;
12132
12133   (* Is the new file different from the current file? *)
12134   if Sys.file_exists filename && files_equal filename filename_new then
12135     unlink filename_new                 (* same, so skip it *)
12136   else (
12137     (* different, overwrite old one *)
12138     (try chmod filename 0o644 with Unix_error _ -> ());
12139     rename filename_new filename;
12140     chmod filename 0o444;
12141     printf "written %s\n%!" filename;
12142   )
12143
12144 let perror msg = function
12145   | Unix_error (err, _, _) ->
12146       eprintf "%s: %s\n" msg (error_message err)
12147   | exn ->
12148       eprintf "%s: %s\n" msg (Printexc.to_string exn)
12149
12150 (* Main program. *)
12151 let () =
12152   let lock_fd =
12153     try openfile "HACKING" [O_RDWR] 0
12154     with
12155     | Unix_error (ENOENT, _, _) ->
12156         eprintf "\
12157 You are probably running this from the wrong directory.
12158 Run it from the top source directory using the command
12159   src/generator.ml
12160 ";
12161         exit 1
12162     | exn ->
12163         perror "open: HACKING" exn;
12164         exit 1 in
12165
12166   (* Acquire a lock so parallel builds won't try to run the generator
12167    * twice at the same time.  Subsequent builds will wait for the first
12168    * one to finish.  Note the lock is released implicitly when the
12169    * program exits.
12170    *)
12171   (try lockf lock_fd F_LOCK 1
12172    with exn ->
12173      perror "lock: HACKING" exn;
12174      exit 1);
12175
12176   check_functions ();
12177
12178   output_to "src/guestfs_protocol.x" generate_xdr;
12179   output_to "src/guestfs-structs.h" generate_structs_h;
12180   output_to "src/guestfs-actions.h" generate_actions_h;
12181   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12182   output_to "src/actions.c" generate_client_actions;
12183   output_to "src/bindtests.c" generate_bindtests;
12184   output_to "src/guestfs-structs.pod" generate_structs_pod;
12185   output_to "src/guestfs-actions.pod" generate_actions_pod;
12186   output_to "src/guestfs-availability.pod" generate_availability_pod;
12187   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12188   output_to "src/libguestfs.syms" generate_linker_script;
12189   output_to "daemon/actions.h" generate_daemon_actions_h;
12190   output_to "daemon/stubs.c" generate_daemon_actions;
12191   output_to "daemon/names.c" generate_daemon_names;
12192   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12193   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12194   output_to "capitests/tests.c" generate_tests;
12195   output_to "fish/cmds.c" generate_fish_cmds;
12196   output_to "fish/completion.c" generate_fish_completion;
12197   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12198   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12199   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12200   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12201   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12202   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12203   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12204   output_to "perl/Guestfs.xs" generate_perl_xs;
12205   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12206   output_to "perl/bindtests.pl" generate_perl_bindtests;
12207   output_to "python/guestfs-py.c" generate_python_c;
12208   output_to "python/guestfs.py" generate_python_py;
12209   output_to "python/bindtests.py" generate_python_bindtests;
12210   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12211   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12212   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12213
12214   List.iter (
12215     fun (typ, jtyp) ->
12216       let cols = cols_of_struct typ in
12217       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12218       output_to filename (generate_java_struct jtyp cols);
12219   ) java_structs;
12220
12221   output_to "java/Makefile.inc" generate_java_makefile_inc;
12222   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12223   output_to "java/Bindtests.java" generate_java_bindtests;
12224   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12225   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12226   output_to "csharp/Libguestfs.cs" generate_csharp;
12227
12228   (* Always generate this file last, and unconditionally.  It's used
12229    * by the Makefile to know when we must re-run the generator.
12230    *)
12231   let chan = open_out "src/stamp-generator" in
12232   fprintf chan "1\n";
12233   close_out chan;
12234
12235   printf "generated %d lines of code\n" !lines