10758781f9a006f8674f28bdfe4d7afe7b74bbf0
[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 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | FishOutput of fish_output_t (* how to display output in guestfish *)
186   | NotInFish             (* do not export via guestfish *)
187   | NotInDocs             (* do not add this function to documentation *)
188   | DeprecatedBy of string (* function is deprecated, use .. instead *)
189   | Optional of string    (* function is part of an optional group *)
190
191 and fish_output_t =
192   | FishOutputOctal       (* for int return, print in octal *)
193   | FishOutputHexadecimal (* for int return, print in hex *)
194
195 (* You can supply zero or as many tests as you want per API call.
196  *
197  * Note that the test environment has 3 block devices, of size 500MB,
198  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
199  * a fourth ISO block device with some known files on it (/dev/sdd).
200  *
201  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
202  * Number of cylinders was 63 for IDE emulated disks with precisely
203  * the same size.  How exactly this is calculated is a mystery.
204  *
205  * The ISO block device (/dev/sdd) comes from images/test.iso.
206  *
207  * To be able to run the tests in a reasonable amount of time,
208  * the virtual machine and block devices are reused between tests.
209  * So don't try testing kill_subprocess :-x
210  *
211  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
212  *
213  * Don't assume anything about the previous contents of the block
214  * devices.  Use 'Init*' to create some initial scenarios.
215  *
216  * You can add a prerequisite clause to any individual test.  This
217  * is a run-time check, which, if it fails, causes the test to be
218  * skipped.  Useful if testing a command which might not work on
219  * all variations of libguestfs builds.  A test that has prerequisite
220  * of 'Always' is run unconditionally.
221  *
222  * In addition, packagers can skip individual tests by setting the
223  * environment variables:     eg:
224  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
225  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
226  *)
227 type tests = (test_init * test_prereq * test) list
228 and test =
229     (* Run the command sequence and just expect nothing to fail. *)
230   | TestRun of seq
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the string.
234      *)
235   | TestOutput of seq * string
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of strings.
239      *)
240   | TestOutputList of seq * string list
241
242     (* Run the command sequence and expect the output of the final
243      * command to be the list of block devices (could be either
244      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
245      * character of each string).
246      *)
247   | TestOutputListOfDevices of seq * string list
248
249     (* Run the command sequence and expect the output of the final
250      * command to be the integer.
251      *)
252   | TestOutputInt of seq * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be <op> <int>, eg. ">=", "1".
256      *)
257   | TestOutputIntOp of seq * string * int
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a true value (!= 0 or != NULL).
261      *)
262   | TestOutputTrue of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a false value (== 0 or == NULL, but not an error).
266      *)
267   | TestOutputFalse of seq
268
269     (* Run the command sequence and expect the output of the final
270      * command to be a list of the given length (but don't care about
271      * content).
272      *)
273   | TestOutputLength of seq * int
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a buffer (RBufferOut), ie. string + size.
277      *)
278   | TestOutputBuffer of seq * string
279
280     (* Run the command sequence and expect the output of the final
281      * command to be a structure.
282      *)
283   | TestOutputStruct of seq * test_field_compare list
284
285     (* Run the command sequence and expect the final command (only)
286      * to fail.
287      *)
288   | TestLastFail of seq
289
290 and test_field_compare =
291   | CompareWithInt of string * int
292   | CompareWithIntOp of string * string * int
293   | CompareWithString of string * string
294   | CompareFieldsIntEq of string * string
295   | CompareFieldsStrEq of string * string
296
297 (* Test prerequisites. *)
298 and test_prereq =
299     (* Test always runs. *)
300   | Always
301
302     (* Test is currently disabled - eg. it fails, or it tests some
303      * unimplemented feature.
304      *)
305   | Disabled
306
307     (* 'string' is some C code (a function body) that should return
308      * true or false.  The test will run if the code returns true.
309      *)
310   | If of string
311
312     (* As for 'If' but the test runs _unless_ the code returns true. *)
313   | Unless 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 ]
389
390 let test_all_rets = [
391   (* except for RErr, which is tested thoroughly elsewhere *)
392   "test0rint",         RInt "valout";
393   "test0rint64",       RInt64 "valout";
394   "test0rbool",        RBool "valout";
395   "test0rconststring", RConstString "valout";
396   "test0rconstoptstring", RConstOptString "valout";
397   "test0rstring",      RString "valout";
398   "test0rstringlist",  RStringList "valout";
399   "test0rstruct",      RStruct ("valout", "lvm_pv");
400   "test0rstructlist",  RStructList ("valout", "lvm_pv");
401   "test0rhashtable",   RHashtable "valout";
402 ]
403
404 let test_functions = [
405   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
406    [],
407    "internal test function - do not use",
408    "\
409 This is an internal test function which is used to test whether
410 the automatically generated bindings can handle every possible
411 parameter type correctly.
412
413 It echos the contents of each parameter to stdout.
414
415 You probably don't want to call this function.");
416 ] @ List.flatten (
417   List.map (
418     fun (name, ret) ->
419       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
420         [],
421         "internal test function - do not use",
422         "\
423 This is an internal test function which is used to test whether
424 the automatically generated bindings can handle every possible
425 return type correctly.
426
427 It converts string C<val> to the return type.
428
429 You probably don't want to call this function.");
430        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
431         [],
432         "internal test function - do not use",
433         "\
434 This is an internal test function which is used to test whether
435 the automatically generated bindings can handle every possible
436 return type correctly.
437
438 This function always returns an error.
439
440 You probably don't want to call this function.")]
441   ) test_all_rets
442 )
443
444 (* non_daemon_functions are any functions which don't get processed
445  * in the daemon, eg. functions for setting and getting local
446  * configuration values.
447  *)
448
449 let non_daemon_functions = test_functions @ [
450   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
451    [],
452    "launch the qemu subprocess",
453    "\
454 Internally libguestfs is implemented by running a virtual machine
455 using L<qemu(1)>.
456
457 You should call this after configuring the handle
458 (eg. adding drives) but before performing any actions.");
459
460   ("wait_ready", (RErr, []), -1, [NotInFish],
461    [],
462    "wait until the qemu subprocess launches (no op)",
463    "\
464 This function is a no op.
465
466 In versions of the API E<lt> 1.0.71 you had to call this function
467 just after calling C<guestfs_launch> to wait for the launch
468 to complete.  However this is no longer necessary because
469 C<guestfs_launch> now does the waiting.
470
471 If you see any calls to this function in code then you can just
472 remove them, unless you want to retain compatibility with older
473 versions of the API.");
474
475   ("kill_subprocess", (RErr, []), -1, [],
476    [],
477    "kill the qemu subprocess",
478    "\
479 This kills the qemu subprocess.  You should never need to call this.");
480
481   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
482    [],
483    "add an image to examine or modify",
484    "\
485 This function adds a virtual machine disk image C<filename> to the
486 guest.  The first time you call this function, the disk appears as IDE
487 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
488 so on.
489
490 You don't necessarily need to be root when using libguestfs.  However
491 you obviously do need sufficient permissions to access the filename
492 for whatever operations you want to perform (ie. read access if you
493 just want to read the image or write access if you want to modify the
494 image).
495
496 This is equivalent to the qemu parameter
497 C<-drive file=filename,cache=off,if=...>.
498
499 C<cache=off> is omitted in cases where it is not supported by
500 the underlying filesystem.
501
502 C<if=...> is set at compile time by the configuration option
503 C<./configure --with-drive-if=...>.  In the rare case where you
504 might need to change this at run time, use C<guestfs_add_drive_with_if>
505 or C<guestfs_add_drive_ro_with_if>.
506
507 Note that this call checks for the existence of C<filename>.  This
508 stops you from specifying other types of drive which are supported
509 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
510 the general C<guestfs_config> call instead.");
511
512   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
513    [],
514    "add a CD-ROM disk image to examine",
515    "\
516 This function adds a virtual CD-ROM disk image to the guest.
517
518 This is equivalent to the qemu parameter C<-cdrom filename>.
519
520 Notes:
521
522 =over 4
523
524 =item *
525
526 This call checks for the existence of C<filename>.  This
527 stops you from specifying other types of drive which are supported
528 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
529 the general C<guestfs_config> call instead.
530
531 =item *
532
533 If you just want to add an ISO file (often you use this as an
534 efficient way to transfer large files into the guest), then you
535 should probably use C<guestfs_add_drive_ro> instead.
536
537 =back");
538
539   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
540    [],
541    "add a drive in snapshot mode (read-only)",
542    "\
543 This adds a drive in snapshot mode, making it effectively
544 read-only.
545
546 Note that writes to the device are allowed, and will be seen for
547 the duration of the guestfs handle, but they are written
548 to a temporary file which is discarded as soon as the guestfs
549 handle is closed.  We don't currently have any method to enable
550 changes to be committed, although qemu can support this.
551
552 This is equivalent to the qemu parameter
553 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
554
555 C<if=...> is set at compile time by the configuration option
556 C<./configure --with-drive-if=...>.  In the rare case where you
557 might need to change this at run time, use C<guestfs_add_drive_with_if>
558 or C<guestfs_add_drive_ro_with_if>.
559
560 C<readonly=on> is only added where qemu supports this option.
561
562 Note that this call checks for the existence of C<filename>.  This
563 stops you from specifying other types of drive which are supported
564 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
565 the general C<guestfs_config> call instead.");
566
567   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
568    [],
569    "add qemu parameters",
570    "\
571 This can be used to add arbitrary qemu command line parameters
572 of the form C<-param value>.  Actually it's not quite arbitrary - we
573 prevent you from setting some parameters which would interfere with
574 parameters that we use.
575
576 The first character of C<param> string must be a C<-> (dash).
577
578 C<value> can be NULL.");
579
580   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
581    [],
582    "set the qemu binary",
583    "\
584 Set the qemu binary that we will use.
585
586 The default is chosen when the library was compiled by the
587 configure script.
588
589 You can also override this by setting the C<LIBGUESTFS_QEMU>
590 environment variable.
591
592 Setting C<qemu> to C<NULL> restores the default qemu binary.
593
594 Note that you should call this function as early as possible
595 after creating the handle.  This is because some pre-launch
596 operations depend on testing qemu features (by running C<qemu -help>).
597 If the qemu binary changes, we don't retest features, and
598 so you might see inconsistent results.  Using the environment
599 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
600 the qemu binary at the same time as the handle is created.");
601
602   ("get_qemu", (RConstString "qemu", []), -1, [],
603    [InitNone, Always, TestRun (
604       [["get_qemu"]])],
605    "get the qemu binary",
606    "\
607 Return the current qemu binary.
608
609 This is always non-NULL.  If it wasn't set already, then this will
610 return the default qemu binary name.");
611
612   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
613    [],
614    "set the search path",
615    "\
616 Set the path that libguestfs searches for kernel and initrd.img.
617
618 The default is C<$libdir/guestfs> unless overridden by setting
619 C<LIBGUESTFS_PATH> environment variable.
620
621 Setting C<path> to C<NULL> restores the default path.");
622
623   ("get_path", (RConstString "path", []), -1, [],
624    [InitNone, Always, TestRun (
625       [["get_path"]])],
626    "get the search path",
627    "\
628 Return the current search path.
629
630 This is always non-NULL.  If it wasn't set already, then this will
631 return the default path.");
632
633   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
634    [],
635    "add options to kernel command line",
636    "\
637 This function is used to add additional options to the
638 guest kernel command line.
639
640 The default is C<NULL> unless overridden by setting
641 C<LIBGUESTFS_APPEND> environment variable.
642
643 Setting C<append> to C<NULL> means I<no> additional options
644 are passed (libguestfs always adds a few of its own).");
645
646   ("get_append", (RConstOptString "append", []), -1, [],
647    (* This cannot be tested with the current framework.  The
648     * function can return NULL in normal operations, which the
649     * test framework interprets as an error.
650     *)
651    [],
652    "get the additional kernel options",
653    "\
654 Return the additional kernel options which are added to the
655 guest kernel command line.
656
657 If C<NULL> then no options are added.");
658
659   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
660    [],
661    "set autosync mode",
662    "\
663 If C<autosync> is true, this enables autosync.  Libguestfs will make a
664 best effort attempt to run C<guestfs_umount_all> followed by
665 C<guestfs_sync> when the handle is closed
666 (also if the program exits without closing handles).
667
668 This is disabled by default (except in guestfish where it is
669 enabled by default).");
670
671   ("get_autosync", (RBool "autosync", []), -1, [],
672    [InitNone, Always, TestRun (
673       [["get_autosync"]])],
674    "get autosync mode",
675    "\
676 Get the autosync flag.");
677
678   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
679    [],
680    "set verbose mode",
681    "\
682 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
683
684 Verbose messages are disabled unless the environment variable
685 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
686
687   ("get_verbose", (RBool "verbose", []), -1, [],
688    [],
689    "get verbose mode",
690    "\
691 This returns the verbose messages flag.");
692
693   ("is_ready", (RBool "ready", []), -1, [],
694    [InitNone, Always, TestOutputTrue (
695       [["is_ready"]])],
696    "is ready to accept commands",
697    "\
698 This returns true iff this handle is ready to accept commands
699 (in the C<READY> state).
700
701 For more information on states, see L<guestfs(3)>.");
702
703   ("is_config", (RBool "config", []), -1, [],
704    [InitNone, Always, TestOutputFalse (
705       [["is_config"]])],
706    "is in configuration state",
707    "\
708 This returns true iff this handle is being configured
709 (in the C<CONFIG> state).
710
711 For more information on states, see L<guestfs(3)>.");
712
713   ("is_launching", (RBool "launching", []), -1, [],
714    [InitNone, Always, TestOutputFalse (
715       [["is_launching"]])],
716    "is launching subprocess",
717    "\
718 This returns true iff this handle is launching the subprocess
719 (in the C<LAUNCHING> state).
720
721 For more information on states, see L<guestfs(3)>.");
722
723   ("is_busy", (RBool "busy", []), -1, [],
724    [InitNone, Always, TestOutputFalse (
725       [["is_busy"]])],
726    "is busy processing a command",
727    "\
728 This returns true iff this handle is busy processing a command
729 (in the C<BUSY> state).
730
731 For more information on states, see L<guestfs(3)>.");
732
733   ("get_state", (RInt "state", []), -1, [],
734    [],
735    "get the current state",
736    "\
737 This returns the current state as an opaque integer.  This is
738 only useful for printing debug and internal error messages.
739
740 For more information on states, see L<guestfs(3)>.");
741
742   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
743    [InitNone, Always, TestOutputInt (
744       [["set_memsize"; "500"];
745        ["get_memsize"]], 500)],
746    "set memory allocated to the qemu subprocess",
747    "\
748 This sets the memory size in megabytes allocated to the
749 qemu subprocess.  This only has any effect if called before
750 C<guestfs_launch>.
751
752 You can also change this by setting the environment
753 variable C<LIBGUESTFS_MEMSIZE> before the handle is
754 created.
755
756 For more information on the architecture of libguestfs,
757 see L<guestfs(3)>.");
758
759   ("get_memsize", (RInt "memsize", []), -1, [],
760    [InitNone, Always, TestOutputIntOp (
761       [["get_memsize"]], ">=", 256)],
762    "get memory allocated to the qemu subprocess",
763    "\
764 This gets the memory size in megabytes allocated to the
765 qemu subprocess.
766
767 If C<guestfs_set_memsize> was not called
768 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
769 then this returns the compiled-in default value for memsize.
770
771 For more information on the architecture of libguestfs,
772 see L<guestfs(3)>.");
773
774   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
775    [InitNone, Always, TestOutputIntOp (
776       [["get_pid"]], ">=", 1)],
777    "get PID of qemu subprocess",
778    "\
779 Return the process ID of the qemu subprocess.  If there is no
780 qemu subprocess, then this will return an error.
781
782 This is an internal call used for debugging and testing.");
783
784   ("version", (RStruct ("version", "version"), []), -1, [],
785    [InitNone, Always, TestOutputStruct (
786       [["version"]], [CompareWithInt ("major", 1)])],
787    "get the library version number",
788    "\
789 Return the libguestfs version number that the program is linked
790 against.
791
792 Note that because of dynamic linking this is not necessarily
793 the version of libguestfs that you compiled against.  You can
794 compile the program, and then at runtime dynamically link
795 against a completely different C<libguestfs.so> library.
796
797 This call was added in version C<1.0.58>.  In previous
798 versions of libguestfs there was no way to get the version
799 number.  From C code you can use ELF weak linking tricks to find out if
800 this symbol exists (if it doesn't, then 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 I<Note:> Don't use this call to test for availability
812 of features.  Distro backports makes this unreliable.  Use
813 C<guestfs_available> instead.");
814
815   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
816    [InitNone, Always, TestOutputTrue (
817       [["set_selinux"; "true"];
818        ["get_selinux"]])],
819    "set SELinux enabled or disabled at appliance boot",
820    "\
821 This sets the selinux flag that is passed to the appliance
822 at boot time.  The default is C<selinux=0> (disabled).
823
824 Note that if SELinux is enabled, it is always in
825 Permissive mode (C<enforcing=0>).
826
827 For more information on the architecture of libguestfs,
828 see L<guestfs(3)>.");
829
830   ("get_selinux", (RBool "selinux", []), -1, [],
831    [],
832    "get SELinux enabled flag",
833    "\
834 This returns the current setting of the selinux flag which
835 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
836
837 For more information on the architecture of libguestfs,
838 see L<guestfs(3)>.");
839
840   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
841    [InitNone, Always, TestOutputFalse (
842       [["set_trace"; "false"];
843        ["get_trace"]])],
844    "enable or disable command traces",
845    "\
846 If the command trace flag is set to 1, then commands are
847 printed on stdout before they are executed in a format
848 which is very similar to the one used by guestfish.  In
849 other words, you can run a program with this enabled, and
850 you will get out a script which you can feed to guestfish
851 to perform the same set of actions.
852
853 If you want to trace C API calls into libguestfs (and
854 other libraries) then possibly a better way is to use
855 the external ltrace(1) command.
856
857 Command traces are disabled unless the environment variable
858 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
859
860   ("get_trace", (RBool "trace", []), -1, [],
861    [],
862    "get command trace enabled flag",
863    "\
864 Return the command trace flag.");
865
866   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
867    [InitNone, Always, TestOutputFalse (
868       [["set_direct"; "false"];
869        ["get_direct"]])],
870    "enable or disable direct appliance mode",
871    "\
872 If the direct appliance mode flag is enabled, then stdin and
873 stdout are passed directly through to the appliance once it
874 is launched.
875
876 One consequence of this is that log messages aren't caught
877 by the library and handled by C<guestfs_set_log_message_callback>,
878 but go straight to stdout.
879
880 You probably don't want to use this unless you know what you
881 are doing.
882
883 The default is disabled.");
884
885   ("get_direct", (RBool "direct", []), -1, [],
886    [],
887    "get direct appliance mode flag",
888    "\
889 Return the direct appliance mode flag.");
890
891   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
892    [InitNone, Always, TestOutputTrue (
893       [["set_recovery_proc"; "true"];
894        ["get_recovery_proc"]])],
895    "enable or disable the recovery process",
896    "\
897 If this is called with the parameter C<false> then
898 C<guestfs_launch> does not create a recovery process.  The
899 purpose of the recovery process is to stop runaway qemu
900 processes in the case where the main program aborts abruptly.
901
902 This only has any effect if called before C<guestfs_launch>,
903 and the default is true.
904
905 About the only time when you would want to disable this is
906 if the main process will fork itself into the background
907 (\"daemonize\" itself).  In this case the recovery process
908 thinks that the main program has disappeared and so kills
909 qemu, which is not very helpful.");
910
911   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
912    [],
913    "get recovery process enabled flag",
914    "\
915 Return the recovery process enabled flag.");
916
917   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
918    [],
919    "add a drive specifying the QEMU block emulation to use",
920    "\
921 This is the same as C<guestfs_add_drive> but it allows you
922 to specify the QEMU interface emulation to use at run time.");
923
924   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
925    [],
926    "add a drive read-only specifying the QEMU block emulation to use",
927    "\
928 This is the same as C<guestfs_add_drive_ro> but it allows you
929 to specify the QEMU interface emulation to use at run time.");
930
931 ]
932
933 (* daemon_functions are any functions which cause some action
934  * to take place in the daemon.
935  *)
936
937 let daemon_functions = [
938   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
939    [InitEmpty, Always, TestOutput (
940       [["part_disk"; "/dev/sda"; "mbr"];
941        ["mkfs"; "ext2"; "/dev/sda1"];
942        ["mount"; "/dev/sda1"; "/"];
943        ["write_file"; "/new"; "new file contents"; "0"];
944        ["cat"; "/new"]], "new file contents")],
945    "mount a guest disk at a position in the filesystem",
946    "\
947 Mount a guest disk at a position in the filesystem.  Block devices
948 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
949 the guest.  If those block devices contain partitions, they will have
950 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
951 names can be used.
952
953 The rules are the same as for L<mount(2)>:  A filesystem must
954 first be mounted on C</> before others can be mounted.  Other
955 filesystems can only be mounted on directories which already
956 exist.
957
958 The mounted filesystem is writable, if we have sufficient permissions
959 on the underlying device.
960
961 The filesystem options C<sync> and C<noatime> are set with this
962 call, in order to improve reliability.");
963
964   ("sync", (RErr, []), 2, [],
965    [ InitEmpty, Always, TestRun [["sync"]]],
966    "sync disks, writes are flushed through to the disk image",
967    "\
968 This syncs the disk, so that any writes are flushed through to the
969 underlying disk image.
970
971 You should always call this if you have modified a disk image, before
972 closing the handle.");
973
974   ("touch", (RErr, [Pathname "path"]), 3, [],
975    [InitBasicFS, Always, TestOutputTrue (
976       [["touch"; "/new"];
977        ["exists"; "/new"]])],
978    "update file timestamps or create a new file",
979    "\
980 Touch acts like the L<touch(1)> command.  It can be used to
981 update the timestamps on a file, or, if the file does not exist,
982 to create a new zero-length file.");
983
984   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
985    [InitISOFS, Always, TestOutput (
986       [["cat"; "/known-2"]], "abcdef\n")],
987    "list the contents of a file",
988    "\
989 Return the contents of the file named C<path>.
990
991 Note that this function cannot correctly handle binary files
992 (specifically, files containing C<\\0> character which is treated
993 as end of string).  For those you need to use the C<guestfs_read_file>
994 or C<guestfs_download> functions which have a more complex interface.");
995
996   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
997    [], (* XXX Tricky to test because it depends on the exact format
998         * of the 'ls -l' command, which changes between F10 and F11.
999         *)
1000    "list the files in a directory (long format)",
1001    "\
1002 List the files in C<directory> (relative to the root directory,
1003 there is no cwd) in the format of 'ls -la'.
1004
1005 This command is mostly useful for interactive sessions.  It
1006 is I<not> intended that you try to parse the output string.");
1007
1008   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1009    [InitBasicFS, Always, TestOutputList (
1010       [["touch"; "/new"];
1011        ["touch"; "/newer"];
1012        ["touch"; "/newest"];
1013        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1014    "list the files in a directory",
1015    "\
1016 List the files in C<directory> (relative to the root directory,
1017 there is no cwd).  The '.' and '..' entries are not returned, but
1018 hidden files are shown.
1019
1020 This command is mostly useful for interactive sessions.  Programs
1021 should probably use C<guestfs_readdir> instead.");
1022
1023   ("list_devices", (RStringList "devices", []), 7, [],
1024    [InitEmpty, Always, TestOutputListOfDevices (
1025       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1026    "list the block devices",
1027    "\
1028 List all the block devices.
1029
1030 The full block device names are returned, eg. C</dev/sda>");
1031
1032   ("list_partitions", (RStringList "partitions", []), 8, [],
1033    [InitBasicFS, Always, TestOutputListOfDevices (
1034       [["list_partitions"]], ["/dev/sda1"]);
1035     InitEmpty, Always, TestOutputListOfDevices (
1036       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1037        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1038    "list the partitions",
1039    "\
1040 List all the partitions detected on all block devices.
1041
1042 The full partition device names are returned, eg. C</dev/sda1>
1043
1044 This does not return logical volumes.  For that you will need to
1045 call C<guestfs_lvs>.");
1046
1047   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1048    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1049       [["pvs"]], ["/dev/sda1"]);
1050     InitEmpty, Always, TestOutputListOfDevices (
1051       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1052        ["pvcreate"; "/dev/sda1"];
1053        ["pvcreate"; "/dev/sda2"];
1054        ["pvcreate"; "/dev/sda3"];
1055        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1056    "list the LVM physical volumes (PVs)",
1057    "\
1058 List all the physical volumes detected.  This is the equivalent
1059 of the L<pvs(8)> command.
1060
1061 This returns a list of just the device names that contain
1062 PVs (eg. C</dev/sda2>).
1063
1064 See also C<guestfs_pvs_full>.");
1065
1066   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1067    [InitBasicFSonLVM, Always, TestOutputList (
1068       [["vgs"]], ["VG"]);
1069     InitEmpty, Always, TestOutputList (
1070       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1071        ["pvcreate"; "/dev/sda1"];
1072        ["pvcreate"; "/dev/sda2"];
1073        ["pvcreate"; "/dev/sda3"];
1074        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1075        ["vgcreate"; "VG2"; "/dev/sda3"];
1076        ["vgs"]], ["VG1"; "VG2"])],
1077    "list the LVM volume groups (VGs)",
1078    "\
1079 List all the volumes groups detected.  This is the equivalent
1080 of the L<vgs(8)> command.
1081
1082 This returns a list of just the volume group names that were
1083 detected (eg. C<VolGroup00>).
1084
1085 See also C<guestfs_vgs_full>.");
1086
1087   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1088    [InitBasicFSonLVM, Always, TestOutputList (
1089       [["lvs"]], ["/dev/VG/LV"]);
1090     InitEmpty, Always, TestOutputList (
1091       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1092        ["pvcreate"; "/dev/sda1"];
1093        ["pvcreate"; "/dev/sda2"];
1094        ["pvcreate"; "/dev/sda3"];
1095        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1096        ["vgcreate"; "VG2"; "/dev/sda3"];
1097        ["lvcreate"; "LV1"; "VG1"; "50"];
1098        ["lvcreate"; "LV2"; "VG1"; "50"];
1099        ["lvcreate"; "LV3"; "VG2"; "50"];
1100        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1101    "list the LVM logical volumes (LVs)",
1102    "\
1103 List all the logical volumes detected.  This is the equivalent
1104 of the L<lvs(8)> command.
1105
1106 This returns a list of the logical volume device names
1107 (eg. C</dev/VolGroup00/LogVol00>).
1108
1109 See also C<guestfs_lvs_full>.");
1110
1111   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1112    [], (* XXX how to test? *)
1113    "list the LVM physical volumes (PVs)",
1114    "\
1115 List all the physical volumes detected.  This is the equivalent
1116 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1117
1118   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1119    [], (* XXX how to test? *)
1120    "list the LVM volume groups (VGs)",
1121    "\
1122 List all the volumes groups detected.  This is the equivalent
1123 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1124
1125   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM logical volumes (LVs)",
1128    "\
1129 List all the logical volumes detected.  This is the equivalent
1130 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1133    [InitISOFS, Always, TestOutputList (
1134       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1135     InitISOFS, Always, TestOutputList (
1136       [["read_lines"; "/empty"]], [])],
1137    "read file as lines",
1138    "\
1139 Return the contents of the file named C<path>.
1140
1141 The file contents are returned as a list of lines.  Trailing
1142 C<LF> and C<CRLF> character sequences are I<not> returned.
1143
1144 Note that this function cannot correctly handle binary files
1145 (specifically, files containing C<\\0> character which is treated
1146 as end of line).  For those you need to use the C<guestfs_read_file>
1147 function which has a more complex interface.");
1148
1149   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1150    [], (* XXX Augeas code needs tests. *)
1151    "create a new Augeas handle",
1152    "\
1153 Create a new Augeas handle for editing configuration files.
1154 If there was any previous Augeas handle associated with this
1155 guestfs session, then it is closed.
1156
1157 You must call this before using any other C<guestfs_aug_*>
1158 commands.
1159
1160 C<root> is the filesystem root.  C<root> must not be NULL,
1161 use C</> instead.
1162
1163 The flags are the same as the flags defined in
1164 E<lt>augeas.hE<gt>, the logical I<or> of the following
1165 integers:
1166
1167 =over 4
1168
1169 =item C<AUG_SAVE_BACKUP> = 1
1170
1171 Keep the original file with a C<.augsave> extension.
1172
1173 =item C<AUG_SAVE_NEWFILE> = 2
1174
1175 Save changes into a file with extension C<.augnew>, and
1176 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1177
1178 =item C<AUG_TYPE_CHECK> = 4
1179
1180 Typecheck lenses (can be expensive).
1181
1182 =item C<AUG_NO_STDINC> = 8
1183
1184 Do not use standard load path for modules.
1185
1186 =item C<AUG_SAVE_NOOP> = 16
1187
1188 Make save a no-op, just record what would have been changed.
1189
1190 =item C<AUG_NO_LOAD> = 32
1191
1192 Do not load the tree in C<guestfs_aug_init>.
1193
1194 =back
1195
1196 To close the handle, you can call C<guestfs_aug_close>.
1197
1198 To find out more about Augeas, see L<http://augeas.net/>.");
1199
1200   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1201    [], (* XXX Augeas code needs tests. *)
1202    "close the current Augeas handle",
1203    "\
1204 Close the current Augeas handle and free up any resources
1205 used by it.  After calling this, you have to call
1206 C<guestfs_aug_init> again before you can use any other
1207 Augeas functions.");
1208
1209   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1210    [], (* XXX Augeas code needs tests. *)
1211    "define an Augeas variable",
1212    "\
1213 Defines an Augeas variable C<name> whose value is the result
1214 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1215 undefined.
1216
1217 On success this returns the number of nodes in C<expr>, or
1218 C<0> if C<expr> evaluates to something which is not a nodeset.");
1219
1220   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1221    [], (* XXX Augeas code needs tests. *)
1222    "define an Augeas node",
1223    "\
1224 Defines a variable C<name> whose value is the result of
1225 evaluating C<expr>.
1226
1227 If C<expr> evaluates to an empty nodeset, a node is created,
1228 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1229 C<name> will be the nodeset containing that single node.
1230
1231 On success this returns a pair containing the
1232 number of nodes in the nodeset, and a boolean flag
1233 if a node was created.");
1234
1235   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1236    [], (* XXX Augeas code needs tests. *)
1237    "look up the value of an Augeas path",
1238    "\
1239 Look up the value associated with C<path>.  If C<path>
1240 matches exactly one node, the C<value> is returned.");
1241
1242   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "set Augeas path to value",
1245    "\
1246 Set the value associated with C<path> to C<val>.
1247
1248 In the Augeas API, it is possible to clear a node by setting
1249 the value to NULL.  Due to an oversight in the libguestfs API
1250 you cannot do that with this call.  Instead you must use the
1251 C<guestfs_aug_clear> call.");
1252
1253   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1254    [], (* XXX Augeas code needs tests. *)
1255    "insert a sibling Augeas node",
1256    "\
1257 Create a new sibling C<label> for C<path>, inserting it into
1258 the tree before or after C<path> (depending on the boolean
1259 flag C<before>).
1260
1261 C<path> must match exactly one existing node in the tree, and
1262 C<label> must be a label, ie. not contain C</>, C<*> or end
1263 with a bracketed index C<[N]>.");
1264
1265   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1266    [], (* XXX Augeas code needs tests. *)
1267    "remove an Augeas path",
1268    "\
1269 Remove C<path> and all of its children.
1270
1271 On success this returns the number of entries which were removed.");
1272
1273   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1274    [], (* XXX Augeas code needs tests. *)
1275    "move Augeas node",
1276    "\
1277 Move the node C<src> to C<dest>.  C<src> must match exactly
1278 one node.  C<dest> is overwritten if it exists.");
1279
1280   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1281    [], (* XXX Augeas code needs tests. *)
1282    "return Augeas nodes which match augpath",
1283    "\
1284 Returns a list of paths which match the path expression C<path>.
1285 The returned paths are sufficiently qualified so that they match
1286 exactly one node in the current tree.");
1287
1288   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1289    [], (* XXX Augeas code needs tests. *)
1290    "write all pending Augeas changes to disk",
1291    "\
1292 This writes all pending changes to disk.
1293
1294 The flags which were passed to C<guestfs_aug_init> affect exactly
1295 how files are saved.");
1296
1297   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1298    [], (* XXX Augeas code needs tests. *)
1299    "load files into the tree",
1300    "\
1301 Load files into the tree.
1302
1303 See C<aug_load> in the Augeas documentation for the full gory
1304 details.");
1305
1306   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1307    [], (* XXX Augeas code needs tests. *)
1308    "list Augeas nodes under augpath",
1309    "\
1310 This is just a shortcut for listing C<guestfs_aug_match>
1311 C<path/*> and sorting the resulting nodes into alphabetical order.");
1312
1313   ("rm", (RErr, [Pathname "path"]), 29, [],
1314    [InitBasicFS, Always, TestRun
1315       [["touch"; "/new"];
1316        ["rm"; "/new"]];
1317     InitBasicFS, Always, TestLastFail
1318       [["rm"; "/new"]];
1319     InitBasicFS, Always, TestLastFail
1320       [["mkdir"; "/new"];
1321        ["rm"; "/new"]]],
1322    "remove a file",
1323    "\
1324 Remove the single file C<path>.");
1325
1326   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1327    [InitBasicFS, Always, TestRun
1328       [["mkdir"; "/new"];
1329        ["rmdir"; "/new"]];
1330     InitBasicFS, Always, TestLastFail
1331       [["rmdir"; "/new"]];
1332     InitBasicFS, Always, TestLastFail
1333       [["touch"; "/new"];
1334        ["rmdir"; "/new"]]],
1335    "remove a directory",
1336    "\
1337 Remove the single directory C<path>.");
1338
1339   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1340    [InitBasicFS, Always, TestOutputFalse
1341       [["mkdir"; "/new"];
1342        ["mkdir"; "/new/foo"];
1343        ["touch"; "/new/foo/bar"];
1344        ["rm_rf"; "/new"];
1345        ["exists"; "/new"]]],
1346    "remove a file or directory recursively",
1347    "\
1348 Remove the file or directory C<path>, recursively removing the
1349 contents if its a directory.  This is like the C<rm -rf> shell
1350 command.");
1351
1352   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir"; "/new"];
1355        ["is_dir"; "/new"]];
1356     InitBasicFS, Always, TestLastFail
1357       [["mkdir"; "/new/foo/bar"]]],
1358    "create a directory",
1359    "\
1360 Create a directory named C<path>.");
1361
1362   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1363    [InitBasicFS, Always, TestOutputTrue
1364       [["mkdir_p"; "/new/foo/bar"];
1365        ["is_dir"; "/new/foo/bar"]];
1366     InitBasicFS, Always, TestOutputTrue
1367       [["mkdir_p"; "/new/foo/bar"];
1368        ["is_dir"; "/new/foo"]];
1369     InitBasicFS, Always, TestOutputTrue
1370       [["mkdir_p"; "/new/foo/bar"];
1371        ["is_dir"; "/new"]];
1372     (* Regression tests for RHBZ#503133: *)
1373     InitBasicFS, Always, TestRun
1374       [["mkdir"; "/new"];
1375        ["mkdir_p"; "/new"]];
1376     InitBasicFS, Always, TestLastFail
1377       [["touch"; "/new"];
1378        ["mkdir_p"; "/new"]]],
1379    "create a directory and parents",
1380    "\
1381 Create a directory named C<path>, creating any parent directories
1382 as necessary.  This is like the C<mkdir -p> shell command.");
1383
1384   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1385    [], (* XXX Need stat command to test *)
1386    "change file mode",
1387    "\
1388 Change the mode (permissions) of C<path> to C<mode>.  Only
1389 numeric modes are supported.
1390
1391 I<Note>: When using this command from guestfish, C<mode>
1392 by default would be decimal, unless you prefix it with
1393 C<0> to get octal, ie. use C<0700> not C<700>.
1394
1395 The mode actually set is affected by the umask.");
1396
1397   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1398    [], (* XXX Need stat command to test *)
1399    "change file owner and group",
1400    "\
1401 Change the file owner to C<owner> and group to C<group>.
1402
1403 Only numeric uid and gid are supported.  If you want to use
1404 names, you will need to locate and parse the password file
1405 yourself (Augeas support makes this relatively easy).");
1406
1407   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1408    [InitISOFS, Always, TestOutputTrue (
1409       [["exists"; "/empty"]]);
1410     InitISOFS, Always, TestOutputTrue (
1411       [["exists"; "/directory"]])],
1412    "test if file or directory exists",
1413    "\
1414 This returns C<true> if and only if there is a file, directory
1415 (or anything) with the given C<path> name.
1416
1417 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1418
1419   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1420    [InitISOFS, Always, TestOutputTrue (
1421       [["is_file"; "/known-1"]]);
1422     InitISOFS, Always, TestOutputFalse (
1423       [["is_file"; "/directory"]])],
1424    "test if file exists",
1425    "\
1426 This returns C<true> if and only if there is a file
1427 with the given C<path> name.  Note that it returns false for
1428 other objects like directories.
1429
1430 See also C<guestfs_stat>.");
1431
1432   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1433    [InitISOFS, Always, TestOutputFalse (
1434       [["is_dir"; "/known-3"]]);
1435     InitISOFS, Always, TestOutputTrue (
1436       [["is_dir"; "/directory"]])],
1437    "test if file exists",
1438    "\
1439 This returns C<true> if and only if there is a directory
1440 with the given C<path> name.  Note that it returns false for
1441 other objects like files.
1442
1443 See also C<guestfs_stat>.");
1444
1445   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1446    [InitEmpty, Always, TestOutputListOfDevices (
1447       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1448        ["pvcreate"; "/dev/sda1"];
1449        ["pvcreate"; "/dev/sda2"];
1450        ["pvcreate"; "/dev/sda3"];
1451        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1452    "create an LVM physical volume",
1453    "\
1454 This creates an LVM physical volume on the named C<device>,
1455 where C<device> should usually be a partition name such
1456 as C</dev/sda1>.");
1457
1458   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1459    [InitEmpty, Always, TestOutputList (
1460       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1461        ["pvcreate"; "/dev/sda1"];
1462        ["pvcreate"; "/dev/sda2"];
1463        ["pvcreate"; "/dev/sda3"];
1464        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1465        ["vgcreate"; "VG2"; "/dev/sda3"];
1466        ["vgs"]], ["VG1"; "VG2"])],
1467    "create an LVM volume group",
1468    "\
1469 This creates an LVM volume group called C<volgroup>
1470 from the non-empty list of physical volumes C<physvols>.");
1471
1472   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [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        ["lvcreate"; "LV1"; "VG1"; "50"];
1481        ["lvcreate"; "LV2"; "VG1"; "50"];
1482        ["lvcreate"; "LV3"; "VG2"; "50"];
1483        ["lvcreate"; "LV4"; "VG2"; "50"];
1484        ["lvcreate"; "LV5"; "VG2"; "50"];
1485        ["lvs"]],
1486       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1487        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1488    "create an LVM logical volume",
1489    "\
1490 This creates an LVM logical volume called C<logvol>
1491 on the volume group C<volgroup>, with C<size> megabytes.");
1492
1493   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1494    [InitEmpty, Always, TestOutput (
1495       [["part_disk"; "/dev/sda"; "mbr"];
1496        ["mkfs"; "ext2"; "/dev/sda1"];
1497        ["mount_options"; ""; "/dev/sda1"; "/"];
1498        ["write_file"; "/new"; "new file contents"; "0"];
1499        ["cat"; "/new"]], "new file contents")],
1500    "make a filesystem",
1501    "\
1502 This creates a filesystem on C<device> (usually a partition
1503 or LVM logical volume).  The filesystem type is C<fstype>, for
1504 example C<ext3>.");
1505
1506   ("sfdisk", (RErr, [Device "device";
1507                      Int "cyls"; Int "heads"; Int "sectors";
1508                      StringList "lines"]), 43, [DangerWillRobinson],
1509    [],
1510    "create partitions on a block device",
1511    "\
1512 This is a direct interface to the L<sfdisk(8)> program for creating
1513 partitions on block devices.
1514
1515 C<device> should be a block device, for example C</dev/sda>.
1516
1517 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1518 and sectors on the device, which are passed directly to sfdisk as
1519 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1520 of these, then the corresponding parameter is omitted.  Usually for
1521 'large' disks, you can just pass C<0> for these, but for small
1522 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1523 out the right geometry and you will need to tell it.
1524
1525 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1526 information refer to the L<sfdisk(8)> manpage.
1527
1528 To create a single partition occupying the whole disk, you would
1529 pass C<lines> as a single element list, when the single element being
1530 the string C<,> (comma).
1531
1532 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1533 C<guestfs_part_init>");
1534
1535   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1536    [InitBasicFS, Always, TestOutput (
1537       [["write_file"; "/new"; "new file contents"; "0"];
1538        ["cat"; "/new"]], "new file contents");
1539     InitBasicFS, Always, TestOutput (
1540       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1541        ["cat"; "/new"]], "\nnew file contents\n");
1542     InitBasicFS, Always, TestOutput (
1543       [["write_file"; "/new"; "\n\n"; "0"];
1544        ["cat"; "/new"]], "\n\n");
1545     InitBasicFS, Always, TestOutput (
1546       [["write_file"; "/new"; ""; "0"];
1547        ["cat"; "/new"]], "");
1548     InitBasicFS, Always, TestOutput (
1549       [["write_file"; "/new"; "\n\n\n"; "0"];
1550        ["cat"; "/new"]], "\n\n\n");
1551     InitBasicFS, Always, TestOutput (
1552       [["write_file"; "/new"; "\n"; "0"];
1553        ["cat"; "/new"]], "\n")],
1554    "create a file",
1555    "\
1556 This call creates a file called C<path>.  The contents of the
1557 file is the string C<content> (which can contain any 8 bit data),
1558 with length C<size>.
1559
1560 As a special case, if C<size> is C<0>
1561 then the length is calculated using C<strlen> (so in this case
1562 the content cannot contain embedded ASCII NULs).
1563
1564 I<NB.> Owing to a bug, writing content containing ASCII NUL
1565 characters does I<not> work, even if the length is specified.
1566 We hope to resolve this bug in a future version.  In the meantime
1567 use C<guestfs_upload>.");
1568
1569   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1570    [InitEmpty, Always, TestOutputListOfDevices (
1571       [["part_disk"; "/dev/sda"; "mbr"];
1572        ["mkfs"; "ext2"; "/dev/sda1"];
1573        ["mount_options"; ""; "/dev/sda1"; "/"];
1574        ["mounts"]], ["/dev/sda1"]);
1575     InitEmpty, Always, TestOutputList (
1576       [["part_disk"; "/dev/sda"; "mbr"];
1577        ["mkfs"; "ext2"; "/dev/sda1"];
1578        ["mount_options"; ""; "/dev/sda1"; "/"];
1579        ["umount"; "/"];
1580        ["mounts"]], [])],
1581    "unmount a filesystem",
1582    "\
1583 This unmounts the given filesystem.  The filesystem may be
1584 specified either by its mountpoint (path) or the device which
1585 contains the filesystem.");
1586
1587   ("mounts", (RStringList "devices", []), 46, [],
1588    [InitBasicFS, Always, TestOutputListOfDevices (
1589       [["mounts"]], ["/dev/sda1"])],
1590    "show mounted filesystems",
1591    "\
1592 This returns the list of currently mounted filesystems.  It returns
1593 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1594
1595 Some internal mounts are not shown.
1596
1597 See also: C<guestfs_mountpoints>");
1598
1599   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1600    [InitBasicFS, Always, TestOutputList (
1601       [["umount_all"];
1602        ["mounts"]], []);
1603     (* check that umount_all can unmount nested mounts correctly: *)
1604     InitEmpty, Always, TestOutputList (
1605       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1606        ["mkfs"; "ext2"; "/dev/sda1"];
1607        ["mkfs"; "ext2"; "/dev/sda2"];
1608        ["mkfs"; "ext2"; "/dev/sda3"];
1609        ["mount_options"; ""; "/dev/sda1"; "/"];
1610        ["mkdir"; "/mp1"];
1611        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1612        ["mkdir"; "/mp1/mp2"];
1613        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1614        ["mkdir"; "/mp1/mp2/mp3"];
1615        ["umount_all"];
1616        ["mounts"]], [])],
1617    "unmount all filesystems",
1618    "\
1619 This unmounts all mounted filesystems.
1620
1621 Some internal mounts are not unmounted by this call.");
1622
1623   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1624    [],
1625    "remove all LVM LVs, VGs and PVs",
1626    "\
1627 This command removes all LVM logical volumes, volume groups
1628 and physical volumes.");
1629
1630   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1631    [InitISOFS, Always, TestOutput (
1632       [["file"; "/empty"]], "empty");
1633     InitISOFS, Always, TestOutput (
1634       [["file"; "/known-1"]], "ASCII text");
1635     InitISOFS, Always, TestLastFail (
1636       [["file"; "/notexists"]])],
1637    "determine file type",
1638    "\
1639 This call uses the standard L<file(1)> command to determine
1640 the type or contents of the file.  This also works on devices,
1641 for example to find out whether a partition contains a filesystem.
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 -zbsL path>.  Note in
1647 particular that the filename is not prepended to the output
1648 (the C<-b> option).");
1649
1650   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1651    [InitBasicFS, Always, TestOutput (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command"; "/test-command 1"]], "Result1");
1655     InitBasicFS, Always, TestOutput (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command"; "/test-command 2"]], "Result2\n");
1659     InitBasicFS, Always, TestOutput (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command"; "/test-command 3"]], "\nResult3");
1663     InitBasicFS, Always, TestOutput (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command"; "/test-command 4"]], "\nResult4\n");
1667     InitBasicFS, Always, TestOutput (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command"; "/test-command 5"]], "\nResult5\n\n");
1671     InitBasicFS, Always, TestOutput (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1675     InitBasicFS, Always, TestOutput (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command"; "/test-command 7"]], "");
1679     InitBasicFS, Always, TestOutput (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command"; "/test-command 8"]], "\n");
1683     InitBasicFS, Always, TestOutput (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command"; "/test-command 9"]], "\n\n");
1687     InitBasicFS, Always, TestOutput (
1688       [["upload"; "test-command"; "/test-command"];
1689        ["chmod"; "0o755"; "/test-command"];
1690        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1691     InitBasicFS, Always, TestOutput (
1692       [["upload"; "test-command"; "/test-command"];
1693        ["chmod"; "0o755"; "/test-command"];
1694        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1695     InitBasicFS, Always, TestLastFail (
1696       [["upload"; "test-command"; "/test-command"];
1697        ["chmod"; "0o755"; "/test-command"];
1698        ["command"; "/test-command"]])],
1699    "run a command from the guest filesystem",
1700    "\
1701 This call runs a command from the guest filesystem.  The
1702 filesystem must be mounted, and must contain a compatible
1703 operating system (ie. something Linux, with the same
1704 or compatible processor architecture).
1705
1706 The single parameter is an argv-style list of arguments.
1707 The first element is the name of the program to run.
1708 Subsequent elements are parameters.  The list must be
1709 non-empty (ie. must contain a program name).  Note that
1710 the command runs directly, and is I<not> invoked via
1711 the shell (see C<guestfs_sh>).
1712
1713 The return value is anything printed to I<stdout> by
1714 the command.
1715
1716 If the command returns a non-zero exit status, then
1717 this function returns an error message.  The error message
1718 string is the content of I<stderr> from the command.
1719
1720 The C<$PATH> environment variable will contain at least
1721 C</usr/bin> and C</bin>.  If you require a program from
1722 another location, you should provide the full path in the
1723 first parameter.
1724
1725 Shared libraries and data files required by the program
1726 must be available on filesystems which are mounted in the
1727 correct places.  It is the caller's responsibility to ensure
1728 all filesystems that are needed are mounted at the right
1729 locations.");
1730
1731   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1732    [InitBasicFS, Always, TestOutputList (
1733       [["upload"; "test-command"; "/test-command"];
1734        ["chmod"; "0o755"; "/test-command"];
1735        ["command_lines"; "/test-command 1"]], ["Result1"]);
1736     InitBasicFS, Always, TestOutputList (
1737       [["upload"; "test-command"; "/test-command"];
1738        ["chmod"; "0o755"; "/test-command"];
1739        ["command_lines"; "/test-command 2"]], ["Result2"]);
1740     InitBasicFS, Always, TestOutputList (
1741       [["upload"; "test-command"; "/test-command"];
1742        ["chmod"; "0o755"; "/test-command"];
1743        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1744     InitBasicFS, Always, TestOutputList (
1745       [["upload"; "test-command"; "/test-command"];
1746        ["chmod"; "0o755"; "/test-command"];
1747        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1748     InitBasicFS, Always, TestOutputList (
1749       [["upload"; "test-command"; "/test-command"];
1750        ["chmod"; "0o755"; "/test-command"];
1751        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1752     InitBasicFS, Always, TestOutputList (
1753       [["upload"; "test-command"; "/test-command"];
1754        ["chmod"; "0o755"; "/test-command"];
1755        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1756     InitBasicFS, Always, TestOutputList (
1757       [["upload"; "test-command"; "/test-command"];
1758        ["chmod"; "0o755"; "/test-command"];
1759        ["command_lines"; "/test-command 7"]], []);
1760     InitBasicFS, Always, TestOutputList (
1761       [["upload"; "test-command"; "/test-command"];
1762        ["chmod"; "0o755"; "/test-command"];
1763        ["command_lines"; "/test-command 8"]], [""]);
1764     InitBasicFS, Always, TestOutputList (
1765       [["upload"; "test-command"; "/test-command"];
1766        ["chmod"; "0o755"; "/test-command"];
1767        ["command_lines"; "/test-command 9"]], ["";""]);
1768     InitBasicFS, Always, TestOutputList (
1769       [["upload"; "test-command"; "/test-command"];
1770        ["chmod"; "0o755"; "/test-command"];
1771        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1772     InitBasicFS, Always, TestOutputList (
1773       [["upload"; "test-command"; "/test-command"];
1774        ["chmod"; "0o755"; "/test-command"];
1775        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1776    "run a command, returning lines",
1777    "\
1778 This is the same as C<guestfs_command>, but splits the
1779 result into a list of lines.
1780
1781 See also: C<guestfs_sh_lines>");
1782
1783   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1784    [InitISOFS, Always, TestOutputStruct (
1785       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1786    "get file information",
1787    "\
1788 Returns file information for the given C<path>.
1789
1790 This is the same as the C<stat(2)> system call.");
1791
1792   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1793    [InitISOFS, Always, TestOutputStruct (
1794       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1795    "get file information for a symbolic link",
1796    "\
1797 Returns file information for the given C<path>.
1798
1799 This is the same as C<guestfs_stat> except that if C<path>
1800 is a symbolic link, then the link is stat-ed, not the file it
1801 refers to.
1802
1803 This is the same as the C<lstat(2)> system call.");
1804
1805   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1806    [InitISOFS, Always, TestOutputStruct (
1807       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1808    "get file system statistics",
1809    "\
1810 Returns file system statistics for any mounted file system.
1811 C<path> should be a file or directory in the mounted file system
1812 (typically it is the mount point itself, but it doesn't need to be).
1813
1814 This is the same as the C<statvfs(2)> system call.");
1815
1816   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1817    [], (* XXX test *)
1818    "get ext2/ext3/ext4 superblock details",
1819    "\
1820 This returns the contents of the ext2, ext3 or ext4 filesystem
1821 superblock on C<device>.
1822
1823 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1824 manpage for more details.  The list of fields returned isn't
1825 clearly defined, and depends on both the version of C<tune2fs>
1826 that libguestfs was built against, and the filesystem itself.");
1827
1828   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1829    [InitEmpty, Always, TestOutputTrue (
1830       [["blockdev_setro"; "/dev/sda"];
1831        ["blockdev_getro"; "/dev/sda"]])],
1832    "set block device to read-only",
1833    "\
1834 Sets the block device named C<device> to read-only.
1835
1836 This uses the L<blockdev(8)> command.");
1837
1838   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1839    [InitEmpty, Always, TestOutputFalse (
1840       [["blockdev_setrw"; "/dev/sda"];
1841        ["blockdev_getro"; "/dev/sda"]])],
1842    "set block device to read-write",
1843    "\
1844 Sets the block device named C<device> to read-write.
1845
1846 This uses the L<blockdev(8)> command.");
1847
1848   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1849    [InitEmpty, Always, TestOutputTrue (
1850       [["blockdev_setro"; "/dev/sda"];
1851        ["blockdev_getro"; "/dev/sda"]])],
1852    "is block device set to read-only",
1853    "\
1854 Returns a boolean indicating if the block device is read-only
1855 (true if read-only, false if not).
1856
1857 This uses the L<blockdev(8)> command.");
1858
1859   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1860    [InitEmpty, Always, TestOutputInt (
1861       [["blockdev_getss"; "/dev/sda"]], 512)],
1862    "get sectorsize of block device",
1863    "\
1864 This returns the size of sectors on a block device.
1865 Usually 512, but can be larger for modern devices.
1866
1867 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1868 for that).
1869
1870 This uses the L<blockdev(8)> command.");
1871
1872   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1873    [InitEmpty, Always, TestOutputInt (
1874       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1875    "get blocksize of block device",
1876    "\
1877 This returns the block size of a device.
1878
1879 (Note this is different from both I<size in blocks> and
1880 I<filesystem block size>).
1881
1882 This uses the L<blockdev(8)> command.");
1883
1884   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1885    [], (* XXX test *)
1886    "set blocksize of block device",
1887    "\
1888 This sets the block size of a device.
1889
1890 (Note this is different from both I<size in blocks> and
1891 I<filesystem block size>).
1892
1893 This uses the L<blockdev(8)> command.");
1894
1895   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1896    [InitEmpty, Always, TestOutputInt (
1897       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1898    "get total size of device in 512-byte sectors",
1899    "\
1900 This returns the size of the device in units of 512-byte sectors
1901 (even if the sectorsize isn't 512 bytes ... weird).
1902
1903 See also C<guestfs_blockdev_getss> for the real sector size of
1904 the device, and C<guestfs_blockdev_getsize64> for the more
1905 useful I<size in bytes>.
1906
1907 This uses the L<blockdev(8)> command.");
1908
1909   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1910    [InitEmpty, Always, TestOutputInt (
1911       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1912    "get total size of device in bytes",
1913    "\
1914 This returns the size of the device in bytes.
1915
1916 See also C<guestfs_blockdev_getsz>.
1917
1918 This uses the L<blockdev(8)> command.");
1919
1920   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1921    [InitEmpty, Always, TestRun
1922       [["blockdev_flushbufs"; "/dev/sda"]]],
1923    "flush device buffers",
1924    "\
1925 This tells the kernel to flush internal buffers associated
1926 with C<device>.
1927
1928 This uses the L<blockdev(8)> command.");
1929
1930   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1931    [InitEmpty, Always, TestRun
1932       [["blockdev_rereadpt"; "/dev/sda"]]],
1933    "reread partition table",
1934    "\
1935 Reread the partition table on C<device>.
1936
1937 This uses the L<blockdev(8)> command.");
1938
1939   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1940    [InitBasicFS, Always, TestOutput (
1941       (* Pick a file from cwd which isn't likely to change. *)
1942       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1943        ["checksum"; "md5"; "/COPYING.LIB"]],
1944       Digest.to_hex (Digest.file "COPYING.LIB"))],
1945    "upload a file from the local machine",
1946    "\
1947 Upload local file C<filename> to C<remotefilename> on the
1948 filesystem.
1949
1950 C<filename> can also be a named pipe.
1951
1952 See also C<guestfs_download>.");
1953
1954   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1955    [InitBasicFS, Always, TestOutput (
1956       (* Pick a file from cwd which isn't likely to change. *)
1957       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1958        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1959        ["upload"; "testdownload.tmp"; "/upload"];
1960        ["checksum"; "md5"; "/upload"]],
1961       Digest.to_hex (Digest.file "COPYING.LIB"))],
1962    "download a file to the local machine",
1963    "\
1964 Download file C<remotefilename> and save it as C<filename>
1965 on the local machine.
1966
1967 C<filename> can also be a named pipe.
1968
1969 See also C<guestfs_upload>, C<guestfs_cat>.");
1970
1971   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1972    [InitISOFS, Always, TestOutput (
1973       [["checksum"; "crc"; "/known-3"]], "2891671662");
1974     InitISOFS, Always, TestLastFail (
1975       [["checksum"; "crc"; "/notexists"]]);
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1978     InitISOFS, Always, TestOutput (
1979       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1980     InitISOFS, Always, TestOutput (
1981       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1982     InitISOFS, Always, TestOutput (
1983       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1984     InitISOFS, Always, TestOutput (
1985       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1986     InitISOFS, Always, TestOutput (
1987       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1988    "compute MD5, SHAx or CRC checksum of file",
1989    "\
1990 This call computes the MD5, SHAx or CRC checksum of the
1991 file named C<path>.
1992
1993 The type of checksum to compute is given by the C<csumtype>
1994 parameter which must have one of the following values:
1995
1996 =over 4
1997
1998 =item C<crc>
1999
2000 Compute the cyclic redundancy check (CRC) specified by POSIX
2001 for the C<cksum> command.
2002
2003 =item C<md5>
2004
2005 Compute the MD5 hash (using the C<md5sum> program).
2006
2007 =item C<sha1>
2008
2009 Compute the SHA1 hash (using the C<sha1sum> program).
2010
2011 =item C<sha224>
2012
2013 Compute the SHA224 hash (using the C<sha224sum> program).
2014
2015 =item C<sha256>
2016
2017 Compute the SHA256 hash (using the C<sha256sum> program).
2018
2019 =item C<sha384>
2020
2021 Compute the SHA384 hash (using the C<sha384sum> program).
2022
2023 =item C<sha512>
2024
2025 Compute the SHA512 hash (using the C<sha512sum> program).
2026
2027 =back
2028
2029 The checksum is returned as a printable string.");
2030
2031   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2032    [InitBasicFS, Always, TestOutput (
2033       [["tar_in"; "../images/helloworld.tar"; "/"];
2034        ["cat"; "/hello"]], "hello\n")],
2035    "unpack tarfile to directory",
2036    "\
2037 This command uploads and unpacks local file C<tarfile> (an
2038 I<uncompressed> tar file) into C<directory>.
2039
2040 To upload a compressed tarball, use C<guestfs_tgz_in>
2041 or C<guestfs_txz_in>.");
2042
2043   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2044    [],
2045    "pack directory into tarfile",
2046    "\
2047 This command packs the contents of C<directory> and downloads
2048 it to local file C<tarfile>.
2049
2050 To download a compressed tarball, use C<guestfs_tgz_out>
2051 or C<guestfs_txz_out>.");
2052
2053   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2054    [InitBasicFS, Always, TestOutput (
2055       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2056        ["cat"; "/hello"]], "hello\n")],
2057    "unpack compressed tarball to directory",
2058    "\
2059 This command uploads and unpacks local file C<tarball> (a
2060 I<gzip compressed> tar file) into C<directory>.
2061
2062 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2063
2064   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2065    [],
2066    "pack directory into compressed tarball",
2067    "\
2068 This command packs the contents of C<directory> and downloads
2069 it to local file C<tarball>.
2070
2071 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2072
2073   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2074    [InitBasicFS, Always, TestLastFail (
2075       [["umount"; "/"];
2076        ["mount_ro"; "/dev/sda1"; "/"];
2077        ["touch"; "/new"]]);
2078     InitBasicFS, Always, TestOutput (
2079       [["write_file"; "/new"; "data"; "0"];
2080        ["umount"; "/"];
2081        ["mount_ro"; "/dev/sda1"; "/"];
2082        ["cat"; "/new"]], "data")],
2083    "mount a guest disk, read-only",
2084    "\
2085 This is the same as the C<guestfs_mount> command, but it
2086 mounts the filesystem with the read-only (I<-o ro>) flag.");
2087
2088   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2089    [],
2090    "mount a guest disk with mount options",
2091    "\
2092 This is the same as the C<guestfs_mount> command, but it
2093 allows you to set the mount options as for the
2094 L<mount(8)> I<-o> flag.");
2095
2096   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2097    [],
2098    "mount a guest disk with mount options and vfstype",
2099    "\
2100 This is the same as the C<guestfs_mount> command, but it
2101 allows you to set both the mount options and the vfstype
2102 as for the L<mount(8)> I<-o> and I<-t> flags.");
2103
2104   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2105    [],
2106    "debugging and internals",
2107    "\
2108 The C<guestfs_debug> command exposes some internals of
2109 C<guestfsd> (the guestfs daemon) that runs inside the
2110 qemu subprocess.
2111
2112 There is no comprehensive help for this command.  You have
2113 to look at the file C<daemon/debug.c> in the libguestfs source
2114 to find out what you can do.");
2115
2116   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2117    [InitEmpty, Always, TestOutputList (
2118       [["part_disk"; "/dev/sda"; "mbr"];
2119        ["pvcreate"; "/dev/sda1"];
2120        ["vgcreate"; "VG"; "/dev/sda1"];
2121        ["lvcreate"; "LV1"; "VG"; "50"];
2122        ["lvcreate"; "LV2"; "VG"; "50"];
2123        ["lvremove"; "/dev/VG/LV1"];
2124        ["lvs"]], ["/dev/VG/LV2"]);
2125     InitEmpty, Always, TestOutputList (
2126       [["part_disk"; "/dev/sda"; "mbr"];
2127        ["pvcreate"; "/dev/sda1"];
2128        ["vgcreate"; "VG"; "/dev/sda1"];
2129        ["lvcreate"; "LV1"; "VG"; "50"];
2130        ["lvcreate"; "LV2"; "VG"; "50"];
2131        ["lvremove"; "/dev/VG"];
2132        ["lvs"]], []);
2133     InitEmpty, Always, TestOutputList (
2134       [["part_disk"; "/dev/sda"; "mbr"];
2135        ["pvcreate"; "/dev/sda1"];
2136        ["vgcreate"; "VG"; "/dev/sda1"];
2137        ["lvcreate"; "LV1"; "VG"; "50"];
2138        ["lvcreate"; "LV2"; "VG"; "50"];
2139        ["lvremove"; "/dev/VG"];
2140        ["vgs"]], ["VG"])],
2141    "remove an LVM logical volume",
2142    "\
2143 Remove an LVM logical volume C<device>, where C<device> is
2144 the path to the LV, such as C</dev/VG/LV>.
2145
2146 You can also remove all LVs in a volume group by specifying
2147 the VG name, C</dev/VG>.");
2148
2149   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2150    [InitEmpty, Always, TestOutputList (
2151       [["part_disk"; "/dev/sda"; "mbr"];
2152        ["pvcreate"; "/dev/sda1"];
2153        ["vgcreate"; "VG"; "/dev/sda1"];
2154        ["lvcreate"; "LV1"; "VG"; "50"];
2155        ["lvcreate"; "LV2"; "VG"; "50"];
2156        ["vgremove"; "VG"];
2157        ["lvs"]], []);
2158     InitEmpty, Always, TestOutputList (
2159       [["part_disk"; "/dev/sda"; "mbr"];
2160        ["pvcreate"; "/dev/sda1"];
2161        ["vgcreate"; "VG"; "/dev/sda1"];
2162        ["lvcreate"; "LV1"; "VG"; "50"];
2163        ["lvcreate"; "LV2"; "VG"; "50"];
2164        ["vgremove"; "VG"];
2165        ["vgs"]], [])],
2166    "remove an LVM volume group",
2167    "\
2168 Remove an LVM volume group C<vgname>, (for example C<VG>).
2169
2170 This also forcibly removes all logical volumes in the volume
2171 group (if any).");
2172
2173   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2174    [InitEmpty, Always, TestOutputListOfDevices (
2175       [["part_disk"; "/dev/sda"; "mbr"];
2176        ["pvcreate"; "/dev/sda1"];
2177        ["vgcreate"; "VG"; "/dev/sda1"];
2178        ["lvcreate"; "LV1"; "VG"; "50"];
2179        ["lvcreate"; "LV2"; "VG"; "50"];
2180        ["vgremove"; "VG"];
2181        ["pvremove"; "/dev/sda1"];
2182        ["lvs"]], []);
2183     InitEmpty, Always, TestOutputListOfDevices (
2184       [["part_disk"; "/dev/sda"; "mbr"];
2185        ["pvcreate"; "/dev/sda1"];
2186        ["vgcreate"; "VG"; "/dev/sda1"];
2187        ["lvcreate"; "LV1"; "VG"; "50"];
2188        ["lvcreate"; "LV2"; "VG"; "50"];
2189        ["vgremove"; "VG"];
2190        ["pvremove"; "/dev/sda1"];
2191        ["vgs"]], []);
2192     InitEmpty, Always, TestOutputListOfDevices (
2193       [["part_disk"; "/dev/sda"; "mbr"];
2194        ["pvcreate"; "/dev/sda1"];
2195        ["vgcreate"; "VG"; "/dev/sda1"];
2196        ["lvcreate"; "LV1"; "VG"; "50"];
2197        ["lvcreate"; "LV2"; "VG"; "50"];
2198        ["vgremove"; "VG"];
2199        ["pvremove"; "/dev/sda1"];
2200        ["pvs"]], [])],
2201    "remove an LVM physical volume",
2202    "\
2203 This wipes a physical volume C<device> so that LVM will no longer
2204 recognise it.
2205
2206 The implementation uses the C<pvremove> command which refuses to
2207 wipe physical volumes that contain any volume groups, so you have
2208 to remove those first.");
2209
2210   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2211    [InitBasicFS, Always, TestOutput (
2212       [["set_e2label"; "/dev/sda1"; "testlabel"];
2213        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2214    "set the ext2/3/4 filesystem label",
2215    "\
2216 This sets the ext2/3/4 filesystem label of the filesystem on
2217 C<device> to C<label>.  Filesystem labels are limited to
2218 16 characters.
2219
2220 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2221 to return the existing label on a filesystem.");
2222
2223   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2224    [],
2225    "get the ext2/3/4 filesystem label",
2226    "\
2227 This returns the ext2/3/4 filesystem label of the filesystem on
2228 C<device>.");
2229
2230   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2231    (let uuid = uuidgen () in
2232     [InitBasicFS, Always, TestOutput (
2233        [["set_e2uuid"; "/dev/sda1"; uuid];
2234         ["get_e2uuid"; "/dev/sda1"]], uuid);
2235      InitBasicFS, Always, TestOutput (
2236        [["set_e2uuid"; "/dev/sda1"; "clear"];
2237         ["get_e2uuid"; "/dev/sda1"]], "");
2238      (* We can't predict what UUIDs will be, so just check the commands run. *)
2239      InitBasicFS, Always, TestRun (
2240        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2241      InitBasicFS, Always, TestRun (
2242        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2243    "set the ext2/3/4 filesystem UUID",
2244    "\
2245 This sets the ext2/3/4 filesystem UUID of the filesystem on
2246 C<device> to C<uuid>.  The format of the UUID and alternatives
2247 such as C<clear>, C<random> and C<time> are described in the
2248 L<tune2fs(8)> manpage.
2249
2250 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2251 to return the existing UUID of a filesystem.");
2252
2253   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2254    [],
2255    "get the ext2/3/4 filesystem UUID",
2256    "\
2257 This returns the ext2/3/4 filesystem UUID of the filesystem on
2258 C<device>.");
2259
2260   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2261    [InitBasicFS, Always, TestOutputInt (
2262       [["umount"; "/dev/sda1"];
2263        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2264     InitBasicFS, Always, TestOutputInt (
2265       [["umount"; "/dev/sda1"];
2266        ["zero"; "/dev/sda1"];
2267        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2268    "run the filesystem checker",
2269    "\
2270 This runs the filesystem checker (fsck) on C<device> which
2271 should have filesystem type C<fstype>.
2272
2273 The returned integer is the status.  See L<fsck(8)> for the
2274 list of status codes from C<fsck>.
2275
2276 Notes:
2277
2278 =over 4
2279
2280 =item *
2281
2282 Multiple status codes can be summed together.
2283
2284 =item *
2285
2286 A non-zero return code can mean \"success\", for example if
2287 errors have been corrected on the filesystem.
2288
2289 =item *
2290
2291 Checking or repairing NTFS volumes is not supported
2292 (by linux-ntfs).
2293
2294 =back
2295
2296 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2297
2298   ("zero", (RErr, [Device "device"]), 85, [],
2299    [InitBasicFS, Always, TestOutput (
2300       [["umount"; "/dev/sda1"];
2301        ["zero"; "/dev/sda1"];
2302        ["file"; "/dev/sda1"]], "data")],
2303    "write zeroes to the device",
2304    "\
2305 This command writes zeroes over the first few blocks of C<device>.
2306
2307 How many blocks are zeroed isn't specified (but it's I<not> enough
2308 to securely wipe the device).  It should be sufficient to remove
2309 any partition tables, filesystem superblocks and so on.
2310
2311 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2312
2313   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2314    (* Test disabled because grub-install incompatible with virtio-blk driver.
2315     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2316     *)
2317    [InitBasicFS, Disabled, TestOutputTrue (
2318       [["grub_install"; "/"; "/dev/sda1"];
2319        ["is_dir"; "/boot"]])],
2320    "install GRUB",
2321    "\
2322 This command installs GRUB (the Grand Unified Bootloader) on
2323 C<device>, with the root directory being C<root>.");
2324
2325   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2326    [InitBasicFS, Always, TestOutput (
2327       [["write_file"; "/old"; "file content"; "0"];
2328        ["cp"; "/old"; "/new"];
2329        ["cat"; "/new"]], "file content");
2330     InitBasicFS, Always, TestOutputTrue (
2331       [["write_file"; "/old"; "file content"; "0"];
2332        ["cp"; "/old"; "/new"];
2333        ["is_file"; "/old"]]);
2334     InitBasicFS, Always, TestOutput (
2335       [["write_file"; "/old"; "file content"; "0"];
2336        ["mkdir"; "/dir"];
2337        ["cp"; "/old"; "/dir/new"];
2338        ["cat"; "/dir/new"]], "file content")],
2339    "copy a file",
2340    "\
2341 This copies a file from C<src> to C<dest> where C<dest> is
2342 either a destination filename or destination directory.");
2343
2344   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2345    [InitBasicFS, Always, TestOutput (
2346       [["mkdir"; "/olddir"];
2347        ["mkdir"; "/newdir"];
2348        ["write_file"; "/olddir/file"; "file content"; "0"];
2349        ["cp_a"; "/olddir"; "/newdir"];
2350        ["cat"; "/newdir/olddir/file"]], "file content")],
2351    "copy a file or directory recursively",
2352    "\
2353 This copies a file or directory from C<src> to C<dest>
2354 recursively using the C<cp -a> command.");
2355
2356   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2357    [InitBasicFS, Always, TestOutput (
2358       [["write_file"; "/old"; "file content"; "0"];
2359        ["mv"; "/old"; "/new"];
2360        ["cat"; "/new"]], "file content");
2361     InitBasicFS, Always, TestOutputFalse (
2362       [["write_file"; "/old"; "file content"; "0"];
2363        ["mv"; "/old"; "/new"];
2364        ["is_file"; "/old"]])],
2365    "move a file",
2366    "\
2367 This moves a file from C<src> to C<dest> where C<dest> is
2368 either a destination filename or destination directory.");
2369
2370   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2371    [InitEmpty, Always, TestRun (
2372       [["drop_caches"; "3"]])],
2373    "drop kernel page cache, dentries and inodes",
2374    "\
2375 This instructs the guest kernel to drop its page cache,
2376 and/or dentries and inode caches.  The parameter C<whattodrop>
2377 tells the kernel what precisely to drop, see
2378 L<http://linux-mm.org/Drop_Caches>
2379
2380 Setting C<whattodrop> to 3 should drop everything.
2381
2382 This automatically calls L<sync(2)> before the operation,
2383 so that the maximum guest memory is freed.");
2384
2385   ("dmesg", (RString "kmsgs", []), 91, [],
2386    [InitEmpty, Always, TestRun (
2387       [["dmesg"]])],
2388    "return kernel messages",
2389    "\
2390 This returns the kernel messages (C<dmesg> output) from
2391 the guest kernel.  This is sometimes useful for extended
2392 debugging of problems.
2393
2394 Another way to get the same information is to enable
2395 verbose messages with C<guestfs_set_verbose> or by setting
2396 the environment variable C<LIBGUESTFS_DEBUG=1> before
2397 running the program.");
2398
2399   ("ping_daemon", (RErr, []), 92, [],
2400    [InitEmpty, Always, TestRun (
2401       [["ping_daemon"]])],
2402    "ping the guest daemon",
2403    "\
2404 This is a test probe into the guestfs daemon running inside
2405 the qemu subprocess.  Calling this function checks that the
2406 daemon responds to the ping message, without affecting the daemon
2407 or attached block device(s) in any other way.");
2408
2409   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2410    [InitBasicFS, Always, TestOutputTrue (
2411       [["write_file"; "/file1"; "contents of a file"; "0"];
2412        ["cp"; "/file1"; "/file2"];
2413        ["equal"; "/file1"; "/file2"]]);
2414     InitBasicFS, Always, TestOutputFalse (
2415       [["write_file"; "/file1"; "contents of a file"; "0"];
2416        ["write_file"; "/file2"; "contents of another file"; "0"];
2417        ["equal"; "/file1"; "/file2"]]);
2418     InitBasicFS, Always, TestLastFail (
2419       [["equal"; "/file1"; "/file2"]])],
2420    "test if two files have equal contents",
2421    "\
2422 This compares the two files C<file1> and C<file2> and returns
2423 true if their content is exactly equal, or false otherwise.
2424
2425 The external L<cmp(1)> program is used for the comparison.");
2426
2427   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2428    [InitISOFS, Always, TestOutputList (
2429       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2430     InitISOFS, Always, TestOutputList (
2431       [["strings"; "/empty"]], [])],
2432    "print the printable strings in a file",
2433    "\
2434 This runs the L<strings(1)> command on a file and returns
2435 the list of printable strings found.");
2436
2437   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2438    [InitISOFS, Always, TestOutputList (
2439       [["strings_e"; "b"; "/known-5"]], []);
2440     InitBasicFS, Disabled, TestOutputList (
2441       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2442        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2443    "print the printable strings in a file",
2444    "\
2445 This is like the C<guestfs_strings> command, but allows you to
2446 specify the encoding.
2447
2448 See the L<strings(1)> manpage for the full list of encodings.
2449
2450 Commonly useful encodings are C<l> (lower case L) which will
2451 show strings inside Windows/x86 files.
2452
2453 The returned strings are transcoded to UTF-8.");
2454
2455   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2456    [InitISOFS, Always, TestOutput (
2457       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2458     (* Test for RHBZ#501888c2 regression which caused large hexdump
2459      * commands to segfault.
2460      *)
2461     InitISOFS, Always, TestRun (
2462       [["hexdump"; "/100krandom"]])],
2463    "dump a file in hexadecimal",
2464    "\
2465 This runs C<hexdump -C> on the given C<path>.  The result is
2466 the human-readable, canonical hex dump of the file.");
2467
2468   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2469    [InitNone, Always, TestOutput (
2470       [["part_disk"; "/dev/sda"; "mbr"];
2471        ["mkfs"; "ext3"; "/dev/sda1"];
2472        ["mount_options"; ""; "/dev/sda1"; "/"];
2473        ["write_file"; "/new"; "test file"; "0"];
2474        ["umount"; "/dev/sda1"];
2475        ["zerofree"; "/dev/sda1"];
2476        ["mount_options"; ""; "/dev/sda1"; "/"];
2477        ["cat"; "/new"]], "test file")],
2478    "zero unused inodes and disk blocks on ext2/3 filesystem",
2479    "\
2480 This runs the I<zerofree> program on C<device>.  This program
2481 claims to zero unused inodes and disk blocks on an ext2/3
2482 filesystem, thus making it possible to compress the filesystem
2483 more effectively.
2484
2485 You should B<not> run this program if the filesystem is
2486 mounted.
2487
2488 It is possible that using this program can damage the filesystem
2489 or data on the filesystem.");
2490
2491   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2492    [],
2493    "resize an LVM physical volume",
2494    "\
2495 This resizes (expands or shrinks) an existing LVM physical
2496 volume to match the new size of the underlying device.");
2497
2498   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2499                        Int "cyls"; Int "heads"; Int "sectors";
2500                        String "line"]), 99, [DangerWillRobinson],
2501    [],
2502    "modify a single partition on a block device",
2503    "\
2504 This runs L<sfdisk(8)> option to modify just the single
2505 partition C<n> (note: C<n> counts from 1).
2506
2507 For other parameters, see C<guestfs_sfdisk>.  You should usually
2508 pass C<0> for the cyls/heads/sectors parameters.
2509
2510 See also: C<guestfs_part_add>");
2511
2512   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2513    [],
2514    "display the partition table",
2515    "\
2516 This displays the partition table on C<device>, in the
2517 human-readable output of the L<sfdisk(8)> command.  It is
2518 not intended to be parsed.
2519
2520 See also: C<guestfs_part_list>");
2521
2522   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2523    [],
2524    "display the kernel geometry",
2525    "\
2526 This displays the kernel's idea of the geometry of C<device>.
2527
2528 The result is in human-readable format, and not designed to
2529 be parsed.");
2530
2531   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2532    [],
2533    "display the disk geometry from the partition table",
2534    "\
2535 This displays the disk geometry of C<device> read from the
2536 partition table.  Especially in the case where the underlying
2537 block device has been resized, this can be different from the
2538 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2539
2540 The result is in human-readable format, and not designed to
2541 be parsed.");
2542
2543   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2544    [],
2545    "activate or deactivate all volume groups",
2546    "\
2547 This command activates or (if C<activate> is false) deactivates
2548 all logical volumes in all volume groups.
2549 If activated, then they are made known to the
2550 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2551 then those devices disappear.
2552
2553 This command is the same as running C<vgchange -a y|n>");
2554
2555   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2556    [],
2557    "activate or deactivate some volume groups",
2558    "\
2559 This command activates or (if C<activate> is false) deactivates
2560 all logical volumes in the listed volume groups C<volgroups>.
2561 If activated, then they are made known to the
2562 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2563 then those devices disappear.
2564
2565 This command is the same as running C<vgchange -a y|n volgroups...>
2566
2567 Note that if C<volgroups> is an empty list then B<all> volume groups
2568 are activated or deactivated.");
2569
2570   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2571    [InitNone, Always, TestOutput (
2572       [["part_disk"; "/dev/sda"; "mbr"];
2573        ["pvcreate"; "/dev/sda1"];
2574        ["vgcreate"; "VG"; "/dev/sda1"];
2575        ["lvcreate"; "LV"; "VG"; "10"];
2576        ["mkfs"; "ext2"; "/dev/VG/LV"];
2577        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2578        ["write_file"; "/new"; "test content"; "0"];
2579        ["umount"; "/"];
2580        ["lvresize"; "/dev/VG/LV"; "20"];
2581        ["e2fsck_f"; "/dev/VG/LV"];
2582        ["resize2fs"; "/dev/VG/LV"];
2583        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2584        ["cat"; "/new"]], "test content")],
2585    "resize an LVM logical volume",
2586    "\
2587 This resizes (expands or shrinks) an existing LVM logical
2588 volume to C<mbytes>.  When reducing, data in the reduced part
2589 is lost.");
2590
2591   ("resize2fs", (RErr, [Device "device"]), 106, [],
2592    [], (* lvresize tests this *)
2593    "resize an ext2/ext3 filesystem",
2594    "\
2595 This resizes an ext2 or ext3 filesystem to match the size of
2596 the underlying device.
2597
2598 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2599 on the C<device> before calling this command.  For unknown reasons
2600 C<resize2fs> sometimes gives an error about this and sometimes not.
2601 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2602 calling this function.");
2603
2604   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2605    [InitBasicFS, Always, TestOutputList (
2606       [["find"; "/"]], ["lost+found"]);
2607     InitBasicFS, Always, TestOutputList (
2608       [["touch"; "/a"];
2609        ["mkdir"; "/b"];
2610        ["touch"; "/b/c"];
2611        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2612     InitBasicFS, Always, TestOutputList (
2613       [["mkdir_p"; "/a/b/c"];
2614        ["touch"; "/a/b/c/d"];
2615        ["find"; "/a/b/"]], ["c"; "c/d"])],
2616    "find all files and directories",
2617    "\
2618 This command lists out all files and directories, recursively,
2619 starting at C<directory>.  It is essentially equivalent to
2620 running the shell command C<find directory -print> but some
2621 post-processing happens on the output, described below.
2622
2623 This returns a list of strings I<without any prefix>.  Thus
2624 if the directory structure was:
2625
2626  /tmp/a
2627  /tmp/b
2628  /tmp/c/d
2629
2630 then the returned list from C<guestfs_find> C</tmp> would be
2631 4 elements:
2632
2633  a
2634  b
2635  c
2636  c/d
2637
2638 If C<directory> is not a directory, then this command returns
2639 an error.
2640
2641 The returned list is sorted.
2642
2643 See also C<guestfs_find0>.");
2644
2645   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2646    [], (* lvresize tests this *)
2647    "check an ext2/ext3 filesystem",
2648    "\
2649 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2650 filesystem checker on C<device>, noninteractively (C<-p>),
2651 even if the filesystem appears to be clean (C<-f>).
2652
2653 This command is only needed because of C<guestfs_resize2fs>
2654 (q.v.).  Normally you should use C<guestfs_fsck>.");
2655
2656   ("sleep", (RErr, [Int "secs"]), 109, [],
2657    [InitNone, Always, TestRun (
2658       [["sleep"; "1"]])],
2659    "sleep for some seconds",
2660    "\
2661 Sleep for C<secs> seconds.");
2662
2663   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2664    [InitNone, Always, TestOutputInt (
2665       [["part_disk"; "/dev/sda"; "mbr"];
2666        ["mkfs"; "ntfs"; "/dev/sda1"];
2667        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2668     InitNone, Always, TestOutputInt (
2669       [["part_disk"; "/dev/sda"; "mbr"];
2670        ["mkfs"; "ext2"; "/dev/sda1"];
2671        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2672    "probe NTFS volume",
2673    "\
2674 This command runs the L<ntfs-3g.probe(8)> command which probes
2675 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2676 be mounted read-write, and some cannot be mounted at all).
2677
2678 C<rw> is a boolean flag.  Set it to true if you want to test
2679 if the volume can be mounted read-write.  Set it to false if
2680 you want to test if the volume can be mounted read-only.
2681
2682 The return value is an integer which C<0> if the operation
2683 would succeed, or some non-zero value documented in the
2684 L<ntfs-3g.probe(8)> manual page.");
2685
2686   ("sh", (RString "output", [String "command"]), 111, [],
2687    [], (* XXX needs tests *)
2688    "run a command via the shell",
2689    "\
2690 This call runs a command from the guest filesystem via the
2691 guest's C</bin/sh>.
2692
2693 This is like C<guestfs_command>, but passes the command to:
2694
2695  /bin/sh -c \"command\"
2696
2697 Depending on the guest's shell, this usually results in
2698 wildcards being expanded, shell expressions being interpolated
2699 and so on.
2700
2701 All the provisos about C<guestfs_command> apply to this call.");
2702
2703   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2704    [], (* XXX needs tests *)
2705    "run a command via the shell returning lines",
2706    "\
2707 This is the same as C<guestfs_sh>, but splits the result
2708 into a list of lines.
2709
2710 See also: C<guestfs_command_lines>");
2711
2712   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2713    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2714     * code in stubs.c, since all valid glob patterns must start with "/".
2715     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2716     *)
2717    [InitBasicFS, Always, TestOutputList (
2718       [["mkdir_p"; "/a/b/c"];
2719        ["touch"; "/a/b/c/d"];
2720        ["touch"; "/a/b/c/e"];
2721        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2722     InitBasicFS, Always, TestOutputList (
2723       [["mkdir_p"; "/a/b/c"];
2724        ["touch"; "/a/b/c/d"];
2725        ["touch"; "/a/b/c/e"];
2726        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2727     InitBasicFS, Always, TestOutputList (
2728       [["mkdir_p"; "/a/b/c"];
2729        ["touch"; "/a/b/c/d"];
2730        ["touch"; "/a/b/c/e"];
2731        ["glob_expand"; "/a/*/x/*"]], [])],
2732    "expand a wildcard path",
2733    "\
2734 This command searches for all the pathnames matching
2735 C<pattern> according to the wildcard expansion rules
2736 used by the shell.
2737
2738 If no paths match, then this returns an empty list
2739 (note: not an error).
2740
2741 It is just a wrapper around the C L<glob(3)> function
2742 with flags C<GLOB_MARK|GLOB_BRACE>.
2743 See that manual page for more details.");
2744
2745   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2746    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2747       [["scrub_device"; "/dev/sdc"]])],
2748    "scrub (securely wipe) a device",
2749    "\
2750 This command writes patterns over C<device> to make data retrieval
2751 more difficult.
2752
2753 It is an interface to the L<scrub(1)> program.  See that
2754 manual page for more details.");
2755
2756   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2757    [InitBasicFS, Always, TestRun (
2758       [["write_file"; "/file"; "content"; "0"];
2759        ["scrub_file"; "/file"]])],
2760    "scrub (securely wipe) a file",
2761    "\
2762 This command writes patterns over a file to make data retrieval
2763 more difficult.
2764
2765 The file is I<removed> after scrubbing.
2766
2767 It is an interface to the L<scrub(1)> program.  See that
2768 manual page for more details.");
2769
2770   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2771    [], (* XXX needs testing *)
2772    "scrub (securely wipe) free space",
2773    "\
2774 This command creates the directory C<dir> and then fills it
2775 with files until the filesystem is full, and scrubs the files
2776 as for C<guestfs_scrub_file>, and deletes them.
2777 The intention is to scrub any free space on the partition
2778 containing C<dir>.
2779
2780 It is an interface to the L<scrub(1)> program.  See that
2781 manual page for more details.");
2782
2783   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2784    [InitBasicFS, Always, TestRun (
2785       [["mkdir"; "/tmp"];
2786        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2787    "create a temporary directory",
2788    "\
2789 This command creates a temporary directory.  The
2790 C<template> parameter should be a full pathname for the
2791 temporary directory name with the final six characters being
2792 \"XXXXXX\".
2793
2794 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2795 the second one being suitable for Windows filesystems.
2796
2797 The name of the temporary directory that was created
2798 is returned.
2799
2800 The temporary directory is created with mode 0700
2801 and is owned by root.
2802
2803 The caller is responsible for deleting the temporary
2804 directory and its contents after use.
2805
2806 See also: L<mkdtemp(3)>");
2807
2808   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2809    [InitISOFS, Always, TestOutputInt (
2810       [["wc_l"; "/10klines"]], 10000)],
2811    "count lines in a file",
2812    "\
2813 This command counts the lines in a file, using the
2814 C<wc -l> external command.");
2815
2816   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2817    [InitISOFS, Always, TestOutputInt (
2818       [["wc_w"; "/10klines"]], 10000)],
2819    "count words in a file",
2820    "\
2821 This command counts the words in a file, using the
2822 C<wc -w> external command.");
2823
2824   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2825    [InitISOFS, Always, TestOutputInt (
2826       [["wc_c"; "/100kallspaces"]], 102400)],
2827    "count characters in a file",
2828    "\
2829 This command counts the characters in a file, using the
2830 C<wc -c> external command.");
2831
2832   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2833    [InitISOFS, Always, TestOutputList (
2834       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2835    "return first 10 lines of a file",
2836    "\
2837 This command returns up to the first 10 lines of a file as
2838 a list of strings.");
2839
2840   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2841    [InitISOFS, Always, TestOutputList (
2842       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2843     InitISOFS, Always, TestOutputList (
2844       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2845     InitISOFS, Always, TestOutputList (
2846       [["head_n"; "0"; "/10klines"]], [])],
2847    "return first N lines of a file",
2848    "\
2849 If the parameter C<nrlines> is a positive number, this returns the first
2850 C<nrlines> lines of the file C<path>.
2851
2852 If the parameter C<nrlines> is a negative number, this returns lines
2853 from the file C<path>, excluding the last C<nrlines> lines.
2854
2855 If the parameter C<nrlines> is zero, this returns an empty list.");
2856
2857   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2858    [InitISOFS, Always, TestOutputList (
2859       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2860    "return last 10 lines of a file",
2861    "\
2862 This command returns up to the last 10 lines of a file as
2863 a list of strings.");
2864
2865   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2866    [InitISOFS, Always, TestOutputList (
2867       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2868     InitISOFS, Always, TestOutputList (
2869       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2870     InitISOFS, Always, TestOutputList (
2871       [["tail_n"; "0"; "/10klines"]], [])],
2872    "return last N lines of a file",
2873    "\
2874 If the parameter C<nrlines> is a positive number, this returns the last
2875 C<nrlines> lines of the file C<path>.
2876
2877 If the parameter C<nrlines> is a negative number, this returns lines
2878 from the file C<path>, starting with the C<-nrlines>th line.
2879
2880 If the parameter C<nrlines> is zero, this returns an empty list.");
2881
2882   ("df", (RString "output", []), 125, [],
2883    [], (* XXX Tricky to test because it depends on the exact format
2884         * of the 'df' command and other imponderables.
2885         *)
2886    "report file system disk space usage",
2887    "\
2888 This command runs the C<df> command to report disk space used.
2889
2890 This command is mostly useful for interactive sessions.  It
2891 is I<not> intended that you try to parse the output string.
2892 Use C<statvfs> from programs.");
2893
2894   ("df_h", (RString "output", []), 126, [],
2895    [], (* XXX Tricky to test because it depends on the exact format
2896         * of the 'df' command and other imponderables.
2897         *)
2898    "report file system disk space usage (human readable)",
2899    "\
2900 This command runs the C<df -h> command to report disk space used
2901 in human-readable format.
2902
2903 This command is mostly useful for interactive sessions.  It
2904 is I<not> intended that you try to parse the output string.
2905 Use C<statvfs> from programs.");
2906
2907   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2908    [InitISOFS, Always, TestOutputInt (
2909       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2910    "estimate file space usage",
2911    "\
2912 This command runs the C<du -s> command to estimate file space
2913 usage for C<path>.
2914
2915 C<path> can be a file or a directory.  If C<path> is a directory
2916 then the estimate includes the contents of the directory and all
2917 subdirectories (recursively).
2918
2919 The result is the estimated size in I<kilobytes>
2920 (ie. units of 1024 bytes).");
2921
2922   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2923    [InitISOFS, Always, TestOutputList (
2924       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2925    "list files in an initrd",
2926    "\
2927 This command lists out files contained in an initrd.
2928
2929 The files are listed without any initial C</> character.  The
2930 files are listed in the order they appear (not necessarily
2931 alphabetical).  Directory names are listed as separate items.
2932
2933 Old Linux kernels (2.4 and earlier) used a compressed ext2
2934 filesystem as initrd.  We I<only> support the newer initramfs
2935 format (compressed cpio files).");
2936
2937   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2938    [],
2939    "mount a file using the loop device",
2940    "\
2941 This command lets you mount C<file> (a filesystem image
2942 in a file) on a mount point.  It is entirely equivalent to
2943 the command C<mount -o loop file mountpoint>.");
2944
2945   ("mkswap", (RErr, [Device "device"]), 130, [],
2946    [InitEmpty, Always, TestRun (
2947       [["part_disk"; "/dev/sda"; "mbr"];
2948        ["mkswap"; "/dev/sda1"]])],
2949    "create a swap partition",
2950    "\
2951 Create a swap partition on C<device>.");
2952
2953   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2954    [InitEmpty, Always, TestRun (
2955       [["part_disk"; "/dev/sda"; "mbr"];
2956        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2957    "create a swap partition with a label",
2958    "\
2959 Create a swap partition on C<device> with label C<label>.
2960
2961 Note that you cannot attach a swap label to a block device
2962 (eg. C</dev/sda>), just to a partition.  This appears to be
2963 a limitation of the kernel or swap tools.");
2964
2965   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2966    (let uuid = uuidgen () in
2967     [InitEmpty, Always, TestRun (
2968        [["part_disk"; "/dev/sda"; "mbr"];
2969         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2970    "create a swap partition with an explicit UUID",
2971    "\
2972 Create a swap partition on C<device> with UUID C<uuid>.");
2973
2974   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2975    [InitBasicFS, Always, TestOutputStruct (
2976       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2977        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2978        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2979     InitBasicFS, Always, TestOutputStruct (
2980       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2981        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2982    "make block, character or FIFO devices",
2983    "\
2984 This call creates block or character special devices, or
2985 named pipes (FIFOs).
2986
2987 The C<mode> parameter should be the mode, using the standard
2988 constants.  C<devmajor> and C<devminor> are the
2989 device major and minor numbers, only used when creating block
2990 and character special devices.
2991
2992 Note that, just like L<mknod(2)>, the mode must be bitwise
2993 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
2994 just creates a regular file).  These constants are
2995 available in the standard Linux header files, or you can use
2996 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
2997 which are wrappers around this command which bitwise OR
2998 in the appropriate constant for you.
2999
3000 The mode actually set is affected by the umask.");
3001
3002   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3003    [InitBasicFS, Always, TestOutputStruct (
3004       [["mkfifo"; "0o777"; "/node"];
3005        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3006    "make FIFO (named pipe)",
3007    "\
3008 This call creates a FIFO (named pipe) called C<path> with
3009 mode C<mode>.  It is just a convenient wrapper around
3010 C<guestfs_mknod>.
3011
3012 The mode actually set is affected by the umask.");
3013
3014   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3015    [InitBasicFS, Always, TestOutputStruct (
3016       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3017        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3018    "make block device node",
3019    "\
3020 This call creates a block device node called C<path> with
3021 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3022 It is just a convenient wrapper around C<guestfs_mknod>.
3023
3024 The mode actually set is affected by the umask.");
3025
3026   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3027    [InitBasicFS, Always, TestOutputStruct (
3028       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3029        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3030    "make char device node",
3031    "\
3032 This call creates a char device node called C<path> with
3033 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3034 It is just a convenient wrapper around C<guestfs_mknod>.
3035
3036 The mode actually set is affected by the umask.");
3037
3038   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3039    [InitEmpty, Always, TestOutputInt (
3040       [["umask"; "0o22"]], 0o22)],
3041    "set file mode creation mask (umask)",
3042    "\
3043 This function sets the mask used for creating new files and
3044 device nodes to C<mask & 0777>.
3045
3046 Typical umask values would be C<022> which creates new files
3047 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3048 C<002> which creates new files with permissions like
3049 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3050
3051 The default umask is C<022>.  This is important because it
3052 means that directories and device nodes will be created with
3053 C<0644> or C<0755> mode even if you specify C<0777>.
3054
3055 See also C<guestfs_get_umask>,
3056 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3057
3058 This call returns the previous umask.");
3059
3060   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3061    [],
3062    "read directories entries",
3063    "\
3064 This returns the list of directory entries in directory C<dir>.
3065
3066 All entries in the directory are returned, including C<.> and
3067 C<..>.  The entries are I<not> sorted, but returned in the same
3068 order as the underlying filesystem.
3069
3070 Also this call returns basic file type information about each
3071 file.  The C<ftyp> field will contain one of the following characters:
3072
3073 =over 4
3074
3075 =item 'b'
3076
3077 Block special
3078
3079 =item 'c'
3080
3081 Char special
3082
3083 =item 'd'
3084
3085 Directory
3086
3087 =item 'f'
3088
3089 FIFO (named pipe)
3090
3091 =item 'l'
3092
3093 Symbolic link
3094
3095 =item 'r'
3096
3097 Regular file
3098
3099 =item 's'
3100
3101 Socket
3102
3103 =item 'u'
3104
3105 Unknown file type
3106
3107 =item '?'
3108
3109 The L<readdir(3)> returned a C<d_type> field with an
3110 unexpected value
3111
3112 =back
3113
3114 This function is primarily intended for use by programs.  To
3115 get a simple list of names, use C<guestfs_ls>.  To get a printable
3116 directory for human consumption, use C<guestfs_ll>.");
3117
3118   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3119    [],
3120    "create partitions on a block device",
3121    "\
3122 This is a simplified interface to the C<guestfs_sfdisk>
3123 command, where partition sizes are specified in megabytes
3124 only (rounded to the nearest cylinder) and you don't need
3125 to specify the cyls, heads and sectors parameters which
3126 were rarely if ever used anyway.
3127
3128 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3129 and C<guestfs_part_disk>");
3130
3131   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3132    [],
3133    "determine file type inside a compressed file",
3134    "\
3135 This command runs C<file> after first decompressing C<path>
3136 using C<method>.
3137
3138 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3139
3140 Since 1.0.63, use C<guestfs_file> instead which can now
3141 process compressed files.");
3142
3143   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3144    [],
3145    "list extended attributes of a file or directory",
3146    "\
3147 This call lists the extended attributes of the file or directory
3148 C<path>.
3149
3150 At the system call level, this is a combination of the
3151 L<listxattr(2)> and L<getxattr(2)> calls.
3152
3153 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3154
3155   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3156    [],
3157    "list extended attributes of a file or directory",
3158    "\
3159 This is the same as C<guestfs_getxattrs>, but if C<path>
3160 is a symbolic link, then it returns the extended attributes
3161 of the link itself.");
3162
3163   ("setxattr", (RErr, [String "xattr";
3164                        String "val"; Int "vallen"; (* will be BufferIn *)
3165                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3166    [],
3167    "set extended attribute of a file or directory",
3168    "\
3169 This call sets the extended attribute named C<xattr>
3170 of the file C<path> to the value C<val> (of length C<vallen>).
3171 The value is arbitrary 8 bit data.
3172
3173 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3174
3175   ("lsetxattr", (RErr, [String "xattr";
3176                         String "val"; Int "vallen"; (* will be BufferIn *)
3177                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3178    [],
3179    "set extended attribute of a file or directory",
3180    "\
3181 This is the same as C<guestfs_setxattr>, but if C<path>
3182 is a symbolic link, then it sets an extended attribute
3183 of the link itself.");
3184
3185   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3186    [],
3187    "remove extended attribute of a file or directory",
3188    "\
3189 This call removes the extended attribute named C<xattr>
3190 of the file C<path>.
3191
3192 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3193
3194   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3195    [],
3196    "remove extended attribute of a file or directory",
3197    "\
3198 This is the same as C<guestfs_removexattr>, but if C<path>
3199 is a symbolic link, then it removes an extended attribute
3200 of the link itself.");
3201
3202   ("mountpoints", (RHashtable "mps", []), 147, [],
3203    [],
3204    "show mountpoints",
3205    "\
3206 This call is similar to C<guestfs_mounts>.  That call returns
3207 a list of devices.  This one returns a hash table (map) of
3208 device name to directory where the device is mounted.");
3209
3210   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3211    (* This is a special case: while you would expect a parameter
3212     * of type "Pathname", that doesn't work, because it implies
3213     * NEED_ROOT in the generated calling code in stubs.c, and
3214     * this function cannot use NEED_ROOT.
3215     *)
3216    [],
3217    "create a mountpoint",
3218    "\
3219 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3220 specialized calls that can be used to create extra mountpoints
3221 before mounting the first filesystem.
3222
3223 These calls are I<only> necessary in some very limited circumstances,
3224 mainly the case where you want to mount a mix of unrelated and/or
3225 read-only filesystems together.
3226
3227 For example, live CDs often contain a \"Russian doll\" nest of
3228 filesystems, an ISO outer layer, with a squashfs image inside, with
3229 an ext2/3 image inside that.  You can unpack this as follows
3230 in guestfish:
3231
3232  add-ro Fedora-11-i686-Live.iso
3233  run
3234  mkmountpoint /cd
3235  mkmountpoint /squash
3236  mkmountpoint /ext3
3237  mount /dev/sda /cd
3238  mount-loop /cd/LiveOS/squashfs.img /squash
3239  mount-loop /squash/LiveOS/ext3fs.img /ext3
3240
3241 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3242
3243   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3244    [],
3245    "remove a mountpoint",
3246    "\
3247 This calls removes a mountpoint that was previously created
3248 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3249 for full details.");
3250
3251   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3252    [InitISOFS, Always, TestOutputBuffer (
3253       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3254    "read a file",
3255    "\
3256 This calls returns the contents of the file C<path> as a
3257 buffer.
3258
3259 Unlike C<guestfs_cat>, this function can correctly
3260 handle files that contain embedded ASCII NUL characters.
3261 However unlike C<guestfs_download>, this function is limited
3262 in the total size of file that can be handled.");
3263
3264   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3265    [InitISOFS, Always, TestOutputList (
3266       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3267     InitISOFS, Always, TestOutputList (
3268       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3269    "return lines matching a pattern",
3270    "\
3271 This calls the external C<grep> program and returns the
3272 matching lines.");
3273
3274   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3275    [InitISOFS, Always, TestOutputList (
3276       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3277    "return lines matching a pattern",
3278    "\
3279 This calls the external C<egrep> program and returns the
3280 matching lines.");
3281
3282   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3283    [InitISOFS, Always, TestOutputList (
3284       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3285    "return lines matching a pattern",
3286    "\
3287 This calls the external C<fgrep> program and returns the
3288 matching lines.");
3289
3290   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3291    [InitISOFS, Always, TestOutputList (
3292       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3293    "return lines matching a pattern",
3294    "\
3295 This calls the external C<grep -i> program and returns the
3296 matching lines.");
3297
3298   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3299    [InitISOFS, Always, TestOutputList (
3300       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3301    "return lines matching a pattern",
3302    "\
3303 This calls the external C<egrep -i> program and returns the
3304 matching lines.");
3305
3306   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3307    [InitISOFS, Always, TestOutputList (
3308       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3309    "return lines matching a pattern",
3310    "\
3311 This calls the external C<fgrep -i> program and returns the
3312 matching lines.");
3313
3314   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3315    [InitISOFS, Always, TestOutputList (
3316       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3317    "return lines matching a pattern",
3318    "\
3319 This calls the external C<zgrep> program and returns the
3320 matching lines.");
3321
3322   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3323    [InitISOFS, Always, TestOutputList (
3324       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3325    "return lines matching a pattern",
3326    "\
3327 This calls the external C<zegrep> program and returns the
3328 matching lines.");
3329
3330   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3331    [InitISOFS, Always, TestOutputList (
3332       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3333    "return lines matching a pattern",
3334    "\
3335 This calls the external C<zfgrep> program and returns the
3336 matching lines.");
3337
3338   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3339    [InitISOFS, Always, TestOutputList (
3340       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3341    "return lines matching a pattern",
3342    "\
3343 This calls the external C<zgrep -i> program and returns the
3344 matching lines.");
3345
3346   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3347    [InitISOFS, Always, TestOutputList (
3348       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3349    "return lines matching a pattern",
3350    "\
3351 This calls the external C<zegrep -i> program and returns the
3352 matching lines.");
3353
3354   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3355    [InitISOFS, Always, TestOutputList (
3356       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3357    "return lines matching a pattern",
3358    "\
3359 This calls the external C<zfgrep -i> program and returns the
3360 matching lines.");
3361
3362   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3363    [InitISOFS, Always, TestOutput (
3364       [["realpath"; "/../directory"]], "/directory")],
3365    "canonicalized absolute pathname",
3366    "\
3367 Return the canonicalized absolute pathname of C<path>.  The
3368 returned path has no C<.>, C<..> or symbolic link path elements.");
3369
3370   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3371    [InitBasicFS, Always, TestOutputStruct (
3372       [["touch"; "/a"];
3373        ["ln"; "/a"; "/b"];
3374        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3375    "create a hard link",
3376    "\
3377 This command creates a hard link using the C<ln> command.");
3378
3379   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3380    [InitBasicFS, Always, TestOutputStruct (
3381       [["touch"; "/a"];
3382        ["touch"; "/b"];
3383        ["ln_f"; "/a"; "/b"];
3384        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3385    "create a hard link",
3386    "\
3387 This command creates a hard link using the C<ln -f> command.
3388 The C<-f> option removes the link (C<linkname>) if it exists already.");
3389
3390   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3391    [InitBasicFS, Always, TestOutputStruct (
3392       [["touch"; "/a"];
3393        ["ln_s"; "a"; "/b"];
3394        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3395    "create a symbolic link",
3396    "\
3397 This command creates a symbolic link using the C<ln -s> command.");
3398
3399   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3400    [InitBasicFS, Always, TestOutput (
3401       [["mkdir_p"; "/a/b"];
3402        ["touch"; "/a/b/c"];
3403        ["ln_sf"; "../d"; "/a/b/c"];
3404        ["readlink"; "/a/b/c"]], "../d")],
3405    "create a symbolic link",
3406    "\
3407 This command creates a symbolic link using the C<ln -sf> command,
3408 The C<-f> option removes the link (C<linkname>) if it exists already.");
3409
3410   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3411    [] (* XXX tested above *),
3412    "read the target of a symbolic link",
3413    "\
3414 This command reads the target of a symbolic link.");
3415
3416   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3417    [InitBasicFS, Always, TestOutputStruct (
3418       [["fallocate"; "/a"; "1000000"];
3419        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3420    "preallocate a file in the guest filesystem",
3421    "\
3422 This command preallocates a file (containing zero bytes) named
3423 C<path> of size C<len> bytes.  If the file exists already, it
3424 is overwritten.
3425
3426 Do not confuse this with the guestfish-specific
3427 C<alloc> command which allocates a file in the host and
3428 attaches it as a device.");
3429
3430   ("swapon_device", (RErr, [Device "device"]), 170, [],
3431    [InitPartition, Always, TestRun (
3432       [["mkswap"; "/dev/sda1"];
3433        ["swapon_device"; "/dev/sda1"];
3434        ["swapoff_device"; "/dev/sda1"]])],
3435    "enable swap on device",
3436    "\
3437 This command enables the libguestfs appliance to use the
3438 swap device or partition named C<device>.  The increased
3439 memory is made available for all commands, for example
3440 those run using C<guestfs_command> or C<guestfs_sh>.
3441
3442 Note that you should not swap to existing guest swap
3443 partitions unless you know what you are doing.  They may
3444 contain hibernation information, or other information that
3445 the guest doesn't want you to trash.  You also risk leaking
3446 information about the host to the guest this way.  Instead,
3447 attach a new host device to the guest and swap on that.");
3448
3449   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3450    [], (* XXX tested by swapon_device *)
3451    "disable swap on device",
3452    "\
3453 This command disables the libguestfs appliance swap
3454 device or partition named C<device>.
3455 See C<guestfs_swapon_device>.");
3456
3457   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3458    [InitBasicFS, Always, TestRun (
3459       [["fallocate"; "/swap"; "8388608"];
3460        ["mkswap_file"; "/swap"];
3461        ["swapon_file"; "/swap"];
3462        ["swapoff_file"; "/swap"]])],
3463    "enable swap on file",
3464    "\
3465 This command enables swap to a file.
3466 See C<guestfs_swapon_device> for other notes.");
3467
3468   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3469    [], (* XXX tested by swapon_file *)
3470    "disable swap on file",
3471    "\
3472 This command disables the libguestfs appliance swap on file.");
3473
3474   ("swapon_label", (RErr, [String "label"]), 174, [],
3475    [InitEmpty, Always, TestRun (
3476       [["part_disk"; "/dev/sdb"; "mbr"];
3477        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3478        ["swapon_label"; "swapit"];
3479        ["swapoff_label"; "swapit"];
3480        ["zero"; "/dev/sdb"];
3481        ["blockdev_rereadpt"; "/dev/sdb"]])],
3482    "enable swap on labeled swap partition",
3483    "\
3484 This command enables swap to a labeled swap partition.
3485 See C<guestfs_swapon_device> for other notes.");
3486
3487   ("swapoff_label", (RErr, [String "label"]), 175, [],
3488    [], (* XXX tested by swapon_label *)
3489    "disable swap on labeled swap partition",
3490    "\
3491 This command disables the libguestfs appliance swap on
3492 labeled swap partition.");
3493
3494   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3495    (let uuid = uuidgen () in
3496     [InitEmpty, Always, TestRun (
3497        [["mkswap_U"; uuid; "/dev/sdb"];
3498         ["swapon_uuid"; uuid];
3499         ["swapoff_uuid"; uuid]])]),
3500    "enable swap on swap partition by UUID",
3501    "\
3502 This command enables swap to a swap partition with the given UUID.
3503 See C<guestfs_swapon_device> for other notes.");
3504
3505   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3506    [], (* XXX tested by swapon_uuid *)
3507    "disable swap on swap partition by UUID",
3508    "\
3509 This command disables the libguestfs appliance swap partition
3510 with the given UUID.");
3511
3512   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3513    [InitBasicFS, Always, TestRun (
3514       [["fallocate"; "/swap"; "8388608"];
3515        ["mkswap_file"; "/swap"]])],
3516    "create a swap file",
3517    "\
3518 Create a swap file.
3519
3520 This command just writes a swap file signature to an existing
3521 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3522
3523   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3524    [InitISOFS, Always, TestRun (
3525       [["inotify_init"; "0"]])],
3526    "create an inotify handle",
3527    "\
3528 This command creates a new inotify handle.
3529 The inotify subsystem can be used to notify events which happen to
3530 objects in the guest filesystem.
3531
3532 C<maxevents> is the maximum number of events which will be
3533 queued up between calls to C<guestfs_inotify_read> or
3534 C<guestfs_inotify_files>.
3535 If this is passed as C<0>, then the kernel (or previously set)
3536 default is used.  For Linux 2.6.29 the default was 16384 events.
3537 Beyond this limit, the kernel throws away events, but records
3538 the fact that it threw them away by setting a flag
3539 C<IN_Q_OVERFLOW> in the returned structure list (see
3540 C<guestfs_inotify_read>).
3541
3542 Before any events are generated, you have to add some
3543 watches to the internal watch list.  See:
3544 C<guestfs_inotify_add_watch>,
3545 C<guestfs_inotify_rm_watch> and
3546 C<guestfs_inotify_watch_all>.
3547
3548 Queued up events should be read periodically by calling
3549 C<guestfs_inotify_read>
3550 (or C<guestfs_inotify_files> which is just a helpful
3551 wrapper around C<guestfs_inotify_read>).  If you don't
3552 read the events out often enough then you risk the internal
3553 queue overflowing.
3554
3555 The handle should be closed after use by calling
3556 C<guestfs_inotify_close>.  This also removes any
3557 watches automatically.
3558
3559 See also L<inotify(7)> for an overview of the inotify interface
3560 as exposed by the Linux kernel, which is roughly what we expose
3561 via libguestfs.  Note that there is one global inotify handle
3562 per libguestfs instance.");
3563
3564   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3565    [InitBasicFS, Always, TestOutputList (
3566       [["inotify_init"; "0"];
3567        ["inotify_add_watch"; "/"; "1073741823"];
3568        ["touch"; "/a"];
3569        ["touch"; "/b"];
3570        ["inotify_files"]], ["a"; "b"])],
3571    "add an inotify watch",
3572    "\
3573 Watch C<path> for the events listed in C<mask>.
3574
3575 Note that if C<path> is a directory then events within that
3576 directory are watched, but this does I<not> happen recursively
3577 (in subdirectories).
3578
3579 Note for non-C or non-Linux callers: the inotify events are
3580 defined by the Linux kernel ABI and are listed in
3581 C</usr/include/sys/inotify.h>.");
3582
3583   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3584    [],
3585    "remove an inotify watch",
3586    "\
3587 Remove a previously defined inotify watch.
3588 See C<guestfs_inotify_add_watch>.");
3589
3590   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3591    [],
3592    "return list of inotify events",
3593    "\
3594 Return the complete queue of events that have happened
3595 since the previous read call.
3596
3597 If no events have happened, this returns an empty list.
3598
3599 I<Note>: In order to make sure that all events have been
3600 read, you must call this function repeatedly until it
3601 returns an empty list.  The reason is that the call will
3602 read events up to the maximum appliance-to-host message
3603 size and leave remaining events in the queue.");
3604
3605   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3606    [],
3607    "return list of watched files that had events",
3608    "\
3609 This function is a helpful wrapper around C<guestfs_inotify_read>
3610 which just returns a list of pathnames of objects that were
3611 touched.  The returned pathnames are sorted and deduplicated.");
3612
3613   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3614    [],
3615    "close the inotify handle",
3616    "\
3617 This closes the inotify handle which was previously
3618 opened by inotify_init.  It removes all watches, throws
3619 away any pending events, and deallocates all resources.");
3620
3621   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3622    [],
3623    "set SELinux security context",
3624    "\
3625 This sets the SELinux security context of the daemon
3626 to the string C<context>.
3627
3628 See the documentation about SELINUX in L<guestfs(3)>.");
3629
3630   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3631    [],
3632    "get SELinux security context",
3633    "\
3634 This gets the SELinux security context of the daemon.
3635
3636 See the documentation about SELINUX in L<guestfs(3)>,
3637 and C<guestfs_setcon>");
3638
3639   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3640    [InitEmpty, Always, TestOutput (
3641       [["part_disk"; "/dev/sda"; "mbr"];
3642        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3643        ["mount_options"; ""; "/dev/sda1"; "/"];
3644        ["write_file"; "/new"; "new file contents"; "0"];
3645        ["cat"; "/new"]], "new file contents")],
3646    "make a filesystem with block size",
3647    "\
3648 This call is similar to C<guestfs_mkfs>, but it allows you to
3649 control the block size of the resulting filesystem.  Supported
3650 block sizes depend on the filesystem type, but typically they
3651 are C<1024>, C<2048> or C<4096> only.");
3652
3653   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3654    [InitEmpty, Always, TestOutput (
3655       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3656        ["mke2journal"; "4096"; "/dev/sda1"];
3657        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3658        ["mount_options"; ""; "/dev/sda2"; "/"];
3659        ["write_file"; "/new"; "new file contents"; "0"];
3660        ["cat"; "/new"]], "new file contents")],
3661    "make ext2/3/4 external journal",
3662    "\
3663 This creates an ext2 external journal on C<device>.  It is equivalent
3664 to the command:
3665
3666  mke2fs -O journal_dev -b blocksize device");
3667
3668   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3669    [InitEmpty, Always, TestOutput (
3670       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3671        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3672        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3673        ["mount_options"; ""; "/dev/sda2"; "/"];
3674        ["write_file"; "/new"; "new file contents"; "0"];
3675        ["cat"; "/new"]], "new file contents")],
3676    "make ext2/3/4 external journal with label",
3677    "\
3678 This creates an ext2 external journal on C<device> with label C<label>.");
3679
3680   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3681    (let uuid = uuidgen () in
3682     [InitEmpty, Always, TestOutput (
3683        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3684         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3685         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3686         ["mount_options"; ""; "/dev/sda2"; "/"];
3687         ["write_file"; "/new"; "new file contents"; "0"];
3688         ["cat"; "/new"]], "new file contents")]),
3689    "make ext2/3/4 external journal with UUID",
3690    "\
3691 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3692
3693   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3694    [],
3695    "make ext2/3/4 filesystem with external journal",
3696    "\
3697 This creates an ext2/3/4 filesystem on C<device> with
3698 an external journal on C<journal>.  It is equivalent
3699 to the command:
3700
3701  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3702
3703 See also C<guestfs_mke2journal>.");
3704
3705   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3706    [],
3707    "make ext2/3/4 filesystem with external journal",
3708    "\
3709 This creates an ext2/3/4 filesystem on C<device> with
3710 an external journal on the journal labeled C<label>.
3711
3712 See also C<guestfs_mke2journal_L>.");
3713
3714   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3715    [],
3716    "make ext2/3/4 filesystem with external journal",
3717    "\
3718 This creates an ext2/3/4 filesystem on C<device> with
3719 an external journal on the journal with UUID C<uuid>.
3720
3721 See also C<guestfs_mke2journal_U>.");
3722
3723   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3724    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3725    "load a kernel module",
3726    "\
3727 This loads a kernel module in the appliance.
3728
3729 The kernel module must have been whitelisted when libguestfs
3730 was built (see C<appliance/kmod.whitelist.in> in the source).");
3731
3732   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3733    [InitNone, Always, TestOutput (
3734       [["echo_daemon"; "This is a test"]], "This is a test"
3735     )],
3736    "echo arguments back to the client",
3737    "\
3738 This command concatenate the list of C<words> passed with single spaces between
3739 them and returns the resulting string.
3740
3741 You can use this command to test the connection through to the daemon.
3742
3743 See also C<guestfs_ping_daemon>.");
3744
3745   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3746    [], (* There is a regression test for this. *)
3747    "find all files and directories, returning NUL-separated list",
3748    "\
3749 This command lists out all files and directories, recursively,
3750 starting at C<directory>, placing the resulting list in the
3751 external file called C<files>.
3752
3753 This command works the same way as C<guestfs_find> with the
3754 following exceptions:
3755
3756 =over 4
3757
3758 =item *
3759
3760 The resulting list is written to an external file.
3761
3762 =item *
3763
3764 Items (filenames) in the result are separated
3765 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3766
3767 =item *
3768
3769 This command is not limited in the number of names that it
3770 can return.
3771
3772 =item *
3773
3774 The result list is not sorted.
3775
3776 =back");
3777
3778   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3779    [InitISOFS, Always, TestOutput (
3780       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3781     InitISOFS, Always, TestOutput (
3782       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3783     InitISOFS, Always, TestOutput (
3784       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3785     InitISOFS, Always, TestLastFail (
3786       [["case_sensitive_path"; "/Known-1/"]]);
3787     InitBasicFS, Always, TestOutput (
3788       [["mkdir"; "/a"];
3789        ["mkdir"; "/a/bbb"];
3790        ["touch"; "/a/bbb/c"];
3791        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3792     InitBasicFS, Always, TestOutput (
3793       [["mkdir"; "/a"];
3794        ["mkdir"; "/a/bbb"];
3795        ["touch"; "/a/bbb/c"];
3796        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3797     InitBasicFS, Always, TestLastFail (
3798       [["mkdir"; "/a"];
3799        ["mkdir"; "/a/bbb"];
3800        ["touch"; "/a/bbb/c"];
3801        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3802    "return true path on case-insensitive filesystem",
3803    "\
3804 This can be used to resolve case insensitive paths on
3805 a filesystem which is case sensitive.  The use case is
3806 to resolve paths which you have read from Windows configuration
3807 files or the Windows Registry, to the true path.
3808
3809 The command handles a peculiarity of the Linux ntfs-3g
3810 filesystem driver (and probably others), which is that although
3811 the underlying filesystem is case-insensitive, the driver
3812 exports the filesystem to Linux as case-sensitive.
3813
3814 One consequence of this is that special directories such
3815 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3816 (or other things) depending on the precise details of how
3817 they were created.  In Windows itself this would not be
3818 a problem.
3819
3820 Bug or feature?  You decide:
3821 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3822
3823 This function resolves the true case of each element in the
3824 path and returns the case-sensitive path.
3825
3826 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3827 might return C<\"/WINDOWS/system32\"> (the exact return value
3828 would depend on details of how the directories were originally
3829 created under Windows).
3830
3831 I<Note>:
3832 This function does not handle drive names, backslashes etc.
3833
3834 See also C<guestfs_realpath>.");
3835
3836   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3837    [InitBasicFS, Always, TestOutput (
3838       [["vfs_type"; "/dev/sda1"]], "ext2")],
3839    "get the Linux VFS type corresponding to a mounted device",
3840    "\
3841 This command gets the block device type corresponding to
3842 a mounted device called C<device>.
3843
3844 Usually the result is the name of the Linux VFS module that
3845 is used to mount this device (probably determined automatically
3846 if you used the C<guestfs_mount> call).");
3847
3848   ("truncate", (RErr, [Pathname "path"]), 199, [],
3849    [InitBasicFS, Always, TestOutputStruct (
3850       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3851        ["truncate"; "/test"];
3852        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3853    "truncate a file to zero size",
3854    "\
3855 This command truncates C<path> to a zero-length file.  The
3856 file must exist already.");
3857
3858   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3859    [InitBasicFS, Always, TestOutputStruct (
3860       [["touch"; "/test"];
3861        ["truncate_size"; "/test"; "1000"];
3862        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3863    "truncate a file to a particular size",
3864    "\
3865 This command truncates C<path> to size C<size> bytes.  The file
3866 must exist already.  If the file is smaller than C<size> then
3867 the file is extended to the required size with null bytes.");
3868
3869   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3870    [InitBasicFS, Always, TestOutputStruct (
3871       [["touch"; "/test"];
3872        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3873        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3874    "set timestamp of a file with nanosecond precision",
3875    "\
3876 This command sets the timestamps of a file with nanosecond
3877 precision.
3878
3879 C<atsecs, atnsecs> are the last access time (atime) in secs and
3880 nanoseconds from the epoch.
3881
3882 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3883 secs and nanoseconds from the epoch.
3884
3885 If the C<*nsecs> field contains the special value C<-1> then
3886 the corresponding timestamp is set to the current time.  (The
3887 C<*secs> field is ignored in this case).
3888
3889 If the C<*nsecs> field contains the special value C<-2> then
3890 the corresponding timestamp is left unchanged.  (The
3891 C<*secs> field is ignored in this case).");
3892
3893   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3894    [InitBasicFS, Always, TestOutputStruct (
3895       [["mkdir_mode"; "/test"; "0o111"];
3896        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3897    "create a directory with a particular mode",
3898    "\
3899 This command creates a directory, setting the initial permissions
3900 of the directory to C<mode>.
3901
3902 For common Linux filesystems, the actual mode which is set will
3903 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3904 interpret the mode in other ways.
3905
3906 See also C<guestfs_mkdir>, C<guestfs_umask>");
3907
3908   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3909    [], (* XXX *)
3910    "change file owner and group",
3911    "\
3912 Change the file owner to C<owner> and group to C<group>.
3913 This is like C<guestfs_chown> but if C<path> is a symlink then
3914 the link itself is changed, not the target.
3915
3916 Only numeric uid and gid are supported.  If you want to use
3917 names, you will need to locate and parse the password file
3918 yourself (Augeas support makes this relatively easy).");
3919
3920   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3921    [], (* XXX *)
3922    "lstat on multiple files",
3923    "\
3924 This call allows you to perform the C<guestfs_lstat> operation
3925 on multiple files, where all files are in the directory C<path>.
3926 C<names> is the list of files from this directory.
3927
3928 On return you get a list of stat structs, with a one-to-one
3929 correspondence to the C<names> list.  If any name did not exist
3930 or could not be lstat'd, then the C<ino> field of that structure
3931 is set to C<-1>.
3932
3933 This call is intended for programs that want to efficiently
3934 list a directory contents without making many round-trips.
3935 See also C<guestfs_lxattrlist> for a similarly efficient call
3936 for getting extended attributes.  Very long directory listings
3937 might cause the protocol message size to be exceeded, causing
3938 this call to fail.  The caller must split up such requests
3939 into smaller groups of names.");
3940
3941   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3942    [], (* XXX *)
3943    "lgetxattr on multiple files",
3944    "\
3945 This call allows you to get the extended attributes
3946 of multiple files, where all files are in the directory C<path>.
3947 C<names> is the list of files from this directory.
3948
3949 On return you get a flat list of xattr structs which must be
3950 interpreted sequentially.  The first xattr struct always has a zero-length
3951 C<attrname>.  C<attrval> in this struct is zero-length
3952 to indicate there was an error doing C<lgetxattr> for this
3953 file, I<or> is a C string which is a decimal number
3954 (the number of following attributes for this file, which could
3955 be C<\"0\">).  Then after the first xattr struct are the
3956 zero or more attributes for the first named file.
3957 This repeats for the second and subsequent files.
3958
3959 This call is intended for programs that want to efficiently
3960 list a directory contents without making many round-trips.
3961 See also C<guestfs_lstatlist> for a similarly efficient call
3962 for getting standard stats.  Very long directory listings
3963 might cause the protocol message size to be exceeded, causing
3964 this call to fail.  The caller must split up such requests
3965 into smaller groups of names.");
3966
3967   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3968    [], (* XXX *)
3969    "readlink on multiple files",
3970    "\
3971 This call allows you to do a C<readlink> operation
3972 on multiple files, where all files are in the directory C<path>.
3973 C<names> is the list of files from this directory.
3974
3975 On return you get a list of strings, with a one-to-one
3976 correspondence to the C<names> list.  Each string is the
3977 value of the symbol link.
3978
3979 If the C<readlink(2)> operation fails on any name, then
3980 the corresponding result string is the empty string C<\"\">.
3981 However the whole operation is completed even if there
3982 were C<readlink(2)> errors, and so you can call this
3983 function with names where you don't know if they are
3984 symbolic links already (albeit slightly less efficient).
3985
3986 This call is intended for programs that want to efficiently
3987 list a directory contents without making many round-trips.
3988 Very long directory listings might cause the protocol
3989 message size to be exceeded, causing
3990 this call to fail.  The caller must split up such requests
3991 into smaller groups of names.");
3992
3993   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3994    [InitISOFS, Always, TestOutputBuffer (
3995       [["pread"; "/known-4"; "1"; "3"]], "\n");
3996     InitISOFS, Always, TestOutputBuffer (
3997       [["pread"; "/empty"; "0"; "100"]], "")],
3998    "read part of a file",
3999    "\
4000 This command lets you read part of a file.  It reads C<count>
4001 bytes of the file, starting at C<offset>, from file C<path>.
4002
4003 This may read fewer bytes than requested.  For further details
4004 see the L<pread(2)> system call.");
4005
4006   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4007    [InitEmpty, Always, TestRun (
4008       [["part_init"; "/dev/sda"; "gpt"]])],
4009    "create an empty partition table",
4010    "\
4011 This creates an empty partition table on C<device> of one of the
4012 partition types listed below.  Usually C<parttype> should be
4013 either C<msdos> or C<gpt> (for large disks).
4014
4015 Initially there are no partitions.  Following this, you should
4016 call C<guestfs_part_add> for each partition required.
4017
4018 Possible values for C<parttype> are:
4019
4020 =over 4
4021
4022 =item B<efi> | B<gpt>
4023
4024 Intel EFI / GPT partition table.
4025
4026 This is recommended for >= 2 TB partitions that will be accessed
4027 from Linux and Intel-based Mac OS X.  It also has limited backwards
4028 compatibility with the C<mbr> format.
4029
4030 =item B<mbr> | B<msdos>
4031
4032 The standard PC \"Master Boot Record\" (MBR) format used
4033 by MS-DOS and Windows.  This partition type will B<only> work
4034 for device sizes up to 2 TB.  For large disks we recommend
4035 using C<gpt>.
4036
4037 =back
4038
4039 Other partition table types that may work but are not
4040 supported include:
4041
4042 =over 4
4043
4044 =item B<aix>
4045
4046 AIX disk labels.
4047
4048 =item B<amiga> | B<rdb>
4049
4050 Amiga \"Rigid Disk Block\" format.
4051
4052 =item B<bsd>
4053
4054 BSD disk labels.
4055
4056 =item B<dasd>
4057
4058 DASD, used on IBM mainframes.
4059
4060 =item B<dvh>
4061
4062 MIPS/SGI volumes.
4063
4064 =item B<mac>
4065
4066 Old Mac partition format.  Modern Macs use C<gpt>.
4067
4068 =item B<pc98>
4069
4070 NEC PC-98 format, common in Japan apparently.
4071
4072 =item B<sun>
4073
4074 Sun disk labels.
4075
4076 =back");
4077
4078   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4079    [InitEmpty, Always, TestRun (
4080       [["part_init"; "/dev/sda"; "mbr"];
4081        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4082     InitEmpty, Always, TestRun (
4083       [["part_init"; "/dev/sda"; "gpt"];
4084        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4085        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4086     InitEmpty, Always, TestRun (
4087       [["part_init"; "/dev/sda"; "mbr"];
4088        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4089        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4090        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4091        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4092    "add a partition to the device",
4093    "\
4094 This command adds a partition to C<device>.  If there is no partition
4095 table on the device, call C<guestfs_part_init> first.
4096
4097 The C<prlogex> parameter is the type of partition.  Normally you
4098 should pass C<p> or C<primary> here, but MBR partition tables also
4099 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4100 types.
4101
4102 C<startsect> and C<endsect> are the start and end of the partition
4103 in I<sectors>.  C<endsect> may be negative, which means it counts
4104 backwards from the end of the disk (C<-1> is the last sector).
4105
4106 Creating a partition which covers the whole disk is not so easy.
4107 Use C<guestfs_part_disk> to do that.");
4108
4109   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4110    [InitEmpty, Always, TestRun (
4111       [["part_disk"; "/dev/sda"; "mbr"]]);
4112     InitEmpty, Always, TestRun (
4113       [["part_disk"; "/dev/sda"; "gpt"]])],
4114    "partition whole disk with a single primary partition",
4115    "\
4116 This command is simply a combination of C<guestfs_part_init>
4117 followed by C<guestfs_part_add> to create a single primary partition
4118 covering the whole disk.
4119
4120 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4121 but other possible values are described in C<guestfs_part_init>.");
4122
4123   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4124    [InitEmpty, Always, TestRun (
4125       [["part_disk"; "/dev/sda"; "mbr"];
4126        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4127    "make a partition bootable",
4128    "\
4129 This sets the bootable flag on partition numbered C<partnum> on
4130 device C<device>.  Note that partitions are numbered from 1.
4131
4132 The bootable flag is used by some operating systems (notably
4133 Windows) to determine which partition to boot from.  It is by
4134 no means universally recognized.");
4135
4136   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4137    [InitEmpty, Always, TestRun (
4138       [["part_disk"; "/dev/sda"; "gpt"];
4139        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4140    "set partition name",
4141    "\
4142 This sets the partition name on partition numbered C<partnum> on
4143 device C<device>.  Note that partitions are numbered from 1.
4144
4145 The partition name can only be set on certain types of partition
4146 table.  This works on C<gpt> but not on C<mbr> partitions.");
4147
4148   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4149    [], (* XXX Add a regression test for this. *)
4150    "list partitions on a device",
4151    "\
4152 This command parses the partition table on C<device> and
4153 returns the list of partitions found.
4154
4155 The fields in the returned structure are:
4156
4157 =over 4
4158
4159 =item B<part_num>
4160
4161 Partition number, counting from 1.
4162
4163 =item B<part_start>
4164
4165 Start of the partition I<in bytes>.  To get sectors you have to
4166 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4167
4168 =item B<part_end>
4169
4170 End of the partition in bytes.
4171
4172 =item B<part_size>
4173
4174 Size of the partition in bytes.
4175
4176 =back");
4177
4178   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4179    [InitEmpty, Always, TestOutput (
4180       [["part_disk"; "/dev/sda"; "gpt"];
4181        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4182    "get the partition table type",
4183    "\
4184 This command examines the partition table on C<device> and
4185 returns the partition table type (format) being used.
4186
4187 Common return values include: C<msdos> (a DOS/Windows style MBR
4188 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4189 values are possible, although unusual.  See C<guestfs_part_init>
4190 for a full list.");
4191
4192   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4193    [InitBasicFS, Always, TestOutputBuffer (
4194       [["fill"; "0x63"; "10"; "/test"];
4195        ["read_file"; "/test"]], "cccccccccc")],
4196    "fill a file with octets",
4197    "\
4198 This command creates a new file called C<path>.  The initial
4199 content of the file is C<len> octets of C<c>, where C<c>
4200 must be a number in the range C<[0..255]>.
4201
4202 To fill a file with zero bytes (sparsely), it is
4203 much more efficient to use C<guestfs_truncate_size>.");
4204
4205   ("available", (RErr, [StringList "groups"]), 216, [],
4206    [InitNone, Always, TestRun [["available"; ""]]],
4207    "test availability of some parts of the API",
4208    "\
4209 This command is used to check the availability of some
4210 groups of functionality in the appliance, which not all builds of
4211 the libguestfs appliance will be able to provide.
4212
4213 The libguestfs groups, and the functions that those
4214 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4215
4216 The argument C<groups> is a list of group names, eg:
4217 C<[\"inotify\", \"augeas\"]> would check for the availability of
4218 the Linux inotify functions and Augeas (configuration file
4219 editing) functions.
4220
4221 The command returns no error if I<all> requested groups are available.
4222
4223 It fails with an error if one or more of the requested
4224 groups is unavailable in the appliance.
4225
4226 If an unknown group name is included in the
4227 list of groups then an error is always returned.
4228
4229 I<Notes:>
4230
4231 =over 4
4232
4233 =item *
4234
4235 You must call C<guestfs_launch> before calling this function.
4236
4237 The reason is because we don't know what groups are
4238 supported by the appliance/daemon until it is running and can
4239 be queried.
4240
4241 =item *
4242
4243 If a group of functions is available, this does not necessarily
4244 mean that they will work.  You still have to check for errors
4245 when calling individual API functions even if they are
4246 available.
4247
4248 =item *
4249
4250 It is usually the job of distro packagers to build
4251 complete functionality into the libguestfs appliance.
4252 Upstream libguestfs, if built from source with all
4253 requirements satisfied, will support everything.
4254
4255 =item *
4256
4257 This call was added in version C<1.0.80>.  In previous
4258 versions of libguestfs all you could do would be to speculatively
4259 execute a command to find out if the daemon implemented it.
4260 See also C<guestfs_version>.
4261
4262 =back");
4263
4264   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4265    [InitBasicFS, Always, TestOutputBuffer (
4266       [["write_file"; "/src"; "hello, world"; "0"];
4267        ["dd"; "/src"; "/dest"];
4268        ["read_file"; "/dest"]], "hello, world")],
4269    "copy from source to destination using dd",
4270    "\
4271 This command copies from one source device or file C<src>
4272 to another destination device or file C<dest>.  Normally you
4273 would use this to copy to or from a device or partition, for
4274 example to duplicate a filesystem.
4275
4276 If the destination is a device, it must be as large or larger
4277 than the source file or device, otherwise the copy will fail.
4278 This command cannot do partial copies (see C<guestfs_copy_size>).");
4279
4280   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4281    [InitBasicFS, Always, TestOutputInt (
4282       [["write_file"; "/file"; "hello, world"; "0"];
4283        ["filesize"; "/file"]], 12)],
4284    "return the size of the file in bytes",
4285    "\
4286 This command returns the size of C<file> in bytes.
4287
4288 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4289 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4290 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4291
4292   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4293    [InitBasicFSonLVM, Always, TestOutputList (
4294       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4295        ["lvs"]], ["/dev/VG/LV2"])],
4296    "rename an LVM logical volume",
4297    "\
4298 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4299
4300   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4301    [InitBasicFSonLVM, Always, TestOutputList (
4302       [["umount"; "/"];
4303        ["vg_activate"; "false"; "VG"];
4304        ["vgrename"; "VG"; "VG2"];
4305        ["vg_activate"; "true"; "VG2"];
4306        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4307        ["vgs"]], ["VG2"])],
4308    "rename an LVM volume group",
4309    "\
4310 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4311
4312   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4313    [InitISOFS, Always, TestOutputBuffer (
4314       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4315    "list the contents of a single file in an initrd",
4316    "\
4317 This command unpacks the file C<filename> from the initrd file
4318 called C<initrdpath>.  The filename must be given I<without> the
4319 initial C</> character.
4320
4321 For example, in guestfish you could use the following command
4322 to examine the boot script (usually called C</init>)
4323 contained in a Linux initrd or initramfs image:
4324
4325  initrd-cat /boot/initrd-<version>.img init
4326
4327 See also C<guestfs_initrd_list>.");
4328
4329   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4330    [],
4331    "get the UUID of a physical volume",
4332    "\
4333 This command returns the UUID of the LVM PV C<device>.");
4334
4335   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4336    [],
4337    "get the UUID of a volume group",
4338    "\
4339 This command returns the UUID of the LVM VG named C<vgname>.");
4340
4341   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4342    [],
4343    "get the UUID of a logical volume",
4344    "\
4345 This command returns the UUID of the LVM LV C<device>.");
4346
4347   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4348    [],
4349    "get the PV UUIDs containing the volume group",
4350    "\
4351 Given a VG called C<vgname>, this returns the UUIDs of all
4352 the physical volumes that this volume group resides on.
4353
4354 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4355 calls to associate physical volumes and volume groups.
4356
4357 See also C<guestfs_vglvuuids>.");
4358
4359   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4360    [],
4361    "get the LV UUIDs of all LVs in the volume group",
4362    "\
4363 Given a VG called C<vgname>, this returns the UUIDs of all
4364 the logical volumes created in this volume group.
4365
4366 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4367 calls to associate logical volumes and volume groups.
4368
4369 See also C<guestfs_vgpvuuids>.");
4370
4371   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4372    [InitBasicFS, Always, TestOutputBuffer (
4373       [["write_file"; "/src"; "hello, world"; "0"];
4374        ["copy_size"; "/src"; "/dest"; "5"];
4375        ["read_file"; "/dest"]], "hello")],
4376    "copy size bytes from source to destination using dd",
4377    "\
4378 This command copies exactly C<size> bytes from one source device
4379 or file C<src> to another destination device or file C<dest>.
4380
4381 Note this will fail if the source is too short or if the destination
4382 is not large enough.");
4383
4384   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4385    [InitBasicFSonLVM, Always, TestRun (
4386       [["zero_device"; "/dev/VG/LV"]])],
4387    "write zeroes to an entire device",
4388    "\
4389 This command writes zeroes over the entire C<device>.  Compare
4390 with C<guestfs_zero> which just zeroes the first few blocks of
4391 a device.");
4392
4393   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4394    [InitBasicFS, Always, TestOutput (
4395       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4396        ["cat"; "/hello"]], "hello\n")],
4397    "unpack compressed tarball to directory",
4398    "\
4399 This command uploads and unpacks local file C<tarball> (an
4400 I<xz compressed> tar file) into C<directory>.");
4401
4402   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4403    [],
4404    "pack directory into compressed tarball",
4405    "\
4406 This command packs the contents of C<directory> and downloads
4407 it to local file C<tarball> (as an xz compressed tar archive).");
4408
4409   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4410    [],
4411    "resize an NTFS filesystem",
4412    "\
4413 This command resizes an NTFS filesystem, expanding or
4414 shrinking it to the size of the underlying device.
4415 See also L<ntfsresize(8)>.");
4416
4417   ("vgscan", (RErr, []), 232, [],
4418    [InitEmpty, Always, TestRun (
4419       [["vgscan"]])],
4420    "rescan for LVM physical volumes, volume groups and logical volumes",
4421    "\
4422 This rescans all block devices and rebuilds the list of LVM
4423 physical volumes, volume groups and logical volumes.");
4424
4425   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4426    [InitEmpty, Always, TestRun (
4427       [["part_init"; "/dev/sda"; "mbr"];
4428        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4429        ["part_del"; "/dev/sda"; "1"]])],
4430    "delete a partition",
4431    "\
4432 This command deletes the partition numbered C<partnum> on C<device>.
4433
4434 Note that in the case of MBR partitioning, deleting an
4435 extended partition also deletes any logical partitions
4436 it contains.");
4437
4438   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4439    [InitEmpty, Always, TestOutputTrue (
4440       [["part_init"; "/dev/sda"; "mbr"];
4441        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4442        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4443        ["part_get_bootable"; "/dev/sda"; "1"]])],
4444    "return true if a partition is bootable",
4445    "\
4446 This command returns true if the partition C<partnum> on
4447 C<device> has the bootable flag set.
4448
4449 See also C<guestfs_part_set_bootable>.");
4450
4451   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4452    [InitEmpty, Always, TestOutputInt (
4453       [["part_init"; "/dev/sda"; "mbr"];
4454        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4455        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4456        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4457    "get the MBR type byte (ID byte) from a partition",
4458    "\
4459 Returns the MBR type byte (also known as the ID byte) from
4460 the numbered partition C<partnum>.
4461
4462 Note that only MBR (old DOS-style) partitions have type bytes.
4463 You will get undefined results for other partition table
4464 types (see C<guestfs_part_get_parttype>).");
4465
4466   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4467    [], (* tested by part_get_mbr_id *)
4468    "set the MBR type byte (ID byte) of a partition",
4469    "\
4470 Sets the MBR type byte (also known as the ID byte) of
4471 the numbered partition C<partnum> to C<idbyte>.  Note
4472 that the type bytes quoted in most documentation are
4473 in fact hexadecimal numbers, but usually documented
4474 without any leading \"0x\" which might be confusing.
4475
4476 Note that only MBR (old DOS-style) partitions have type bytes.
4477 You will get undefined results for other partition table
4478 types (see C<guestfs_part_get_parttype>).");
4479
4480   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4481    [InitISOFS, Always, TestOutput (
4482       [["checksum_device"; "md5"; "/dev/sdd"]],
4483       (Digest.to_hex (Digest.file "images/test.iso")))],
4484    "compute MD5, SHAx or CRC checksum of the contents of a device",
4485    "\
4486 This call computes the MD5, SHAx or CRC checksum of the
4487 contents of the device named C<device>.  For the types of
4488 checksums supported see the C<guestfs_checksum> command.");
4489
4490   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4491    [InitNone, Always, TestRun (
4492       [["part_disk"; "/dev/sda"; "mbr"];
4493        ["pvcreate"; "/dev/sda1"];
4494        ["vgcreate"; "VG"; "/dev/sda1"];
4495        ["lvcreate"; "LV"; "VG"; "10"];
4496        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4497    "expand an LV to fill free space",
4498    "\
4499 This expands an existing logical volume C<lv> so that it fills
4500 C<pc>% of the remaining free space in the volume group.  Commonly
4501 you would call this with pc = 100 which expands the logical volume
4502 as much as possible, using all remaining free space in the volume
4503 group.");
4504
4505   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4506    [], (* XXX Augeas code needs tests. *)
4507    "clear Augeas path",
4508    "\
4509 Set the value associated with C<path> to C<NULL>.  This
4510 is the same as the L<augtool(1)> C<clear> command.");
4511
4512   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4513    [InitEmpty, Always, TestOutputInt (
4514       [["get_umask"]], 0o22)],
4515    "get the current umask",
4516    "\
4517 Return the current umask.  By default the umask is C<022>
4518 unless it has been set by calling C<guestfs_umask>.");
4519
4520   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4521    [],
4522    "upload a file to the appliance (internal use only)",
4523    "\
4524 The C<guestfs_debug_upload> command uploads a file to
4525 the libguestfs appliance.
4526
4527 There is no comprehensive help for this command.  You have
4528 to look at the file C<daemon/debug.c> in the libguestfs source
4529 to find out what it is for.");
4530
4531   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4532    [InitBasicFS, Always, TestOutput (
4533       [["base64_in"; "../images/hello.b64"; "/hello"];
4534        ["cat"; "/hello"]], "hello\n")],
4535    "upload base64-encoded data to file",
4536    "\
4537 This command uploads base64-encoded data from C<base64file>
4538 to C<filename>.");
4539
4540   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4541    [],
4542    "download file and encode as base64",
4543    "\
4544 This command downloads the contents of C<filename>, writing
4545 it out to local file C<base64file> encoded as base64.");
4546
4547 ]
4548
4549 let all_functions = non_daemon_functions @ daemon_functions
4550
4551 (* In some places we want the functions to be displayed sorted
4552  * alphabetically, so this is useful:
4553  *)
4554 let all_functions_sorted =
4555   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4556                compare n1 n2) all_functions
4557
4558 (* Field types for structures. *)
4559 type field =
4560   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4561   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4562   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4563   | FUInt32
4564   | FInt32
4565   | FUInt64
4566   | FInt64
4567   | FBytes                      (* Any int measure that counts bytes. *)
4568   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4569   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4570
4571 (* Because we generate extra parsing code for LVM command line tools,
4572  * we have to pull out the LVM columns separately here.
4573  *)
4574 let lvm_pv_cols = [
4575   "pv_name", FString;
4576   "pv_uuid", FUUID;
4577   "pv_fmt", FString;
4578   "pv_size", FBytes;
4579   "dev_size", FBytes;
4580   "pv_free", FBytes;
4581   "pv_used", FBytes;
4582   "pv_attr", FString (* XXX *);
4583   "pv_pe_count", FInt64;
4584   "pv_pe_alloc_count", FInt64;
4585   "pv_tags", FString;
4586   "pe_start", FBytes;
4587   "pv_mda_count", FInt64;
4588   "pv_mda_free", FBytes;
4589   (* Not in Fedora 10:
4590      "pv_mda_size", FBytes;
4591   *)
4592 ]
4593 let lvm_vg_cols = [
4594   "vg_name", FString;
4595   "vg_uuid", FUUID;
4596   "vg_fmt", FString;
4597   "vg_attr", FString (* XXX *);
4598   "vg_size", FBytes;
4599   "vg_free", FBytes;
4600   "vg_sysid", FString;
4601   "vg_extent_size", FBytes;
4602   "vg_extent_count", FInt64;
4603   "vg_free_count", FInt64;
4604   "max_lv", FInt64;
4605   "max_pv", FInt64;
4606   "pv_count", FInt64;
4607   "lv_count", FInt64;
4608   "snap_count", FInt64;
4609   "vg_seqno", FInt64;
4610   "vg_tags", FString;
4611   "vg_mda_count", FInt64;
4612   "vg_mda_free", FBytes;
4613   (* Not in Fedora 10:
4614      "vg_mda_size", FBytes;
4615   *)
4616 ]
4617 let lvm_lv_cols = [
4618   "lv_name", FString;
4619   "lv_uuid", FUUID;
4620   "lv_attr", FString (* XXX *);
4621   "lv_major", FInt64;
4622   "lv_minor", FInt64;
4623   "lv_kernel_major", FInt64;
4624   "lv_kernel_minor", FInt64;
4625   "lv_size", FBytes;
4626   "seg_count", FInt64;
4627   "origin", FString;
4628   "snap_percent", FOptPercent;
4629   "copy_percent", FOptPercent;
4630   "move_pv", FString;
4631   "lv_tags", FString;
4632   "mirror_log", FString;
4633   "modules", FString;
4634 ]
4635
4636 (* Names and fields in all structures (in RStruct and RStructList)
4637  * that we support.
4638  *)
4639 let structs = [
4640   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4641    * not use this struct in any new code.
4642    *)
4643   "int_bool", [
4644     "i", FInt32;                (* for historical compatibility *)
4645     "b", FInt32;                (* for historical compatibility *)
4646   ];
4647
4648   (* LVM PVs, VGs, LVs. *)
4649   "lvm_pv", lvm_pv_cols;
4650   "lvm_vg", lvm_vg_cols;
4651   "lvm_lv", lvm_lv_cols;
4652
4653   (* Column names and types from stat structures.
4654    * NB. Can't use things like 'st_atime' because glibc header files
4655    * define some of these as macros.  Ugh.
4656    *)
4657   "stat", [
4658     "dev", FInt64;
4659     "ino", FInt64;
4660     "mode", FInt64;
4661     "nlink", FInt64;
4662     "uid", FInt64;
4663     "gid", FInt64;
4664     "rdev", FInt64;
4665     "size", FInt64;
4666     "blksize", FInt64;
4667     "blocks", FInt64;
4668     "atime", FInt64;
4669     "mtime", FInt64;
4670     "ctime", FInt64;
4671   ];
4672   "statvfs", [
4673     "bsize", FInt64;
4674     "frsize", FInt64;
4675     "blocks", FInt64;
4676     "bfree", FInt64;
4677     "bavail", FInt64;
4678     "files", FInt64;
4679     "ffree", FInt64;
4680     "favail", FInt64;
4681     "fsid", FInt64;
4682     "flag", FInt64;
4683     "namemax", FInt64;
4684   ];
4685
4686   (* Column names in dirent structure. *)
4687   "dirent", [
4688     "ino", FInt64;
4689     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4690     "ftyp", FChar;
4691     "name", FString;
4692   ];
4693
4694   (* Version numbers. *)
4695   "version", [
4696     "major", FInt64;
4697     "minor", FInt64;
4698     "release", FInt64;
4699     "extra", FString;
4700   ];
4701
4702   (* Extended attribute. *)
4703   "xattr", [
4704     "attrname", FString;
4705     "attrval", FBuffer;
4706   ];
4707
4708   (* Inotify events. *)
4709   "inotify_event", [
4710     "in_wd", FInt64;
4711     "in_mask", FUInt32;
4712     "in_cookie", FUInt32;
4713     "in_name", FString;
4714   ];
4715
4716   (* Partition table entry. *)
4717   "partition", [
4718     "part_num", FInt32;
4719     "part_start", FBytes;
4720     "part_end", FBytes;
4721     "part_size", FBytes;
4722   ];
4723 ] (* end of structs *)
4724
4725 (* Ugh, Java has to be different ..
4726  * These names are also used by the Haskell bindings.
4727  *)
4728 let java_structs = [
4729   "int_bool", "IntBool";
4730   "lvm_pv", "PV";
4731   "lvm_vg", "VG";
4732   "lvm_lv", "LV";
4733   "stat", "Stat";
4734   "statvfs", "StatVFS";
4735   "dirent", "Dirent";
4736   "version", "Version";
4737   "xattr", "XAttr";
4738   "inotify_event", "INotifyEvent";
4739   "partition", "Partition";
4740 ]
4741
4742 (* What structs are actually returned. *)
4743 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4744
4745 (* Returns a list of RStruct/RStructList structs that are returned
4746  * by any function.  Each element of returned list is a pair:
4747  *
4748  * (structname, RStructOnly)
4749  *    == there exists function which returns RStruct (_, structname)
4750  * (structname, RStructListOnly)
4751  *    == there exists function which returns RStructList (_, structname)
4752  * (structname, RStructAndList)
4753  *    == there are functions returning both RStruct (_, structname)
4754  *                                      and RStructList (_, structname)
4755  *)
4756 let rstructs_used_by functions =
4757   (* ||| is a "logical OR" for rstructs_used_t *)
4758   let (|||) a b =
4759     match a, b with
4760     | RStructAndList, _
4761     | _, RStructAndList -> RStructAndList
4762     | RStructOnly, RStructListOnly
4763     | RStructListOnly, RStructOnly -> RStructAndList
4764     | RStructOnly, RStructOnly -> RStructOnly
4765     | RStructListOnly, RStructListOnly -> RStructListOnly
4766   in
4767
4768   let h = Hashtbl.create 13 in
4769
4770   (* if elem->oldv exists, update entry using ||| operator,
4771    * else just add elem->newv to the hash
4772    *)
4773   let update elem newv =
4774     try  let oldv = Hashtbl.find h elem in
4775          Hashtbl.replace h elem (newv ||| oldv)
4776     with Not_found -> Hashtbl.add h elem newv
4777   in
4778
4779   List.iter (
4780     fun (_, style, _, _, _, _, _) ->
4781       match fst style with
4782       | RStruct (_, structname) -> update structname RStructOnly
4783       | RStructList (_, structname) -> update structname RStructListOnly
4784       | _ -> ()
4785   ) functions;
4786
4787   (* return key->values as a list of (key,value) *)
4788   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4789
4790 (* Used for testing language bindings. *)
4791 type callt =
4792   | CallString of string
4793   | CallOptString of string option
4794   | CallStringList of string list
4795   | CallInt of int
4796   | CallInt64 of int64
4797   | CallBool of bool
4798
4799 (* Used to memoize the result of pod2text. *)
4800 let pod2text_memo_filename = "src/.pod2text.data"
4801 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4802   try
4803     let chan = open_in pod2text_memo_filename in
4804     let v = input_value chan in
4805     close_in chan;
4806     v
4807   with
4808     _ -> Hashtbl.create 13
4809 let pod2text_memo_updated () =
4810   let chan = open_out pod2text_memo_filename in
4811   output_value chan pod2text_memo;
4812   close_out chan
4813
4814 (* Useful functions.
4815  * Note we don't want to use any external OCaml libraries which
4816  * makes this a bit harder than it should be.
4817  *)
4818 module StringMap = Map.Make (String)
4819
4820 let failwithf fs = ksprintf failwith fs
4821
4822 let unique = let i = ref 0 in fun () -> incr i; !i
4823
4824 let replace_char s c1 c2 =
4825   let s2 = String.copy s in
4826   let r = ref false in
4827   for i = 0 to String.length s2 - 1 do
4828     if String.unsafe_get s2 i = c1 then (
4829       String.unsafe_set s2 i c2;
4830       r := true
4831     )
4832   done;
4833   if not !r then s else s2
4834
4835 let isspace c =
4836   c = ' '
4837   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4838
4839 let triml ?(test = isspace) str =
4840   let i = ref 0 in
4841   let n = ref (String.length str) in
4842   while !n > 0 && test str.[!i]; do
4843     decr n;
4844     incr i
4845   done;
4846   if !i = 0 then str
4847   else String.sub str !i !n
4848
4849 let trimr ?(test = isspace) str =
4850   let n = ref (String.length str) in
4851   while !n > 0 && test str.[!n-1]; do
4852     decr n
4853   done;
4854   if !n = String.length str then str
4855   else String.sub str 0 !n
4856
4857 let trim ?(test = isspace) str =
4858   trimr ~test (triml ~test str)
4859
4860 let rec find s sub =
4861   let len = String.length s in
4862   let sublen = String.length sub in
4863   let rec loop i =
4864     if i <= len-sublen then (
4865       let rec loop2 j =
4866         if j < sublen then (
4867           if s.[i+j] = sub.[j] then loop2 (j+1)
4868           else -1
4869         ) else
4870           i (* found *)
4871       in
4872       let r = loop2 0 in
4873       if r = -1 then loop (i+1) else r
4874     ) else
4875       -1 (* not found *)
4876   in
4877   loop 0
4878
4879 let rec replace_str s s1 s2 =
4880   let len = String.length s in
4881   let sublen = String.length s1 in
4882   let i = find s s1 in
4883   if i = -1 then s
4884   else (
4885     let s' = String.sub s 0 i in
4886     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4887     s' ^ s2 ^ replace_str s'' s1 s2
4888   )
4889
4890 let rec string_split sep str =
4891   let len = String.length str in
4892   let seplen = String.length sep in
4893   let i = find str sep in
4894   if i = -1 then [str]
4895   else (
4896     let s' = String.sub str 0 i in
4897     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4898     s' :: string_split sep s''
4899   )
4900
4901 let files_equal n1 n2 =
4902   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4903   match Sys.command cmd with
4904   | 0 -> true
4905   | 1 -> false
4906   | i -> failwithf "%s: failed with error code %d" cmd i
4907
4908 let rec filter_map f = function
4909   | [] -> []
4910   | x :: xs ->
4911       match f x with
4912       | Some y -> y :: filter_map f xs
4913       | None -> filter_map f xs
4914
4915 let rec find_map f = function
4916   | [] -> raise Not_found
4917   | x :: xs ->
4918       match f x with
4919       | Some y -> y
4920       | None -> find_map f xs
4921
4922 let iteri f xs =
4923   let rec loop i = function
4924     | [] -> ()
4925     | x :: xs -> f i x; loop (i+1) xs
4926   in
4927   loop 0 xs
4928
4929 let mapi f xs =
4930   let rec loop i = function
4931     | [] -> []
4932     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4933   in
4934   loop 0 xs
4935
4936 let count_chars c str =
4937   let count = ref 0 in
4938   for i = 0 to String.length str - 1 do
4939     if c = String.unsafe_get str i then incr count
4940   done;
4941   !count
4942
4943 let name_of_argt = function
4944   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4945   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4946   | FileIn n | FileOut n -> n
4947
4948 let java_name_of_struct typ =
4949   try List.assoc typ java_structs
4950   with Not_found ->
4951     failwithf
4952       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4953
4954 let cols_of_struct typ =
4955   try List.assoc typ structs
4956   with Not_found ->
4957     failwithf "cols_of_struct: unknown struct %s" typ
4958
4959 let seq_of_test = function
4960   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4961   | TestOutputListOfDevices (s, _)
4962   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4963   | TestOutputTrue s | TestOutputFalse s
4964   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4965   | TestOutputStruct (s, _)
4966   | TestLastFail s -> s
4967
4968 (* Handling for function flags. *)
4969 let protocol_limit_warning =
4970   "Because of the message protocol, there is a transfer limit
4971 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4972
4973 let danger_will_robinson =
4974   "B<This command is dangerous.  Without careful use you
4975 can easily destroy all your data>."
4976
4977 let deprecation_notice flags =
4978   try
4979     let alt =
4980       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4981     let txt =
4982       sprintf "This function is deprecated.
4983 In new code, use the C<%s> call instead.
4984
4985 Deprecated functions will not be removed from the API, but the
4986 fact that they are deprecated indicates that there are problems
4987 with correct use of these functions." alt in
4988     Some txt
4989   with
4990     Not_found -> None
4991
4992 (* Create list of optional groups. *)
4993 let optgroups =
4994   let h = Hashtbl.create 13 in
4995   List.iter (
4996     fun (name, _, _, flags, _, _, _) ->
4997       List.iter (
4998         function
4999         | Optional group ->
5000             let names = try Hashtbl.find h group with Not_found -> [] in
5001             Hashtbl.replace h group (name :: names)
5002         | _ -> ()
5003       ) flags
5004   ) daemon_functions;
5005   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5006   let groups =
5007     List.map (
5008       fun group -> group, List.sort compare (Hashtbl.find h group)
5009     ) groups in
5010   List.sort (fun x y -> compare (fst x) (fst y)) groups
5011
5012 (* Check function names etc. for consistency. *)
5013 let check_functions () =
5014   let contains_uppercase str =
5015     let len = String.length str in
5016     let rec loop i =
5017       if i >= len then false
5018       else (
5019         let c = str.[i] in
5020         if c >= 'A' && c <= 'Z' then true
5021         else loop (i+1)
5022       )
5023     in
5024     loop 0
5025   in
5026
5027   (* Check function names. *)
5028   List.iter (
5029     fun (name, _, _, _, _, _, _) ->
5030       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5031         failwithf "function name %s does not need 'guestfs' prefix" name;
5032       if name = "" then
5033         failwithf "function name is empty";
5034       if name.[0] < 'a' || name.[0] > 'z' then
5035         failwithf "function name %s must start with lowercase a-z" name;
5036       if String.contains name '-' then
5037         failwithf "function name %s should not contain '-', use '_' instead."
5038           name
5039   ) all_functions;
5040
5041   (* Check function parameter/return names. *)
5042   List.iter (
5043     fun (name, style, _, _, _, _, _) ->
5044       let check_arg_ret_name n =
5045         if contains_uppercase n then
5046           failwithf "%s param/ret %s should not contain uppercase chars"
5047             name n;
5048         if String.contains n '-' || String.contains n '_' then
5049           failwithf "%s param/ret %s should not contain '-' or '_'"
5050             name n;
5051         if n = "value" then
5052           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;
5053         if n = "int" || n = "char" || n = "short" || n = "long" then
5054           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5055         if n = "i" || n = "n" then
5056           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5057         if n = "argv" || n = "args" then
5058           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5059
5060         (* List Haskell, OCaml and C keywords here.
5061          * http://www.haskell.org/haskellwiki/Keywords
5062          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5063          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5064          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5065          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5066          * Omitting _-containing words, since they're handled above.
5067          * Omitting the OCaml reserved word, "val", is ok,
5068          * and saves us from renaming several parameters.
5069          *)
5070         let reserved = [
5071           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5072           "char"; "class"; "const"; "constraint"; "continue"; "data";
5073           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5074           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5075           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5076           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5077           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5078           "interface";
5079           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5080           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5081           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5082           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5083           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5084           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5085           "volatile"; "when"; "where"; "while";
5086           ] in
5087         if List.mem n reserved then
5088           failwithf "%s has param/ret using reserved word %s" name n;
5089       in
5090
5091       (match fst style with
5092        | RErr -> ()
5093        | RInt n | RInt64 n | RBool n
5094        | RConstString n | RConstOptString n | RString n
5095        | RStringList n | RStruct (n, _) | RStructList (n, _)
5096        | RHashtable n | RBufferOut n ->
5097            check_arg_ret_name n
5098       );
5099       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5100   ) all_functions;
5101
5102   (* Check short descriptions. *)
5103   List.iter (
5104     fun (name, _, _, _, _, shortdesc, _) ->
5105       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5106         failwithf "short description of %s should begin with lowercase." name;
5107       let c = shortdesc.[String.length shortdesc-1] in
5108       if c = '\n' || c = '.' then
5109         failwithf "short description of %s should not end with . or \\n." name
5110   ) all_functions;
5111
5112   (* Check long descriptions. *)
5113   List.iter (
5114     fun (name, _, _, _, _, _, longdesc) ->
5115       if longdesc.[String.length longdesc-1] = '\n' then
5116         failwithf "long description of %s should not end with \\n." name
5117   ) all_functions;
5118
5119   (* Check proc_nrs. *)
5120   List.iter (
5121     fun (name, _, proc_nr, _, _, _, _) ->
5122       if proc_nr <= 0 then
5123         failwithf "daemon function %s should have proc_nr > 0" name
5124   ) daemon_functions;
5125
5126   List.iter (
5127     fun (name, _, proc_nr, _, _, _, _) ->
5128       if proc_nr <> -1 then
5129         failwithf "non-daemon function %s should have proc_nr -1" name
5130   ) non_daemon_functions;
5131
5132   let proc_nrs =
5133     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5134       daemon_functions in
5135   let proc_nrs =
5136     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5137   let rec loop = function
5138     | [] -> ()
5139     | [_] -> ()
5140     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5141         loop rest
5142     | (name1,nr1) :: (name2,nr2) :: _ ->
5143         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5144           name1 name2 nr1 nr2
5145   in
5146   loop proc_nrs;
5147
5148   (* Check tests. *)
5149   List.iter (
5150     function
5151       (* Ignore functions that have no tests.  We generate a
5152        * warning when the user does 'make check' instead.
5153        *)
5154     | name, _, _, _, [], _, _ -> ()
5155     | name, _, _, _, tests, _, _ ->
5156         let funcs =
5157           List.map (
5158             fun (_, _, test) ->
5159               match seq_of_test test with
5160               | [] ->
5161                   failwithf "%s has a test containing an empty sequence" name
5162               | cmds -> List.map List.hd cmds
5163           ) tests in
5164         let funcs = List.flatten funcs in
5165
5166         let tested = List.mem name funcs in
5167
5168         if not tested then
5169           failwithf "function %s has tests but does not test itself" name
5170   ) all_functions
5171
5172 (* 'pr' prints to the current output file. *)
5173 let chan = ref Pervasives.stdout
5174 let lines = ref 0
5175 let pr fs =
5176   ksprintf
5177     (fun str ->
5178        let i = count_chars '\n' str in
5179        lines := !lines + i;
5180        output_string !chan str
5181     ) fs
5182
5183 let copyright_years =
5184   let this_year = 1900 + (localtime (time ())).tm_year in
5185   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5186
5187 (* Generate a header block in a number of standard styles. *)
5188 type comment_style =
5189     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5190 type license = GPLv2plus | LGPLv2plus
5191
5192 let generate_header ?(extra_inputs = []) comment license =
5193   let inputs = "src/generator.ml" :: extra_inputs in
5194   let c = match comment with
5195     | CStyle ->         pr "/* "; " *"
5196     | CPlusPlusStyle -> pr "// "; "//"
5197     | HashStyle ->      pr "# ";  "#"
5198     | OCamlStyle ->     pr "(* "; " *"
5199     | HaskellStyle ->   pr "{- "; "  " in
5200   pr "libguestfs generated file\n";
5201   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5202   List.iter (pr "%s   %s\n" c) inputs;
5203   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5204   pr "%s\n" c;
5205   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5206   pr "%s\n" c;
5207   (match license with
5208    | GPLv2plus ->
5209        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5210        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5211        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5212        pr "%s (at your option) any later version.\n" c;
5213        pr "%s\n" c;
5214        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5215        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5216        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5217        pr "%s GNU General Public License for more details.\n" c;
5218        pr "%s\n" c;
5219        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5220        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5221        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5222
5223    | LGPLv2plus ->
5224        pr "%s This library is free software; you can redistribute it and/or\n" c;
5225        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5226        pr "%s License as published by the Free Software Foundation; either\n" c;
5227        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5228        pr "%s\n" c;
5229        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5230        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5231        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5232        pr "%s Lesser General Public License for more details.\n" c;
5233        pr "%s\n" c;
5234        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5235        pr "%s License along with this library; if not, write to the Free Software\n" c;
5236        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5237   );
5238   (match comment with
5239    | CStyle -> pr " */\n"
5240    | CPlusPlusStyle
5241    | HashStyle -> ()
5242    | OCamlStyle -> pr " *)\n"
5243    | HaskellStyle -> pr "-}\n"
5244   );
5245   pr "\n"
5246
5247 (* Start of main code generation functions below this line. *)
5248
5249 (* Generate the pod documentation for the C API. *)
5250 let rec generate_actions_pod () =
5251   List.iter (
5252     fun (shortname, style, _, flags, _, _, longdesc) ->
5253       if not (List.mem NotInDocs flags) then (
5254         let name = "guestfs_" ^ shortname in
5255         pr "=head2 %s\n\n" name;
5256         pr " ";
5257         generate_prototype ~extern:false ~handle:"g" name style;
5258         pr "\n\n";
5259         pr "%s\n\n" longdesc;
5260         (match fst style with
5261          | RErr ->
5262              pr "This function returns 0 on success or -1 on error.\n\n"
5263          | RInt _ ->
5264              pr "On error this function returns -1.\n\n"
5265          | RInt64 _ ->
5266              pr "On error this function returns -1.\n\n"
5267          | RBool _ ->
5268              pr "This function returns a C truth value on success or -1 on error.\n\n"
5269          | RConstString _ ->
5270              pr "This function returns a string, or NULL on error.
5271 The string is owned by the guest handle and must I<not> be freed.\n\n"
5272          | RConstOptString _ ->
5273              pr "This function returns a string which may be NULL.
5274 There is way to return an error from this function.
5275 The string is owned by the guest handle and must I<not> be freed.\n\n"
5276          | RString _ ->
5277              pr "This function returns a string, or NULL on error.
5278 I<The caller must free the returned string after use>.\n\n"
5279          | RStringList _ ->
5280              pr "This function returns a NULL-terminated array of strings
5281 (like L<environ(3)>), or NULL if there was an error.
5282 I<The caller must free the strings and the array after use>.\n\n"
5283          | RStruct (_, typ) ->
5284              pr "This function returns a C<struct guestfs_%s *>,
5285 or NULL if there was an error.
5286 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5287          | RStructList (_, typ) ->
5288              pr "This function returns a C<struct guestfs_%s_list *>
5289 (see E<lt>guestfs-structs.hE<gt>),
5290 or NULL if there was an error.
5291 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5292          | RHashtable _ ->
5293              pr "This function returns a NULL-terminated array of
5294 strings, or NULL if there was an error.
5295 The array of strings will always have length C<2n+1>, where
5296 C<n> keys and values alternate, followed by the trailing NULL entry.
5297 I<The caller must free the strings and the array after use>.\n\n"
5298          | RBufferOut _ ->
5299              pr "This function returns a buffer, or NULL on error.
5300 The size of the returned buffer is written to C<*size_r>.
5301 I<The caller must free the returned buffer after use>.\n\n"
5302         );
5303         if List.mem ProtocolLimitWarning flags then
5304           pr "%s\n\n" protocol_limit_warning;
5305         if List.mem DangerWillRobinson flags then
5306           pr "%s\n\n" danger_will_robinson;
5307         match deprecation_notice flags with
5308         | None -> ()
5309         | Some txt -> pr "%s\n\n" txt
5310       )
5311   ) all_functions_sorted
5312
5313 and generate_structs_pod () =
5314   (* Structs documentation. *)
5315   List.iter (
5316     fun (typ, cols) ->
5317       pr "=head2 guestfs_%s\n" typ;
5318       pr "\n";
5319       pr " struct guestfs_%s {\n" typ;
5320       List.iter (
5321         function
5322         | name, FChar -> pr "   char %s;\n" name
5323         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5324         | name, FInt32 -> pr "   int32_t %s;\n" name
5325         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5326         | name, FInt64 -> pr "   int64_t %s;\n" name
5327         | name, FString -> pr "   char *%s;\n" name
5328         | name, FBuffer ->
5329             pr "   /* The next two fields describe a byte array. */\n";
5330             pr "   uint32_t %s_len;\n" name;
5331             pr "   char *%s;\n" name
5332         | name, FUUID ->
5333             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5334             pr "   char %s[32];\n" name
5335         | name, FOptPercent ->
5336             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5337             pr "   float %s;\n" name
5338       ) cols;
5339       pr " };\n";
5340       pr " \n";
5341       pr " struct guestfs_%s_list {\n" typ;
5342       pr "   uint32_t len; /* Number of elements in list. */\n";
5343       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5344       pr " };\n";
5345       pr " \n";
5346       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5347       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5348         typ typ;
5349       pr "\n"
5350   ) structs
5351
5352 and generate_availability_pod () =
5353   (* Availability documentation. *)
5354   pr "=over 4\n";
5355   pr "\n";
5356   List.iter (
5357     fun (group, functions) ->
5358       pr "=item B<%s>\n" group;
5359       pr "\n";
5360       pr "The following functions:\n";
5361       List.iter (pr "L</guestfs_%s>\n") functions;
5362       pr "\n"
5363   ) optgroups;
5364   pr "=back\n";
5365   pr "\n"
5366
5367 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5368  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5369  *
5370  * We have to use an underscore instead of a dash because otherwise
5371  * rpcgen generates incorrect code.
5372  *
5373  * This header is NOT exported to clients, but see also generate_structs_h.
5374  *)
5375 and generate_xdr () =
5376   generate_header CStyle LGPLv2plus;
5377
5378   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5379   pr "typedef string str<>;\n";
5380   pr "\n";
5381
5382   (* Internal structures. *)
5383   List.iter (
5384     function
5385     | typ, cols ->
5386         pr "struct guestfs_int_%s {\n" typ;
5387         List.iter (function
5388                    | name, FChar -> pr "  char %s;\n" name
5389                    | name, FString -> pr "  string %s<>;\n" name
5390                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5391                    | name, FUUID -> pr "  opaque %s[32];\n" name
5392                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5393                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5394                    | name, FOptPercent -> pr "  float %s;\n" name
5395                   ) cols;
5396         pr "};\n";
5397         pr "\n";
5398         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5399         pr "\n";
5400   ) structs;
5401
5402   List.iter (
5403     fun (shortname, style, _, _, _, _, _) ->
5404       let name = "guestfs_" ^ shortname in
5405
5406       (match snd style with
5407        | [] -> ()
5408        | args ->
5409            pr "struct %s_args {\n" name;
5410            List.iter (
5411              function
5412              | Pathname n | Device n | Dev_or_Path n | String n ->
5413                  pr "  string %s<>;\n" n
5414              | OptString n -> pr "  str *%s;\n" n
5415              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5416              | Bool n -> pr "  bool %s;\n" n
5417              | Int n -> pr "  int %s;\n" n
5418              | Int64 n -> pr "  hyper %s;\n" n
5419              | FileIn _ | FileOut _ -> ()
5420            ) args;
5421            pr "};\n\n"
5422       );
5423       (match fst style with
5424        | RErr -> ()
5425        | RInt n ->
5426            pr "struct %s_ret {\n" name;
5427            pr "  int %s;\n" n;
5428            pr "};\n\n"
5429        | RInt64 n ->
5430            pr "struct %s_ret {\n" name;
5431            pr "  hyper %s;\n" n;
5432            pr "};\n\n"
5433        | RBool n ->
5434            pr "struct %s_ret {\n" name;
5435            pr "  bool %s;\n" n;
5436            pr "};\n\n"
5437        | RConstString _ | RConstOptString _ ->
5438            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5439        | RString n ->
5440            pr "struct %s_ret {\n" name;
5441            pr "  string %s<>;\n" n;
5442            pr "};\n\n"
5443        | RStringList n ->
5444            pr "struct %s_ret {\n" name;
5445            pr "  str %s<>;\n" n;
5446            pr "};\n\n"
5447        | RStruct (n, typ) ->
5448            pr "struct %s_ret {\n" name;
5449            pr "  guestfs_int_%s %s;\n" typ n;
5450            pr "};\n\n"
5451        | RStructList (n, typ) ->
5452            pr "struct %s_ret {\n" name;
5453            pr "  guestfs_int_%s_list %s;\n" typ n;
5454            pr "};\n\n"
5455        | RHashtable n ->
5456            pr "struct %s_ret {\n" name;
5457            pr "  str %s<>;\n" n;
5458            pr "};\n\n"
5459        | RBufferOut n ->
5460            pr "struct %s_ret {\n" name;
5461            pr "  opaque %s<>;\n" n;
5462            pr "};\n\n"
5463       );
5464   ) daemon_functions;
5465
5466   (* Table of procedure numbers. *)
5467   pr "enum guestfs_procedure {\n";
5468   List.iter (
5469     fun (shortname, _, proc_nr, _, _, _, _) ->
5470       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5471   ) daemon_functions;
5472   pr "  GUESTFS_PROC_NR_PROCS\n";
5473   pr "};\n";
5474   pr "\n";
5475
5476   (* Having to choose a maximum message size is annoying for several
5477    * reasons (it limits what we can do in the API), but it (a) makes
5478    * the protocol a lot simpler, and (b) provides a bound on the size
5479    * of the daemon which operates in limited memory space.
5480    *)
5481   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5482   pr "\n";
5483
5484   (* Message header, etc. *)
5485   pr "\
5486 /* The communication protocol is now documented in the guestfs(3)
5487  * manpage.
5488  */
5489
5490 const GUESTFS_PROGRAM = 0x2000F5F5;
5491 const GUESTFS_PROTOCOL_VERSION = 1;
5492
5493 /* These constants must be larger than any possible message length. */
5494 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5495 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5496
5497 enum guestfs_message_direction {
5498   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5499   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5500 };
5501
5502 enum guestfs_message_status {
5503   GUESTFS_STATUS_OK = 0,
5504   GUESTFS_STATUS_ERROR = 1
5505 };
5506
5507 const GUESTFS_ERROR_LEN = 256;
5508
5509 struct guestfs_message_error {
5510   string error_message<GUESTFS_ERROR_LEN>;
5511 };
5512
5513 struct guestfs_message_header {
5514   unsigned prog;                     /* GUESTFS_PROGRAM */
5515   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5516   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5517   guestfs_message_direction direction;
5518   unsigned serial;                   /* message serial number */
5519   guestfs_message_status status;
5520 };
5521
5522 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5523
5524 struct guestfs_chunk {
5525   int cancel;                        /* if non-zero, transfer is cancelled */
5526   /* data size is 0 bytes if the transfer has finished successfully */
5527   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5528 };
5529 "
5530
5531 (* Generate the guestfs-structs.h file. *)
5532 and generate_structs_h () =
5533   generate_header CStyle LGPLv2plus;
5534
5535   (* This is a public exported header file containing various
5536    * structures.  The structures are carefully written to have
5537    * exactly the same in-memory format as the XDR structures that
5538    * we use on the wire to the daemon.  The reason for creating
5539    * copies of these structures here is just so we don't have to
5540    * export the whole of guestfs_protocol.h (which includes much
5541    * unrelated and XDR-dependent stuff that we don't want to be
5542    * public, or required by clients).
5543    *
5544    * To reiterate, we will pass these structures to and from the
5545    * client with a simple assignment or memcpy, so the format
5546    * must be identical to what rpcgen / the RFC defines.
5547    *)
5548
5549   (* Public structures. *)
5550   List.iter (
5551     fun (typ, cols) ->
5552       pr "struct guestfs_%s {\n" typ;
5553       List.iter (
5554         function
5555         | name, FChar -> pr "  char %s;\n" name
5556         | name, FString -> pr "  char *%s;\n" name
5557         | name, FBuffer ->
5558             pr "  uint32_t %s_len;\n" name;
5559             pr "  char *%s;\n" name
5560         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5561         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5562         | name, FInt32 -> pr "  int32_t %s;\n" name
5563         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5564         | name, FInt64 -> pr "  int64_t %s;\n" name
5565         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5566       ) cols;
5567       pr "};\n";
5568       pr "\n";
5569       pr "struct guestfs_%s_list {\n" typ;
5570       pr "  uint32_t len;\n";
5571       pr "  struct guestfs_%s *val;\n" typ;
5572       pr "};\n";
5573       pr "\n";
5574       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5575       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5576       pr "\n"
5577   ) structs
5578
5579 (* Generate the guestfs-actions.h file. *)
5580 and generate_actions_h () =
5581   generate_header CStyle LGPLv2plus;
5582   List.iter (
5583     fun (shortname, style, _, _, _, _, _) ->
5584       let name = "guestfs_" ^ shortname in
5585       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5586         name style
5587   ) all_functions
5588
5589 (* Generate the guestfs-internal-actions.h file. *)
5590 and generate_internal_actions_h () =
5591   generate_header CStyle LGPLv2plus;
5592   List.iter (
5593     fun (shortname, style, _, _, _, _, _) ->
5594       let name = "guestfs__" ^ shortname in
5595       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5596         name style
5597   ) non_daemon_functions
5598
5599 (* Generate the client-side dispatch stubs. *)
5600 and generate_client_actions () =
5601   generate_header CStyle LGPLv2plus;
5602
5603   pr "\
5604 #include <stdio.h>
5605 #include <stdlib.h>
5606 #include <stdint.h>
5607 #include <string.h>
5608 #include <inttypes.h>
5609
5610 #include \"guestfs.h\"
5611 #include \"guestfs-internal.h\"
5612 #include \"guestfs-internal-actions.h\"
5613 #include \"guestfs_protocol.h\"
5614
5615 #define error guestfs_error
5616 //#define perrorf guestfs_perrorf
5617 #define safe_malloc guestfs_safe_malloc
5618 #define safe_realloc guestfs_safe_realloc
5619 //#define safe_strdup guestfs_safe_strdup
5620 #define safe_memdup guestfs_safe_memdup
5621
5622 /* Check the return message from a call for validity. */
5623 static int
5624 check_reply_header (guestfs_h *g,
5625                     const struct guestfs_message_header *hdr,
5626                     unsigned int proc_nr, unsigned int serial)
5627 {
5628   if (hdr->prog != GUESTFS_PROGRAM) {
5629     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5630     return -1;
5631   }
5632   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5633     error (g, \"wrong protocol version (%%d/%%d)\",
5634            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5635     return -1;
5636   }
5637   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5638     error (g, \"unexpected message direction (%%d/%%d)\",
5639            hdr->direction, GUESTFS_DIRECTION_REPLY);
5640     return -1;
5641   }
5642   if (hdr->proc != proc_nr) {
5643     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5644     return -1;
5645   }
5646   if (hdr->serial != serial) {
5647     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5648     return -1;
5649   }
5650
5651   return 0;
5652 }
5653
5654 /* Check we are in the right state to run a high-level action. */
5655 static int
5656 check_state (guestfs_h *g, const char *caller)
5657 {
5658   if (!guestfs__is_ready (g)) {
5659     if (guestfs__is_config (g) || guestfs__is_launching (g))
5660       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5661         caller);
5662     else
5663       error (g, \"%%s called from the wrong state, %%d != READY\",
5664         caller, guestfs__get_state (g));
5665     return -1;
5666   }
5667   return 0;
5668 }
5669
5670 ";
5671
5672   (* Generate code to generate guestfish call traces. *)
5673   let trace_call shortname style =
5674     pr "  if (guestfs__get_trace (g)) {\n";
5675
5676     let needs_i =
5677       List.exists (function
5678                    | StringList _ | DeviceList _ -> true
5679                    | _ -> false) (snd style) in
5680     if needs_i then (
5681       pr "    int i;\n";
5682       pr "\n"
5683     );
5684
5685     pr "    printf (\"%s\");\n" shortname;
5686     List.iter (
5687       function
5688       | String n                        (* strings *)
5689       | Device n
5690       | Pathname n
5691       | Dev_or_Path n
5692       | FileIn n
5693       | FileOut n ->
5694           (* guestfish doesn't support string escaping, so neither do we *)
5695           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5696       | OptString n ->                  (* string option *)
5697           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5698           pr "    else printf (\" null\");\n"
5699       | StringList n
5700       | DeviceList n ->                 (* string list *)
5701           pr "    putchar (' ');\n";
5702           pr "    putchar ('\"');\n";
5703           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5704           pr "      if (i > 0) putchar (' ');\n";
5705           pr "      fputs (%s[i], stdout);\n" n;
5706           pr "    }\n";
5707           pr "    putchar ('\"');\n";
5708       | Bool n ->                       (* boolean *)
5709           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5710       | Int n ->                        (* int *)
5711           pr "    printf (\" %%d\", %s);\n" n
5712       | Int64 n ->
5713           pr "    printf (\" %%\" PRIi64, %s);\n" n
5714     ) (snd style);
5715     pr "    putchar ('\\n');\n";
5716     pr "  }\n";
5717     pr "\n";
5718   in
5719
5720   (* For non-daemon functions, generate a wrapper around each function. *)
5721   List.iter (
5722     fun (shortname, style, _, _, _, _, _) ->
5723       let name = "guestfs_" ^ shortname in
5724
5725       generate_prototype ~extern:false ~semicolon:false ~newline:true
5726         ~handle:"g" name style;
5727       pr "{\n";
5728       trace_call shortname style;
5729       pr "  return guestfs__%s " shortname;
5730       generate_c_call_args ~handle:"g" style;
5731       pr ";\n";
5732       pr "}\n";
5733       pr "\n"
5734   ) non_daemon_functions;
5735
5736   (* Client-side stubs for each function. *)
5737   List.iter (
5738     fun (shortname, style, _, _, _, _, _) ->
5739       let name = "guestfs_" ^ shortname in
5740
5741       (* Generate the action stub. *)
5742       generate_prototype ~extern:false ~semicolon:false ~newline:true
5743         ~handle:"g" name style;
5744
5745       let error_code =
5746         match fst style with
5747         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5748         | RConstString _ | RConstOptString _ ->
5749             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5750         | RString _ | RStringList _
5751         | RStruct _ | RStructList _
5752         | RHashtable _ | RBufferOut _ ->
5753             "NULL" in
5754
5755       pr "{\n";
5756
5757       (match snd style with
5758        | [] -> ()
5759        | _ -> pr "  struct %s_args args;\n" name
5760       );
5761
5762       pr "  guestfs_message_header hdr;\n";
5763       pr "  guestfs_message_error err;\n";
5764       let has_ret =
5765         match fst style with
5766         | RErr -> false
5767         | RConstString _ | RConstOptString _ ->
5768             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5769         | RInt _ | RInt64 _
5770         | RBool _ | RString _ | RStringList _
5771         | RStruct _ | RStructList _
5772         | RHashtable _ | RBufferOut _ ->
5773             pr "  struct %s_ret ret;\n" name;
5774             true in
5775
5776       pr "  int serial;\n";
5777       pr "  int r;\n";
5778       pr "\n";
5779       trace_call shortname style;
5780       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5781         shortname error_code;
5782       pr "  guestfs___set_busy (g);\n";
5783       pr "\n";
5784
5785       (* Send the main header and arguments. *)
5786       (match snd style with
5787        | [] ->
5788            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5789              (String.uppercase shortname)
5790        | args ->
5791            List.iter (
5792              function
5793              | Pathname n | Device n | Dev_or_Path n | String n ->
5794                  pr "  args.%s = (char *) %s;\n" n n
5795              | OptString n ->
5796                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5797              | StringList n | DeviceList n ->
5798                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5799                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5800              | Bool n ->
5801                  pr "  args.%s = %s;\n" n n
5802              | Int n ->
5803                  pr "  args.%s = %s;\n" n n
5804              | Int64 n ->
5805                  pr "  args.%s = %s;\n" n n
5806              | FileIn _ | FileOut _ -> ()
5807            ) args;
5808            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5809              (String.uppercase shortname);
5810            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5811              name;
5812       );
5813       pr "  if (serial == -1) {\n";
5814       pr "    guestfs___end_busy (g);\n";
5815       pr "    return %s;\n" error_code;
5816       pr "  }\n";
5817       pr "\n";
5818
5819       (* Send any additional files (FileIn) requested. *)
5820       let need_read_reply_label = ref false in
5821       List.iter (
5822         function
5823         | FileIn n ->
5824             pr "  r = guestfs___send_file (g, %s);\n" n;
5825             pr "  if (r == -1) {\n";
5826             pr "    guestfs___end_busy (g);\n";
5827             pr "    return %s;\n" error_code;
5828             pr "  }\n";
5829             pr "  if (r == -2) /* daemon cancelled */\n";
5830             pr "    goto read_reply;\n";
5831             need_read_reply_label := true;
5832             pr "\n";
5833         | _ -> ()
5834       ) (snd style);
5835
5836       (* Wait for the reply from the remote end. *)
5837       if !need_read_reply_label then pr " read_reply:\n";
5838       pr "  memset (&hdr, 0, sizeof hdr);\n";
5839       pr "  memset (&err, 0, sizeof err);\n";
5840       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5841       pr "\n";
5842       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5843       if not has_ret then
5844         pr "NULL, NULL"
5845       else
5846         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5847       pr ");\n";
5848
5849       pr "  if (r == -1) {\n";
5850       pr "    guestfs___end_busy (g);\n";
5851       pr "    return %s;\n" error_code;
5852       pr "  }\n";
5853       pr "\n";
5854
5855       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5856         (String.uppercase shortname);
5857       pr "    guestfs___end_busy (g);\n";
5858       pr "    return %s;\n" error_code;
5859       pr "  }\n";
5860       pr "\n";
5861
5862       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5863       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5864       pr "    free (err.error_message);\n";
5865       pr "    guestfs___end_busy (g);\n";
5866       pr "    return %s;\n" error_code;
5867       pr "  }\n";
5868       pr "\n";
5869
5870       (* Expecting to receive further files (FileOut)? *)
5871       List.iter (
5872         function
5873         | FileOut n ->
5874             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5875             pr "    guestfs___end_busy (g);\n";
5876             pr "    return %s;\n" error_code;
5877             pr "  }\n";
5878             pr "\n";
5879         | _ -> ()
5880       ) (snd style);
5881
5882       pr "  guestfs___end_busy (g);\n";
5883
5884       (match fst style with
5885        | RErr -> pr "  return 0;\n"
5886        | RInt n | RInt64 n | RBool n ->
5887            pr "  return ret.%s;\n" n
5888        | RConstString _ | RConstOptString _ ->
5889            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5890        | RString n ->
5891            pr "  return ret.%s; /* caller will free */\n" n
5892        | RStringList n | RHashtable n ->
5893            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5894            pr "  ret.%s.%s_val =\n" n n;
5895            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5896            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5897              n n;
5898            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5899            pr "  return ret.%s.%s_val;\n" n n
5900        | RStruct (n, _) ->
5901            pr "  /* caller will free this */\n";
5902            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5903        | RStructList (n, _) ->
5904            pr "  /* caller will free this */\n";
5905            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5906        | RBufferOut n ->
5907            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5908            pr "   * _val might be NULL here.  To make the API saner for\n";
5909            pr "   * callers, we turn this case into a unique pointer (using\n";
5910            pr "   * malloc(1)).\n";
5911            pr "   */\n";
5912            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5913            pr "    *size_r = ret.%s.%s_len;\n" n n;
5914            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5915            pr "  } else {\n";
5916            pr "    free (ret.%s.%s_val);\n" n n;
5917            pr "    char *p = safe_malloc (g, 1);\n";
5918            pr "    *size_r = ret.%s.%s_len;\n" n n;
5919            pr "    return p;\n";
5920            pr "  }\n";
5921       );
5922
5923       pr "}\n\n"
5924   ) daemon_functions;
5925
5926   (* Functions to free structures. *)
5927   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5928   pr " * structure format is identical to the XDR format.  See note in\n";
5929   pr " * generator.ml.\n";
5930   pr " */\n";
5931   pr "\n";
5932
5933   List.iter (
5934     fun (typ, _) ->
5935       pr "void\n";
5936       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5937       pr "{\n";
5938       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5939       pr "  free (x);\n";
5940       pr "}\n";
5941       pr "\n";
5942
5943       pr "void\n";
5944       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5945       pr "{\n";
5946       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5947       pr "  free (x);\n";
5948       pr "}\n";
5949       pr "\n";
5950
5951   ) structs;
5952
5953 (* Generate daemon/actions.h. *)
5954 and generate_daemon_actions_h () =
5955   generate_header CStyle GPLv2plus;
5956
5957   pr "#include \"../src/guestfs_protocol.h\"\n";
5958   pr "\n";
5959
5960   List.iter (
5961     fun (name, style, _, _, _, _, _) ->
5962       generate_prototype
5963         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5964         name style;
5965   ) daemon_functions
5966
5967 (* Generate the linker script which controls the visibility of
5968  * symbols in the public ABI and ensures no other symbols get
5969  * exported accidentally.
5970  *)
5971 and generate_linker_script () =
5972   generate_header HashStyle GPLv2plus;
5973
5974   let globals = [
5975     "guestfs_create";
5976     "guestfs_close";
5977     "guestfs_get_error_handler";
5978     "guestfs_get_out_of_memory_handler";
5979     "guestfs_last_error";
5980     "guestfs_set_error_handler";
5981     "guestfs_set_launch_done_callback";
5982     "guestfs_set_log_message_callback";
5983     "guestfs_set_out_of_memory_handler";
5984     "guestfs_set_subprocess_quit_callback";
5985
5986     (* Unofficial parts of the API: the bindings code use these
5987      * functions, so it is useful to export them.
5988      *)
5989     "guestfs_safe_calloc";
5990     "guestfs_safe_malloc";
5991   ] in
5992   let functions =
5993     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5994       all_functions in
5995   let structs =
5996     List.concat (
5997       List.map (fun (typ, _) ->
5998                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5999         structs
6000     ) in
6001   let globals = List.sort compare (globals @ functions @ structs) in
6002
6003   pr "{\n";
6004   pr "    global:\n";
6005   List.iter (pr "        %s;\n") globals;
6006   pr "\n";
6007
6008   pr "    local:\n";
6009   pr "        *;\n";
6010   pr "};\n"
6011
6012 (* Generate the server-side stubs. *)
6013 and generate_daemon_actions () =
6014   generate_header CStyle GPLv2plus;
6015
6016   pr "#include <config.h>\n";
6017   pr "\n";
6018   pr "#include <stdio.h>\n";
6019   pr "#include <stdlib.h>\n";
6020   pr "#include <string.h>\n";
6021   pr "#include <inttypes.h>\n";
6022   pr "#include <rpc/types.h>\n";
6023   pr "#include <rpc/xdr.h>\n";
6024   pr "\n";
6025   pr "#include \"daemon.h\"\n";
6026   pr "#include \"c-ctype.h\"\n";
6027   pr "#include \"../src/guestfs_protocol.h\"\n";
6028   pr "#include \"actions.h\"\n";
6029   pr "\n";
6030
6031   List.iter (
6032     fun (name, style, _, _, _, _, _) ->
6033       (* Generate server-side stubs. *)
6034       pr "static void %s_stub (XDR *xdr_in)\n" name;
6035       pr "{\n";
6036       let error_code =
6037         match fst style with
6038         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6039         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6040         | RBool _ -> pr "  int r;\n"; "-1"
6041         | RConstString _ | RConstOptString _ ->
6042             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6043         | RString _ -> pr "  char *r;\n"; "NULL"
6044         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6045         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6046         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6047         | RBufferOut _ ->
6048             pr "  size_t size = 1;\n";
6049             pr "  char *r;\n";
6050             "NULL" in
6051
6052       (match snd style with
6053        | [] -> ()
6054        | args ->
6055            pr "  struct guestfs_%s_args args;\n" name;
6056            List.iter (
6057              function
6058              | Device n | Dev_or_Path n
6059              | Pathname n
6060              | String n -> ()
6061              | OptString n -> pr "  char *%s;\n" n
6062              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6063              | Bool n -> pr "  int %s;\n" n
6064              | Int n -> pr "  int %s;\n" n
6065              | Int64 n -> pr "  int64_t %s;\n" n
6066              | FileIn _ | FileOut _ -> ()
6067            ) args
6068       );
6069       pr "\n";
6070
6071       let is_filein =
6072         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6073
6074       (match snd style with
6075        | [] -> ()
6076        | args ->
6077            pr "  memset (&args, 0, sizeof args);\n";
6078            pr "\n";
6079            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6080            if is_filein then
6081              pr "    cancel_receive ();\n";
6082            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6083            pr "    goto done;\n";
6084            pr "  }\n";
6085            let pr_args n =
6086              pr "  char *%s = args.%s;\n" n n
6087            in
6088            let pr_list_handling_code n =
6089              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6090              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6091              pr "  if (%s == NULL) {\n" n;
6092              if is_filein then
6093                pr "    cancel_receive ();\n";
6094              pr "    reply_with_perror (\"realloc\");\n";
6095              pr "    goto done;\n";
6096              pr "  }\n";
6097              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6098              pr "  args.%s.%s_val = %s;\n" n n n;
6099            in
6100            List.iter (
6101              function
6102              | Pathname n ->
6103                  pr_args n;
6104                  pr "  ABS_PATH (%s, %s, goto done);\n"
6105                    n (if is_filein then "cancel_receive ()" else "");
6106              | Device n ->
6107                  pr_args n;
6108                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6109                    n (if is_filein then "cancel_receive ()" else "");
6110              | Dev_or_Path n ->
6111                  pr_args n;
6112                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6113                    n (if is_filein then "cancel_receive ()" else "");
6114              | String n -> pr_args n
6115              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6116              | StringList n ->
6117                  pr_list_handling_code n;
6118              | DeviceList n ->
6119                  pr_list_handling_code n;
6120                  pr "  /* Ensure that each is a device,\n";
6121                  pr "   * and perform device name translation. */\n";
6122                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6123                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6124                    (if is_filein then "cancel_receive ()" else "");
6125                  pr "  }\n";
6126              | Bool n -> pr "  %s = args.%s;\n" n n
6127              | Int n -> pr "  %s = args.%s;\n" n n
6128              | Int64 n -> pr "  %s = args.%s;\n" n n
6129              | FileIn _ | FileOut _ -> ()
6130            ) args;
6131            pr "\n"
6132       );
6133
6134
6135       (* this is used at least for do_equal *)
6136       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6137         (* Emit NEED_ROOT just once, even when there are two or
6138            more Pathname args *)
6139         pr "  NEED_ROOT (%s, goto done);\n"
6140           (if is_filein then "cancel_receive ()" else "");
6141       );
6142
6143       (* Don't want to call the impl with any FileIn or FileOut
6144        * parameters, since these go "outside" the RPC protocol.
6145        *)
6146       let args' =
6147         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6148           (snd style) in
6149       pr "  r = do_%s " name;
6150       generate_c_call_args (fst style, args');
6151       pr ";\n";
6152
6153       (match fst style with
6154        | RErr | RInt _ | RInt64 _ | RBool _
6155        | RConstString _ | RConstOptString _
6156        | RString _ | RStringList _ | RHashtable _
6157        | RStruct (_, _) | RStructList (_, _) ->
6158            pr "  if (r == %s)\n" error_code;
6159            pr "    /* do_%s has already called reply_with_error */\n" name;
6160            pr "    goto done;\n";
6161            pr "\n"
6162        | RBufferOut _ ->
6163            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6164            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6165            pr "   */\n";
6166            pr "  if (size == 1 && r == %s)\n" error_code;
6167            pr "    /* do_%s has already called reply_with_error */\n" name;
6168            pr "    goto done;\n";
6169            pr "\n"
6170       );
6171
6172       (* If there are any FileOut parameters, then the impl must
6173        * send its own reply.
6174        *)
6175       let no_reply =
6176         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6177       if no_reply then
6178         pr "  /* do_%s has already sent a reply */\n" name
6179       else (
6180         match fst style with
6181         | RErr -> pr "  reply (NULL, NULL);\n"
6182         | RInt n | RInt64 n | RBool n ->
6183             pr "  struct guestfs_%s_ret ret;\n" name;
6184             pr "  ret.%s = r;\n" n;
6185             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6186               name
6187         | RConstString _ | RConstOptString _ ->
6188             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6189         | RString n ->
6190             pr "  struct guestfs_%s_ret ret;\n" name;
6191             pr "  ret.%s = r;\n" n;
6192             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6193               name;
6194             pr "  free (r);\n"
6195         | RStringList n | RHashtable n ->
6196             pr "  struct guestfs_%s_ret ret;\n" name;
6197             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6198             pr "  ret.%s.%s_val = r;\n" n n;
6199             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6200               name;
6201             pr "  free_strings (r);\n"
6202         | RStruct (n, _) ->
6203             pr "  struct guestfs_%s_ret ret;\n" name;
6204             pr "  ret.%s = *r;\n" n;
6205             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6206               name;
6207             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6208               name
6209         | RStructList (n, _) ->
6210             pr "  struct guestfs_%s_ret ret;\n" name;
6211             pr "  ret.%s = *r;\n" n;
6212             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6213               name;
6214             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6215               name
6216         | RBufferOut n ->
6217             pr "  struct guestfs_%s_ret ret;\n" name;
6218             pr "  ret.%s.%s_val = r;\n" n n;
6219             pr "  ret.%s.%s_len = size;\n" n n;
6220             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6221               name;
6222             pr "  free (r);\n"
6223       );
6224
6225       (* Free the args. *)
6226       pr "done:\n";
6227       (match snd style with
6228        | [] -> ()
6229        | _ ->
6230            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6231              name
6232       );
6233       pr "  return;\n";
6234       pr "}\n\n";
6235   ) daemon_functions;
6236
6237   (* Dispatch function. *)
6238   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6239   pr "{\n";
6240   pr "  switch (proc_nr) {\n";
6241
6242   List.iter (
6243     fun (name, style, _, _, _, _, _) ->
6244       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6245       pr "      %s_stub (xdr_in);\n" name;
6246       pr "      break;\n"
6247   ) daemon_functions;
6248
6249   pr "    default:\n";
6250   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";
6251   pr "  }\n";
6252   pr "}\n";
6253   pr "\n";
6254
6255   (* LVM columns and tokenization functions. *)
6256   (* XXX This generates crap code.  We should rethink how we
6257    * do this parsing.
6258    *)
6259   List.iter (
6260     function
6261     | typ, cols ->
6262         pr "static const char *lvm_%s_cols = \"%s\";\n"
6263           typ (String.concat "," (List.map fst cols));
6264         pr "\n";
6265
6266         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6267         pr "{\n";
6268         pr "  char *tok, *p, *next;\n";
6269         pr "  int i, j;\n";
6270         pr "\n";
6271         (*
6272           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6273           pr "\n";
6274         *)
6275         pr "  if (!str) {\n";
6276         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6277         pr "    return -1;\n";
6278         pr "  }\n";
6279         pr "  if (!*str || c_isspace (*str)) {\n";
6280         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6281         pr "    return -1;\n";
6282         pr "  }\n";
6283         pr "  tok = str;\n";
6284         List.iter (
6285           fun (name, coltype) ->
6286             pr "  if (!tok) {\n";
6287             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6288             pr "    return -1;\n";
6289             pr "  }\n";
6290             pr "  p = strchrnul (tok, ',');\n";
6291             pr "  if (*p) next = p+1; else next = NULL;\n";
6292             pr "  *p = '\\0';\n";
6293             (match coltype with
6294              | FString ->
6295                  pr "  r->%s = strdup (tok);\n" name;
6296                  pr "  if (r->%s == NULL) {\n" name;
6297                  pr "    perror (\"strdup\");\n";
6298                  pr "    return -1;\n";
6299                  pr "  }\n"
6300              | FUUID ->
6301                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6302                  pr "    if (tok[j] == '\\0') {\n";
6303                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6304                  pr "      return -1;\n";
6305                  pr "    } else if (tok[j] != '-')\n";
6306                  pr "      r->%s[i++] = tok[j];\n" name;
6307                  pr "  }\n";
6308              | FBytes ->
6309                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6310                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6311                  pr "    return -1;\n";
6312                  pr "  }\n";
6313              | FInt64 ->
6314                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6315                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6316                  pr "    return -1;\n";
6317                  pr "  }\n";
6318              | FOptPercent ->
6319                  pr "  if (tok[0] == '\\0')\n";
6320                  pr "    r->%s = -1;\n" name;
6321                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6322                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6323                  pr "    return -1;\n";
6324                  pr "  }\n";
6325              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6326                  assert false (* can never be an LVM column *)
6327             );
6328             pr "  tok = next;\n";
6329         ) cols;
6330
6331         pr "  if (tok != NULL) {\n";
6332         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6333         pr "    return -1;\n";
6334         pr "  }\n";
6335         pr "  return 0;\n";
6336         pr "}\n";
6337         pr "\n";
6338
6339         pr "guestfs_int_lvm_%s_list *\n" typ;
6340         pr "parse_command_line_%ss (void)\n" typ;
6341         pr "{\n";
6342         pr "  char *out, *err;\n";
6343         pr "  char *p, *pend;\n";
6344         pr "  int r, i;\n";
6345         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6346         pr "  void *newp;\n";
6347         pr "\n";
6348         pr "  ret = malloc (sizeof *ret);\n";
6349         pr "  if (!ret) {\n";
6350         pr "    reply_with_perror (\"malloc\");\n";
6351         pr "    return NULL;\n";
6352         pr "  }\n";
6353         pr "\n";
6354         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6355         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6356         pr "\n";
6357         pr "  r = command (&out, &err,\n";
6358         pr "           \"lvm\", \"%ss\",\n" typ;
6359         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6360         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6361         pr "  if (r == -1) {\n";
6362         pr "    reply_with_error (\"%%s\", err);\n";
6363         pr "    free (out);\n";
6364         pr "    free (err);\n";
6365         pr "    free (ret);\n";
6366         pr "    return NULL;\n";
6367         pr "  }\n";
6368         pr "\n";
6369         pr "  free (err);\n";
6370         pr "\n";
6371         pr "  /* Tokenize each line of the output. */\n";
6372         pr "  p = out;\n";
6373         pr "  i = 0;\n";
6374         pr "  while (p) {\n";
6375         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6376         pr "    if (pend) {\n";
6377         pr "      *pend = '\\0';\n";
6378         pr "      pend++;\n";
6379         pr "    }\n";
6380         pr "\n";
6381         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6382         pr "      p++;\n";
6383         pr "\n";
6384         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6385         pr "      p = pend;\n";
6386         pr "      continue;\n";
6387         pr "    }\n";
6388         pr "\n";
6389         pr "    /* Allocate some space to store this next entry. */\n";
6390         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6391         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6392         pr "    if (newp == NULL) {\n";
6393         pr "      reply_with_perror (\"realloc\");\n";
6394         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6395         pr "      free (ret);\n";
6396         pr "      free (out);\n";
6397         pr "      return NULL;\n";
6398         pr "    }\n";
6399         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6400         pr "\n";
6401         pr "    /* Tokenize the next entry. */\n";
6402         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6403         pr "    if (r == -1) {\n";
6404         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6405         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6406         pr "      free (ret);\n";
6407         pr "      free (out);\n";
6408         pr "      return NULL;\n";
6409         pr "    }\n";
6410         pr "\n";
6411         pr "    ++i;\n";
6412         pr "    p = pend;\n";
6413         pr "  }\n";
6414         pr "\n";
6415         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6416         pr "\n";
6417         pr "  free (out);\n";
6418         pr "  return ret;\n";
6419         pr "}\n"
6420
6421   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6422
6423 (* Generate a list of function names, for debugging in the daemon.. *)
6424 and generate_daemon_names () =
6425   generate_header CStyle GPLv2plus;
6426
6427   pr "#include <config.h>\n";
6428   pr "\n";
6429   pr "#include \"daemon.h\"\n";
6430   pr "\n";
6431
6432   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6433   pr "const char *function_names[] = {\n";
6434   List.iter (
6435     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6436   ) daemon_functions;
6437   pr "};\n";
6438
6439 (* Generate the optional groups for the daemon to implement
6440  * guestfs_available.
6441  *)
6442 and generate_daemon_optgroups_c () =
6443   generate_header CStyle GPLv2plus;
6444
6445   pr "#include <config.h>\n";
6446   pr "\n";
6447   pr "#include \"daemon.h\"\n";
6448   pr "#include \"optgroups.h\"\n";
6449   pr "\n";
6450
6451   pr "struct optgroup optgroups[] = {\n";
6452   List.iter (
6453     fun (group, _) ->
6454       pr "  { \"%s\", optgroup_%s_available },\n" group group
6455   ) optgroups;
6456   pr "  { NULL, NULL }\n";
6457   pr "};\n"
6458
6459 and generate_daemon_optgroups_h () =
6460   generate_header CStyle GPLv2plus;
6461
6462   List.iter (
6463     fun (group, _) ->
6464       pr "extern int optgroup_%s_available (void);\n" group
6465   ) optgroups
6466
6467 (* Generate the tests. *)
6468 and generate_tests () =
6469   generate_header CStyle GPLv2plus;
6470
6471   pr "\
6472 #include <stdio.h>
6473 #include <stdlib.h>
6474 #include <string.h>
6475 #include <unistd.h>
6476 #include <sys/types.h>
6477 #include <fcntl.h>
6478
6479 #include \"guestfs.h\"
6480 #include \"guestfs-internal.h\"
6481
6482 static guestfs_h *g;
6483 static int suppress_error = 0;
6484
6485 static void print_error (guestfs_h *g, void *data, const char *msg)
6486 {
6487   if (!suppress_error)
6488     fprintf (stderr, \"%%s\\n\", msg);
6489 }
6490
6491 /* FIXME: nearly identical code appears in fish.c */
6492 static void print_strings (char *const *argv)
6493 {
6494   int argc;
6495
6496   for (argc = 0; argv[argc] != NULL; ++argc)
6497     printf (\"\\t%%s\\n\", argv[argc]);
6498 }
6499
6500 /*
6501 static void print_table (char const *const *argv)
6502 {
6503   int i;
6504
6505   for (i = 0; argv[i] != NULL; i += 2)
6506     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6507 }
6508 */
6509
6510 ";
6511
6512   (* Generate a list of commands which are not tested anywhere. *)
6513   pr "static void no_test_warnings (void)\n";
6514   pr "{\n";
6515
6516   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6517   List.iter (
6518     fun (_, _, _, _, tests, _, _) ->
6519       let tests = filter_map (
6520         function
6521         | (_, (Always|If _|Unless _), test) -> Some test
6522         | (_, Disabled, _) -> None
6523       ) tests in
6524       let seq = List.concat (List.map seq_of_test tests) in
6525       let cmds_tested = List.map List.hd seq in
6526       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6527   ) all_functions;
6528
6529   List.iter (
6530     fun (name, _, _, _, _, _, _) ->
6531       if not (Hashtbl.mem hash name) then
6532         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6533   ) all_functions;
6534
6535   pr "}\n";
6536   pr "\n";
6537
6538   (* Generate the actual tests.  Note that we generate the tests
6539    * in reverse order, deliberately, so that (in general) the
6540    * newest tests run first.  This makes it quicker and easier to
6541    * debug them.
6542    *)
6543   let test_names =
6544     List.map (
6545       fun (name, _, _, flags, tests, _, _) ->
6546         mapi (generate_one_test name flags) tests
6547     ) (List.rev all_functions) in
6548   let test_names = List.concat test_names in
6549   let nr_tests = List.length test_names in
6550
6551   pr "\
6552 int main (int argc, char *argv[])
6553 {
6554   char c = 0;
6555   unsigned long int n_failed = 0;
6556   const char *filename;
6557   int fd;
6558   int nr_tests, test_num = 0;
6559
6560   setbuf (stdout, NULL);
6561
6562   no_test_warnings ();
6563
6564   g = guestfs_create ();
6565   if (g == NULL) {
6566     printf (\"guestfs_create FAILED\\n\");
6567     exit (EXIT_FAILURE);
6568   }
6569
6570   guestfs_set_error_handler (g, print_error, NULL);
6571
6572   guestfs_set_path (g, \"../appliance\");
6573
6574   filename = \"test1.img\";
6575   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6576   if (fd == -1) {
6577     perror (filename);
6578     exit (EXIT_FAILURE);
6579   }
6580   if (lseek (fd, %d, SEEK_SET) == -1) {
6581     perror (\"lseek\");
6582     close (fd);
6583     unlink (filename);
6584     exit (EXIT_FAILURE);
6585   }
6586   if (write (fd, &c, 1) == -1) {
6587     perror (\"write\");
6588     close (fd);
6589     unlink (filename);
6590     exit (EXIT_FAILURE);
6591   }
6592   if (close (fd) == -1) {
6593     perror (filename);
6594     unlink (filename);
6595     exit (EXIT_FAILURE);
6596   }
6597   if (guestfs_add_drive (g, filename) == -1) {
6598     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6599     exit (EXIT_FAILURE);
6600   }
6601
6602   filename = \"test2.img\";
6603   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6604   if (fd == -1) {
6605     perror (filename);
6606     exit (EXIT_FAILURE);
6607   }
6608   if (lseek (fd, %d, SEEK_SET) == -1) {
6609     perror (\"lseek\");
6610     close (fd);
6611     unlink (filename);
6612     exit (EXIT_FAILURE);
6613   }
6614   if (write (fd, &c, 1) == -1) {
6615     perror (\"write\");
6616     close (fd);
6617     unlink (filename);
6618     exit (EXIT_FAILURE);
6619   }
6620   if (close (fd) == -1) {
6621     perror (filename);
6622     unlink (filename);
6623     exit (EXIT_FAILURE);
6624   }
6625   if (guestfs_add_drive (g, filename) == -1) {
6626     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6627     exit (EXIT_FAILURE);
6628   }
6629
6630   filename = \"test3.img\";
6631   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6632   if (fd == -1) {
6633     perror (filename);
6634     exit (EXIT_FAILURE);
6635   }
6636   if (lseek (fd, %d, SEEK_SET) == -1) {
6637     perror (\"lseek\");
6638     close (fd);
6639     unlink (filename);
6640     exit (EXIT_FAILURE);
6641   }
6642   if (write (fd, &c, 1) == -1) {
6643     perror (\"write\");
6644     close (fd);
6645     unlink (filename);
6646     exit (EXIT_FAILURE);
6647   }
6648   if (close (fd) == -1) {
6649     perror (filename);
6650     unlink (filename);
6651     exit (EXIT_FAILURE);
6652   }
6653   if (guestfs_add_drive (g, filename) == -1) {
6654     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6655     exit (EXIT_FAILURE);
6656   }
6657
6658   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6659     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6660     exit (EXIT_FAILURE);
6661   }
6662
6663   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6664   alarm (600);
6665
6666   if (guestfs_launch (g) == -1) {
6667     printf (\"guestfs_launch FAILED\\n\");
6668     exit (EXIT_FAILURE);
6669   }
6670
6671   /* Cancel previous alarm. */
6672   alarm (0);
6673
6674   nr_tests = %d;
6675
6676 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6677
6678   iteri (
6679     fun i test_name ->
6680       pr "  test_num++;\n";
6681       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6682       pr "  if (%s () == -1) {\n" test_name;
6683       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6684       pr "    n_failed++;\n";
6685       pr "  }\n";
6686   ) test_names;
6687   pr "\n";
6688
6689   pr "  guestfs_close (g);\n";
6690   pr "  unlink (\"test1.img\");\n";
6691   pr "  unlink (\"test2.img\");\n";
6692   pr "  unlink (\"test3.img\");\n";
6693   pr "\n";
6694
6695   pr "  if (n_failed > 0) {\n";
6696   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6697   pr "    exit (EXIT_FAILURE);\n";
6698   pr "  }\n";
6699   pr "\n";
6700
6701   pr "  exit (EXIT_SUCCESS);\n";
6702   pr "}\n"
6703
6704 and generate_one_test name flags i (init, prereq, test) =
6705   let test_name = sprintf "test_%s_%d" name i in
6706
6707   pr "\
6708 static int %s_skip (void)
6709 {
6710   const char *str;
6711
6712   str = getenv (\"TEST_ONLY\");
6713   if (str)
6714     return strstr (str, \"%s\") == NULL;
6715   str = getenv (\"SKIP_%s\");
6716   if (str && STREQ (str, \"1\")) return 1;
6717   str = getenv (\"SKIP_TEST_%s\");
6718   if (str && STREQ (str, \"1\")) return 1;
6719   return 0;
6720 }
6721
6722 " test_name name (String.uppercase test_name) (String.uppercase name);
6723
6724   (match prereq with
6725    | Disabled | Always -> ()
6726    | If code | Unless code ->
6727        pr "static int %s_prereq (void)\n" test_name;
6728        pr "{\n";
6729        pr "  %s\n" code;
6730        pr "}\n";
6731        pr "\n";
6732   );
6733
6734   pr "\
6735 static int %s (void)
6736 {
6737   if (%s_skip ()) {
6738     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6739     return 0;
6740   }
6741
6742 " test_name test_name test_name;
6743
6744   (* Optional functions should only be tested if the relevant
6745    * support is available in the daemon.
6746    *)
6747   List.iter (
6748     function
6749     | Optional group ->
6750         pr "  {\n";
6751         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6752         pr "    int r;\n";
6753         pr "    suppress_error = 1;\n";
6754         pr "    r = guestfs_available (g, (char **) groups);\n";
6755         pr "    suppress_error = 0;\n";
6756         pr "    if (r == -1) {\n";
6757         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6758         pr "      return 0;\n";
6759         pr "    }\n";
6760         pr "  }\n";
6761     | _ -> ()
6762   ) flags;
6763
6764   (match prereq with
6765    | Disabled ->
6766        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6767    | If _ ->
6768        pr "  if (! %s_prereq ()) {\n" test_name;
6769        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6770        pr "    return 0;\n";
6771        pr "  }\n";
6772        pr "\n";
6773        generate_one_test_body name i test_name init test;
6774    | Unless _ ->
6775        pr "  if (%s_prereq ()) {\n" test_name;
6776        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6777        pr "    return 0;\n";
6778        pr "  }\n";
6779        pr "\n";
6780        generate_one_test_body name i test_name init test;
6781    | Always ->
6782        generate_one_test_body name i test_name init test
6783   );
6784
6785   pr "  return 0;\n";
6786   pr "}\n";
6787   pr "\n";
6788   test_name
6789
6790 and generate_one_test_body name i test_name init test =
6791   (match init with
6792    | InitNone (* XXX at some point, InitNone and InitEmpty became
6793                * folded together as the same thing.  Really we should
6794                * make InitNone do nothing at all, but the tests may
6795                * need to be checked to make sure this is OK.
6796                *)
6797    | InitEmpty ->
6798        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6799        List.iter (generate_test_command_call test_name)
6800          [["blockdev_setrw"; "/dev/sda"];
6801           ["umount_all"];
6802           ["lvm_remove_all"]]
6803    | InitPartition ->
6804        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6805        List.iter (generate_test_command_call test_name)
6806          [["blockdev_setrw"; "/dev/sda"];
6807           ["umount_all"];
6808           ["lvm_remove_all"];
6809           ["part_disk"; "/dev/sda"; "mbr"]]
6810    | InitBasicFS ->
6811        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6812        List.iter (generate_test_command_call test_name)
6813          [["blockdev_setrw"; "/dev/sda"];
6814           ["umount_all"];
6815           ["lvm_remove_all"];
6816           ["part_disk"; "/dev/sda"; "mbr"];
6817           ["mkfs"; "ext2"; "/dev/sda1"];
6818           ["mount_options"; ""; "/dev/sda1"; "/"]]
6819    | InitBasicFSonLVM ->
6820        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6821          test_name;
6822        List.iter (generate_test_command_call test_name)
6823          [["blockdev_setrw"; "/dev/sda"];
6824           ["umount_all"];
6825           ["lvm_remove_all"];
6826           ["part_disk"; "/dev/sda"; "mbr"];
6827           ["pvcreate"; "/dev/sda1"];
6828           ["vgcreate"; "VG"; "/dev/sda1"];
6829           ["lvcreate"; "LV"; "VG"; "8"];
6830           ["mkfs"; "ext2"; "/dev/VG/LV"];
6831           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6832    | InitISOFS ->
6833        pr "  /* InitISOFS for %s */\n" test_name;
6834        List.iter (generate_test_command_call test_name)
6835          [["blockdev_setrw"; "/dev/sda"];
6836           ["umount_all"];
6837           ["lvm_remove_all"];
6838           ["mount_ro"; "/dev/sdd"; "/"]]
6839   );
6840
6841   let get_seq_last = function
6842     | [] ->
6843         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6844           test_name
6845     | seq ->
6846         let seq = List.rev seq in
6847         List.rev (List.tl seq), List.hd seq
6848   in
6849
6850   match test with
6851   | TestRun seq ->
6852       pr "  /* TestRun for %s (%d) */\n" name i;
6853       List.iter (generate_test_command_call test_name) seq
6854   | TestOutput (seq, expected) ->
6855       pr "  /* TestOutput for %s (%d) */\n" name i;
6856       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6857       let seq, last = get_seq_last seq in
6858       let test () =
6859         pr "    if (STRNEQ (r, expected)) {\n";
6860         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6861         pr "      return -1;\n";
6862         pr "    }\n"
6863       in
6864       List.iter (generate_test_command_call test_name) seq;
6865       generate_test_command_call ~test test_name last
6866   | TestOutputList (seq, expected) ->
6867       pr "  /* TestOutputList for %s (%d) */\n" name i;
6868       let seq, last = get_seq_last seq in
6869       let test () =
6870         iteri (
6871           fun i str ->
6872             pr "    if (!r[%d]) {\n" i;
6873             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6874             pr "      print_strings (r);\n";
6875             pr "      return -1;\n";
6876             pr "    }\n";
6877             pr "    {\n";
6878             pr "      const char *expected = \"%s\";\n" (c_quote str);
6879             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6880             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6881             pr "        return -1;\n";
6882             pr "      }\n";
6883             pr "    }\n"
6884         ) expected;
6885         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6886         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6887           test_name;
6888         pr "      print_strings (r);\n";
6889         pr "      return -1;\n";
6890         pr "    }\n"
6891       in
6892       List.iter (generate_test_command_call test_name) seq;
6893       generate_test_command_call ~test test_name last
6894   | TestOutputListOfDevices (seq, expected) ->
6895       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6896       let seq, last = get_seq_last seq in
6897       let test () =
6898         iteri (
6899           fun i str ->
6900             pr "    if (!r[%d]) {\n" i;
6901             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6902             pr "      print_strings (r);\n";
6903             pr "      return -1;\n";
6904             pr "    }\n";
6905             pr "    {\n";
6906             pr "      const char *expected = \"%s\";\n" (c_quote str);
6907             pr "      r[%d][5] = 's';\n" i;
6908             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6909             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6910             pr "        return -1;\n";
6911             pr "      }\n";
6912             pr "    }\n"
6913         ) expected;
6914         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6915         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6916           test_name;
6917         pr "      print_strings (r);\n";
6918         pr "      return -1;\n";
6919         pr "    }\n"
6920       in
6921       List.iter (generate_test_command_call test_name) seq;
6922       generate_test_command_call ~test test_name last
6923   | TestOutputInt (seq, expected) ->
6924       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6925       let seq, last = get_seq_last seq in
6926       let test () =
6927         pr "    if (r != %d) {\n" expected;
6928         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6929           test_name expected;
6930         pr "               (int) r);\n";
6931         pr "      return -1;\n";
6932         pr "    }\n"
6933       in
6934       List.iter (generate_test_command_call test_name) seq;
6935       generate_test_command_call ~test test_name last
6936   | TestOutputIntOp (seq, op, expected) ->
6937       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6938       let seq, last = get_seq_last seq in
6939       let test () =
6940         pr "    if (! (r %s %d)) {\n" op expected;
6941         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6942           test_name op expected;
6943         pr "               (int) r);\n";
6944         pr "      return -1;\n";
6945         pr "    }\n"
6946       in
6947       List.iter (generate_test_command_call test_name) seq;
6948       generate_test_command_call ~test test_name last
6949   | TestOutputTrue seq ->
6950       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6951       let seq, last = get_seq_last seq in
6952       let test () =
6953         pr "    if (!r) {\n";
6954         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6955           test_name;
6956         pr "      return -1;\n";
6957         pr "    }\n"
6958       in
6959       List.iter (generate_test_command_call test_name) seq;
6960       generate_test_command_call ~test test_name last
6961   | TestOutputFalse seq ->
6962       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6963       let seq, last = get_seq_last seq in
6964       let test () =
6965         pr "    if (r) {\n";
6966         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6967           test_name;
6968         pr "      return -1;\n";
6969         pr "    }\n"
6970       in
6971       List.iter (generate_test_command_call test_name) seq;
6972       generate_test_command_call ~test test_name last
6973   | TestOutputLength (seq, expected) ->
6974       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6975       let seq, last = get_seq_last seq in
6976       let test () =
6977         pr "    int j;\n";
6978         pr "    for (j = 0; j < %d; ++j)\n" expected;
6979         pr "      if (r[j] == NULL) {\n";
6980         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6981           test_name;
6982         pr "        print_strings (r);\n";
6983         pr "        return -1;\n";
6984         pr "      }\n";
6985         pr "    if (r[j] != NULL) {\n";
6986         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6987           test_name;
6988         pr "      print_strings (r);\n";
6989         pr "      return -1;\n";
6990         pr "    }\n"
6991       in
6992       List.iter (generate_test_command_call test_name) seq;
6993       generate_test_command_call ~test test_name last
6994   | TestOutputBuffer (seq, expected) ->
6995       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6996       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6997       let seq, last = get_seq_last seq in
6998       let len = String.length expected in
6999       let test () =
7000         pr "    if (size != %d) {\n" len;
7001         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7002         pr "      return -1;\n";
7003         pr "    }\n";
7004         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7005         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7006         pr "      return -1;\n";
7007         pr "    }\n"
7008       in
7009       List.iter (generate_test_command_call test_name) seq;
7010       generate_test_command_call ~test test_name last
7011   | TestOutputStruct (seq, checks) ->
7012       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7013       let seq, last = get_seq_last seq in
7014       let test () =
7015         List.iter (
7016           function
7017           | CompareWithInt (field, expected) ->
7018               pr "    if (r->%s != %d) {\n" field expected;
7019               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7020                 test_name field expected;
7021               pr "               (int) r->%s);\n" field;
7022               pr "      return -1;\n";
7023               pr "    }\n"
7024           | CompareWithIntOp (field, op, expected) ->
7025               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7026               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7027                 test_name field op expected;
7028               pr "               (int) r->%s);\n" field;
7029               pr "      return -1;\n";
7030               pr "    }\n"
7031           | CompareWithString (field, expected) ->
7032               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7033               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7034                 test_name field expected;
7035               pr "               r->%s);\n" field;
7036               pr "      return -1;\n";
7037               pr "    }\n"
7038           | CompareFieldsIntEq (field1, field2) ->
7039               pr "    if (r->%s != r->%s) {\n" field1 field2;
7040               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7041                 test_name field1 field2;
7042               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7043               pr "      return -1;\n";
7044               pr "    }\n"
7045           | CompareFieldsStrEq (field1, field2) ->
7046               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7047               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7048                 test_name field1 field2;
7049               pr "               r->%s, r->%s);\n" field1 field2;
7050               pr "      return -1;\n";
7051               pr "    }\n"
7052         ) checks
7053       in
7054       List.iter (generate_test_command_call test_name) seq;
7055       generate_test_command_call ~test test_name last
7056   | TestLastFail seq ->
7057       pr "  /* TestLastFail for %s (%d) */\n" name i;
7058       let seq, last = get_seq_last seq in
7059       List.iter (generate_test_command_call test_name) seq;
7060       generate_test_command_call test_name ~expect_error:true last
7061
7062 (* Generate the code to run a command, leaving the result in 'r'.
7063  * If you expect to get an error then you should set expect_error:true.
7064  *)
7065 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7066   match cmd with
7067   | [] -> assert false
7068   | name :: args ->
7069       (* Look up the command to find out what args/ret it has. *)
7070       let style =
7071         try
7072           let _, style, _, _, _, _, _ =
7073             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7074           style
7075         with Not_found ->
7076           failwithf "%s: in test, command %s was not found" test_name name in
7077
7078       if List.length (snd style) <> List.length args then
7079         failwithf "%s: in test, wrong number of args given to %s"
7080           test_name name;
7081
7082       pr "  {\n";
7083
7084       List.iter (
7085         function
7086         | OptString n, "NULL" -> ()
7087         | Pathname n, arg
7088         | Device n, arg
7089         | Dev_or_Path n, arg
7090         | String n, arg
7091         | OptString n, arg ->
7092             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7093         | Int _, _
7094         | Int64 _, _
7095         | Bool _, _
7096         | FileIn _, _ | FileOut _, _ -> ()
7097         | StringList n, "" | DeviceList n, "" ->
7098             pr "    const char *const %s[1] = { NULL };\n" n
7099         | StringList n, arg | DeviceList n, arg ->
7100             let strs = string_split " " arg in
7101             iteri (
7102               fun i str ->
7103                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7104             ) strs;
7105             pr "    const char *const %s[] = {\n" n;
7106             iteri (
7107               fun i _ -> pr "      %s_%d,\n" n i
7108             ) strs;
7109             pr "      NULL\n";
7110             pr "    };\n";
7111       ) (List.combine (snd style) args);
7112
7113       let error_code =
7114         match fst style with
7115         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7116         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7117         | RConstString _ | RConstOptString _ ->
7118             pr "    const char *r;\n"; "NULL"
7119         | RString _ -> pr "    char *r;\n"; "NULL"
7120         | RStringList _ | RHashtable _ ->
7121             pr "    char **r;\n";
7122             pr "    int i;\n";
7123             "NULL"
7124         | RStruct (_, typ) ->
7125             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7126         | RStructList (_, typ) ->
7127             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7128         | RBufferOut _ ->
7129             pr "    char *r;\n";
7130             pr "    size_t size;\n";
7131             "NULL" in
7132
7133       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7134       pr "    r = guestfs_%s (g" name;
7135
7136       (* Generate the parameters. *)
7137       List.iter (
7138         function
7139         | OptString _, "NULL" -> pr ", NULL"
7140         | Pathname n, _
7141         | Device n, _ | Dev_or_Path n, _
7142         | String n, _
7143         | OptString n, _ ->
7144             pr ", %s" n
7145         | FileIn _, arg | FileOut _, arg ->
7146             pr ", \"%s\"" (c_quote arg)
7147         | StringList n, _ | DeviceList n, _ ->
7148             pr ", (char **) %s" n
7149         | Int _, arg ->
7150             let i =
7151               try int_of_string arg
7152               with Failure "int_of_string" ->
7153                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7154             pr ", %d" i
7155         | Int64 _, arg ->
7156             let i =
7157               try Int64.of_string arg
7158               with Failure "int_of_string" ->
7159                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7160             pr ", %Ld" i
7161         | Bool _, arg ->
7162             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7163       ) (List.combine (snd style) args);
7164
7165       (match fst style with
7166        | RBufferOut _ -> pr ", &size"
7167        | _ -> ()
7168       );
7169
7170       pr ");\n";
7171
7172       if not expect_error then
7173         pr "    if (r == %s)\n" error_code
7174       else
7175         pr "    if (r != %s)\n" error_code;
7176       pr "      return -1;\n";
7177
7178       (* Insert the test code. *)
7179       (match test with
7180        | None -> ()
7181        | Some f -> f ()
7182       );
7183
7184       (match fst style with
7185        | RErr | RInt _ | RInt64 _ | RBool _
7186        | RConstString _ | RConstOptString _ -> ()
7187        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7188        | RStringList _ | RHashtable _ ->
7189            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7190            pr "      free (r[i]);\n";
7191            pr "    free (r);\n"
7192        | RStruct (_, typ) ->
7193            pr "    guestfs_free_%s (r);\n" typ
7194        | RStructList (_, typ) ->
7195            pr "    guestfs_free_%s_list (r);\n" typ
7196       );
7197
7198       pr "  }\n"
7199
7200 and c_quote str =
7201   let str = replace_str str "\r" "\\r" in
7202   let str = replace_str str "\n" "\\n" in
7203   let str = replace_str str "\t" "\\t" in
7204   let str = replace_str str "\000" "\\0" in
7205   str
7206
7207 (* Generate a lot of different functions for guestfish. *)
7208 and generate_fish_cmds () =
7209   generate_header CStyle GPLv2plus;
7210
7211   let all_functions =
7212     List.filter (
7213       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7214     ) all_functions in
7215   let all_functions_sorted =
7216     List.filter (
7217       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7218     ) all_functions_sorted in
7219
7220   pr "#include <config.h>\n";
7221   pr "\n";
7222   pr "#include <stdio.h>\n";
7223   pr "#include <stdlib.h>\n";
7224   pr "#include <string.h>\n";
7225   pr "#include <inttypes.h>\n";
7226   pr "\n";
7227   pr "#include <guestfs.h>\n";
7228   pr "#include \"c-ctype.h\"\n";
7229   pr "#include \"full-write.h\"\n";
7230   pr "#include \"xstrtol.h\"\n";
7231   pr "#include \"fish.h\"\n";
7232   pr "\n";
7233
7234   (* list_commands function, which implements guestfish -h *)
7235   pr "void list_commands (void)\n";
7236   pr "{\n";
7237   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7238   pr "  list_builtin_commands ();\n";
7239   List.iter (
7240     fun (name, _, _, flags, _, shortdesc, _) ->
7241       let name = replace_char name '_' '-' in
7242       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7243         name shortdesc
7244   ) all_functions_sorted;
7245   pr "  printf (\"    %%s\\n\",";
7246   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7247   pr "}\n";
7248   pr "\n";
7249
7250   (* display_command function, which implements guestfish -h cmd *)
7251   pr "void display_command (const char *cmd)\n";
7252   pr "{\n";
7253   List.iter (
7254     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7255       let name2 = replace_char name '_' '-' in
7256       let alias =
7257         try find_map (function FishAlias n -> Some n | _ -> None) flags
7258         with Not_found -> name in
7259       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7260       let synopsis =
7261         match snd style with
7262         | [] -> name2
7263         | args ->
7264             sprintf "%s %s"
7265               name2 (String.concat " " (List.map name_of_argt args)) in
7266
7267       let warnings =
7268         if List.mem ProtocolLimitWarning flags then
7269           ("\n\n" ^ protocol_limit_warning)
7270         else "" in
7271
7272       (* For DangerWillRobinson commands, we should probably have
7273        * guestfish prompt before allowing you to use them (especially
7274        * in interactive mode). XXX
7275        *)
7276       let warnings =
7277         warnings ^
7278           if List.mem DangerWillRobinson flags then
7279             ("\n\n" ^ danger_will_robinson)
7280           else "" in
7281
7282       let warnings =
7283         warnings ^
7284           match deprecation_notice flags with
7285           | None -> ""
7286           | Some txt -> "\n\n" ^ txt in
7287
7288       let describe_alias =
7289         if name <> alias then
7290           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7291         else "" in
7292
7293       pr "  if (";
7294       pr "STRCASEEQ (cmd, \"%s\")" name;
7295       if name <> name2 then
7296         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7297       if name <> alias then
7298         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7299       pr ")\n";
7300       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7301         name2 shortdesc
7302         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7303          "=head1 DESCRIPTION\n\n" ^
7304          longdesc ^ warnings ^ describe_alias);
7305       pr "  else\n"
7306   ) all_functions;
7307   pr "    display_builtin_command (cmd);\n";
7308   pr "}\n";
7309   pr "\n";
7310
7311   let emit_print_list_function typ =
7312     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7313       typ typ typ;
7314     pr "{\n";
7315     pr "  unsigned int i;\n";
7316     pr "\n";
7317     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7318     pr "    printf (\"[%%d] = {\\n\", i);\n";
7319     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7320     pr "    printf (\"}\\n\");\n";
7321     pr "  }\n";
7322     pr "}\n";
7323     pr "\n";
7324   in
7325
7326   (* print_* functions *)
7327   List.iter (
7328     fun (typ, cols) ->
7329       let needs_i =
7330         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7331
7332       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7333       pr "{\n";
7334       if needs_i then (
7335         pr "  unsigned int i;\n";
7336         pr "\n"
7337       );
7338       List.iter (
7339         function
7340         | name, FString ->
7341             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7342         | name, FUUID ->
7343             pr "  printf (\"%%s%s: \", indent);\n" name;
7344             pr "  for (i = 0; i < 32; ++i)\n";
7345             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7346             pr "  printf (\"\\n\");\n"
7347         | name, FBuffer ->
7348             pr "  printf (\"%%s%s: \", indent);\n" name;
7349             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7350             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7351             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7352             pr "    else\n";
7353             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7354             pr "  printf (\"\\n\");\n"
7355         | name, (FUInt64|FBytes) ->
7356             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7357               name typ name
7358         | name, FInt64 ->
7359             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7360               name typ name
7361         | name, FUInt32 ->
7362             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7363               name typ name
7364         | name, FInt32 ->
7365             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7366               name typ name
7367         | name, FChar ->
7368             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7369               name typ name
7370         | name, FOptPercent ->
7371             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7372               typ name name typ name;
7373             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7374       ) cols;
7375       pr "}\n";
7376       pr "\n";
7377   ) structs;
7378
7379   (* Emit a print_TYPE_list function definition only if that function is used. *)
7380   List.iter (
7381     function
7382     | typ, (RStructListOnly | RStructAndList) ->
7383         (* generate the function for typ *)
7384         emit_print_list_function typ
7385     | typ, _ -> () (* empty *)
7386   ) (rstructs_used_by all_functions);
7387
7388   (* Emit a print_TYPE function definition only if that function is used. *)
7389   List.iter (
7390     function
7391     | typ, (RStructOnly | RStructAndList) ->
7392         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7393         pr "{\n";
7394         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7395         pr "}\n";
7396         pr "\n";
7397     | typ, _ -> () (* empty *)
7398   ) (rstructs_used_by all_functions);
7399
7400   (* run_<action> actions *)
7401   List.iter (
7402     fun (name, style, _, flags, _, _, _) ->
7403       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7404       pr "{\n";
7405       (match fst style with
7406        | RErr
7407        | RInt _
7408        | RBool _ -> pr "  int r;\n"
7409        | RInt64 _ -> pr "  int64_t r;\n"
7410        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7411        | RString _ -> pr "  char *r;\n"
7412        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7413        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7414        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7415        | RBufferOut _ ->
7416            pr "  char *r;\n";
7417            pr "  size_t size;\n";
7418       );
7419       List.iter (
7420         function
7421         | Device n
7422         | String n
7423         | OptString n -> pr "  const char *%s;\n" n
7424         | Pathname n
7425         | Dev_or_Path n
7426         | FileIn n
7427         | FileOut n -> pr "  char *%s;\n" n
7428         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7429         | Bool n -> pr "  int %s;\n" n
7430         | Int n -> pr "  int %s;\n" n
7431         | Int64 n -> pr "  int64_t %s;\n" n
7432       ) (snd style);
7433
7434       (* Check and convert parameters. *)
7435       let argc_expected = List.length (snd style) in
7436       pr "  if (argc != %d) {\n" argc_expected;
7437       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7438         argc_expected;
7439       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7440       pr "    return -1;\n";
7441       pr "  }\n";
7442
7443       let parse_integer fn fntyp rtyp range name i =
7444         pr "  {\n";
7445         pr "    strtol_error xerr;\n";
7446         pr "    %s r;\n" fntyp;
7447         pr "\n";
7448         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7449         pr "    if (xerr != LONGINT_OK) {\n";
7450         pr "      fprintf (stderr,\n";
7451         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7452         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7453         pr "      return -1;\n";
7454         pr "    }\n";
7455         (match range with
7456          | None -> ()
7457          | Some (min, max, comment) ->
7458              pr "    /* %s */\n" comment;
7459              pr "    if (r < %s || r > %s) {\n" min max;
7460              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7461                name;
7462              pr "      return -1;\n";
7463              pr "    }\n";
7464              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7465         );
7466         pr "    %s = r;\n" name;
7467         pr "  }\n";
7468       in
7469
7470       iteri (
7471         fun i ->
7472           function
7473           | Device name
7474           | String name ->
7475               pr "  %s = argv[%d];\n" name i
7476           | Pathname name
7477           | Dev_or_Path name ->
7478               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7479               pr "  if (%s == NULL) return -1;\n" name
7480           | OptString name ->
7481               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7482                 name i i
7483           | FileIn name ->
7484               pr "  %s = file_in (argv[%d]);\n" name i;
7485               pr "  if (%s == NULL) return -1;\n" name
7486           | FileOut name ->
7487               pr "  %s = file_out (argv[%d]);\n" name i;
7488               pr "  if (%s == NULL) return -1;\n" name
7489           | StringList name | DeviceList name ->
7490               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7491               pr "  if (%s == NULL) return -1;\n" name;
7492           | Bool name ->
7493               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7494           | Int name ->
7495               let range =
7496                 let min = "(-(2LL<<30))"
7497                 and max = "((2LL<<30)-1)"
7498                 and comment =
7499                   "The Int type in the generator is a signed 31 bit int." in
7500                 Some (min, max, comment) in
7501               parse_integer "xstrtoll" "long long" "int" range name i
7502           | Int64 name ->
7503               parse_integer "xstrtoll" "long long" "int64_t" None name i
7504       ) (snd style);
7505
7506       (* Call C API function. *)
7507       let fn =
7508         try find_map (function FishAction n -> Some n | _ -> None) flags
7509         with Not_found -> sprintf "guestfs_%s" name in
7510       pr "  r = %s " fn;
7511       generate_c_call_args ~handle:"g" style;
7512       pr ";\n";
7513
7514       List.iter (
7515         function
7516         | Device name | String name
7517         | OptString name | Bool name
7518         | Int name | Int64 name -> ()
7519         | Pathname name | Dev_or_Path name | FileOut name ->
7520             pr "  free (%s);\n" name
7521         | FileIn name ->
7522             pr "  free_file_in (%s);\n" name
7523         | StringList name | DeviceList name ->
7524             pr "  free_strings (%s);\n" name
7525       ) (snd style);
7526
7527       (* Any output flags? *)
7528       let fish_output =
7529         let flags = filter_map (
7530           function FishOutput flag -> Some flag | _ -> None
7531         ) flags in
7532         match flags with
7533         | [] -> None
7534         | [f] -> Some f
7535         | _ ->
7536             failwithf "%s: more than one FishOutput flag is not allowed" name in
7537
7538       (* Check return value for errors and display command results. *)
7539       (match fst style with
7540        | RErr -> pr "  return r;\n"
7541        | RInt _ ->
7542            pr "  if (r == -1) return -1;\n";
7543            (match fish_output with
7544             | None ->
7545                 pr "  printf (\"%%d\\n\", r);\n";
7546             | Some FishOutputOctal ->
7547                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7548             | Some FishOutputHexadecimal ->
7549                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7550            pr "  return 0;\n"
7551        | RInt64 _ ->
7552            pr "  if (r == -1) return -1;\n";
7553            (match fish_output with
7554             | None ->
7555                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7556             | Some FishOutputOctal ->
7557                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7558             | Some FishOutputHexadecimal ->
7559                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7560            pr "  return 0;\n"
7561        | RBool _ ->
7562            pr "  if (r == -1) return -1;\n";
7563            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7564            pr "  return 0;\n"
7565        | RConstString _ ->
7566            pr "  if (r == NULL) return -1;\n";
7567            pr "  printf (\"%%s\\n\", r);\n";
7568            pr "  return 0;\n"
7569        | RConstOptString _ ->
7570            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7571            pr "  return 0;\n"
7572        | RString _ ->
7573            pr "  if (r == NULL) return -1;\n";
7574            pr "  printf (\"%%s\\n\", r);\n";
7575            pr "  free (r);\n";
7576            pr "  return 0;\n"
7577        | RStringList _ ->
7578            pr "  if (r == NULL) return -1;\n";
7579            pr "  print_strings (r);\n";
7580            pr "  free_strings (r);\n";
7581            pr "  return 0;\n"
7582        | RStruct (_, typ) ->
7583            pr "  if (r == NULL) return -1;\n";
7584            pr "  print_%s (r);\n" typ;
7585            pr "  guestfs_free_%s (r);\n" typ;
7586            pr "  return 0;\n"
7587        | RStructList (_, typ) ->
7588            pr "  if (r == NULL) return -1;\n";
7589            pr "  print_%s_list (r);\n" typ;
7590            pr "  guestfs_free_%s_list (r);\n" typ;
7591            pr "  return 0;\n"
7592        | RHashtable _ ->
7593            pr "  if (r == NULL) return -1;\n";
7594            pr "  print_table (r);\n";
7595            pr "  free_strings (r);\n";
7596            pr "  return 0;\n"
7597        | RBufferOut _ ->
7598            pr "  if (r == NULL) return -1;\n";
7599            pr "  if (full_write (1, r, size) != size) {\n";
7600            pr "    perror (\"write\");\n";
7601            pr "    free (r);\n";
7602            pr "    return -1;\n";
7603            pr "  }\n";
7604            pr "  free (r);\n";
7605            pr "  return 0;\n"
7606       );
7607       pr "}\n";
7608       pr "\n"
7609   ) all_functions;
7610
7611   (* run_action function *)
7612   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7613   pr "{\n";
7614   List.iter (
7615     fun (name, _, _, flags, _, _, _) ->
7616       let name2 = replace_char name '_' '-' in
7617       let alias =
7618         try find_map (function FishAlias n -> Some n | _ -> None) flags
7619         with Not_found -> name in
7620       pr "  if (";
7621       pr "STRCASEEQ (cmd, \"%s\")" name;
7622       if name <> name2 then
7623         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7624       if name <> alias then
7625         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7626       pr ")\n";
7627       pr "    return run_%s (cmd, argc, argv);\n" name;
7628       pr "  else\n";
7629   ) all_functions;
7630   pr "    {\n";
7631   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7632   pr "      if (command_num == 1)\n";
7633   pr "        extended_help_message ();\n";
7634   pr "      return -1;\n";
7635   pr "    }\n";
7636   pr "  return 0;\n";
7637   pr "}\n";
7638   pr "\n"
7639
7640 (* Readline completion for guestfish. *)
7641 and generate_fish_completion () =
7642   generate_header CStyle GPLv2plus;
7643
7644   let all_functions =
7645     List.filter (
7646       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7647     ) all_functions in
7648
7649   pr "\
7650 #include <config.h>
7651
7652 #include <stdio.h>
7653 #include <stdlib.h>
7654 #include <string.h>
7655
7656 #ifdef HAVE_LIBREADLINE
7657 #include <readline/readline.h>
7658 #endif
7659
7660 #include \"fish.h\"
7661
7662 #ifdef HAVE_LIBREADLINE
7663
7664 static const char *const commands[] = {
7665   BUILTIN_COMMANDS_FOR_COMPLETION,
7666 ";
7667
7668   (* Get the commands, including the aliases.  They don't need to be
7669    * sorted - the generator() function just does a dumb linear search.
7670    *)
7671   let commands =
7672     List.map (
7673       fun (name, _, _, flags, _, _, _) ->
7674         let name2 = replace_char name '_' '-' in
7675         let alias =
7676           try find_map (function FishAlias n -> Some n | _ -> None) flags
7677           with Not_found -> name in
7678
7679         if name <> alias then [name2; alias] else [name2]
7680     ) all_functions in
7681   let commands = List.flatten commands in
7682
7683   List.iter (pr "  \"%s\",\n") commands;
7684
7685   pr "  NULL
7686 };
7687
7688 static char *
7689 generator (const char *text, int state)
7690 {
7691   static int index, len;
7692   const char *name;
7693
7694   if (!state) {
7695     index = 0;
7696     len = strlen (text);
7697   }
7698
7699   rl_attempted_completion_over = 1;
7700
7701   while ((name = commands[index]) != NULL) {
7702     index++;
7703     if (STRCASEEQLEN (name, text, len))
7704       return strdup (name);
7705   }
7706
7707   return NULL;
7708 }
7709
7710 #endif /* HAVE_LIBREADLINE */
7711
7712 #ifdef HAVE_RL_COMPLETION_MATCHES
7713 #define RL_COMPLETION_MATCHES rl_completion_matches
7714 #else
7715 #ifdef HAVE_COMPLETION_MATCHES
7716 #define RL_COMPLETION_MATCHES completion_matches
7717 #endif
7718 #endif /* else just fail if we don't have either symbol */
7719
7720 char **
7721 do_completion (const char *text, int start, int end)
7722 {
7723   char **matches = NULL;
7724
7725 #ifdef HAVE_LIBREADLINE
7726   rl_completion_append_character = ' ';
7727
7728   if (start == 0)
7729     matches = RL_COMPLETION_MATCHES (text, generator);
7730   else if (complete_dest_paths)
7731     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7732 #endif
7733
7734   return matches;
7735 }
7736 ";
7737
7738 (* Generate the POD documentation for guestfish. *)
7739 and generate_fish_actions_pod () =
7740   let all_functions_sorted =
7741     List.filter (
7742       fun (_, _, _, flags, _, _, _) ->
7743         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7744     ) all_functions_sorted in
7745
7746   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7747
7748   List.iter (
7749     fun (name, style, _, flags, _, _, longdesc) ->
7750       let longdesc =
7751         Str.global_substitute rex (
7752           fun s ->
7753             let sub =
7754               try Str.matched_group 1 s
7755               with Not_found ->
7756                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7757             "C<" ^ replace_char sub '_' '-' ^ ">"
7758         ) longdesc in
7759       let name = replace_char name '_' '-' in
7760       let alias =
7761         try find_map (function FishAlias n -> Some n | _ -> None) flags
7762         with Not_found -> name in
7763
7764       pr "=head2 %s" name;
7765       if name <> alias then
7766         pr " | %s" alias;
7767       pr "\n";
7768       pr "\n";
7769       pr " %s" name;
7770       List.iter (
7771         function
7772         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7773         | OptString n -> pr " %s" n
7774         | StringList n | DeviceList n -> pr " '%s ...'" n
7775         | Bool _ -> pr " true|false"
7776         | Int n -> pr " %s" n
7777         | Int64 n -> pr " %s" n
7778         | FileIn n | FileOut n -> pr " (%s|-)" n
7779       ) (snd style);
7780       pr "\n";
7781       pr "\n";
7782       pr "%s\n\n" longdesc;
7783
7784       if List.exists (function FileIn _ | FileOut _ -> true
7785                       | _ -> false) (snd style) then
7786         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7787
7788       if List.mem ProtocolLimitWarning flags then
7789         pr "%s\n\n" protocol_limit_warning;
7790
7791       if List.mem DangerWillRobinson flags then
7792         pr "%s\n\n" danger_will_robinson;
7793
7794       match deprecation_notice flags with
7795       | None -> ()
7796       | Some txt -> pr "%s\n\n" txt
7797   ) all_functions_sorted
7798
7799 (* Generate a C function prototype. *)
7800 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7801     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7802     ?(prefix = "")
7803     ?handle name style =
7804   if extern then pr "extern ";
7805   if static then pr "static ";
7806   (match fst style with
7807    | RErr -> pr "int "
7808    | RInt _ -> pr "int "
7809    | RInt64 _ -> pr "int64_t "
7810    | RBool _ -> pr "int "
7811    | RConstString _ | RConstOptString _ -> pr "const char *"
7812    | RString _ | RBufferOut _ -> pr "char *"
7813    | RStringList _ | RHashtable _ -> pr "char **"
7814    | RStruct (_, typ) ->
7815        if not in_daemon then pr "struct guestfs_%s *" typ
7816        else pr "guestfs_int_%s *" typ
7817    | RStructList (_, typ) ->
7818        if not in_daemon then pr "struct guestfs_%s_list *" typ
7819        else pr "guestfs_int_%s_list *" typ
7820   );
7821   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7822   pr "%s%s (" prefix name;
7823   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7824     pr "void"
7825   else (
7826     let comma = ref false in
7827     (match handle with
7828      | None -> ()
7829      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7830     );
7831     let next () =
7832       if !comma then (
7833         if single_line then pr ", " else pr ",\n\t\t"
7834       );
7835       comma := true
7836     in
7837     List.iter (
7838       function
7839       | Pathname n
7840       | Device n | Dev_or_Path n
7841       | String n
7842       | OptString n ->
7843           next ();
7844           pr "const char *%s" n
7845       | StringList n | DeviceList n ->
7846           next ();
7847           pr "char *const *%s" n
7848       | Bool n -> next (); pr "int %s" n
7849       | Int n -> next (); pr "int %s" n
7850       | Int64 n -> next (); pr "int64_t %s" n
7851       | FileIn n
7852       | FileOut n ->
7853           if not in_daemon then (next (); pr "const char *%s" n)
7854     ) (snd style);
7855     if is_RBufferOut then (next (); pr "size_t *size_r");
7856   );
7857   pr ")";
7858   if semicolon then pr ";";
7859   if newline then pr "\n"
7860
7861 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7862 and generate_c_call_args ?handle ?(decl = false) style =
7863   pr "(";
7864   let comma = ref false in
7865   let next () =
7866     if !comma then pr ", ";
7867     comma := true
7868   in
7869   (match handle with
7870    | None -> ()
7871    | Some handle -> pr "%s" handle; comma := true
7872   );
7873   List.iter (
7874     fun arg ->
7875       next ();
7876       pr "%s" (name_of_argt arg)
7877   ) (snd style);
7878   (* For RBufferOut calls, add implicit &size parameter. *)
7879   if not decl then (
7880     match fst style with
7881     | RBufferOut _ ->
7882         next ();
7883         pr "&size"
7884     | _ -> ()
7885   );
7886   pr ")"
7887
7888 (* Generate the OCaml bindings interface. *)
7889 and generate_ocaml_mli () =
7890   generate_header OCamlStyle LGPLv2plus;
7891
7892   pr "\
7893 (** For API documentation you should refer to the C API
7894     in the guestfs(3) manual page.  The OCaml API uses almost
7895     exactly the same calls. *)
7896
7897 type t
7898 (** A [guestfs_h] handle. *)
7899
7900 exception Error of string
7901 (** This exception is raised when there is an error. *)
7902
7903 exception Handle_closed of string
7904 (** This exception is raised if you use a {!Guestfs.t} handle
7905     after calling {!close} on it.  The string is the name of
7906     the function. *)
7907
7908 val create : unit -> t
7909 (** Create a {!Guestfs.t} handle. *)
7910
7911 val close : t -> unit
7912 (** Close the {!Guestfs.t} handle and free up all resources used
7913     by it immediately.
7914
7915     Handles are closed by the garbage collector when they become
7916     unreferenced, but callers can call this in order to provide
7917     predictable cleanup. *)
7918
7919 ";
7920   generate_ocaml_structure_decls ();
7921
7922   (* The actions. *)
7923   List.iter (
7924     fun (name, style, _, _, _, shortdesc, _) ->
7925       generate_ocaml_prototype name style;
7926       pr "(** %s *)\n" shortdesc;
7927       pr "\n"
7928   ) all_functions_sorted
7929
7930 (* Generate the OCaml bindings implementation. *)
7931 and generate_ocaml_ml () =
7932   generate_header OCamlStyle LGPLv2plus;
7933
7934   pr "\
7935 type t
7936
7937 exception Error of string
7938 exception Handle_closed of string
7939
7940 external create : unit -> t = \"ocaml_guestfs_create\"
7941 external close : t -> unit = \"ocaml_guestfs_close\"
7942
7943 (* Give the exceptions names, so they can be raised from the C code. *)
7944 let () =
7945   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7946   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7947
7948 ";
7949
7950   generate_ocaml_structure_decls ();
7951
7952   (* The actions. *)
7953   List.iter (
7954     fun (name, style, _, _, _, shortdesc, _) ->
7955       generate_ocaml_prototype ~is_external:true name style;
7956   ) all_functions_sorted
7957
7958 (* Generate the OCaml bindings C implementation. *)
7959 and generate_ocaml_c () =
7960   generate_header CStyle LGPLv2plus;
7961
7962   pr "\
7963 #include <stdio.h>
7964 #include <stdlib.h>
7965 #include <string.h>
7966
7967 #include <caml/config.h>
7968 #include <caml/alloc.h>
7969 #include <caml/callback.h>
7970 #include <caml/fail.h>
7971 #include <caml/memory.h>
7972 #include <caml/mlvalues.h>
7973 #include <caml/signals.h>
7974
7975 #include <guestfs.h>
7976
7977 #include \"guestfs_c.h\"
7978
7979 /* Copy a hashtable of string pairs into an assoc-list.  We return
7980  * the list in reverse order, but hashtables aren't supposed to be
7981  * ordered anyway.
7982  */
7983 static CAMLprim value
7984 copy_table (char * const * argv)
7985 {
7986   CAMLparam0 ();
7987   CAMLlocal5 (rv, pairv, kv, vv, cons);
7988   int i;
7989
7990   rv = Val_int (0);
7991   for (i = 0; argv[i] != NULL; i += 2) {
7992     kv = caml_copy_string (argv[i]);
7993     vv = caml_copy_string (argv[i+1]);
7994     pairv = caml_alloc (2, 0);
7995     Store_field (pairv, 0, kv);
7996     Store_field (pairv, 1, vv);
7997     cons = caml_alloc (2, 0);
7998     Store_field (cons, 1, rv);
7999     rv = cons;
8000     Store_field (cons, 0, pairv);
8001   }
8002
8003   CAMLreturn (rv);
8004 }
8005
8006 ";
8007
8008   (* Struct copy functions. *)
8009
8010   let emit_ocaml_copy_list_function typ =
8011     pr "static CAMLprim value\n";
8012     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8013     pr "{\n";
8014     pr "  CAMLparam0 ();\n";
8015     pr "  CAMLlocal2 (rv, v);\n";
8016     pr "  unsigned int i;\n";
8017     pr "\n";
8018     pr "  if (%ss->len == 0)\n" typ;
8019     pr "    CAMLreturn (Atom (0));\n";
8020     pr "  else {\n";
8021     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8022     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8023     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8024     pr "      caml_modify (&Field (rv, i), v);\n";
8025     pr "    }\n";
8026     pr "    CAMLreturn (rv);\n";
8027     pr "  }\n";
8028     pr "}\n";
8029     pr "\n";
8030   in
8031
8032   List.iter (
8033     fun (typ, cols) ->
8034       let has_optpercent_col =
8035         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8036
8037       pr "static CAMLprim value\n";
8038       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8039       pr "{\n";
8040       pr "  CAMLparam0 ();\n";
8041       if has_optpercent_col then
8042         pr "  CAMLlocal3 (rv, v, v2);\n"
8043       else
8044         pr "  CAMLlocal2 (rv, v);\n";
8045       pr "\n";
8046       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8047       iteri (
8048         fun i col ->
8049           (match col with
8050            | name, FString ->
8051                pr "  v = caml_copy_string (%s->%s);\n" typ name
8052            | name, FBuffer ->
8053                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8054                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8055                  typ name typ name
8056            | name, FUUID ->
8057                pr "  v = caml_alloc_string (32);\n";
8058                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8059            | name, (FBytes|FInt64|FUInt64) ->
8060                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8061            | name, (FInt32|FUInt32) ->
8062                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8063            | name, FOptPercent ->
8064                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8065                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8066                pr "    v = caml_alloc (1, 0);\n";
8067                pr "    Store_field (v, 0, v2);\n";
8068                pr "  } else /* None */\n";
8069                pr "    v = Val_int (0);\n";
8070            | name, FChar ->
8071                pr "  v = Val_int (%s->%s);\n" typ name
8072           );
8073           pr "  Store_field (rv, %d, v);\n" i
8074       ) cols;
8075       pr "  CAMLreturn (rv);\n";
8076       pr "}\n";
8077       pr "\n";
8078   ) structs;
8079
8080   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8081   List.iter (
8082     function
8083     | typ, (RStructListOnly | RStructAndList) ->
8084         (* generate the function for typ *)
8085         emit_ocaml_copy_list_function typ
8086     | typ, _ -> () (* empty *)
8087   ) (rstructs_used_by all_functions);
8088
8089   (* The wrappers. *)
8090   List.iter (
8091     fun (name, style, _, _, _, _, _) ->
8092       pr "/* Automatically generated wrapper for function\n";
8093       pr " * ";
8094       generate_ocaml_prototype name style;
8095       pr " */\n";
8096       pr "\n";
8097
8098       let params =
8099         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8100
8101       let needs_extra_vs =
8102         match fst style with RConstOptString _ -> true | _ -> false in
8103
8104       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8105       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8106       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8107       pr "\n";
8108
8109       pr "CAMLprim value\n";
8110       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8111       List.iter (pr ", value %s") (List.tl params);
8112       pr ")\n";
8113       pr "{\n";
8114
8115       (match params with
8116        | [p1; p2; p3; p4; p5] ->
8117            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8118        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8119            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8120            pr "  CAMLxparam%d (%s);\n"
8121              (List.length rest) (String.concat ", " rest)
8122        | ps ->
8123            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8124       );
8125       if not needs_extra_vs then
8126         pr "  CAMLlocal1 (rv);\n"
8127       else
8128         pr "  CAMLlocal3 (rv, v, v2);\n";
8129       pr "\n";
8130
8131       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8132       pr "  if (g == NULL)\n";
8133       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8134       pr "\n";
8135
8136       List.iter (
8137         function
8138         | Pathname n
8139         | Device n | Dev_or_Path n
8140         | String n
8141         | FileIn n
8142         | FileOut n ->
8143             pr "  const char *%s = String_val (%sv);\n" n n
8144         | OptString n ->
8145             pr "  const char *%s =\n" n;
8146             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8147               n n
8148         | StringList n | DeviceList n ->
8149             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8150         | Bool n ->
8151             pr "  int %s = Bool_val (%sv);\n" n n
8152         | Int n ->
8153             pr "  int %s = Int_val (%sv);\n" n n
8154         | Int64 n ->
8155             pr "  int64_t %s = Int64_val (%sv);\n" n n
8156       ) (snd style);
8157       let error_code =
8158         match fst style with
8159         | RErr -> pr "  int r;\n"; "-1"
8160         | RInt _ -> pr "  int r;\n"; "-1"
8161         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8162         | RBool _ -> pr "  int r;\n"; "-1"
8163         | RConstString _ | RConstOptString _ ->
8164             pr "  const char *r;\n"; "NULL"
8165         | RString _ -> pr "  char *r;\n"; "NULL"
8166         | RStringList _ ->
8167             pr "  int i;\n";
8168             pr "  char **r;\n";
8169             "NULL"
8170         | RStruct (_, typ) ->
8171             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8172         | RStructList (_, typ) ->
8173             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8174         | RHashtable _ ->
8175             pr "  int i;\n";
8176             pr "  char **r;\n";
8177             "NULL"
8178         | RBufferOut _ ->
8179             pr "  char *r;\n";
8180             pr "  size_t size;\n";
8181             "NULL" in
8182       pr "\n";
8183
8184       pr "  caml_enter_blocking_section ();\n";
8185       pr "  r = guestfs_%s " name;
8186       generate_c_call_args ~handle:"g" style;
8187       pr ";\n";
8188       pr "  caml_leave_blocking_section ();\n";
8189
8190       List.iter (
8191         function
8192         | StringList n | DeviceList n ->
8193             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8194         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8195         | Bool _ | Int _ | Int64 _
8196         | FileIn _ | FileOut _ -> ()
8197       ) (snd style);
8198
8199       pr "  if (r == %s)\n" error_code;
8200       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8201       pr "\n";
8202
8203       (match fst style with
8204        | RErr -> pr "  rv = Val_unit;\n"
8205        | RInt _ -> pr "  rv = Val_int (r);\n"
8206        | RInt64 _ ->
8207            pr "  rv = caml_copy_int64 (r);\n"
8208        | RBool _ -> pr "  rv = Val_bool (r);\n"
8209        | RConstString _ ->
8210            pr "  rv = caml_copy_string (r);\n"
8211        | RConstOptString _ ->
8212            pr "  if (r) { /* Some string */\n";
8213            pr "    v = caml_alloc (1, 0);\n";
8214            pr "    v2 = caml_copy_string (r);\n";
8215            pr "    Store_field (v, 0, v2);\n";
8216            pr "  } else /* None */\n";
8217            pr "    v = Val_int (0);\n";
8218        | RString _ ->
8219            pr "  rv = caml_copy_string (r);\n";
8220            pr "  free (r);\n"
8221        | RStringList _ ->
8222            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8223            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8224            pr "  free (r);\n"
8225        | RStruct (_, typ) ->
8226            pr "  rv = copy_%s (r);\n" typ;
8227            pr "  guestfs_free_%s (r);\n" typ;
8228        | RStructList (_, typ) ->
8229            pr "  rv = copy_%s_list (r);\n" typ;
8230            pr "  guestfs_free_%s_list (r);\n" typ;
8231        | RHashtable _ ->
8232            pr "  rv = copy_table (r);\n";
8233            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8234            pr "  free (r);\n";
8235        | RBufferOut _ ->
8236            pr "  rv = caml_alloc_string (size);\n";
8237            pr "  memcpy (String_val (rv), r, size);\n";
8238       );
8239
8240       pr "  CAMLreturn (rv);\n";
8241       pr "}\n";
8242       pr "\n";
8243
8244       if List.length params > 5 then (
8245         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8246         pr "CAMLprim value ";
8247         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8248         pr "CAMLprim value\n";
8249         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8250         pr "{\n";
8251         pr "  return ocaml_guestfs_%s (argv[0]" name;
8252         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8253         pr ");\n";
8254         pr "}\n";
8255         pr "\n"
8256       )
8257   ) all_functions_sorted
8258
8259 and generate_ocaml_structure_decls () =
8260   List.iter (
8261     fun (typ, cols) ->
8262       pr "type %s = {\n" typ;
8263       List.iter (
8264         function
8265         | name, FString -> pr "  %s : string;\n" name
8266         | name, FBuffer -> pr "  %s : string;\n" name
8267         | name, FUUID -> pr "  %s : string;\n" name
8268         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8269         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8270         | name, FChar -> pr "  %s : char;\n" name
8271         | name, FOptPercent -> pr "  %s : float option;\n" name
8272       ) cols;
8273       pr "}\n";
8274       pr "\n"
8275   ) structs
8276
8277 and generate_ocaml_prototype ?(is_external = false) name style =
8278   if is_external then pr "external " else pr "val ";
8279   pr "%s : t -> " name;
8280   List.iter (
8281     function
8282     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8283     | OptString _ -> pr "string option -> "
8284     | StringList _ | DeviceList _ -> pr "string array -> "
8285     | Bool _ -> pr "bool -> "
8286     | Int _ -> pr "int -> "
8287     | Int64 _ -> pr "int64 -> "
8288   ) (snd style);
8289   (match fst style with
8290    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8291    | RInt _ -> pr "int"
8292    | RInt64 _ -> pr "int64"
8293    | RBool _ -> pr "bool"
8294    | RConstString _ -> pr "string"
8295    | RConstOptString _ -> pr "string option"
8296    | RString _ | RBufferOut _ -> pr "string"
8297    | RStringList _ -> pr "string array"
8298    | RStruct (_, typ) -> pr "%s" typ
8299    | RStructList (_, typ) -> pr "%s array" typ
8300    | RHashtable _ -> pr "(string * string) list"
8301   );
8302   if is_external then (
8303     pr " = ";
8304     if List.length (snd style) + 1 > 5 then
8305       pr "\"ocaml_guestfs_%s_byte\" " name;
8306     pr "\"ocaml_guestfs_%s\"" name
8307   );
8308   pr "\n"
8309
8310 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8311 and generate_perl_xs () =
8312   generate_header CStyle LGPLv2plus;
8313
8314   pr "\
8315 #include \"EXTERN.h\"
8316 #include \"perl.h\"
8317 #include \"XSUB.h\"
8318
8319 #include <guestfs.h>
8320
8321 #ifndef PRId64
8322 #define PRId64 \"lld\"
8323 #endif
8324
8325 static SV *
8326 my_newSVll(long long val) {
8327 #ifdef USE_64_BIT_ALL
8328   return newSViv(val);
8329 #else
8330   char buf[100];
8331   int len;
8332   len = snprintf(buf, 100, \"%%\" PRId64, val);
8333   return newSVpv(buf, len);
8334 #endif
8335 }
8336
8337 #ifndef PRIu64
8338 #define PRIu64 \"llu\"
8339 #endif
8340
8341 static SV *
8342 my_newSVull(unsigned long long val) {
8343 #ifdef USE_64_BIT_ALL
8344   return newSVuv(val);
8345 #else
8346   char buf[100];
8347   int len;
8348   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8349   return newSVpv(buf, len);
8350 #endif
8351 }
8352
8353 /* http://www.perlmonks.org/?node_id=680842 */
8354 static char **
8355 XS_unpack_charPtrPtr (SV *arg) {
8356   char **ret;
8357   AV *av;
8358   I32 i;
8359
8360   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8361     croak (\"array reference expected\");
8362
8363   av = (AV *)SvRV (arg);
8364   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8365   if (!ret)
8366     croak (\"malloc failed\");
8367
8368   for (i = 0; i <= av_len (av); i++) {
8369     SV **elem = av_fetch (av, i, 0);
8370
8371     if (!elem || !*elem)
8372       croak (\"missing element in list\");
8373
8374     ret[i] = SvPV_nolen (*elem);
8375   }
8376
8377   ret[i] = NULL;
8378
8379   return ret;
8380 }
8381
8382 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8383
8384 PROTOTYPES: ENABLE
8385
8386 guestfs_h *
8387 _create ()
8388    CODE:
8389       RETVAL = guestfs_create ();
8390       if (!RETVAL)
8391         croak (\"could not create guestfs handle\");
8392       guestfs_set_error_handler (RETVAL, NULL, NULL);
8393  OUTPUT:
8394       RETVAL
8395
8396 void
8397 DESTROY (g)
8398       guestfs_h *g;
8399  PPCODE:
8400       guestfs_close (g);
8401
8402 ";
8403
8404   List.iter (
8405     fun (name, style, _, _, _, _, _) ->
8406       (match fst style with
8407        | RErr -> pr "void\n"
8408        | RInt _ -> pr "SV *\n"
8409        | RInt64 _ -> pr "SV *\n"
8410        | RBool _ -> pr "SV *\n"
8411        | RConstString _ -> pr "SV *\n"
8412        | RConstOptString _ -> pr "SV *\n"
8413        | RString _ -> pr "SV *\n"
8414        | RBufferOut _ -> pr "SV *\n"
8415        | RStringList _
8416        | RStruct _ | RStructList _
8417        | RHashtable _ ->
8418            pr "void\n" (* all lists returned implictly on the stack *)
8419       );
8420       (* Call and arguments. *)
8421       pr "%s " name;
8422       generate_c_call_args ~handle:"g" ~decl:true style;
8423       pr "\n";
8424       pr "      guestfs_h *g;\n";
8425       iteri (
8426         fun i ->
8427           function
8428           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8429               pr "      char *%s;\n" n
8430           | OptString n ->
8431               (* http://www.perlmonks.org/?node_id=554277
8432                * Note that the implicit handle argument means we have
8433                * to add 1 to the ST(x) operator.
8434                *)
8435               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8436           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8437           | Bool n -> pr "      int %s;\n" n
8438           | Int n -> pr "      int %s;\n" n
8439           | Int64 n -> pr "      int64_t %s;\n" n
8440       ) (snd style);
8441
8442       let do_cleanups () =
8443         List.iter (
8444           function
8445           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8446           | Bool _ | Int _ | Int64 _
8447           | FileIn _ | FileOut _ -> ()
8448           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8449         ) (snd style)
8450       in
8451
8452       (* Code. *)
8453       (match fst style with
8454        | RErr ->
8455            pr "PREINIT:\n";
8456            pr "      int r;\n";
8457            pr " PPCODE:\n";
8458            pr "      r = guestfs_%s " name;
8459            generate_c_call_args ~handle:"g" style;
8460            pr ";\n";
8461            do_cleanups ();
8462            pr "      if (r == -1)\n";
8463            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8464        | RInt n
8465        | RBool n ->
8466            pr "PREINIT:\n";
8467            pr "      int %s;\n" n;
8468            pr "   CODE:\n";
8469            pr "      %s = guestfs_%s " n name;
8470            generate_c_call_args ~handle:"g" style;
8471            pr ";\n";
8472            do_cleanups ();
8473            pr "      if (%s == -1)\n" n;
8474            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8475            pr "      RETVAL = newSViv (%s);\n" n;
8476            pr " OUTPUT:\n";
8477            pr "      RETVAL\n"
8478        | RInt64 n ->
8479            pr "PREINIT:\n";
8480            pr "      int64_t %s;\n" n;
8481            pr "   CODE:\n";
8482            pr "      %s = guestfs_%s " n name;
8483            generate_c_call_args ~handle:"g" style;
8484            pr ";\n";
8485            do_cleanups ();
8486            pr "      if (%s == -1)\n" n;
8487            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8488            pr "      RETVAL = my_newSVll (%s);\n" n;
8489            pr " OUTPUT:\n";
8490            pr "      RETVAL\n"
8491        | RConstString n ->
8492            pr "PREINIT:\n";
8493            pr "      const char *%s;\n" n;
8494            pr "   CODE:\n";
8495            pr "      %s = guestfs_%s " n name;
8496            generate_c_call_args ~handle:"g" style;
8497            pr ";\n";
8498            do_cleanups ();
8499            pr "      if (%s == NULL)\n" n;
8500            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8501            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8502            pr " OUTPUT:\n";
8503            pr "      RETVAL\n"
8504        | RConstOptString n ->
8505            pr "PREINIT:\n";
8506            pr "      const char *%s;\n" n;
8507            pr "   CODE:\n";
8508            pr "      %s = guestfs_%s " n name;
8509            generate_c_call_args ~handle:"g" style;
8510            pr ";\n";
8511            do_cleanups ();
8512            pr "      if (%s == NULL)\n" n;
8513            pr "        RETVAL = &PL_sv_undef;\n";
8514            pr "      else\n";
8515            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8516            pr " OUTPUT:\n";
8517            pr "      RETVAL\n"
8518        | RString n ->
8519            pr "PREINIT:\n";
8520            pr "      char *%s;\n" n;
8521            pr "   CODE:\n";
8522            pr "      %s = guestfs_%s " n name;
8523            generate_c_call_args ~handle:"g" style;
8524            pr ";\n";
8525            do_cleanups ();
8526            pr "      if (%s == NULL)\n" n;
8527            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8528            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8529            pr "      free (%s);\n" n;
8530            pr " OUTPUT:\n";
8531            pr "      RETVAL\n"
8532        | RStringList n | RHashtable n ->
8533            pr "PREINIT:\n";
8534            pr "      char **%s;\n" n;
8535            pr "      int i, n;\n";
8536            pr " PPCODE:\n";
8537            pr "      %s = guestfs_%s " n name;
8538            generate_c_call_args ~handle:"g" style;
8539            pr ";\n";
8540            do_cleanups ();
8541            pr "      if (%s == NULL)\n" n;
8542            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8543            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8544            pr "      EXTEND (SP, n);\n";
8545            pr "      for (i = 0; i < n; ++i) {\n";
8546            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8547            pr "        free (%s[i]);\n" n;
8548            pr "      }\n";
8549            pr "      free (%s);\n" n;
8550        | RStruct (n, typ) ->
8551            let cols = cols_of_struct typ in
8552            generate_perl_struct_code typ cols name style n do_cleanups
8553        | RStructList (n, typ) ->
8554            let cols = cols_of_struct typ in
8555            generate_perl_struct_list_code typ cols name style n do_cleanups
8556        | RBufferOut n ->
8557            pr "PREINIT:\n";
8558            pr "      char *%s;\n" n;
8559            pr "      size_t size;\n";
8560            pr "   CODE:\n";
8561            pr "      %s = guestfs_%s " n name;
8562            generate_c_call_args ~handle:"g" style;
8563            pr ";\n";
8564            do_cleanups ();
8565            pr "      if (%s == NULL)\n" n;
8566            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8567            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8568            pr "      free (%s);\n" n;
8569            pr " OUTPUT:\n";
8570            pr "      RETVAL\n"
8571       );
8572
8573       pr "\n"
8574   ) all_functions
8575
8576 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8577   pr "PREINIT:\n";
8578   pr "      struct guestfs_%s_list *%s;\n" typ n;
8579   pr "      int i;\n";
8580   pr "      HV *hv;\n";
8581   pr " PPCODE:\n";
8582   pr "      %s = guestfs_%s " n name;
8583   generate_c_call_args ~handle:"g" style;
8584   pr ";\n";
8585   do_cleanups ();
8586   pr "      if (%s == NULL)\n" n;
8587   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8588   pr "      EXTEND (SP, %s->len);\n" n;
8589   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8590   pr "        hv = newHV ();\n";
8591   List.iter (
8592     function
8593     | name, FString ->
8594         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8595           name (String.length name) n name
8596     | name, FUUID ->
8597         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8598           name (String.length name) n name
8599     | name, FBuffer ->
8600         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8601           name (String.length name) n name n name
8602     | name, (FBytes|FUInt64) ->
8603         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8604           name (String.length name) n name
8605     | name, FInt64 ->
8606         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8607           name (String.length name) n name
8608     | name, (FInt32|FUInt32) ->
8609         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8610           name (String.length name) n name
8611     | name, FChar ->
8612         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8613           name (String.length name) n name
8614     | name, FOptPercent ->
8615         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8616           name (String.length name) n name
8617   ) cols;
8618   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8619   pr "      }\n";
8620   pr "      guestfs_free_%s_list (%s);\n" typ n
8621
8622 and generate_perl_struct_code typ cols name style n do_cleanups =
8623   pr "PREINIT:\n";
8624   pr "      struct guestfs_%s *%s;\n" typ n;
8625   pr " PPCODE:\n";
8626   pr "      %s = guestfs_%s " n name;
8627   generate_c_call_args ~handle:"g" style;
8628   pr ";\n";
8629   do_cleanups ();
8630   pr "      if (%s == NULL)\n" n;
8631   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8632   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8633   List.iter (
8634     fun ((name, _) as col) ->
8635       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8636
8637       match col with
8638       | name, FString ->
8639           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8640             n name
8641       | name, FBuffer ->
8642           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8643             n name n name
8644       | name, FUUID ->
8645           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8646             n name
8647       | name, (FBytes|FUInt64) ->
8648           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8649             n name
8650       | name, FInt64 ->
8651           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8652             n name
8653       | name, (FInt32|FUInt32) ->
8654           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8655             n name
8656       | name, FChar ->
8657           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8658             n name
8659       | name, FOptPercent ->
8660           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8661             n name
8662   ) cols;
8663   pr "      free (%s);\n" n
8664
8665 (* Generate Sys/Guestfs.pm. *)
8666 and generate_perl_pm () =
8667   generate_header HashStyle LGPLv2plus;
8668
8669   pr "\
8670 =pod
8671
8672 =head1 NAME
8673
8674 Sys::Guestfs - Perl bindings for libguestfs
8675
8676 =head1 SYNOPSIS
8677
8678  use Sys::Guestfs;
8679
8680  my $h = Sys::Guestfs->new ();
8681  $h->add_drive ('guest.img');
8682  $h->launch ();
8683  $h->mount ('/dev/sda1', '/');
8684  $h->touch ('/hello');
8685  $h->sync ();
8686
8687 =head1 DESCRIPTION
8688
8689 The C<Sys::Guestfs> module provides a Perl XS binding to the
8690 libguestfs API for examining and modifying virtual machine
8691 disk images.
8692
8693 Amongst the things this is good for: making batch configuration
8694 changes to guests, getting disk used/free statistics (see also:
8695 virt-df), migrating between virtualization systems (see also:
8696 virt-p2v), performing partial backups, performing partial guest
8697 clones, cloning guests and changing registry/UUID/hostname info, and
8698 much else besides.
8699
8700 Libguestfs uses Linux kernel and qemu code, and can access any type of
8701 guest filesystem that Linux and qemu can, including but not limited
8702 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8703 schemes, qcow, qcow2, vmdk.
8704
8705 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8706 LVs, what filesystem is in each LV, etc.).  It can also run commands
8707 in the context of the guest.  Also you can access filesystems over
8708 FUSE.
8709
8710 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8711 functions for using libguestfs from Perl, including integration
8712 with libvirt.
8713
8714 =head1 ERRORS
8715
8716 All errors turn into calls to C<croak> (see L<Carp(3)>).
8717
8718 =head1 METHODS
8719
8720 =over 4
8721
8722 =cut
8723
8724 package Sys::Guestfs;
8725
8726 use strict;
8727 use warnings;
8728
8729 require XSLoader;
8730 XSLoader::load ('Sys::Guestfs');
8731
8732 =item $h = Sys::Guestfs->new ();
8733
8734 Create a new guestfs handle.
8735
8736 =cut
8737
8738 sub new {
8739   my $proto = shift;
8740   my $class = ref ($proto) || $proto;
8741
8742   my $self = Sys::Guestfs::_create ();
8743   bless $self, $class;
8744   return $self;
8745 }
8746
8747 ";
8748
8749   (* Actions.  We only need to print documentation for these as
8750    * they are pulled in from the XS code automatically.
8751    *)
8752   List.iter (
8753     fun (name, style, _, flags, _, _, longdesc) ->
8754       if not (List.mem NotInDocs flags) then (
8755         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8756         pr "=item ";
8757         generate_perl_prototype name style;
8758         pr "\n\n";
8759         pr "%s\n\n" longdesc;
8760         if List.mem ProtocolLimitWarning flags then
8761           pr "%s\n\n" protocol_limit_warning;
8762         if List.mem DangerWillRobinson flags then
8763           pr "%s\n\n" danger_will_robinson;
8764         match deprecation_notice flags with
8765         | None -> ()
8766         | Some txt -> pr "%s\n\n" txt
8767       )
8768   ) all_functions_sorted;
8769
8770   (* End of file. *)
8771   pr "\
8772 =cut
8773
8774 1;
8775
8776 =back
8777
8778 =head1 COPYRIGHT
8779
8780 Copyright (C) %s Red Hat Inc.
8781
8782 =head1 LICENSE
8783
8784 Please see the file COPYING.LIB for the full license.
8785
8786 =head1 SEE ALSO
8787
8788 L<guestfs(3)>,
8789 L<guestfish(1)>,
8790 L<http://libguestfs.org>,
8791 L<Sys::Guestfs::Lib(3)>.
8792
8793 =cut
8794 " copyright_years
8795
8796 and generate_perl_prototype name style =
8797   (match fst style with
8798    | RErr -> ()
8799    | RBool n
8800    | RInt n
8801    | RInt64 n
8802    | RConstString n
8803    | RConstOptString n
8804    | RString n
8805    | RBufferOut n -> pr "$%s = " n
8806    | RStruct (n,_)
8807    | RHashtable n -> pr "%%%s = " n
8808    | RStringList n
8809    | RStructList (n,_) -> pr "@%s = " n
8810   );
8811   pr "$h->%s (" name;
8812   let comma = ref false in
8813   List.iter (
8814     fun arg ->
8815       if !comma then pr ", ";
8816       comma := true;
8817       match arg with
8818       | Pathname n | Device n | Dev_or_Path n | String n
8819       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8820           pr "$%s" n
8821       | StringList n | DeviceList n ->
8822           pr "\\@%s" n
8823   ) (snd style);
8824   pr ");"
8825
8826 (* Generate Python C module. *)
8827 and generate_python_c () =
8828   generate_header CStyle LGPLv2plus;
8829
8830   pr "\
8831 #include <Python.h>
8832
8833 #include <stdio.h>
8834 #include <stdlib.h>
8835 #include <assert.h>
8836
8837 #include \"guestfs.h\"
8838
8839 typedef struct {
8840   PyObject_HEAD
8841   guestfs_h *g;
8842 } Pyguestfs_Object;
8843
8844 static guestfs_h *
8845 get_handle (PyObject *obj)
8846 {
8847   assert (obj);
8848   assert (obj != Py_None);
8849   return ((Pyguestfs_Object *) obj)->g;
8850 }
8851
8852 static PyObject *
8853 put_handle (guestfs_h *g)
8854 {
8855   assert (g);
8856   return
8857     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8858 }
8859
8860 /* This list should be freed (but not the strings) after use. */
8861 static char **
8862 get_string_list (PyObject *obj)
8863 {
8864   int i, len;
8865   char **r;
8866
8867   assert (obj);
8868
8869   if (!PyList_Check (obj)) {
8870     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8871     return NULL;
8872   }
8873
8874   len = PyList_Size (obj);
8875   r = malloc (sizeof (char *) * (len+1));
8876   if (r == NULL) {
8877     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8878     return NULL;
8879   }
8880
8881   for (i = 0; i < len; ++i)
8882     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8883   r[len] = NULL;
8884
8885   return r;
8886 }
8887
8888 static PyObject *
8889 put_string_list (char * const * const argv)
8890 {
8891   PyObject *list;
8892   int argc, i;
8893
8894   for (argc = 0; argv[argc] != NULL; ++argc)
8895     ;
8896
8897   list = PyList_New (argc);
8898   for (i = 0; i < argc; ++i)
8899     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8900
8901   return list;
8902 }
8903
8904 static PyObject *
8905 put_table (char * const * const argv)
8906 {
8907   PyObject *list, *item;
8908   int argc, i;
8909
8910   for (argc = 0; argv[argc] != NULL; ++argc)
8911     ;
8912
8913   list = PyList_New (argc >> 1);
8914   for (i = 0; i < argc; i += 2) {
8915     item = PyTuple_New (2);
8916     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8917     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8918     PyList_SetItem (list, i >> 1, item);
8919   }
8920
8921   return list;
8922 }
8923
8924 static void
8925 free_strings (char **argv)
8926 {
8927   int argc;
8928
8929   for (argc = 0; argv[argc] != NULL; ++argc)
8930     free (argv[argc]);
8931   free (argv);
8932 }
8933
8934 static PyObject *
8935 py_guestfs_create (PyObject *self, PyObject *args)
8936 {
8937   guestfs_h *g;
8938
8939   g = guestfs_create ();
8940   if (g == NULL) {
8941     PyErr_SetString (PyExc_RuntimeError,
8942                      \"guestfs.create: failed to allocate handle\");
8943     return NULL;
8944   }
8945   guestfs_set_error_handler (g, NULL, NULL);
8946   return put_handle (g);
8947 }
8948
8949 static PyObject *
8950 py_guestfs_close (PyObject *self, PyObject *args)
8951 {
8952   PyObject *py_g;
8953   guestfs_h *g;
8954
8955   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8956     return NULL;
8957   g = get_handle (py_g);
8958
8959   guestfs_close (g);
8960
8961   Py_INCREF (Py_None);
8962   return Py_None;
8963 }
8964
8965 ";
8966
8967   let emit_put_list_function typ =
8968     pr "static PyObject *\n";
8969     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8970     pr "{\n";
8971     pr "  PyObject *list;\n";
8972     pr "  int i;\n";
8973     pr "\n";
8974     pr "  list = PyList_New (%ss->len);\n" typ;
8975     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8976     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8977     pr "  return list;\n";
8978     pr "};\n";
8979     pr "\n"
8980   in
8981
8982   (* Structures, turned into Python dictionaries. *)
8983   List.iter (
8984     fun (typ, cols) ->
8985       pr "static PyObject *\n";
8986       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8987       pr "{\n";
8988       pr "  PyObject *dict;\n";
8989       pr "\n";
8990       pr "  dict = PyDict_New ();\n";
8991       List.iter (
8992         function
8993         | name, FString ->
8994             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8995             pr "                        PyString_FromString (%s->%s));\n"
8996               typ name
8997         | name, FBuffer ->
8998             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8999             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9000               typ name typ name
9001         | name, FUUID ->
9002             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9003             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9004               typ name
9005         | name, (FBytes|FUInt64) ->
9006             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9007             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9008               typ name
9009         | name, FInt64 ->
9010             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9011             pr "                        PyLong_FromLongLong (%s->%s));\n"
9012               typ name
9013         | name, FUInt32 ->
9014             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9015             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9016               typ name
9017         | name, FInt32 ->
9018             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9019             pr "                        PyLong_FromLong (%s->%s));\n"
9020               typ name
9021         | name, FOptPercent ->
9022             pr "  if (%s->%s >= 0)\n" typ name;
9023             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9024             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9025               typ name;
9026             pr "  else {\n";
9027             pr "    Py_INCREF (Py_None);\n";
9028             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9029             pr "  }\n"
9030         | name, FChar ->
9031             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9032             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9033       ) cols;
9034       pr "  return dict;\n";
9035       pr "};\n";
9036       pr "\n";
9037
9038   ) structs;
9039
9040   (* Emit a put_TYPE_list function definition only if that function is used. *)
9041   List.iter (
9042     function
9043     | typ, (RStructListOnly | RStructAndList) ->
9044         (* generate the function for typ *)
9045         emit_put_list_function typ
9046     | typ, _ -> () (* empty *)
9047   ) (rstructs_used_by all_functions);
9048
9049   (* Python wrapper functions. *)
9050   List.iter (
9051     fun (name, style, _, _, _, _, _) ->
9052       pr "static PyObject *\n";
9053       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9054       pr "{\n";
9055
9056       pr "  PyObject *py_g;\n";
9057       pr "  guestfs_h *g;\n";
9058       pr "  PyObject *py_r;\n";
9059
9060       let error_code =
9061         match fst style with
9062         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9063         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9064         | RConstString _ | RConstOptString _ ->
9065             pr "  const char *r;\n"; "NULL"
9066         | RString _ -> pr "  char *r;\n"; "NULL"
9067         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9068         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9069         | RStructList (_, typ) ->
9070             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9071         | RBufferOut _ ->
9072             pr "  char *r;\n";
9073             pr "  size_t size;\n";
9074             "NULL" in
9075
9076       List.iter (
9077         function
9078         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9079             pr "  const char *%s;\n" n
9080         | OptString n -> pr "  const char *%s;\n" n
9081         | StringList n | DeviceList n ->
9082             pr "  PyObject *py_%s;\n" n;
9083             pr "  char **%s;\n" n
9084         | Bool n -> pr "  int %s;\n" n
9085         | Int n -> pr "  int %s;\n" n
9086         | Int64 n -> pr "  long long %s;\n" n
9087       ) (snd style);
9088
9089       pr "\n";
9090
9091       (* Convert the parameters. *)
9092       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9093       List.iter (
9094         function
9095         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9096         | OptString _ -> pr "z"
9097         | StringList _ | DeviceList _ -> pr "O"
9098         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9099         | Int _ -> pr "i"
9100         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9101                              * emulate C's int/long/long long in Python?
9102                              *)
9103       ) (snd style);
9104       pr ":guestfs_%s\",\n" name;
9105       pr "                         &py_g";
9106       List.iter (
9107         function
9108         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9109         | OptString n -> pr ", &%s" n
9110         | StringList n | DeviceList n -> pr ", &py_%s" n
9111         | Bool n -> pr ", &%s" n
9112         | Int n -> pr ", &%s" n
9113         | Int64 n -> pr ", &%s" n
9114       ) (snd style);
9115
9116       pr "))\n";
9117       pr "    return NULL;\n";
9118
9119       pr "  g = get_handle (py_g);\n";
9120       List.iter (
9121         function
9122         | Pathname _ | Device _ | Dev_or_Path _ | String _
9123         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9124         | StringList n | DeviceList n ->
9125             pr "  %s = get_string_list (py_%s);\n" n n;
9126             pr "  if (!%s) return NULL;\n" n
9127       ) (snd style);
9128
9129       pr "\n";
9130
9131       pr "  r = guestfs_%s " name;
9132       generate_c_call_args ~handle:"g" style;
9133       pr ";\n";
9134
9135       List.iter (
9136         function
9137         | Pathname _ | Device _ | Dev_or_Path _ | String _
9138         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9139         | StringList n | DeviceList n ->
9140             pr "  free (%s);\n" n
9141       ) (snd style);
9142
9143       pr "  if (r == %s) {\n" error_code;
9144       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9145       pr "    return NULL;\n";
9146       pr "  }\n";
9147       pr "\n";
9148
9149       (match fst style with
9150        | RErr ->
9151            pr "  Py_INCREF (Py_None);\n";
9152            pr "  py_r = Py_None;\n"
9153        | RInt _
9154        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9155        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9156        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9157        | RConstOptString _ ->
9158            pr "  if (r)\n";
9159            pr "    py_r = PyString_FromString (r);\n";
9160            pr "  else {\n";
9161            pr "    Py_INCREF (Py_None);\n";
9162            pr "    py_r = Py_None;\n";
9163            pr "  }\n"
9164        | RString _ ->
9165            pr "  py_r = PyString_FromString (r);\n";
9166            pr "  free (r);\n"
9167        | RStringList _ ->
9168            pr "  py_r = put_string_list (r);\n";
9169            pr "  free_strings (r);\n"
9170        | RStruct (_, typ) ->
9171            pr "  py_r = put_%s (r);\n" typ;
9172            pr "  guestfs_free_%s (r);\n" typ
9173        | RStructList (_, typ) ->
9174            pr "  py_r = put_%s_list (r);\n" typ;
9175            pr "  guestfs_free_%s_list (r);\n" typ
9176        | RHashtable n ->
9177            pr "  py_r = put_table (r);\n";
9178            pr "  free_strings (r);\n"
9179        | RBufferOut _ ->
9180            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9181            pr "  free (r);\n"
9182       );
9183
9184       pr "  return py_r;\n";
9185       pr "}\n";
9186       pr "\n"
9187   ) all_functions;
9188
9189   (* Table of functions. *)
9190   pr "static PyMethodDef methods[] = {\n";
9191   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9192   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9193   List.iter (
9194     fun (name, _, _, _, _, _, _) ->
9195       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9196         name name
9197   ) all_functions;
9198   pr "  { NULL, NULL, 0, NULL }\n";
9199   pr "};\n";
9200   pr "\n";
9201
9202   (* Init function. *)
9203   pr "\
9204 void
9205 initlibguestfsmod (void)
9206 {
9207   static int initialized = 0;
9208
9209   if (initialized) return;
9210   Py_InitModule ((char *) \"libguestfsmod\", methods);
9211   initialized = 1;
9212 }
9213 "
9214
9215 (* Generate Python module. *)
9216 and generate_python_py () =
9217   generate_header HashStyle LGPLv2plus;
9218
9219   pr "\
9220 u\"\"\"Python bindings for libguestfs
9221
9222 import guestfs
9223 g = guestfs.GuestFS ()
9224 g.add_drive (\"guest.img\")
9225 g.launch ()
9226 parts = g.list_partitions ()
9227
9228 The guestfs module provides a Python binding to the libguestfs API
9229 for examining and modifying virtual machine disk images.
9230
9231 Amongst the things this is good for: making batch configuration
9232 changes to guests, getting disk used/free statistics (see also:
9233 virt-df), migrating between virtualization systems (see also:
9234 virt-p2v), performing partial backups, performing partial guest
9235 clones, cloning guests and changing registry/UUID/hostname info, and
9236 much else besides.
9237
9238 Libguestfs uses Linux kernel and qemu code, and can access any type of
9239 guest filesystem that Linux and qemu can, including but not limited
9240 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9241 schemes, qcow, qcow2, vmdk.
9242
9243 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9244 LVs, what filesystem is in each LV, etc.).  It can also run commands
9245 in the context of the guest.  Also you can access filesystems over
9246 FUSE.
9247
9248 Errors which happen while using the API are turned into Python
9249 RuntimeError exceptions.
9250
9251 To create a guestfs handle you usually have to perform the following
9252 sequence of calls:
9253
9254 # Create the handle, call add_drive at least once, and possibly
9255 # several times if the guest has multiple block devices:
9256 g = guestfs.GuestFS ()
9257 g.add_drive (\"guest.img\")
9258
9259 # Launch the qemu subprocess and wait for it to become ready:
9260 g.launch ()
9261
9262 # Now you can issue commands, for example:
9263 logvols = g.lvs ()
9264
9265 \"\"\"
9266
9267 import libguestfsmod
9268
9269 class GuestFS:
9270     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9271
9272     def __init__ (self):
9273         \"\"\"Create a new libguestfs handle.\"\"\"
9274         self._o = libguestfsmod.create ()
9275
9276     def __del__ (self):
9277         libguestfsmod.close (self._o)
9278
9279 ";
9280
9281   List.iter (
9282     fun (name, style, _, flags, _, _, longdesc) ->
9283       pr "    def %s " name;
9284       generate_py_call_args ~handle:"self" (snd style);
9285       pr ":\n";
9286
9287       if not (List.mem NotInDocs flags) then (
9288         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9289         let doc =
9290           match fst style with
9291           | RErr | RInt _ | RInt64 _ | RBool _
9292           | RConstOptString _ | RConstString _
9293           | RString _ | RBufferOut _ -> doc
9294           | RStringList _ ->
9295               doc ^ "\n\nThis function returns a list of strings."
9296           | RStruct (_, typ) ->
9297               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9298           | RStructList (_, typ) ->
9299               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9300           | RHashtable _ ->
9301               doc ^ "\n\nThis function returns a dictionary." in
9302         let doc =
9303           if List.mem ProtocolLimitWarning flags then
9304             doc ^ "\n\n" ^ protocol_limit_warning
9305           else doc in
9306         let doc =
9307           if List.mem DangerWillRobinson flags then
9308             doc ^ "\n\n" ^ danger_will_robinson
9309           else doc in
9310         let doc =
9311           match deprecation_notice flags with
9312           | None -> doc
9313           | Some txt -> doc ^ "\n\n" ^ txt in
9314         let doc = pod2text ~width:60 name doc in
9315         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9316         let doc = String.concat "\n        " doc in
9317         pr "        u\"\"\"%s\"\"\"\n" doc;
9318       );
9319       pr "        return libguestfsmod.%s " name;
9320       generate_py_call_args ~handle:"self._o" (snd style);
9321       pr "\n";
9322       pr "\n";
9323   ) all_functions
9324
9325 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9326 and generate_py_call_args ~handle args =
9327   pr "(%s" handle;
9328   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9329   pr ")"
9330
9331 (* Useful if you need the longdesc POD text as plain text.  Returns a
9332  * list of lines.
9333  *
9334  * Because this is very slow (the slowest part of autogeneration),
9335  * we memoize the results.
9336  *)
9337 and pod2text ~width name longdesc =
9338   let key = width, name, longdesc in
9339   try Hashtbl.find pod2text_memo key
9340   with Not_found ->
9341     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9342     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9343     close_out chan;
9344     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9345     let chan = open_process_in cmd in
9346     let lines = ref [] in
9347     let rec loop i =
9348       let line = input_line chan in
9349       if i = 1 then             (* discard the first line of output *)
9350         loop (i+1)
9351       else (
9352         let line = triml line in
9353         lines := line :: !lines;
9354         loop (i+1)
9355       ) in
9356     let lines = try loop 1 with End_of_file -> List.rev !lines in
9357     unlink filename;
9358     (match close_process_in chan with
9359      | WEXITED 0 -> ()
9360      | WEXITED i ->
9361          failwithf "pod2text: process exited with non-zero status (%d)" i
9362      | WSIGNALED i | WSTOPPED i ->
9363          failwithf "pod2text: process signalled or stopped by signal %d" i
9364     );
9365     Hashtbl.add pod2text_memo key lines;
9366     pod2text_memo_updated ();
9367     lines
9368
9369 (* Generate ruby bindings. *)
9370 and generate_ruby_c () =
9371   generate_header CStyle LGPLv2plus;
9372
9373   pr "\
9374 #include <stdio.h>
9375 #include <stdlib.h>
9376
9377 #include <ruby.h>
9378
9379 #include \"guestfs.h\"
9380
9381 #include \"extconf.h\"
9382
9383 /* For Ruby < 1.9 */
9384 #ifndef RARRAY_LEN
9385 #define RARRAY_LEN(r) (RARRAY((r))->len)
9386 #endif
9387
9388 static VALUE m_guestfs;                 /* guestfs module */
9389 static VALUE c_guestfs;                 /* guestfs_h handle */
9390 static VALUE e_Error;                   /* used for all errors */
9391
9392 static void ruby_guestfs_free (void *p)
9393 {
9394   if (!p) return;
9395   guestfs_close ((guestfs_h *) p);
9396 }
9397
9398 static VALUE ruby_guestfs_create (VALUE m)
9399 {
9400   guestfs_h *g;
9401
9402   g = guestfs_create ();
9403   if (!g)
9404     rb_raise (e_Error, \"failed to create guestfs handle\");
9405
9406   /* Don't print error messages to stderr by default. */
9407   guestfs_set_error_handler (g, NULL, NULL);
9408
9409   /* Wrap it, and make sure the close function is called when the
9410    * handle goes away.
9411    */
9412   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9413 }
9414
9415 static VALUE ruby_guestfs_close (VALUE gv)
9416 {
9417   guestfs_h *g;
9418   Data_Get_Struct (gv, guestfs_h, g);
9419
9420   ruby_guestfs_free (g);
9421   DATA_PTR (gv) = NULL;
9422
9423   return Qnil;
9424 }
9425
9426 ";
9427
9428   List.iter (
9429     fun (name, style, _, _, _, _, _) ->
9430       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9431       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9432       pr ")\n";
9433       pr "{\n";
9434       pr "  guestfs_h *g;\n";
9435       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9436       pr "  if (!g)\n";
9437       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9438         name;
9439       pr "\n";
9440
9441       List.iter (
9442         function
9443         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9444             pr "  Check_Type (%sv, T_STRING);\n" n;
9445             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9446             pr "  if (!%s)\n" n;
9447             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9448             pr "              \"%s\", \"%s\");\n" n name
9449         | OptString n ->
9450             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9451         | StringList n | DeviceList n ->
9452             pr "  char **%s;\n" n;
9453             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9454             pr "  {\n";
9455             pr "    int i, len;\n";
9456             pr "    len = RARRAY_LEN (%sv);\n" n;
9457             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9458               n;
9459             pr "    for (i = 0; i < len; ++i) {\n";
9460             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9461             pr "      %s[i] = StringValueCStr (v);\n" n;
9462             pr "    }\n";
9463             pr "    %s[len] = NULL;\n" n;
9464             pr "  }\n";
9465         | Bool n ->
9466             pr "  int %s = RTEST (%sv);\n" n n
9467         | Int n ->
9468             pr "  int %s = NUM2INT (%sv);\n" n n
9469         | Int64 n ->
9470             pr "  long long %s = NUM2LL (%sv);\n" n n
9471       ) (snd style);
9472       pr "\n";
9473
9474       let error_code =
9475         match fst style with
9476         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9477         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9478         | RConstString _ | RConstOptString _ ->
9479             pr "  const char *r;\n"; "NULL"
9480         | RString _ -> pr "  char *r;\n"; "NULL"
9481         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9482         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9483         | RStructList (_, typ) ->
9484             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9485         | RBufferOut _ ->
9486             pr "  char *r;\n";
9487             pr "  size_t size;\n";
9488             "NULL" in
9489       pr "\n";
9490
9491       pr "  r = guestfs_%s " name;
9492       generate_c_call_args ~handle:"g" style;
9493       pr ";\n";
9494
9495       List.iter (
9496         function
9497         | Pathname _ | Device _ | Dev_or_Path _ | String _
9498         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9499         | StringList n | DeviceList n ->
9500             pr "  free (%s);\n" n
9501       ) (snd style);
9502
9503       pr "  if (r == %s)\n" error_code;
9504       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9505       pr "\n";
9506
9507       (match fst style with
9508        | RErr ->
9509            pr "  return Qnil;\n"
9510        | RInt _ | RBool _ ->
9511            pr "  return INT2NUM (r);\n"
9512        | RInt64 _ ->
9513            pr "  return ULL2NUM (r);\n"
9514        | RConstString _ ->
9515            pr "  return rb_str_new2 (r);\n";
9516        | RConstOptString _ ->
9517            pr "  if (r)\n";
9518            pr "    return rb_str_new2 (r);\n";
9519            pr "  else\n";
9520            pr "    return Qnil;\n";
9521        | RString _ ->
9522            pr "  VALUE rv = rb_str_new2 (r);\n";
9523            pr "  free (r);\n";
9524            pr "  return rv;\n";
9525        | RStringList _ ->
9526            pr "  int i, len = 0;\n";
9527            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9528            pr "  VALUE rv = rb_ary_new2 (len);\n";
9529            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9530            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9531            pr "    free (r[i]);\n";
9532            pr "  }\n";
9533            pr "  free (r);\n";
9534            pr "  return rv;\n"
9535        | RStruct (_, typ) ->
9536            let cols = cols_of_struct typ in
9537            generate_ruby_struct_code typ cols
9538        | RStructList (_, typ) ->
9539            let cols = cols_of_struct typ in
9540            generate_ruby_struct_list_code typ cols
9541        | RHashtable _ ->
9542            pr "  VALUE rv = rb_hash_new ();\n";
9543            pr "  int i;\n";
9544            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9545            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9546            pr "    free (r[i]);\n";
9547            pr "    free (r[i+1]);\n";
9548            pr "  }\n";
9549            pr "  free (r);\n";
9550            pr "  return rv;\n"
9551        | RBufferOut _ ->
9552            pr "  VALUE rv = rb_str_new (r, size);\n";
9553            pr "  free (r);\n";
9554            pr "  return rv;\n";
9555       );
9556
9557       pr "}\n";
9558       pr "\n"
9559   ) all_functions;
9560
9561   pr "\
9562 /* Initialize the module. */
9563 void Init__guestfs ()
9564 {
9565   m_guestfs = rb_define_module (\"Guestfs\");
9566   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9567   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9568
9569   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9570   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9571
9572 ";
9573   (* Define the rest of the methods. *)
9574   List.iter (
9575     fun (name, style, _, _, _, _, _) ->
9576       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9577       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9578   ) all_functions;
9579
9580   pr "}\n"
9581
9582 (* Ruby code to return a struct. *)
9583 and generate_ruby_struct_code typ cols =
9584   pr "  VALUE rv = rb_hash_new ();\n";
9585   List.iter (
9586     function
9587     | name, FString ->
9588         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9589     | name, FBuffer ->
9590         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9591     | name, FUUID ->
9592         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9593     | name, (FBytes|FUInt64) ->
9594         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9595     | name, FInt64 ->
9596         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9597     | name, FUInt32 ->
9598         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9599     | name, FInt32 ->
9600         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9601     | name, FOptPercent ->
9602         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9603     | name, FChar -> (* XXX wrong? *)
9604         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9605   ) cols;
9606   pr "  guestfs_free_%s (r);\n" typ;
9607   pr "  return rv;\n"
9608
9609 (* Ruby code to return a struct list. *)
9610 and generate_ruby_struct_list_code typ cols =
9611   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9612   pr "  int i;\n";
9613   pr "  for (i = 0; i < r->len; ++i) {\n";
9614   pr "    VALUE hv = rb_hash_new ();\n";
9615   List.iter (
9616     function
9617     | name, FString ->
9618         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9619     | name, FBuffer ->
9620         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
9621     | name, FUUID ->
9622         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9623     | name, (FBytes|FUInt64) ->
9624         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9625     | name, FInt64 ->
9626         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9627     | name, FUInt32 ->
9628         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9629     | name, FInt32 ->
9630         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9631     | name, FOptPercent ->
9632         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9633     | name, FChar -> (* XXX wrong? *)
9634         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9635   ) cols;
9636   pr "    rb_ary_push (rv, hv);\n";
9637   pr "  }\n";
9638   pr "  guestfs_free_%s_list (r);\n" typ;
9639   pr "  return rv;\n"
9640
9641 (* Generate Java bindings GuestFS.java file. *)
9642 and generate_java_java () =
9643   generate_header CStyle LGPLv2plus;
9644
9645   pr "\
9646 package com.redhat.et.libguestfs;
9647
9648 import java.util.HashMap;
9649 import com.redhat.et.libguestfs.LibGuestFSException;
9650 import com.redhat.et.libguestfs.PV;
9651 import com.redhat.et.libguestfs.VG;
9652 import com.redhat.et.libguestfs.LV;
9653 import com.redhat.et.libguestfs.Stat;
9654 import com.redhat.et.libguestfs.StatVFS;
9655 import com.redhat.et.libguestfs.IntBool;
9656 import com.redhat.et.libguestfs.Dirent;
9657
9658 /**
9659  * The GuestFS object is a libguestfs handle.
9660  *
9661  * @author rjones
9662  */
9663 public class GuestFS {
9664   // Load the native code.
9665   static {
9666     System.loadLibrary (\"guestfs_jni\");
9667   }
9668
9669   /**
9670    * The native guestfs_h pointer.
9671    */
9672   long g;
9673
9674   /**
9675    * Create a libguestfs handle.
9676    *
9677    * @throws LibGuestFSException
9678    */
9679   public GuestFS () throws LibGuestFSException
9680   {
9681     g = _create ();
9682   }
9683   private native long _create () throws LibGuestFSException;
9684
9685   /**
9686    * Close a libguestfs handle.
9687    *
9688    * You can also leave handles to be collected by the garbage
9689    * collector, but this method ensures that the resources used
9690    * by the handle are freed up immediately.  If you call any
9691    * other methods after closing the handle, you will get an
9692    * exception.
9693    *
9694    * @throws LibGuestFSException
9695    */
9696   public void close () throws LibGuestFSException
9697   {
9698     if (g != 0)
9699       _close (g);
9700     g = 0;
9701   }
9702   private native void _close (long g) throws LibGuestFSException;
9703
9704   public void finalize () throws LibGuestFSException
9705   {
9706     close ();
9707   }
9708
9709 ";
9710
9711   List.iter (
9712     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9713       if not (List.mem NotInDocs flags); then (
9714         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9715         let doc =
9716           if List.mem ProtocolLimitWarning flags then
9717             doc ^ "\n\n" ^ protocol_limit_warning
9718           else doc in
9719         let doc =
9720           if List.mem DangerWillRobinson flags then
9721             doc ^ "\n\n" ^ danger_will_robinson
9722           else doc in
9723         let doc =
9724           match deprecation_notice flags with
9725           | None -> doc
9726           | Some txt -> doc ^ "\n\n" ^ txt in
9727         let doc = pod2text ~width:60 name doc in
9728         let doc = List.map (            (* RHBZ#501883 *)
9729           function
9730           | "" -> "<p>"
9731           | nonempty -> nonempty
9732         ) doc in
9733         let doc = String.concat "\n   * " doc in
9734
9735         pr "  /**\n";
9736         pr "   * %s\n" shortdesc;
9737         pr "   * <p>\n";
9738         pr "   * %s\n" doc;
9739         pr "   * @throws LibGuestFSException\n";
9740         pr "   */\n";
9741         pr "  ";
9742       );
9743       generate_java_prototype ~public:true ~semicolon:false name style;
9744       pr "\n";
9745       pr "  {\n";
9746       pr "    if (g == 0)\n";
9747       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9748         name;
9749       pr "    ";
9750       if fst style <> RErr then pr "return ";
9751       pr "_%s " name;
9752       generate_java_call_args ~handle:"g" (snd style);
9753       pr ";\n";
9754       pr "  }\n";
9755       pr "  ";
9756       generate_java_prototype ~privat:true ~native:true name style;
9757       pr "\n";
9758       pr "\n";
9759   ) all_functions;
9760
9761   pr "}\n"
9762
9763 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9764 and generate_java_call_args ~handle args =
9765   pr "(%s" handle;
9766   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9767   pr ")"
9768
9769 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9770     ?(semicolon=true) name style =
9771   if privat then pr "private ";
9772   if public then pr "public ";
9773   if native then pr "native ";
9774
9775   (* return type *)
9776   (match fst style with
9777    | RErr -> pr "void ";
9778    | RInt _ -> pr "int ";
9779    | RInt64 _ -> pr "long ";
9780    | RBool _ -> pr "boolean ";
9781    | RConstString _ | RConstOptString _ | RString _
9782    | RBufferOut _ -> pr "String ";
9783    | RStringList _ -> pr "String[] ";
9784    | RStruct (_, typ) ->
9785        let name = java_name_of_struct typ in
9786        pr "%s " name;
9787    | RStructList (_, typ) ->
9788        let name = java_name_of_struct typ in
9789        pr "%s[] " name;
9790    | RHashtable _ -> pr "HashMap<String,String> ";
9791   );
9792
9793   if native then pr "_%s " name else pr "%s " name;
9794   pr "(";
9795   let needs_comma = ref false in
9796   if native then (
9797     pr "long g";
9798     needs_comma := true
9799   );
9800
9801   (* args *)
9802   List.iter (
9803     fun arg ->
9804       if !needs_comma then pr ", ";
9805       needs_comma := true;
9806
9807       match arg with
9808       | Pathname n
9809       | Device n | Dev_or_Path n
9810       | String n
9811       | OptString n
9812       | FileIn n
9813       | FileOut n ->
9814           pr "String %s" n
9815       | StringList n | DeviceList n ->
9816           pr "String[] %s" n
9817       | Bool n ->
9818           pr "boolean %s" n
9819       | Int n ->
9820           pr "int %s" n
9821       | Int64 n ->
9822           pr "long %s" n
9823   ) (snd style);
9824
9825   pr ")\n";
9826   pr "    throws LibGuestFSException";
9827   if semicolon then pr ";"
9828
9829 and generate_java_struct jtyp cols () =
9830   generate_header CStyle LGPLv2plus;
9831
9832   pr "\
9833 package com.redhat.et.libguestfs;
9834
9835 /**
9836  * Libguestfs %s structure.
9837  *
9838  * @author rjones
9839  * @see GuestFS
9840  */
9841 public class %s {
9842 " jtyp jtyp;
9843
9844   List.iter (
9845     function
9846     | name, FString
9847     | name, FUUID
9848     | name, FBuffer -> pr "  public String %s;\n" name
9849     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9850     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9851     | name, FChar -> pr "  public char %s;\n" name
9852     | name, FOptPercent ->
9853         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9854         pr "  public float %s;\n" name
9855   ) cols;
9856
9857   pr "}\n"
9858
9859 and generate_java_c () =
9860   generate_header CStyle LGPLv2plus;
9861
9862   pr "\
9863 #include <stdio.h>
9864 #include <stdlib.h>
9865 #include <string.h>
9866
9867 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9868 #include \"guestfs.h\"
9869
9870 /* Note that this function returns.  The exception is not thrown
9871  * until after the wrapper function returns.
9872  */
9873 static void
9874 throw_exception (JNIEnv *env, const char *msg)
9875 {
9876   jclass cl;
9877   cl = (*env)->FindClass (env,
9878                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9879   (*env)->ThrowNew (env, cl, msg);
9880 }
9881
9882 JNIEXPORT jlong JNICALL
9883 Java_com_redhat_et_libguestfs_GuestFS__1create
9884   (JNIEnv *env, jobject obj)
9885 {
9886   guestfs_h *g;
9887
9888   g = guestfs_create ();
9889   if (g == NULL) {
9890     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9891     return 0;
9892   }
9893   guestfs_set_error_handler (g, NULL, NULL);
9894   return (jlong) (long) g;
9895 }
9896
9897 JNIEXPORT void JNICALL
9898 Java_com_redhat_et_libguestfs_GuestFS__1close
9899   (JNIEnv *env, jobject obj, jlong jg)
9900 {
9901   guestfs_h *g = (guestfs_h *) (long) jg;
9902   guestfs_close (g);
9903 }
9904
9905 ";
9906
9907   List.iter (
9908     fun (name, style, _, _, _, _, _) ->
9909       pr "JNIEXPORT ";
9910       (match fst style with
9911        | RErr -> pr "void ";
9912        | RInt _ -> pr "jint ";
9913        | RInt64 _ -> pr "jlong ";
9914        | RBool _ -> pr "jboolean ";
9915        | RConstString _ | RConstOptString _ | RString _
9916        | RBufferOut _ -> pr "jstring ";
9917        | RStruct _ | RHashtable _ ->
9918            pr "jobject ";
9919        | RStringList _ | RStructList _ ->
9920            pr "jobjectArray ";
9921       );
9922       pr "JNICALL\n";
9923       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9924       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9925       pr "\n";
9926       pr "  (JNIEnv *env, jobject obj, jlong jg";
9927       List.iter (
9928         function
9929         | Pathname n
9930         | Device n | Dev_or_Path n
9931         | String n
9932         | OptString n
9933         | FileIn n
9934         | FileOut n ->
9935             pr ", jstring j%s" n
9936         | StringList n | DeviceList n ->
9937             pr ", jobjectArray j%s" n
9938         | Bool n ->
9939             pr ", jboolean j%s" n
9940         | Int n ->
9941             pr ", jint j%s" n
9942         | Int64 n ->
9943             pr ", jlong j%s" n
9944       ) (snd style);
9945       pr ")\n";
9946       pr "{\n";
9947       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9948       let error_code, no_ret =
9949         match fst style with
9950         | RErr -> pr "  int r;\n"; "-1", ""
9951         | RBool _
9952         | RInt _ -> pr "  int r;\n"; "-1", "0"
9953         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9954         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9955         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9956         | RString _ ->
9957             pr "  jstring jr;\n";
9958             pr "  char *r;\n"; "NULL", "NULL"
9959         | RStringList _ ->
9960             pr "  jobjectArray jr;\n";
9961             pr "  int r_len;\n";
9962             pr "  jclass cl;\n";
9963             pr "  jstring jstr;\n";
9964             pr "  char **r;\n"; "NULL", "NULL"
9965         | RStruct (_, typ) ->
9966             pr "  jobject jr;\n";
9967             pr "  jclass cl;\n";
9968             pr "  jfieldID fl;\n";
9969             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9970         | RStructList (_, typ) ->
9971             pr "  jobjectArray jr;\n";
9972             pr "  jclass cl;\n";
9973             pr "  jfieldID fl;\n";
9974             pr "  jobject jfl;\n";
9975             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9976         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9977         | RBufferOut _ ->
9978             pr "  jstring jr;\n";
9979             pr "  char *r;\n";
9980             pr "  size_t size;\n";
9981             "NULL", "NULL" in
9982       List.iter (
9983         function
9984         | Pathname n
9985         | Device n | Dev_or_Path n
9986         | String n
9987         | OptString n
9988         | FileIn n
9989         | FileOut n ->
9990             pr "  const char *%s;\n" n
9991         | StringList n | DeviceList n ->
9992             pr "  int %s_len;\n" n;
9993             pr "  const char **%s;\n" n
9994         | Bool n
9995         | Int n ->
9996             pr "  int %s;\n" n
9997         | Int64 n ->
9998             pr "  int64_t %s;\n" n
9999       ) (snd style);
10000
10001       let needs_i =
10002         (match fst style with
10003          | RStringList _ | RStructList _ -> true
10004          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10005          | RConstOptString _
10006          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10007           List.exists (function
10008                        | StringList _ -> true
10009                        | DeviceList _ -> true
10010                        | _ -> false) (snd style) in
10011       if needs_i then
10012         pr "  int i;\n";
10013
10014       pr "\n";
10015
10016       (* Get the parameters. *)
10017       List.iter (
10018         function
10019         | Pathname n
10020         | Device n | Dev_or_Path n
10021         | String n
10022         | FileIn n
10023         | FileOut n ->
10024             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10025         | OptString n ->
10026             (* This is completely undocumented, but Java null becomes
10027              * a NULL parameter.
10028              *)
10029             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10030         | StringList n | DeviceList n ->
10031             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10032             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10033             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10034             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10035               n;
10036             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10037             pr "  }\n";
10038             pr "  %s[%s_len] = NULL;\n" n n;
10039         | Bool n
10040         | Int n
10041         | Int64 n ->
10042             pr "  %s = j%s;\n" n n
10043       ) (snd style);
10044
10045       (* Make the call. *)
10046       pr "  r = guestfs_%s " name;
10047       generate_c_call_args ~handle:"g" style;
10048       pr ";\n";
10049
10050       (* Release the parameters. *)
10051       List.iter (
10052         function
10053         | Pathname n
10054         | Device n | Dev_or_Path n
10055         | String n
10056         | FileIn n
10057         | FileOut n ->
10058             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10059         | OptString n ->
10060             pr "  if (j%s)\n" n;
10061             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10062         | StringList n | DeviceList n ->
10063             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10064             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10065               n;
10066             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10067             pr "  }\n";
10068             pr "  free (%s);\n" n
10069         | Bool n
10070         | Int n
10071         | Int64 n -> ()
10072       ) (snd style);
10073
10074       (* Check for errors. *)
10075       pr "  if (r == %s) {\n" error_code;
10076       pr "    throw_exception (env, guestfs_last_error (g));\n";
10077       pr "    return %s;\n" no_ret;
10078       pr "  }\n";
10079
10080       (* Return value. *)
10081       (match fst style with
10082        | RErr -> ()
10083        | RInt _ -> pr "  return (jint) r;\n"
10084        | RBool _ -> pr "  return (jboolean) r;\n"
10085        | RInt64 _ -> pr "  return (jlong) r;\n"
10086        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10087        | RConstOptString _ ->
10088            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10089        | RString _ ->
10090            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10091            pr "  free (r);\n";
10092            pr "  return jr;\n"
10093        | RStringList _ ->
10094            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10095            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10096            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10097            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10098            pr "  for (i = 0; i < r_len; ++i) {\n";
10099            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10100            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10101            pr "    free (r[i]);\n";
10102            pr "  }\n";
10103            pr "  free (r);\n";
10104            pr "  return jr;\n"
10105        | RStruct (_, typ) ->
10106            let jtyp = java_name_of_struct typ in
10107            let cols = cols_of_struct typ in
10108            generate_java_struct_return typ jtyp cols
10109        | RStructList (_, typ) ->
10110            let jtyp = java_name_of_struct typ in
10111            let cols = cols_of_struct typ in
10112            generate_java_struct_list_return typ jtyp cols
10113        | RHashtable _ ->
10114            (* XXX *)
10115            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10116            pr "  return NULL;\n"
10117        | RBufferOut _ ->
10118            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10119            pr "  free (r);\n";
10120            pr "  return jr;\n"
10121       );
10122
10123       pr "}\n";
10124       pr "\n"
10125   ) all_functions
10126
10127 and generate_java_struct_return typ jtyp cols =
10128   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10129   pr "  jr = (*env)->AllocObject (env, cl);\n";
10130   List.iter (
10131     function
10132     | name, FString ->
10133         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10134         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10135     | name, FUUID ->
10136         pr "  {\n";
10137         pr "    char s[33];\n";
10138         pr "    memcpy (s, r->%s, 32);\n" name;
10139         pr "    s[32] = 0;\n";
10140         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10141         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10142         pr "  }\n";
10143     | name, FBuffer ->
10144         pr "  {\n";
10145         pr "    int len = r->%s_len;\n" name;
10146         pr "    char s[len+1];\n";
10147         pr "    memcpy (s, r->%s, len);\n" name;
10148         pr "    s[len] = 0;\n";
10149         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10150         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10151         pr "  }\n";
10152     | name, (FBytes|FUInt64|FInt64) ->
10153         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10154         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10155     | name, (FUInt32|FInt32) ->
10156         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10157         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10158     | name, FOptPercent ->
10159         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10160         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10161     | name, FChar ->
10162         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10163         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10164   ) cols;
10165   pr "  free (r);\n";
10166   pr "  return jr;\n"
10167
10168 and generate_java_struct_list_return typ jtyp cols =
10169   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10170   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10171   pr "  for (i = 0; i < r->len; ++i) {\n";
10172   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10173   List.iter (
10174     function
10175     | name, FString ->
10176         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10177         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10178     | name, FUUID ->
10179         pr "    {\n";
10180         pr "      char s[33];\n";
10181         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10182         pr "      s[32] = 0;\n";
10183         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10184         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10185         pr "    }\n";
10186     | name, FBuffer ->
10187         pr "    {\n";
10188         pr "      int len = r->val[i].%s_len;\n" name;
10189         pr "      char s[len+1];\n";
10190         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10191         pr "      s[len] = 0;\n";
10192         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10193         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10194         pr "    }\n";
10195     | name, (FBytes|FUInt64|FInt64) ->
10196         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10197         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10198     | name, (FUInt32|FInt32) ->
10199         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10200         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10201     | name, FOptPercent ->
10202         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10203         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10204     | name, FChar ->
10205         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10206         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10207   ) cols;
10208   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10209   pr "  }\n";
10210   pr "  guestfs_free_%s_list (r);\n" typ;
10211   pr "  return jr;\n"
10212
10213 and generate_java_makefile_inc () =
10214   generate_header HashStyle GPLv2plus;
10215
10216   pr "java_built_sources = \\\n";
10217   List.iter (
10218     fun (typ, jtyp) ->
10219         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10220   ) java_structs;
10221   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10222
10223 and generate_haskell_hs () =
10224   generate_header HaskellStyle LGPLv2plus;
10225
10226   (* XXX We only know how to generate partial FFI for Haskell
10227    * at the moment.  Please help out!
10228    *)
10229   let can_generate style =
10230     match style with
10231     | RErr, _
10232     | RInt _, _
10233     | RInt64 _, _ -> true
10234     | RBool _, _
10235     | RConstString _, _
10236     | RConstOptString _, _
10237     | RString _, _
10238     | RStringList _, _
10239     | RStruct _, _
10240     | RStructList _, _
10241     | RHashtable _, _
10242     | RBufferOut _, _ -> false in
10243
10244   pr "\
10245 {-# INCLUDE <guestfs.h> #-}
10246 {-# LANGUAGE ForeignFunctionInterface #-}
10247
10248 module Guestfs (
10249   create";
10250
10251   (* List out the names of the actions we want to export. *)
10252   List.iter (
10253     fun (name, style, _, _, _, _, _) ->
10254       if can_generate style then pr ",\n  %s" name
10255   ) all_functions;
10256
10257   pr "
10258   ) where
10259
10260 -- Unfortunately some symbols duplicate ones already present
10261 -- in Prelude.  We don't know which, so we hard-code a list
10262 -- here.
10263 import Prelude hiding (truncate)
10264
10265 import Foreign
10266 import Foreign.C
10267 import Foreign.C.Types
10268 import IO
10269 import Control.Exception
10270 import Data.Typeable
10271
10272 data GuestfsS = GuestfsS            -- represents the opaque C struct
10273 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10274 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10275
10276 -- XXX define properly later XXX
10277 data PV = PV
10278 data VG = VG
10279 data LV = LV
10280 data IntBool = IntBool
10281 data Stat = Stat
10282 data StatVFS = StatVFS
10283 data Hashtable = Hashtable
10284
10285 foreign import ccall unsafe \"guestfs_create\" c_create
10286   :: IO GuestfsP
10287 foreign import ccall unsafe \"&guestfs_close\" c_close
10288   :: FunPtr (GuestfsP -> IO ())
10289 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10290   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10291
10292 create :: IO GuestfsH
10293 create = do
10294   p <- c_create
10295   c_set_error_handler p nullPtr nullPtr
10296   h <- newForeignPtr c_close p
10297   return h
10298
10299 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10300   :: GuestfsP -> IO CString
10301
10302 -- last_error :: GuestfsH -> IO (Maybe String)
10303 -- last_error h = do
10304 --   str <- withForeignPtr h (\\p -> c_last_error p)
10305 --   maybePeek peekCString str
10306
10307 last_error :: GuestfsH -> IO (String)
10308 last_error h = do
10309   str <- withForeignPtr h (\\p -> c_last_error p)
10310   if (str == nullPtr)
10311     then return \"no error\"
10312     else peekCString str
10313
10314 ";
10315
10316   (* Generate wrappers for each foreign function. *)
10317   List.iter (
10318     fun (name, style, _, _, _, _, _) ->
10319       if can_generate style then (
10320         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10321         pr "  :: ";
10322         generate_haskell_prototype ~handle:"GuestfsP" style;
10323         pr "\n";
10324         pr "\n";
10325         pr "%s :: " name;
10326         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10327         pr "\n";
10328         pr "%s %s = do\n" name
10329           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10330         pr "  r <- ";
10331         (* Convert pointer arguments using with* functions. *)
10332         List.iter (
10333           function
10334           | FileIn n
10335           | FileOut n
10336           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10337           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10338           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10339           | Bool _ | Int _ | Int64 _ -> ()
10340         ) (snd style);
10341         (* Convert integer arguments. *)
10342         let args =
10343           List.map (
10344             function
10345             | Bool n -> sprintf "(fromBool %s)" n
10346             | Int n -> sprintf "(fromIntegral %s)" n
10347             | Int64 n -> sprintf "(fromIntegral %s)" n
10348             | FileIn n | FileOut n
10349             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10350           ) (snd style) in
10351         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10352           (String.concat " " ("p" :: args));
10353         (match fst style with
10354          | RErr | RInt _ | RInt64 _ | RBool _ ->
10355              pr "  if (r == -1)\n";
10356              pr "    then do\n";
10357              pr "      err <- last_error h\n";
10358              pr "      fail err\n";
10359          | RConstString _ | RConstOptString _ | RString _
10360          | RStringList _ | RStruct _
10361          | RStructList _ | RHashtable _ | RBufferOut _ ->
10362              pr "  if (r == nullPtr)\n";
10363              pr "    then do\n";
10364              pr "      err <- last_error h\n";
10365              pr "      fail err\n";
10366         );
10367         (match fst style with
10368          | RErr ->
10369              pr "    else return ()\n"
10370          | RInt _ ->
10371              pr "    else return (fromIntegral r)\n"
10372          | RInt64 _ ->
10373              pr "    else return (fromIntegral r)\n"
10374          | RBool _ ->
10375              pr "    else return (toBool r)\n"
10376          | RConstString _
10377          | RConstOptString _
10378          | RString _
10379          | RStringList _
10380          | RStruct _
10381          | RStructList _
10382          | RHashtable _
10383          | RBufferOut _ ->
10384              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10385         );
10386         pr "\n";
10387       )
10388   ) all_functions
10389
10390 and generate_haskell_prototype ~handle ?(hs = false) style =
10391   pr "%s -> " handle;
10392   let string = if hs then "String" else "CString" in
10393   let int = if hs then "Int" else "CInt" in
10394   let bool = if hs then "Bool" else "CInt" in
10395   let int64 = if hs then "Integer" else "Int64" in
10396   List.iter (
10397     fun arg ->
10398       (match arg with
10399        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10400        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10401        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10402        | Bool _ -> pr "%s" bool
10403        | Int _ -> pr "%s" int
10404        | Int64 _ -> pr "%s" int
10405        | FileIn _ -> pr "%s" string
10406        | FileOut _ -> pr "%s" string
10407       );
10408       pr " -> ";
10409   ) (snd style);
10410   pr "IO (";
10411   (match fst style with
10412    | RErr -> if not hs then pr "CInt"
10413    | RInt _ -> pr "%s" int
10414    | RInt64 _ -> pr "%s" int64
10415    | RBool _ -> pr "%s" bool
10416    | RConstString _ -> pr "%s" string
10417    | RConstOptString _ -> pr "Maybe %s" string
10418    | RString _ -> pr "%s" string
10419    | RStringList _ -> pr "[%s]" string
10420    | RStruct (_, typ) ->
10421        let name = java_name_of_struct typ in
10422        pr "%s" name
10423    | RStructList (_, typ) ->
10424        let name = java_name_of_struct typ in
10425        pr "[%s]" name
10426    | RHashtable _ -> pr "Hashtable"
10427    | RBufferOut _ -> pr "%s" string
10428   );
10429   pr ")"
10430
10431 and generate_csharp () =
10432   generate_header CPlusPlusStyle LGPLv2plus;
10433
10434   (* XXX Make this configurable by the C# assembly users. *)
10435   let library = "libguestfs.so.0" in
10436
10437   pr "\
10438 // These C# bindings are highly experimental at present.
10439 //
10440 // Firstly they only work on Linux (ie. Mono).  In order to get them
10441 // to work on Windows (ie. .Net) you would need to port the library
10442 // itself to Windows first.
10443 //
10444 // The second issue is that some calls are known to be incorrect and
10445 // can cause Mono to segfault.  Particularly: calls which pass or
10446 // return string[], or return any structure value.  This is because
10447 // we haven't worked out the correct way to do this from C#.
10448 //
10449 // The third issue is that when compiling you get a lot of warnings.
10450 // We are not sure whether the warnings are important or not.
10451 //
10452 // Fourthly we do not routinely build or test these bindings as part
10453 // of the make && make check cycle, which means that regressions might
10454 // go unnoticed.
10455 //
10456 // Suggestions and patches are welcome.
10457
10458 // To compile:
10459 //
10460 // gmcs Libguestfs.cs
10461 // mono Libguestfs.exe
10462 //
10463 // (You'll probably want to add a Test class / static main function
10464 // otherwise this won't do anything useful).
10465
10466 using System;
10467 using System.IO;
10468 using System.Runtime.InteropServices;
10469 using System.Runtime.Serialization;
10470 using System.Collections;
10471
10472 namespace Guestfs
10473 {
10474   class Error : System.ApplicationException
10475   {
10476     public Error (string message) : base (message) {}
10477     protected Error (SerializationInfo info, StreamingContext context) {}
10478   }
10479
10480   class Guestfs
10481   {
10482     IntPtr _handle;
10483
10484     [DllImport (\"%s\")]
10485     static extern IntPtr guestfs_create ();
10486
10487     public Guestfs ()
10488     {
10489       _handle = guestfs_create ();
10490       if (_handle == IntPtr.Zero)
10491         throw new Error (\"could not create guestfs handle\");
10492     }
10493
10494     [DllImport (\"%s\")]
10495     static extern void guestfs_close (IntPtr h);
10496
10497     ~Guestfs ()
10498     {
10499       guestfs_close (_handle);
10500     }
10501
10502     [DllImport (\"%s\")]
10503     static extern string guestfs_last_error (IntPtr h);
10504
10505 " library library library;
10506
10507   (* Generate C# structure bindings.  We prefix struct names with
10508    * underscore because C# cannot have conflicting struct names and
10509    * method names (eg. "class stat" and "stat").
10510    *)
10511   List.iter (
10512     fun (typ, cols) ->
10513       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10514       pr "    public class _%s {\n" typ;
10515       List.iter (
10516         function
10517         | name, FChar -> pr "      char %s;\n" name
10518         | name, FString -> pr "      string %s;\n" name
10519         | name, FBuffer ->
10520             pr "      uint %s_len;\n" name;
10521             pr "      string %s;\n" name
10522         | name, FUUID ->
10523             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10524             pr "      string %s;\n" name
10525         | name, FUInt32 -> pr "      uint %s;\n" name
10526         | name, FInt32 -> pr "      int %s;\n" name
10527         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10528         | name, FInt64 -> pr "      long %s;\n" name
10529         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10530       ) cols;
10531       pr "    }\n";
10532       pr "\n"
10533   ) structs;
10534
10535   (* Generate C# function bindings. *)
10536   List.iter (
10537     fun (name, style, _, _, _, shortdesc, _) ->
10538       let rec csharp_return_type () =
10539         match fst style with
10540         | RErr -> "void"
10541         | RBool n -> "bool"
10542         | RInt n -> "int"
10543         | RInt64 n -> "long"
10544         | RConstString n
10545         | RConstOptString n
10546         | RString n
10547         | RBufferOut n -> "string"
10548         | RStruct (_,n) -> "_" ^ n
10549         | RHashtable n -> "Hashtable"
10550         | RStringList n -> "string[]"
10551         | RStructList (_,n) -> sprintf "_%s[]" n
10552
10553       and c_return_type () =
10554         match fst style with
10555         | RErr
10556         | RBool _
10557         | RInt _ -> "int"
10558         | RInt64 _ -> "long"
10559         | RConstString _
10560         | RConstOptString _
10561         | RString _
10562         | RBufferOut _ -> "string"
10563         | RStruct (_,n) -> "_" ^ n
10564         | RHashtable _
10565         | RStringList _ -> "string[]"
10566         | RStructList (_,n) -> sprintf "_%s[]" n
10567
10568       and c_error_comparison () =
10569         match fst style with
10570         | RErr
10571         | RBool _
10572         | RInt _
10573         | RInt64 _ -> "== -1"
10574         | RConstString _
10575         | RConstOptString _
10576         | RString _
10577         | RBufferOut _
10578         | RStruct (_,_)
10579         | RHashtable _
10580         | RStringList _
10581         | RStructList (_,_) -> "== null"
10582
10583       and generate_extern_prototype () =
10584         pr "    static extern %s guestfs_%s (IntPtr h"
10585           (c_return_type ()) name;
10586         List.iter (
10587           function
10588           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10589           | FileIn n | FileOut n ->
10590               pr ", [In] string %s" n
10591           | StringList n | DeviceList n ->
10592               pr ", [In] string[] %s" n
10593           | Bool n ->
10594               pr ", bool %s" n
10595           | Int n ->
10596               pr ", int %s" n
10597           | Int64 n ->
10598               pr ", long %s" n
10599         ) (snd style);
10600         pr ");\n"
10601
10602       and generate_public_prototype () =
10603         pr "    public %s %s (" (csharp_return_type ()) name;
10604         let comma = ref false in
10605         let next () =
10606           if !comma then pr ", ";
10607           comma := true
10608         in
10609         List.iter (
10610           function
10611           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10612           | FileIn n | FileOut n ->
10613               next (); pr "string %s" n
10614           | StringList n | DeviceList n ->
10615               next (); pr "string[] %s" n
10616           | Bool n ->
10617               next (); pr "bool %s" n
10618           | Int n ->
10619               next (); pr "int %s" n
10620           | Int64 n ->
10621               next (); pr "long %s" n
10622         ) (snd style);
10623         pr ")\n"
10624
10625       and generate_call () =
10626         pr "guestfs_%s (_handle" name;
10627         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10628         pr ");\n";
10629       in
10630
10631       pr "    [DllImport (\"%s\")]\n" library;
10632       generate_extern_prototype ();
10633       pr "\n";
10634       pr "    /// <summary>\n";
10635       pr "    /// %s\n" shortdesc;
10636       pr "    /// </summary>\n";
10637       generate_public_prototype ();
10638       pr "    {\n";
10639       pr "      %s r;\n" (c_return_type ());
10640       pr "      r = ";
10641       generate_call ();
10642       pr "      if (r %s)\n" (c_error_comparison ());
10643       pr "        throw new Error (guestfs_last_error (_handle));\n";
10644       (match fst style with
10645        | RErr -> ()
10646        | RBool _ ->
10647            pr "      return r != 0 ? true : false;\n"
10648        | RHashtable _ ->
10649            pr "      Hashtable rr = new Hashtable ();\n";
10650            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10651            pr "        rr.Add (r[i], r[i+1]);\n";
10652            pr "      return rr;\n"
10653        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10654        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10655        | RStructList _ ->
10656            pr "      return r;\n"
10657       );
10658       pr "    }\n";
10659       pr "\n";
10660   ) all_functions_sorted;
10661
10662   pr "  }
10663 }
10664 "
10665
10666 and generate_bindtests () =
10667   generate_header CStyle LGPLv2plus;
10668
10669   pr "\
10670 #include <stdio.h>
10671 #include <stdlib.h>
10672 #include <inttypes.h>
10673 #include <string.h>
10674
10675 #include \"guestfs.h\"
10676 #include \"guestfs-internal.h\"
10677 #include \"guestfs-internal-actions.h\"
10678 #include \"guestfs_protocol.h\"
10679
10680 #define error guestfs_error
10681 #define safe_calloc guestfs_safe_calloc
10682 #define safe_malloc guestfs_safe_malloc
10683
10684 static void
10685 print_strings (char *const *argv)
10686 {
10687   int argc;
10688
10689   printf (\"[\");
10690   for (argc = 0; argv[argc] != NULL; ++argc) {
10691     if (argc > 0) printf (\", \");
10692     printf (\"\\\"%%s\\\"\", argv[argc]);
10693   }
10694   printf (\"]\\n\");
10695 }
10696
10697 /* The test0 function prints its parameters to stdout. */
10698 ";
10699
10700   let test0, tests =
10701     match test_functions with
10702     | [] -> assert false
10703     | test0 :: tests -> test0, tests in
10704
10705   let () =
10706     let (name, style, _, _, _, _, _) = test0 in
10707     generate_prototype ~extern:false ~semicolon:false ~newline:true
10708       ~handle:"g" ~prefix:"guestfs__" name style;
10709     pr "{\n";
10710     List.iter (
10711       function
10712       | Pathname n
10713       | Device n | Dev_or_Path n
10714       | String n
10715       | FileIn n
10716       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10717       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10718       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10719       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10720       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10721       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10722     ) (snd style);
10723     pr "  /* Java changes stdout line buffering so we need this: */\n";
10724     pr "  fflush (stdout);\n";
10725     pr "  return 0;\n";
10726     pr "}\n";
10727     pr "\n" in
10728
10729   List.iter (
10730     fun (name, style, _, _, _, _, _) ->
10731       if String.sub name (String.length name - 3) 3 <> "err" then (
10732         pr "/* Test normal return. */\n";
10733         generate_prototype ~extern:false ~semicolon:false ~newline:true
10734           ~handle:"g" ~prefix:"guestfs__" name style;
10735         pr "{\n";
10736         (match fst style with
10737          | RErr ->
10738              pr "  return 0;\n"
10739          | RInt _ ->
10740              pr "  int r;\n";
10741              pr "  sscanf (val, \"%%d\", &r);\n";
10742              pr "  return r;\n"
10743          | RInt64 _ ->
10744              pr "  int64_t r;\n";
10745              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10746              pr "  return r;\n"
10747          | RBool _ ->
10748              pr "  return STREQ (val, \"true\");\n"
10749          | RConstString _
10750          | RConstOptString _ ->
10751              (* Can't return the input string here.  Return a static
10752               * string so we ensure we get a segfault if the caller
10753               * tries to free it.
10754               *)
10755              pr "  return \"static string\";\n"
10756          | RString _ ->
10757              pr "  return strdup (val);\n"
10758          | RStringList _ ->
10759              pr "  char **strs;\n";
10760              pr "  int n, i;\n";
10761              pr "  sscanf (val, \"%%d\", &n);\n";
10762              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10763              pr "  for (i = 0; i < n; ++i) {\n";
10764              pr "    strs[i] = safe_malloc (g, 16);\n";
10765              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10766              pr "  }\n";
10767              pr "  strs[n] = NULL;\n";
10768              pr "  return strs;\n"
10769          | RStruct (_, typ) ->
10770              pr "  struct guestfs_%s *r;\n" typ;
10771              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10772              pr "  return r;\n"
10773          | RStructList (_, typ) ->
10774              pr "  struct guestfs_%s_list *r;\n" typ;
10775              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10776              pr "  sscanf (val, \"%%d\", &r->len);\n";
10777              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10778              pr "  return r;\n"
10779          | RHashtable _ ->
10780              pr "  char **strs;\n";
10781              pr "  int n, i;\n";
10782              pr "  sscanf (val, \"%%d\", &n);\n";
10783              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10784              pr "  for (i = 0; i < n; ++i) {\n";
10785              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10786              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10787              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10788              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10789              pr "  }\n";
10790              pr "  strs[n*2] = NULL;\n";
10791              pr "  return strs;\n"
10792          | RBufferOut _ ->
10793              pr "  return strdup (val);\n"
10794         );
10795         pr "}\n";
10796         pr "\n"
10797       ) else (
10798         pr "/* Test error return. */\n";
10799         generate_prototype ~extern:false ~semicolon:false ~newline:true
10800           ~handle:"g" ~prefix:"guestfs__" name style;
10801         pr "{\n";
10802         pr "  error (g, \"error\");\n";
10803         (match fst style with
10804          | RErr | RInt _ | RInt64 _ | RBool _ ->
10805              pr "  return -1;\n"
10806          | RConstString _ | RConstOptString _
10807          | RString _ | RStringList _ | RStruct _
10808          | RStructList _
10809          | RHashtable _
10810          | RBufferOut _ ->
10811              pr "  return NULL;\n"
10812         );
10813         pr "}\n";
10814         pr "\n"
10815       )
10816   ) tests
10817
10818 and generate_ocaml_bindtests () =
10819   generate_header OCamlStyle GPLv2plus;
10820
10821   pr "\
10822 let () =
10823   let g = Guestfs.create () in
10824 ";
10825
10826   let mkargs args =
10827     String.concat " " (
10828       List.map (
10829         function
10830         | CallString s -> "\"" ^ s ^ "\""
10831         | CallOptString None -> "None"
10832         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10833         | CallStringList xs ->
10834             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10835         | CallInt i when i >= 0 -> string_of_int i
10836         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10837         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10838         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10839         | CallBool b -> string_of_bool b
10840       ) args
10841     )
10842   in
10843
10844   generate_lang_bindtests (
10845     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10846   );
10847
10848   pr "print_endline \"EOF\"\n"
10849
10850 and generate_perl_bindtests () =
10851   pr "#!/usr/bin/perl -w\n";
10852   generate_header HashStyle GPLv2plus;
10853
10854   pr "\
10855 use strict;
10856
10857 use Sys::Guestfs;
10858
10859 my $g = Sys::Guestfs->new ();
10860 ";
10861
10862   let mkargs args =
10863     String.concat ", " (
10864       List.map (
10865         function
10866         | CallString s -> "\"" ^ s ^ "\""
10867         | CallOptString None -> "undef"
10868         | CallOptString (Some s) -> sprintf "\"%s\"" s
10869         | CallStringList xs ->
10870             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10871         | CallInt i -> string_of_int i
10872         | CallInt64 i -> Int64.to_string i
10873         | CallBool b -> if b then "1" else "0"
10874       ) args
10875     )
10876   in
10877
10878   generate_lang_bindtests (
10879     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10880   );
10881
10882   pr "print \"EOF\\n\"\n"
10883
10884 and generate_python_bindtests () =
10885   generate_header HashStyle GPLv2plus;
10886
10887   pr "\
10888 import guestfs
10889
10890 g = guestfs.GuestFS ()
10891 ";
10892
10893   let mkargs args =
10894     String.concat ", " (
10895       List.map (
10896         function
10897         | CallString s -> "\"" ^ s ^ "\""
10898         | CallOptString None -> "None"
10899         | CallOptString (Some s) -> sprintf "\"%s\"" s
10900         | CallStringList xs ->
10901             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10902         | CallInt i -> string_of_int i
10903         | CallInt64 i -> Int64.to_string i
10904         | CallBool b -> if b then "1" else "0"
10905       ) args
10906     )
10907   in
10908
10909   generate_lang_bindtests (
10910     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10911   );
10912
10913   pr "print \"EOF\"\n"
10914
10915 and generate_ruby_bindtests () =
10916   generate_header HashStyle GPLv2plus;
10917
10918   pr "\
10919 require 'guestfs'
10920
10921 g = Guestfs::create()
10922 ";
10923
10924   let mkargs args =
10925     String.concat ", " (
10926       List.map (
10927         function
10928         | CallString s -> "\"" ^ s ^ "\""
10929         | CallOptString None -> "nil"
10930         | CallOptString (Some s) -> sprintf "\"%s\"" s
10931         | CallStringList xs ->
10932             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10933         | CallInt i -> string_of_int i
10934         | CallInt64 i -> Int64.to_string i
10935         | CallBool b -> string_of_bool b
10936       ) args
10937     )
10938   in
10939
10940   generate_lang_bindtests (
10941     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10942   );
10943
10944   pr "print \"EOF\\n\"\n"
10945
10946 and generate_java_bindtests () =
10947   generate_header CStyle GPLv2plus;
10948
10949   pr "\
10950 import com.redhat.et.libguestfs.*;
10951
10952 public class Bindtests {
10953     public static void main (String[] argv)
10954     {
10955         try {
10956             GuestFS g = new GuestFS ();
10957 ";
10958
10959   let mkargs args =
10960     String.concat ", " (
10961       List.map (
10962         function
10963         | CallString s -> "\"" ^ s ^ "\""
10964         | CallOptString None -> "null"
10965         | CallOptString (Some s) -> sprintf "\"%s\"" s
10966         | CallStringList xs ->
10967             "new String[]{" ^
10968               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10969         | CallInt i -> string_of_int i
10970         | CallInt64 i -> Int64.to_string i
10971         | CallBool b -> string_of_bool b
10972       ) args
10973     )
10974   in
10975
10976   generate_lang_bindtests (
10977     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10978   );
10979
10980   pr "
10981             System.out.println (\"EOF\");
10982         }
10983         catch (Exception exn) {
10984             System.err.println (exn);
10985             System.exit (1);
10986         }
10987     }
10988 }
10989 "
10990
10991 and generate_haskell_bindtests () =
10992   generate_header HaskellStyle GPLv2plus;
10993
10994   pr "\
10995 module Bindtests where
10996 import qualified Guestfs
10997
10998 main = do
10999   g <- Guestfs.create
11000 ";
11001
11002   let mkargs args =
11003     String.concat " " (
11004       List.map (
11005         function
11006         | CallString s -> "\"" ^ s ^ "\""
11007         | CallOptString None -> "Nothing"
11008         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11009         | CallStringList xs ->
11010             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11011         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11012         | CallInt i -> string_of_int i
11013         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11014         | CallInt64 i -> Int64.to_string i
11015         | CallBool true -> "True"
11016         | CallBool false -> "False"
11017       ) args
11018     )
11019   in
11020
11021   generate_lang_bindtests (
11022     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11023   );
11024
11025   pr "  putStrLn \"EOF\"\n"
11026
11027 (* Language-independent bindings tests - we do it this way to
11028  * ensure there is parity in testing bindings across all languages.
11029  *)
11030 and generate_lang_bindtests call =
11031   call "test0" [CallString "abc"; CallOptString (Some "def");
11032                 CallStringList []; CallBool false;
11033                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11034   call "test0" [CallString "abc"; CallOptString None;
11035                 CallStringList []; CallBool false;
11036                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11037   call "test0" [CallString ""; CallOptString (Some "def");
11038                 CallStringList []; CallBool false;
11039                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11040   call "test0" [CallString ""; CallOptString (Some "");
11041                 CallStringList []; CallBool false;
11042                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11043   call "test0" [CallString "abc"; CallOptString (Some "def");
11044                 CallStringList ["1"]; CallBool false;
11045                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11046   call "test0" [CallString "abc"; CallOptString (Some "def");
11047                 CallStringList ["1"; "2"]; CallBool false;
11048                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11049   call "test0" [CallString "abc"; CallOptString (Some "def");
11050                 CallStringList ["1"]; CallBool true;
11051                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11052   call "test0" [CallString "abc"; CallOptString (Some "def");
11053                 CallStringList ["1"]; CallBool false;
11054                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11055   call "test0" [CallString "abc"; CallOptString (Some "def");
11056                 CallStringList ["1"]; CallBool false;
11057                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11058   call "test0" [CallString "abc"; CallOptString (Some "def");
11059                 CallStringList ["1"]; CallBool false;
11060                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11061   call "test0" [CallString "abc"; CallOptString (Some "def");
11062                 CallStringList ["1"]; CallBool false;
11063                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11064   call "test0" [CallString "abc"; CallOptString (Some "def");
11065                 CallStringList ["1"]; CallBool false;
11066                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11067   call "test0" [CallString "abc"; CallOptString (Some "def");
11068                 CallStringList ["1"]; CallBool false;
11069                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11070
11071 (* XXX Add here tests of the return and error functions. *)
11072
11073 (* Code to generator bindings for virt-inspector.  Currently only
11074  * implemented for OCaml code (for virt-p2v 2.0).
11075  *)
11076 let rng_input = "inspector/virt-inspector.rng"
11077
11078 (* Read the input file and parse it into internal structures.  This is
11079  * by no means a complete RELAX NG parser, but is just enough to be
11080  * able to parse the specific input file.
11081  *)
11082 type rng =
11083   | Element of string * rng list        (* <element name=name/> *)
11084   | Attribute of string * rng list        (* <attribute name=name/> *)
11085   | Interleave of rng list                (* <interleave/> *)
11086   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11087   | OneOrMore of rng                        (* <oneOrMore/> *)
11088   | Optional of rng                        (* <optional/> *)
11089   | Choice of string list                (* <choice><value/>*</choice> *)
11090   | Value of string                        (* <value>str</value> *)
11091   | Text                                (* <text/> *)
11092
11093 let rec string_of_rng = function
11094   | Element (name, xs) ->
11095       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11096   | Attribute (name, xs) ->
11097       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11098   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11099   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11100   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11101   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11102   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11103   | Value value -> "Value \"" ^ value ^ "\""
11104   | Text -> "Text"
11105
11106 and string_of_rng_list xs =
11107   String.concat ", " (List.map string_of_rng xs)
11108
11109 let rec parse_rng ?defines context = function
11110   | [] -> []
11111   | Xml.Element ("element", ["name", name], children) :: rest ->
11112       Element (name, parse_rng ?defines context children)
11113       :: parse_rng ?defines context rest
11114   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11115       Attribute (name, parse_rng ?defines context children)
11116       :: parse_rng ?defines context rest
11117   | Xml.Element ("interleave", [], children) :: rest ->
11118       Interleave (parse_rng ?defines context children)
11119       :: parse_rng ?defines context rest
11120   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11121       let rng = parse_rng ?defines context [child] in
11122       (match rng with
11123        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11124        | _ ->
11125            failwithf "%s: <zeroOrMore> contains more than one child element"
11126              context
11127       )
11128   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11129       let rng = parse_rng ?defines context [child] in
11130       (match rng with
11131        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11132        | _ ->
11133            failwithf "%s: <oneOrMore> contains more than one child element"
11134              context
11135       )
11136   | Xml.Element ("optional", [], [child]) :: rest ->
11137       let rng = parse_rng ?defines context [child] in
11138       (match rng with
11139        | [child] -> Optional child :: parse_rng ?defines context rest
11140        | _ ->
11141            failwithf "%s: <optional> contains more than one child element"
11142              context
11143       )
11144   | Xml.Element ("choice", [], children) :: rest ->
11145       let values = List.map (
11146         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11147         | _ ->
11148             failwithf "%s: can't handle anything except <value> in <choice>"
11149               context
11150       ) children in
11151       Choice values
11152       :: parse_rng ?defines context rest
11153   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11154       Value value :: parse_rng ?defines context rest
11155   | Xml.Element ("text", [], []) :: rest ->
11156       Text :: parse_rng ?defines context rest
11157   | Xml.Element ("ref", ["name", name], []) :: rest ->
11158       (* Look up the reference.  Because of limitations in this parser,
11159        * we can't handle arbitrarily nested <ref> yet.  You can only
11160        * use <ref> from inside <start>.
11161        *)
11162       (match defines with
11163        | None ->
11164            failwithf "%s: contains <ref>, but no refs are defined yet" context
11165        | Some map ->
11166            let rng = StringMap.find name map in
11167            rng @ parse_rng ?defines context rest
11168       )
11169   | x :: _ ->
11170       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11171
11172 let grammar =
11173   let xml = Xml.parse_file rng_input in
11174   match xml with
11175   | Xml.Element ("grammar", _,
11176                  Xml.Element ("start", _, gram) :: defines) ->
11177       (* The <define/> elements are referenced in the <start> section,
11178        * so build a map of those first.
11179        *)
11180       let defines = List.fold_left (
11181         fun map ->
11182           function Xml.Element ("define", ["name", name], defn) ->
11183             StringMap.add name defn map
11184           | _ ->
11185               failwithf "%s: expected <define name=name/>" rng_input
11186       ) StringMap.empty defines in
11187       let defines = StringMap.mapi parse_rng defines in
11188
11189       (* Parse the <start> clause, passing the defines. *)
11190       parse_rng ~defines "<start>" gram
11191   | _ ->
11192       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11193         rng_input
11194
11195 let name_of_field = function
11196   | Element (name, _) | Attribute (name, _)
11197   | ZeroOrMore (Element (name, _))
11198   | OneOrMore (Element (name, _))
11199   | Optional (Element (name, _)) -> name
11200   | Optional (Attribute (name, _)) -> name
11201   | Text -> (* an unnamed field in an element *)
11202       "data"
11203   | rng ->
11204       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11205
11206 (* At the moment this function only generates OCaml types.  However we
11207  * should parameterize it later so it can generate types/structs in a
11208  * variety of languages.
11209  *)
11210 let generate_types xs =
11211   (* A simple type is one that can be printed out directly, eg.
11212    * "string option".  A complex type is one which has a name and has
11213    * to be defined via another toplevel definition, eg. a struct.
11214    *
11215    * generate_type generates code for either simple or complex types.
11216    * In the simple case, it returns the string ("string option").  In
11217    * the complex case, it returns the name ("mountpoint").  In the
11218    * complex case it has to print out the definition before returning,
11219    * so it should only be called when we are at the beginning of a
11220    * new line (BOL context).
11221    *)
11222   let rec generate_type = function
11223     | Text ->                                (* string *)
11224         "string", true
11225     | Choice values ->                        (* [`val1|`val2|...] *)
11226         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11227     | ZeroOrMore rng ->                        (* <rng> list *)
11228         let t, is_simple = generate_type rng in
11229         t ^ " list (* 0 or more *)", is_simple
11230     | OneOrMore rng ->                        (* <rng> list *)
11231         let t, is_simple = generate_type rng in
11232         t ^ " list (* 1 or more *)", is_simple
11233                                         (* virt-inspector hack: bool *)
11234     | Optional (Attribute (name, [Value "1"])) ->
11235         "bool", true
11236     | Optional rng ->                        (* <rng> list *)
11237         let t, is_simple = generate_type rng in
11238         t ^ " option", is_simple
11239                                         (* type name = { fields ... } *)
11240     | Element (name, fields) when is_attrs_interleave fields ->
11241         generate_type_struct name (get_attrs_interleave fields)
11242     | Element (name, [field])                (* type name = field *)
11243     | Attribute (name, [field]) ->
11244         let t, is_simple = generate_type field in
11245         if is_simple then (t, true)
11246         else (
11247           pr "type %s = %s\n" name t;
11248           name, false
11249         )
11250     | Element (name, fields) ->              (* type name = { fields ... } *)
11251         generate_type_struct name fields
11252     | rng ->
11253         failwithf "generate_type failed at: %s" (string_of_rng rng)
11254
11255   and is_attrs_interleave = function
11256     | [Interleave _] -> true
11257     | Attribute _ :: fields -> is_attrs_interleave fields
11258     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11259     | _ -> false
11260
11261   and get_attrs_interleave = function
11262     | [Interleave fields] -> fields
11263     | ((Attribute _) as field) :: fields
11264     | ((Optional (Attribute _)) as field) :: fields ->
11265         field :: get_attrs_interleave fields
11266     | _ -> assert false
11267
11268   and generate_types xs =
11269     List.iter (fun x -> ignore (generate_type x)) xs
11270
11271   and generate_type_struct name fields =
11272     (* Calculate the types of the fields first.  We have to do this
11273      * before printing anything so we are still in BOL context.
11274      *)
11275     let types = List.map fst (List.map generate_type fields) in
11276
11277     (* Special case of a struct containing just a string and another
11278      * field.  Turn it into an assoc list.
11279      *)
11280     match types with
11281     | ["string"; other] ->
11282         let fname1, fname2 =
11283           match fields with
11284           | [f1; f2] -> name_of_field f1, name_of_field f2
11285           | _ -> assert false in
11286         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11287         name, false
11288
11289     | types ->
11290         pr "type %s = {\n" name;
11291         List.iter (
11292           fun (field, ftype) ->
11293             let fname = name_of_field field in
11294             pr "  %s_%s : %s;\n" name fname ftype
11295         ) (List.combine fields types);
11296         pr "}\n";
11297         (* Return the name of this type, and
11298          * false because it's not a simple type.
11299          *)
11300         name, false
11301   in
11302
11303   generate_types xs
11304
11305 let generate_parsers xs =
11306   (* As for generate_type above, generate_parser makes a parser for
11307    * some type, and returns the name of the parser it has generated.
11308    * Because it (may) need to print something, it should always be
11309    * called in BOL context.
11310    *)
11311   let rec generate_parser = function
11312     | Text ->                                (* string *)
11313         "string_child_or_empty"
11314     | Choice values ->                        (* [`val1|`val2|...] *)
11315         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11316           (String.concat "|"
11317              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11318     | ZeroOrMore rng ->                        (* <rng> list *)
11319         let pa = generate_parser rng in
11320         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11321     | OneOrMore rng ->                        (* <rng> list *)
11322         let pa = generate_parser rng in
11323         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11324                                         (* virt-inspector hack: bool *)
11325     | Optional (Attribute (name, [Value "1"])) ->
11326         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11327     | Optional rng ->                        (* <rng> list *)
11328         let pa = generate_parser rng in
11329         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11330                                         (* type name = { fields ... } *)
11331     | Element (name, fields) when is_attrs_interleave fields ->
11332         generate_parser_struct name (get_attrs_interleave fields)
11333     | Element (name, [field]) ->        (* type name = field *)
11334         let pa = generate_parser field in
11335         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11336         pr "let %s =\n" parser_name;
11337         pr "  %s\n" pa;
11338         pr "let parse_%s = %s\n" name parser_name;
11339         parser_name
11340     | Attribute (name, [field]) ->
11341         let pa = generate_parser field in
11342         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11343         pr "let %s =\n" parser_name;
11344         pr "  %s\n" pa;
11345         pr "let parse_%s = %s\n" name parser_name;
11346         parser_name
11347     | Element (name, fields) ->              (* type name = { fields ... } *)
11348         generate_parser_struct name ([], fields)
11349     | rng ->
11350         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11351
11352   and is_attrs_interleave = function
11353     | [Interleave _] -> true
11354     | Attribute _ :: fields -> is_attrs_interleave fields
11355     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11356     | _ -> false
11357
11358   and get_attrs_interleave = function
11359     | [Interleave fields] -> [], fields
11360     | ((Attribute _) as field) :: fields
11361     | ((Optional (Attribute _)) as field) :: fields ->
11362         let attrs, interleaves = get_attrs_interleave fields in
11363         (field :: attrs), interleaves
11364     | _ -> assert false
11365
11366   and generate_parsers xs =
11367     List.iter (fun x -> ignore (generate_parser x)) xs
11368
11369   and generate_parser_struct name (attrs, interleaves) =
11370     (* Generate parsers for the fields first.  We have to do this
11371      * before printing anything so we are still in BOL context.
11372      *)
11373     let fields = attrs @ interleaves in
11374     let pas = List.map generate_parser fields in
11375
11376     (* Generate an intermediate tuple from all the fields first.
11377      * If the type is just a string + another field, then we will
11378      * return this directly, otherwise it is turned into a record.
11379      *
11380      * RELAX NG note: This code treats <interleave> and plain lists of
11381      * fields the same.  In other words, it doesn't bother enforcing
11382      * any ordering of fields in the XML.
11383      *)
11384     pr "let parse_%s x =\n" name;
11385     pr "  let t = (\n    ";
11386     let comma = ref false in
11387     List.iter (
11388       fun x ->
11389         if !comma then pr ",\n    ";
11390         comma := true;
11391         match x with
11392         | Optional (Attribute (fname, [field])), pa ->
11393             pr "%s x" pa
11394         | Optional (Element (fname, [field])), pa ->
11395             pr "%s (optional_child %S x)" pa fname
11396         | Attribute (fname, [Text]), _ ->
11397             pr "attribute %S x" fname
11398         | (ZeroOrMore _ | OneOrMore _), pa ->
11399             pr "%s x" pa
11400         | Text, pa ->
11401             pr "%s x" pa
11402         | (field, pa) ->
11403             let fname = name_of_field field in
11404             pr "%s (child %S x)" pa fname
11405     ) (List.combine fields pas);
11406     pr "\n  ) in\n";
11407
11408     (match fields with
11409      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11410          pr "  t\n"
11411
11412      | _ ->
11413          pr "  (Obj.magic t : %s)\n" name
11414 (*
11415          List.iter (
11416            function
11417            | (Optional (Attribute (fname, [field])), pa) ->
11418                pr "  %s_%s =\n" name fname;
11419                pr "    %s x;\n" pa
11420            | (Optional (Element (fname, [field])), pa) ->
11421                pr "  %s_%s =\n" name fname;
11422                pr "    (let x = optional_child %S x in\n" fname;
11423                pr "     %s x);\n" pa
11424            | (field, pa) ->
11425                let fname = name_of_field field in
11426                pr "  %s_%s =\n" name fname;
11427                pr "    (let x = child %S x in\n" fname;
11428                pr "     %s x);\n" pa
11429          ) (List.combine fields pas);
11430          pr "}\n"
11431 *)
11432     );
11433     sprintf "parse_%s" name
11434   in
11435
11436   generate_parsers xs
11437
11438 (* Generate ocaml/guestfs_inspector.mli. *)
11439 let generate_ocaml_inspector_mli () =
11440   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11441
11442   pr "\
11443 (** This is an OCaml language binding to the external [virt-inspector]
11444     program.
11445
11446     For more information, please read the man page [virt-inspector(1)].
11447 *)
11448
11449 ";
11450
11451   generate_types grammar;
11452   pr "(** The nested information returned from the {!inspect} function. *)\n";
11453   pr "\n";
11454
11455   pr "\
11456 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11457 (** To inspect a libvirt domain called [name], pass a singleton
11458     list: [inspect [name]].  When using libvirt only, you may
11459     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11460
11461     To inspect a disk image or images, pass a list of the filenames
11462     of the disk images: [inspect filenames]
11463
11464     This function inspects the given guest or disk images and
11465     returns a list of operating system(s) found and a large amount
11466     of information about them.  In the vast majority of cases,
11467     a virtual machine only contains a single operating system.
11468
11469     If the optional [~xml] parameter is given, then this function
11470     skips running the external virt-inspector program and just
11471     parses the given XML directly (which is expected to be XML
11472     produced from a previous run of virt-inspector).  The list of
11473     names and connect URI are ignored in this case.
11474
11475     This function can throw a wide variety of exceptions, for example
11476     if the external virt-inspector program cannot be found, or if
11477     it doesn't generate valid XML.
11478 *)
11479 "
11480
11481 (* Generate ocaml/guestfs_inspector.ml. *)
11482 let generate_ocaml_inspector_ml () =
11483   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11484
11485   pr "open Unix\n";
11486   pr "\n";
11487
11488   generate_types grammar;
11489   pr "\n";
11490
11491   pr "\
11492 (* Misc functions which are used by the parser code below. *)
11493 let first_child = function
11494   | Xml.Element (_, _, c::_) -> c
11495   | Xml.Element (name, _, []) ->
11496       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11497   | Xml.PCData str ->
11498       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11499
11500 let string_child_or_empty = function
11501   | Xml.Element (_, _, [Xml.PCData s]) -> s
11502   | Xml.Element (_, _, []) -> \"\"
11503   | Xml.Element (x, _, _) ->
11504       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11505                 x ^ \" instead\")
11506   | Xml.PCData str ->
11507       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11508
11509 let optional_child name xml =
11510   let children = Xml.children xml in
11511   try
11512     Some (List.find (function
11513                      | Xml.Element (n, _, _) when n = name -> true
11514                      | _ -> false) children)
11515   with
11516     Not_found -> None
11517
11518 let child name xml =
11519   match optional_child name xml with
11520   | Some c -> c
11521   | None ->
11522       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11523
11524 let attribute name xml =
11525   try Xml.attrib xml name
11526   with Xml.No_attribute _ ->
11527     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11528
11529 ";
11530
11531   generate_parsers grammar;
11532   pr "\n";
11533
11534   pr "\
11535 (* Run external virt-inspector, then use parser to parse the XML. *)
11536 let inspect ?connect ?xml names =
11537   let xml =
11538     match xml with
11539     | None ->
11540         if names = [] then invalid_arg \"inspect: no names given\";
11541         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11542           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11543           names in
11544         let cmd = List.map Filename.quote cmd in
11545         let cmd = String.concat \" \" cmd in
11546         let chan = open_process_in cmd in
11547         let xml = Xml.parse_in chan in
11548         (match close_process_in chan with
11549          | WEXITED 0 -> ()
11550          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11551          | WSIGNALED i | WSTOPPED i ->
11552              failwith (\"external virt-inspector command died or stopped on sig \" ^
11553                        string_of_int i)
11554         );
11555         xml
11556     | Some doc ->
11557         Xml.parse_string doc in
11558   parse_operatingsystems xml
11559 "
11560
11561 (* This is used to generate the src/MAX_PROC_NR file which
11562  * contains the maximum procedure number, a surrogate for the
11563  * ABI version number.  See src/Makefile.am for the details.
11564  *)
11565 and generate_max_proc_nr () =
11566   let proc_nrs = List.map (
11567     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11568   ) daemon_functions in
11569
11570   let max_proc_nr = List.fold_left max 0 proc_nrs in
11571
11572   pr "%d\n" max_proc_nr
11573
11574 let output_to filename k =
11575   let filename_new = filename ^ ".new" in
11576   chan := open_out filename_new;
11577   k ();
11578   close_out !chan;
11579   chan := Pervasives.stdout;
11580
11581   (* Is the new file different from the current file? *)
11582   if Sys.file_exists filename && files_equal filename filename_new then
11583     unlink filename_new                 (* same, so skip it *)
11584   else (
11585     (* different, overwrite old one *)
11586     (try chmod filename 0o644 with Unix_error _ -> ());
11587     rename filename_new filename;
11588     chmod filename 0o444;
11589     printf "written %s\n%!" filename;
11590   )
11591
11592 let perror msg = function
11593   | Unix_error (err, _, _) ->
11594       eprintf "%s: %s\n" msg (error_message err)
11595   | exn ->
11596       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11597
11598 (* Main program. *)
11599 let () =
11600   let lock_fd =
11601     try openfile "HACKING" [O_RDWR] 0
11602     with
11603     | Unix_error (ENOENT, _, _) ->
11604         eprintf "\
11605 You are probably running this from the wrong directory.
11606 Run it from the top source directory using the command
11607   src/generator.ml
11608 ";
11609         exit 1
11610     | exn ->
11611         perror "open: HACKING" exn;
11612         exit 1 in
11613
11614   (* Acquire a lock so parallel builds won't try to run the generator
11615    * twice at the same time.  Subsequent builds will wait for the first
11616    * one to finish.  Note the lock is released implicitly when the
11617    * program exits.
11618    *)
11619   (try lockf lock_fd F_LOCK 1
11620    with exn ->
11621      perror "lock: HACKING" exn;
11622      exit 1);
11623
11624   check_functions ();
11625
11626   output_to "src/guestfs_protocol.x" generate_xdr;
11627   output_to "src/guestfs-structs.h" generate_structs_h;
11628   output_to "src/guestfs-actions.h" generate_actions_h;
11629   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11630   output_to "src/guestfs-actions.c" generate_client_actions;
11631   output_to "src/guestfs-bindtests.c" generate_bindtests;
11632   output_to "src/guestfs-structs.pod" generate_structs_pod;
11633   output_to "src/guestfs-actions.pod" generate_actions_pod;
11634   output_to "src/guestfs-availability.pod" generate_availability_pod;
11635   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11636   output_to "src/libguestfs.syms" generate_linker_script;
11637   output_to "daemon/actions.h" generate_daemon_actions_h;
11638   output_to "daemon/stubs.c" generate_daemon_actions;
11639   output_to "daemon/names.c" generate_daemon_names;
11640   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11641   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11642   output_to "capitests/tests.c" generate_tests;
11643   output_to "fish/cmds.c" generate_fish_cmds;
11644   output_to "fish/completion.c" generate_fish_completion;
11645   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11646   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11647   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11648   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11649   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11650   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11651   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11652   output_to "perl/Guestfs.xs" generate_perl_xs;
11653   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11654   output_to "perl/bindtests.pl" generate_perl_bindtests;
11655   output_to "python/guestfs-py.c" generate_python_c;
11656   output_to "python/guestfs.py" generate_python_py;
11657   output_to "python/bindtests.py" generate_python_bindtests;
11658   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11659   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11660   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11661
11662   List.iter (
11663     fun (typ, jtyp) ->
11664       let cols = cols_of_struct typ in
11665       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11666       output_to filename (generate_java_struct jtyp cols);
11667   ) java_structs;
11668
11669   output_to "java/Makefile.inc" generate_java_makefile_inc;
11670   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11671   output_to "java/Bindtests.java" generate_java_bindtests;
11672   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11673   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11674   output_to "csharp/Libguestfs.cs" generate_csharp;
11675
11676   (* Always generate this file last, and unconditionally.  It's used
11677    * by the Makefile to know when we must re-run the generator.
11678    *)
11679   let chan = open_out "src/stamp-generator" in
11680   fprintf chan "1\n";
11681   close_out chan;
11682
11683   printf "generated %d lines of code\n" !lines