ffdfb1817c2f6b476e70a945049fea5d3847c169
[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 B<Important note:>
962 When you use this call, the filesystem options C<sync> and C<noatime>
963 are set implicitly.  This was originally done because we thought it
964 would improve reliability, but it turns out that I<-o sync> has a
965 very large negative performance impact and negligible effect on
966 reliability.  Therefore we recommend that you avoid using
967 C<guestfs_mount> in any code that needs performance, and instead
968 use C<guestfs_mount_options> (use an empty string for the first
969 parameter if you don't want any options).");
970
971   ("sync", (RErr, []), 2, [],
972    [ InitEmpty, Always, TestRun [["sync"]]],
973    "sync disks, writes are flushed through to the disk image",
974    "\
975 This syncs the disk, so that any writes are flushed through to the
976 underlying disk image.
977
978 You should always call this if you have modified a disk image, before
979 closing the handle.");
980
981   ("touch", (RErr, [Pathname "path"]), 3, [],
982    [InitBasicFS, Always, TestOutputTrue (
983       [["touch"; "/new"];
984        ["exists"; "/new"]])],
985    "update file timestamps or create a new file",
986    "\
987 Touch acts like the L<touch(1)> command.  It can be used to
988 update the timestamps on a file, or, if the file does not exist,
989 to create a new zero-length file.");
990
991   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
992    [InitISOFS, Always, TestOutput (
993       [["cat"; "/known-2"]], "abcdef\n")],
994    "list the contents of a file",
995    "\
996 Return the contents of the file named C<path>.
997
998 Note that this function cannot correctly handle binary files
999 (specifically, files containing C<\\0> character which is treated
1000 as end of string).  For those you need to use the C<guestfs_read_file>
1001 or C<guestfs_download> functions which have a more complex interface.");
1002
1003   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1004    [], (* XXX Tricky to test because it depends on the exact format
1005         * of the 'ls -l' command, which changes between F10 and F11.
1006         *)
1007    "list the files in a directory (long format)",
1008    "\
1009 List the files in C<directory> (relative to the root directory,
1010 there is no cwd) in the format of 'ls -la'.
1011
1012 This command is mostly useful for interactive sessions.  It
1013 is I<not> intended that you try to parse the output string.");
1014
1015   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1016    [InitBasicFS, Always, TestOutputList (
1017       [["touch"; "/new"];
1018        ["touch"; "/newer"];
1019        ["touch"; "/newest"];
1020        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1021    "list the files in a directory",
1022    "\
1023 List the files in C<directory> (relative to the root directory,
1024 there is no cwd).  The '.' and '..' entries are not returned, but
1025 hidden files are shown.
1026
1027 This command is mostly useful for interactive sessions.  Programs
1028 should probably use C<guestfs_readdir> instead.");
1029
1030   ("list_devices", (RStringList "devices", []), 7, [],
1031    [InitEmpty, Always, TestOutputListOfDevices (
1032       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1033    "list the block devices",
1034    "\
1035 List all the block devices.
1036
1037 The full block device names are returned, eg. C</dev/sda>");
1038
1039   ("list_partitions", (RStringList "partitions", []), 8, [],
1040    [InitBasicFS, Always, TestOutputListOfDevices (
1041       [["list_partitions"]], ["/dev/sda1"]);
1042     InitEmpty, Always, TestOutputListOfDevices (
1043       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1044        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1045    "list the partitions",
1046    "\
1047 List all the partitions detected on all block devices.
1048
1049 The full partition device names are returned, eg. C</dev/sda1>
1050
1051 This does not return logical volumes.  For that you will need to
1052 call C<guestfs_lvs>.");
1053
1054   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1055    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1056       [["pvs"]], ["/dev/sda1"]);
1057     InitEmpty, Always, TestOutputListOfDevices (
1058       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1059        ["pvcreate"; "/dev/sda1"];
1060        ["pvcreate"; "/dev/sda2"];
1061        ["pvcreate"; "/dev/sda3"];
1062        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1063    "list the LVM physical volumes (PVs)",
1064    "\
1065 List all the physical volumes detected.  This is the equivalent
1066 of the L<pvs(8)> command.
1067
1068 This returns a list of just the device names that contain
1069 PVs (eg. C</dev/sda2>).
1070
1071 See also C<guestfs_pvs_full>.");
1072
1073   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1074    [InitBasicFSonLVM, Always, TestOutputList (
1075       [["vgs"]], ["VG"]);
1076     InitEmpty, Always, TestOutputList (
1077       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1078        ["pvcreate"; "/dev/sda1"];
1079        ["pvcreate"; "/dev/sda2"];
1080        ["pvcreate"; "/dev/sda3"];
1081        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1082        ["vgcreate"; "VG2"; "/dev/sda3"];
1083        ["vgs"]], ["VG1"; "VG2"])],
1084    "list the LVM volume groups (VGs)",
1085    "\
1086 List all the volumes groups detected.  This is the equivalent
1087 of the L<vgs(8)> command.
1088
1089 This returns a list of just the volume group names that were
1090 detected (eg. C<VolGroup00>).
1091
1092 See also C<guestfs_vgs_full>.");
1093
1094   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1095    [InitBasicFSonLVM, Always, TestOutputList (
1096       [["lvs"]], ["/dev/VG/LV"]);
1097     InitEmpty, Always, TestOutputList (
1098       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1099        ["pvcreate"; "/dev/sda1"];
1100        ["pvcreate"; "/dev/sda2"];
1101        ["pvcreate"; "/dev/sda3"];
1102        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1103        ["vgcreate"; "VG2"; "/dev/sda3"];
1104        ["lvcreate"; "LV1"; "VG1"; "50"];
1105        ["lvcreate"; "LV2"; "VG1"; "50"];
1106        ["lvcreate"; "LV3"; "VG2"; "50"];
1107        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1108    "list the LVM logical volumes (LVs)",
1109    "\
1110 List all the logical volumes detected.  This is the equivalent
1111 of the L<lvs(8)> command.
1112
1113 This returns a list of the logical volume device names
1114 (eg. C</dev/VolGroup00/LogVol00>).
1115
1116 See also C<guestfs_lvs_full>.");
1117
1118   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1119    [], (* XXX how to test? *)
1120    "list the LVM physical volumes (PVs)",
1121    "\
1122 List all the physical volumes detected.  This is the equivalent
1123 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1124
1125   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM volume groups (VGs)",
1128    "\
1129 List all the volumes groups detected.  This is the equivalent
1130 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1133    [], (* XXX how to test? *)
1134    "list the LVM logical volumes (LVs)",
1135    "\
1136 List all the logical volumes detected.  This is the equivalent
1137 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1138
1139   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1140    [InitISOFS, Always, TestOutputList (
1141       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1142     InitISOFS, Always, TestOutputList (
1143       [["read_lines"; "/empty"]], [])],
1144    "read file as lines",
1145    "\
1146 Return the contents of the file named C<path>.
1147
1148 The file contents are returned as a list of lines.  Trailing
1149 C<LF> and C<CRLF> character sequences are I<not> returned.
1150
1151 Note that this function cannot correctly handle binary files
1152 (specifically, files containing C<\\0> character which is treated
1153 as end of line).  For those you need to use the C<guestfs_read_file>
1154 function which has a more complex interface.");
1155
1156   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1157    [], (* XXX Augeas code needs tests. *)
1158    "create a new Augeas handle",
1159    "\
1160 Create a new Augeas handle for editing configuration files.
1161 If there was any previous Augeas handle associated with this
1162 guestfs session, then it is closed.
1163
1164 You must call this before using any other C<guestfs_aug_*>
1165 commands.
1166
1167 C<root> is the filesystem root.  C<root> must not be NULL,
1168 use C</> instead.
1169
1170 The flags are the same as the flags defined in
1171 E<lt>augeas.hE<gt>, the logical I<or> of the following
1172 integers:
1173
1174 =over 4
1175
1176 =item C<AUG_SAVE_BACKUP> = 1
1177
1178 Keep the original file with a C<.augsave> extension.
1179
1180 =item C<AUG_SAVE_NEWFILE> = 2
1181
1182 Save changes into a file with extension C<.augnew>, and
1183 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1184
1185 =item C<AUG_TYPE_CHECK> = 4
1186
1187 Typecheck lenses (can be expensive).
1188
1189 =item C<AUG_NO_STDINC> = 8
1190
1191 Do not use standard load path for modules.
1192
1193 =item C<AUG_SAVE_NOOP> = 16
1194
1195 Make save a no-op, just record what would have been changed.
1196
1197 =item C<AUG_NO_LOAD> = 32
1198
1199 Do not load the tree in C<guestfs_aug_init>.
1200
1201 =back
1202
1203 To close the handle, you can call C<guestfs_aug_close>.
1204
1205 To find out more about Augeas, see L<http://augeas.net/>.");
1206
1207   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1208    [], (* XXX Augeas code needs tests. *)
1209    "close the current Augeas handle",
1210    "\
1211 Close the current Augeas handle and free up any resources
1212 used by it.  After calling this, you have to call
1213 C<guestfs_aug_init> again before you can use any other
1214 Augeas functions.");
1215
1216   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1217    [], (* XXX Augeas code needs tests. *)
1218    "define an Augeas variable",
1219    "\
1220 Defines an Augeas variable C<name> whose value is the result
1221 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1222 undefined.
1223
1224 On success this returns the number of nodes in C<expr>, or
1225 C<0> if C<expr> evaluates to something which is not a nodeset.");
1226
1227   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1228    [], (* XXX Augeas code needs tests. *)
1229    "define an Augeas node",
1230    "\
1231 Defines a variable C<name> whose value is the result of
1232 evaluating C<expr>.
1233
1234 If C<expr> evaluates to an empty nodeset, a node is created,
1235 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1236 C<name> will be the nodeset containing that single node.
1237
1238 On success this returns a pair containing the
1239 number of nodes in the nodeset, and a boolean flag
1240 if a node was created.");
1241
1242   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "look up the value of an Augeas path",
1245    "\
1246 Look up the value associated with C<path>.  If C<path>
1247 matches exactly one node, the C<value> is returned.");
1248
1249   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1250    [], (* XXX Augeas code needs tests. *)
1251    "set Augeas path to value",
1252    "\
1253 Set the value associated with C<path> to C<val>.
1254
1255 In the Augeas API, it is possible to clear a node by setting
1256 the value to NULL.  Due to an oversight in the libguestfs API
1257 you cannot do that with this call.  Instead you must use the
1258 C<guestfs_aug_clear> call.");
1259
1260   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1261    [], (* XXX Augeas code needs tests. *)
1262    "insert a sibling Augeas node",
1263    "\
1264 Create a new sibling C<label> for C<path>, inserting it into
1265 the tree before or after C<path> (depending on the boolean
1266 flag C<before>).
1267
1268 C<path> must match exactly one existing node in the tree, and
1269 C<label> must be a label, ie. not contain C</>, C<*> or end
1270 with a bracketed index C<[N]>.");
1271
1272   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1273    [], (* XXX Augeas code needs tests. *)
1274    "remove an Augeas path",
1275    "\
1276 Remove C<path> and all of its children.
1277
1278 On success this returns the number of entries which were removed.");
1279
1280   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1281    [], (* XXX Augeas code needs tests. *)
1282    "move Augeas node",
1283    "\
1284 Move the node C<src> to C<dest>.  C<src> must match exactly
1285 one node.  C<dest> is overwritten if it exists.");
1286
1287   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "return Augeas nodes which match augpath",
1290    "\
1291 Returns a list of paths which match the path expression C<path>.
1292 The returned paths are sufficiently qualified so that they match
1293 exactly one node in the current tree.");
1294
1295   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1296    [], (* XXX Augeas code needs tests. *)
1297    "write all pending Augeas changes to disk",
1298    "\
1299 This writes all pending changes to disk.
1300
1301 The flags which were passed to C<guestfs_aug_init> affect exactly
1302 how files are saved.");
1303
1304   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1305    [], (* XXX Augeas code needs tests. *)
1306    "load files into the tree",
1307    "\
1308 Load files into the tree.
1309
1310 See C<aug_load> in the Augeas documentation for the full gory
1311 details.");
1312
1313   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1314    [], (* XXX Augeas code needs tests. *)
1315    "list Augeas nodes under augpath",
1316    "\
1317 This is just a shortcut for listing C<guestfs_aug_match>
1318 C<path/*> and sorting the resulting nodes into alphabetical order.");
1319
1320   ("rm", (RErr, [Pathname "path"]), 29, [],
1321    [InitBasicFS, Always, TestRun
1322       [["touch"; "/new"];
1323        ["rm"; "/new"]];
1324     InitBasicFS, Always, TestLastFail
1325       [["rm"; "/new"]];
1326     InitBasicFS, Always, TestLastFail
1327       [["mkdir"; "/new"];
1328        ["rm"; "/new"]]],
1329    "remove a file",
1330    "\
1331 Remove the single file C<path>.");
1332
1333   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1334    [InitBasicFS, Always, TestRun
1335       [["mkdir"; "/new"];
1336        ["rmdir"; "/new"]];
1337     InitBasicFS, Always, TestLastFail
1338       [["rmdir"; "/new"]];
1339     InitBasicFS, Always, TestLastFail
1340       [["touch"; "/new"];
1341        ["rmdir"; "/new"]]],
1342    "remove a directory",
1343    "\
1344 Remove the single directory C<path>.");
1345
1346   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1347    [InitBasicFS, Always, TestOutputFalse
1348       [["mkdir"; "/new"];
1349        ["mkdir"; "/new/foo"];
1350        ["touch"; "/new/foo/bar"];
1351        ["rm_rf"; "/new"];
1352        ["exists"; "/new"]]],
1353    "remove a file or directory recursively",
1354    "\
1355 Remove the file or directory C<path>, recursively removing the
1356 contents if its a directory.  This is like the C<rm -rf> shell
1357 command.");
1358
1359   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1360    [InitBasicFS, Always, TestOutputTrue
1361       [["mkdir"; "/new"];
1362        ["is_dir"; "/new"]];
1363     InitBasicFS, Always, TestLastFail
1364       [["mkdir"; "/new/foo/bar"]]],
1365    "create a directory",
1366    "\
1367 Create a directory named C<path>.");
1368
1369   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1370    [InitBasicFS, Always, TestOutputTrue
1371       [["mkdir_p"; "/new/foo/bar"];
1372        ["is_dir"; "/new/foo/bar"]];
1373     InitBasicFS, Always, TestOutputTrue
1374       [["mkdir_p"; "/new/foo/bar"];
1375        ["is_dir"; "/new/foo"]];
1376     InitBasicFS, Always, TestOutputTrue
1377       [["mkdir_p"; "/new/foo/bar"];
1378        ["is_dir"; "/new"]];
1379     (* Regression tests for RHBZ#503133: *)
1380     InitBasicFS, Always, TestRun
1381       [["mkdir"; "/new"];
1382        ["mkdir_p"; "/new"]];
1383     InitBasicFS, Always, TestLastFail
1384       [["touch"; "/new"];
1385        ["mkdir_p"; "/new"]]],
1386    "create a directory and parents",
1387    "\
1388 Create a directory named C<path>, creating any parent directories
1389 as necessary.  This is like the C<mkdir -p> shell command.");
1390
1391   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1392    [], (* XXX Need stat command to test *)
1393    "change file mode",
1394    "\
1395 Change the mode (permissions) of C<path> to C<mode>.  Only
1396 numeric modes are supported.
1397
1398 I<Note>: When using this command from guestfish, C<mode>
1399 by default would be decimal, unless you prefix it with
1400 C<0> to get octal, ie. use C<0700> not C<700>.
1401
1402 The mode actually set is affected by the umask.");
1403
1404   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1405    [], (* XXX Need stat command to test *)
1406    "change file owner and group",
1407    "\
1408 Change the file owner to C<owner> and group to C<group>.
1409
1410 Only numeric uid and gid are supported.  If you want to use
1411 names, you will need to locate and parse the password file
1412 yourself (Augeas support makes this relatively easy).");
1413
1414   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1415    [InitISOFS, Always, TestOutputTrue (
1416       [["exists"; "/empty"]]);
1417     InitISOFS, Always, TestOutputTrue (
1418       [["exists"; "/directory"]])],
1419    "test if file or directory exists",
1420    "\
1421 This returns C<true> if and only if there is a file, directory
1422 (or anything) with the given C<path> name.
1423
1424 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1425
1426   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1427    [InitISOFS, Always, TestOutputTrue (
1428       [["is_file"; "/known-1"]]);
1429     InitISOFS, Always, TestOutputFalse (
1430       [["is_file"; "/directory"]])],
1431    "test if file exists",
1432    "\
1433 This returns C<true> if and only if there is a file
1434 with the given C<path> name.  Note that it returns false for
1435 other objects like directories.
1436
1437 See also C<guestfs_stat>.");
1438
1439   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1440    [InitISOFS, Always, TestOutputFalse (
1441       [["is_dir"; "/known-3"]]);
1442     InitISOFS, Always, TestOutputTrue (
1443       [["is_dir"; "/directory"]])],
1444    "test if file exists",
1445    "\
1446 This returns C<true> if and only if there is a directory
1447 with the given C<path> name.  Note that it returns false for
1448 other objects like files.
1449
1450 See also C<guestfs_stat>.");
1451
1452   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1453    [InitEmpty, Always, TestOutputListOfDevices (
1454       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1455        ["pvcreate"; "/dev/sda1"];
1456        ["pvcreate"; "/dev/sda2"];
1457        ["pvcreate"; "/dev/sda3"];
1458        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1459    "create an LVM physical volume",
1460    "\
1461 This creates an LVM physical volume on the named C<device>,
1462 where C<device> should usually be a partition name such
1463 as C</dev/sda1>.");
1464
1465   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1466    [InitEmpty, Always, TestOutputList (
1467       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1468        ["pvcreate"; "/dev/sda1"];
1469        ["pvcreate"; "/dev/sda2"];
1470        ["pvcreate"; "/dev/sda3"];
1471        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1472        ["vgcreate"; "VG2"; "/dev/sda3"];
1473        ["vgs"]], ["VG1"; "VG2"])],
1474    "create an LVM volume group",
1475    "\
1476 This creates an LVM volume group called C<volgroup>
1477 from the non-empty list of physical volumes C<physvols>.");
1478
1479   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1480    [InitEmpty, Always, TestOutputList (
1481       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1482        ["pvcreate"; "/dev/sda1"];
1483        ["pvcreate"; "/dev/sda2"];
1484        ["pvcreate"; "/dev/sda3"];
1485        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1486        ["vgcreate"; "VG2"; "/dev/sda3"];
1487        ["lvcreate"; "LV1"; "VG1"; "50"];
1488        ["lvcreate"; "LV2"; "VG1"; "50"];
1489        ["lvcreate"; "LV3"; "VG2"; "50"];
1490        ["lvcreate"; "LV4"; "VG2"; "50"];
1491        ["lvcreate"; "LV5"; "VG2"; "50"];
1492        ["lvs"]],
1493       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1494        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1495    "create an LVM logical volume",
1496    "\
1497 This creates an LVM logical volume called C<logvol>
1498 on the volume group C<volgroup>, with C<size> megabytes.");
1499
1500   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1501    [InitEmpty, Always, TestOutput (
1502       [["part_disk"; "/dev/sda"; "mbr"];
1503        ["mkfs"; "ext2"; "/dev/sda1"];
1504        ["mount_options"; ""; "/dev/sda1"; "/"];
1505        ["write_file"; "/new"; "new file contents"; "0"];
1506        ["cat"; "/new"]], "new file contents")],
1507    "make a filesystem",
1508    "\
1509 This creates a filesystem on C<device> (usually a partition
1510 or LVM logical volume).  The filesystem type is C<fstype>, for
1511 example C<ext3>.");
1512
1513   ("sfdisk", (RErr, [Device "device";
1514                      Int "cyls"; Int "heads"; Int "sectors";
1515                      StringList "lines"]), 43, [DangerWillRobinson],
1516    [],
1517    "create partitions on a block device",
1518    "\
1519 This is a direct interface to the L<sfdisk(8)> program for creating
1520 partitions on block devices.
1521
1522 C<device> should be a block device, for example C</dev/sda>.
1523
1524 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1525 and sectors on the device, which are passed directly to sfdisk as
1526 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1527 of these, then the corresponding parameter is omitted.  Usually for
1528 'large' disks, you can just pass C<0> for these, but for small
1529 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1530 out the right geometry and you will need to tell it.
1531
1532 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1533 information refer to the L<sfdisk(8)> manpage.
1534
1535 To create a single partition occupying the whole disk, you would
1536 pass C<lines> as a single element list, when the single element being
1537 the string C<,> (comma).
1538
1539 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1540 C<guestfs_part_init>");
1541
1542   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1543    [InitBasicFS, Always, TestOutput (
1544       [["write_file"; "/new"; "new file contents"; "0"];
1545        ["cat"; "/new"]], "new file contents");
1546     InitBasicFS, Always, TestOutput (
1547       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1548        ["cat"; "/new"]], "\nnew file contents\n");
1549     InitBasicFS, Always, TestOutput (
1550       [["write_file"; "/new"; "\n\n"; "0"];
1551        ["cat"; "/new"]], "\n\n");
1552     InitBasicFS, Always, TestOutput (
1553       [["write_file"; "/new"; ""; "0"];
1554        ["cat"; "/new"]], "");
1555     InitBasicFS, Always, TestOutput (
1556       [["write_file"; "/new"; "\n\n\n"; "0"];
1557        ["cat"; "/new"]], "\n\n\n");
1558     InitBasicFS, Always, TestOutput (
1559       [["write_file"; "/new"; "\n"; "0"];
1560        ["cat"; "/new"]], "\n")],
1561    "create a file",
1562    "\
1563 This call creates a file called C<path>.  The contents of the
1564 file is the string C<content> (which can contain any 8 bit data),
1565 with length C<size>.
1566
1567 As a special case, if C<size> is C<0>
1568 then the length is calculated using C<strlen> (so in this case
1569 the content cannot contain embedded ASCII NULs).
1570
1571 I<NB.> Owing to a bug, writing content containing ASCII NUL
1572 characters does I<not> work, even if the length is specified.
1573 We hope to resolve this bug in a future version.  In the meantime
1574 use C<guestfs_upload>.");
1575
1576   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1577    [InitEmpty, Always, TestOutputListOfDevices (
1578       [["part_disk"; "/dev/sda"; "mbr"];
1579        ["mkfs"; "ext2"; "/dev/sda1"];
1580        ["mount_options"; ""; "/dev/sda1"; "/"];
1581        ["mounts"]], ["/dev/sda1"]);
1582     InitEmpty, Always, TestOutputList (
1583       [["part_disk"; "/dev/sda"; "mbr"];
1584        ["mkfs"; "ext2"; "/dev/sda1"];
1585        ["mount_options"; ""; "/dev/sda1"; "/"];
1586        ["umount"; "/"];
1587        ["mounts"]], [])],
1588    "unmount a filesystem",
1589    "\
1590 This unmounts the given filesystem.  The filesystem may be
1591 specified either by its mountpoint (path) or the device which
1592 contains the filesystem.");
1593
1594   ("mounts", (RStringList "devices", []), 46, [],
1595    [InitBasicFS, Always, TestOutputListOfDevices (
1596       [["mounts"]], ["/dev/sda1"])],
1597    "show mounted filesystems",
1598    "\
1599 This returns the list of currently mounted filesystems.  It returns
1600 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1601
1602 Some internal mounts are not shown.
1603
1604 See also: C<guestfs_mountpoints>");
1605
1606   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1607    [InitBasicFS, Always, TestOutputList (
1608       [["umount_all"];
1609        ["mounts"]], []);
1610     (* check that umount_all can unmount nested mounts correctly: *)
1611     InitEmpty, Always, TestOutputList (
1612       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1613        ["mkfs"; "ext2"; "/dev/sda1"];
1614        ["mkfs"; "ext2"; "/dev/sda2"];
1615        ["mkfs"; "ext2"; "/dev/sda3"];
1616        ["mount_options"; ""; "/dev/sda1"; "/"];
1617        ["mkdir"; "/mp1"];
1618        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1619        ["mkdir"; "/mp1/mp2"];
1620        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1621        ["mkdir"; "/mp1/mp2/mp3"];
1622        ["umount_all"];
1623        ["mounts"]], [])],
1624    "unmount all filesystems",
1625    "\
1626 This unmounts all mounted filesystems.
1627
1628 Some internal mounts are not unmounted by this call.");
1629
1630   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1631    [],
1632    "remove all LVM LVs, VGs and PVs",
1633    "\
1634 This command removes all LVM logical volumes, volume groups
1635 and physical volumes.");
1636
1637   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1638    [InitISOFS, Always, TestOutput (
1639       [["file"; "/empty"]], "empty");
1640     InitISOFS, Always, TestOutput (
1641       [["file"; "/known-1"]], "ASCII text");
1642     InitISOFS, Always, TestLastFail (
1643       [["file"; "/notexists"]])],
1644    "determine file type",
1645    "\
1646 This call uses the standard L<file(1)> command to determine
1647 the type or contents of the file.  This also works on devices,
1648 for example to find out whether a partition contains a filesystem.
1649
1650 This call will also transparently look inside various types
1651 of compressed file.
1652
1653 The exact command which runs is C<file -zbsL path>.  Note in
1654 particular that the filename is not prepended to the output
1655 (the C<-b> option).");
1656
1657   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1658    [InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 1"]], "Result1");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 2"]], "Result2\n");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 3"]], "\nResult3");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 4"]], "\nResult4\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 5"]], "\nResult5\n\n");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1682     InitBasicFS, Always, TestOutput (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command 7"]], "");
1686     InitBasicFS, Always, TestOutput (
1687       [["upload"; "test-command"; "/test-command"];
1688        ["chmod"; "0o755"; "/test-command"];
1689        ["command"; "/test-command 8"]], "\n");
1690     InitBasicFS, Always, TestOutput (
1691       [["upload"; "test-command"; "/test-command"];
1692        ["chmod"; "0o755"; "/test-command"];
1693        ["command"; "/test-command 9"]], "\n\n");
1694     InitBasicFS, Always, TestOutput (
1695       [["upload"; "test-command"; "/test-command"];
1696        ["chmod"; "0o755"; "/test-command"];
1697        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1698     InitBasicFS, Always, TestOutput (
1699       [["upload"; "test-command"; "/test-command"];
1700        ["chmod"; "0o755"; "/test-command"];
1701        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1702     InitBasicFS, Always, TestLastFail (
1703       [["upload"; "test-command"; "/test-command"];
1704        ["chmod"; "0o755"; "/test-command"];
1705        ["command"; "/test-command"]])],
1706    "run a command from the guest filesystem",
1707    "\
1708 This call runs a command from the guest filesystem.  The
1709 filesystem must be mounted, and must contain a compatible
1710 operating system (ie. something Linux, with the same
1711 or compatible processor architecture).
1712
1713 The single parameter is an argv-style list of arguments.
1714 The first element is the name of the program to run.
1715 Subsequent elements are parameters.  The list must be
1716 non-empty (ie. must contain a program name).  Note that
1717 the command runs directly, and is I<not> invoked via
1718 the shell (see C<guestfs_sh>).
1719
1720 The return value is anything printed to I<stdout> by
1721 the command.
1722
1723 If the command returns a non-zero exit status, then
1724 this function returns an error message.  The error message
1725 string is the content of I<stderr> from the command.
1726
1727 The C<$PATH> environment variable will contain at least
1728 C</usr/bin> and C</bin>.  If you require a program from
1729 another location, you should provide the full path in the
1730 first parameter.
1731
1732 Shared libraries and data files required by the program
1733 must be available on filesystems which are mounted in the
1734 correct places.  It is the caller's responsibility to ensure
1735 all filesystems that are needed are mounted at the right
1736 locations.");
1737
1738   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1739    [InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 1"]], ["Result1"]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 2"]], ["Result2"]);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1763     InitBasicFS, Always, TestOutputList (
1764       [["upload"; "test-command"; "/test-command"];
1765        ["chmod"; "0o755"; "/test-command"];
1766        ["command_lines"; "/test-command 7"]], []);
1767     InitBasicFS, Always, TestOutputList (
1768       [["upload"; "test-command"; "/test-command"];
1769        ["chmod"; "0o755"; "/test-command"];
1770        ["command_lines"; "/test-command 8"]], [""]);
1771     InitBasicFS, Always, TestOutputList (
1772       [["upload"; "test-command"; "/test-command"];
1773        ["chmod"; "0o755"; "/test-command"];
1774        ["command_lines"; "/test-command 9"]], ["";""]);
1775     InitBasicFS, Always, TestOutputList (
1776       [["upload"; "test-command"; "/test-command"];
1777        ["chmod"; "0o755"; "/test-command"];
1778        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1779     InitBasicFS, Always, TestOutputList (
1780       [["upload"; "test-command"; "/test-command"];
1781        ["chmod"; "0o755"; "/test-command"];
1782        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1783    "run a command, returning lines",
1784    "\
1785 This is the same as C<guestfs_command>, but splits the
1786 result into a list of lines.
1787
1788 See also: C<guestfs_sh_lines>");
1789
1790   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1791    [InitISOFS, Always, TestOutputStruct (
1792       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1793    "get file information",
1794    "\
1795 Returns file information for the given C<path>.
1796
1797 This is the same as the C<stat(2)> system call.");
1798
1799   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1800    [InitISOFS, Always, TestOutputStruct (
1801       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1802    "get file information for a symbolic link",
1803    "\
1804 Returns file information for the given C<path>.
1805
1806 This is the same as C<guestfs_stat> except that if C<path>
1807 is a symbolic link, then the link is stat-ed, not the file it
1808 refers to.
1809
1810 This is the same as the C<lstat(2)> system call.");
1811
1812   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1813    [InitISOFS, Always, TestOutputStruct (
1814       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1815    "get file system statistics",
1816    "\
1817 Returns file system statistics for any mounted file system.
1818 C<path> should be a file or directory in the mounted file system
1819 (typically it is the mount point itself, but it doesn't need to be).
1820
1821 This is the same as the C<statvfs(2)> system call.");
1822
1823   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1824    [], (* XXX test *)
1825    "get ext2/ext3/ext4 superblock details",
1826    "\
1827 This returns the contents of the ext2, ext3 or ext4 filesystem
1828 superblock on C<device>.
1829
1830 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1831 manpage for more details.  The list of fields returned isn't
1832 clearly defined, and depends on both the version of C<tune2fs>
1833 that libguestfs was built against, and the filesystem itself.");
1834
1835   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1836    [InitEmpty, Always, TestOutputTrue (
1837       [["blockdev_setro"; "/dev/sda"];
1838        ["blockdev_getro"; "/dev/sda"]])],
1839    "set block device to read-only",
1840    "\
1841 Sets the block device named C<device> to read-only.
1842
1843 This uses the L<blockdev(8)> command.");
1844
1845   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1846    [InitEmpty, Always, TestOutputFalse (
1847       [["blockdev_setrw"; "/dev/sda"];
1848        ["blockdev_getro"; "/dev/sda"]])],
1849    "set block device to read-write",
1850    "\
1851 Sets the block device named C<device> to read-write.
1852
1853 This uses the L<blockdev(8)> command.");
1854
1855   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1856    [InitEmpty, Always, TestOutputTrue (
1857       [["blockdev_setro"; "/dev/sda"];
1858        ["blockdev_getro"; "/dev/sda"]])],
1859    "is block device set to read-only",
1860    "\
1861 Returns a boolean indicating if the block device is read-only
1862 (true if read-only, false if not).
1863
1864 This uses the L<blockdev(8)> command.");
1865
1866   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1867    [InitEmpty, Always, TestOutputInt (
1868       [["blockdev_getss"; "/dev/sda"]], 512)],
1869    "get sectorsize of block device",
1870    "\
1871 This returns the size of sectors on a block device.
1872 Usually 512, but can be larger for modern devices.
1873
1874 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1875 for that).
1876
1877 This uses the L<blockdev(8)> command.");
1878
1879   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1880    [InitEmpty, Always, TestOutputInt (
1881       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1882    "get blocksize of block device",
1883    "\
1884 This returns the block size of a device.
1885
1886 (Note this is different from both I<size in blocks> and
1887 I<filesystem block size>).
1888
1889 This uses the L<blockdev(8)> command.");
1890
1891   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1892    [], (* XXX test *)
1893    "set blocksize of block device",
1894    "\
1895 This sets the block size of a device.
1896
1897 (Note this is different from both I<size in blocks> and
1898 I<filesystem block size>).
1899
1900 This uses the L<blockdev(8)> command.");
1901
1902   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1903    [InitEmpty, Always, TestOutputInt (
1904       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1905    "get total size of device in 512-byte sectors",
1906    "\
1907 This returns the size of the device in units of 512-byte sectors
1908 (even if the sectorsize isn't 512 bytes ... weird).
1909
1910 See also C<guestfs_blockdev_getss> for the real sector size of
1911 the device, and C<guestfs_blockdev_getsize64> for the more
1912 useful I<size in bytes>.
1913
1914 This uses the L<blockdev(8)> command.");
1915
1916   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1917    [InitEmpty, Always, TestOutputInt (
1918       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1919    "get total size of device in bytes",
1920    "\
1921 This returns the size of the device in bytes.
1922
1923 See also C<guestfs_blockdev_getsz>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1928    [InitEmpty, Always, TestRun
1929       [["blockdev_flushbufs"; "/dev/sda"]]],
1930    "flush device buffers",
1931    "\
1932 This tells the kernel to flush internal buffers associated
1933 with C<device>.
1934
1935 This uses the L<blockdev(8)> command.");
1936
1937   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1938    [InitEmpty, Always, TestRun
1939       [["blockdev_rereadpt"; "/dev/sda"]]],
1940    "reread partition table",
1941    "\
1942 Reread the partition table on C<device>.
1943
1944 This uses the L<blockdev(8)> command.");
1945
1946   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1947    [InitBasicFS, Always, TestOutput (
1948       (* Pick a file from cwd which isn't likely to change. *)
1949       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1950        ["checksum"; "md5"; "/COPYING.LIB"]],
1951       Digest.to_hex (Digest.file "COPYING.LIB"))],
1952    "upload a file from the local machine",
1953    "\
1954 Upload local file C<filename> to C<remotefilename> on the
1955 filesystem.
1956
1957 C<filename> can also be a named pipe.
1958
1959 See also C<guestfs_download>.");
1960
1961   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1962    [InitBasicFS, Always, TestOutput (
1963       (* Pick a file from cwd which isn't likely to change. *)
1964       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1965        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1966        ["upload"; "testdownload.tmp"; "/upload"];
1967        ["checksum"; "md5"; "/upload"]],
1968       Digest.to_hex (Digest.file "COPYING.LIB"))],
1969    "download a file to the local machine",
1970    "\
1971 Download file C<remotefilename> and save it as C<filename>
1972 on the local machine.
1973
1974 C<filename> can also be a named pipe.
1975
1976 See also C<guestfs_upload>, C<guestfs_cat>.");
1977
1978   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1979    [InitISOFS, Always, TestOutput (
1980       [["checksum"; "crc"; "/known-3"]], "2891671662");
1981     InitISOFS, Always, TestLastFail (
1982       [["checksum"; "crc"; "/notexists"]]);
1983     InitISOFS, Always, TestOutput (
1984       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1985     InitISOFS, Always, TestOutput (
1986       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1987     InitISOFS, Always, TestOutput (
1988       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1989     InitISOFS, Always, TestOutput (
1990       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1991     InitISOFS, Always, TestOutput (
1992       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1993     InitISOFS, Always, TestOutput (
1994       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1995     (* Test for RHBZ#579608, absolute symbolic links. *)
1996     InitISOFS, Always, TestOutput (
1997       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1998    "compute MD5, SHAx or CRC checksum of file",
1999    "\
2000 This call computes the MD5, SHAx or CRC checksum of the
2001 file named C<path>.
2002
2003 The type of checksum to compute is given by the C<csumtype>
2004 parameter which must have one of the following values:
2005
2006 =over 4
2007
2008 =item C<crc>
2009
2010 Compute the cyclic redundancy check (CRC) specified by POSIX
2011 for the C<cksum> command.
2012
2013 =item C<md5>
2014
2015 Compute the MD5 hash (using the C<md5sum> program).
2016
2017 =item C<sha1>
2018
2019 Compute the SHA1 hash (using the C<sha1sum> program).
2020
2021 =item C<sha224>
2022
2023 Compute the SHA224 hash (using the C<sha224sum> program).
2024
2025 =item C<sha256>
2026
2027 Compute the SHA256 hash (using the C<sha256sum> program).
2028
2029 =item C<sha384>
2030
2031 Compute the SHA384 hash (using the C<sha384sum> program).
2032
2033 =item C<sha512>
2034
2035 Compute the SHA512 hash (using the C<sha512sum> program).
2036
2037 =back
2038
2039 The checksum is returned as a printable string.
2040
2041 To get the checksum for a device, use C<guestfs_checksum_device>.
2042
2043 To get the checksums for many files, use C<guestfs_checksums_out>.");
2044
2045   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2046    [InitBasicFS, Always, TestOutput (
2047       [["tar_in"; "../images/helloworld.tar"; "/"];
2048        ["cat"; "/hello"]], "hello\n")],
2049    "unpack tarfile to directory",
2050    "\
2051 This command uploads and unpacks local file C<tarfile> (an
2052 I<uncompressed> tar file) into C<directory>.
2053
2054 To upload a compressed tarball, use C<guestfs_tgz_in>
2055 or C<guestfs_txz_in>.");
2056
2057   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2058    [],
2059    "pack directory into tarfile",
2060    "\
2061 This command packs the contents of C<directory> and downloads
2062 it to local file C<tarfile>.
2063
2064 To download a compressed tarball, use C<guestfs_tgz_out>
2065 or C<guestfs_txz_out>.");
2066
2067   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2068    [InitBasicFS, Always, TestOutput (
2069       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2070        ["cat"; "/hello"]], "hello\n")],
2071    "unpack compressed tarball to directory",
2072    "\
2073 This command uploads and unpacks local file C<tarball> (a
2074 I<gzip compressed> tar file) into C<directory>.
2075
2076 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2077
2078   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2079    [],
2080    "pack directory into compressed tarball",
2081    "\
2082 This command packs the contents of C<directory> and downloads
2083 it to local file C<tarball>.
2084
2085 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2086
2087   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2088    [InitBasicFS, Always, TestLastFail (
2089       [["umount"; "/"];
2090        ["mount_ro"; "/dev/sda1"; "/"];
2091        ["touch"; "/new"]]);
2092     InitBasicFS, Always, TestOutput (
2093       [["write_file"; "/new"; "data"; "0"];
2094        ["umount"; "/"];
2095        ["mount_ro"; "/dev/sda1"; "/"];
2096        ["cat"; "/new"]], "data")],
2097    "mount a guest disk, read-only",
2098    "\
2099 This is the same as the C<guestfs_mount> command, but it
2100 mounts the filesystem with the read-only (I<-o ro>) flag.");
2101
2102   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2103    [],
2104    "mount a guest disk with mount options",
2105    "\
2106 This is the same as the C<guestfs_mount> command, but it
2107 allows you to set the mount options as for the
2108 L<mount(8)> I<-o> flag.
2109
2110 If the C<options> parameter is an empty string, then
2111 no options are passed (all options default to whatever
2112 the filesystem uses).");
2113
2114   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2115    [],
2116    "mount a guest disk with mount options and vfstype",
2117    "\
2118 This is the same as the C<guestfs_mount> command, but it
2119 allows you to set both the mount options and the vfstype
2120 as for the L<mount(8)> I<-o> and I<-t> flags.");
2121
2122   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2123    [],
2124    "debugging and internals",
2125    "\
2126 The C<guestfs_debug> command exposes some internals of
2127 C<guestfsd> (the guestfs daemon) that runs inside the
2128 qemu subprocess.
2129
2130 There is no comprehensive help for this command.  You have
2131 to look at the file C<daemon/debug.c> in the libguestfs source
2132 to find out what you can do.");
2133
2134   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2135    [InitEmpty, Always, TestOutputList (
2136       [["part_disk"; "/dev/sda"; "mbr"];
2137        ["pvcreate"; "/dev/sda1"];
2138        ["vgcreate"; "VG"; "/dev/sda1"];
2139        ["lvcreate"; "LV1"; "VG"; "50"];
2140        ["lvcreate"; "LV2"; "VG"; "50"];
2141        ["lvremove"; "/dev/VG/LV1"];
2142        ["lvs"]], ["/dev/VG/LV2"]);
2143     InitEmpty, Always, TestOutputList (
2144       [["part_disk"; "/dev/sda"; "mbr"];
2145        ["pvcreate"; "/dev/sda1"];
2146        ["vgcreate"; "VG"; "/dev/sda1"];
2147        ["lvcreate"; "LV1"; "VG"; "50"];
2148        ["lvcreate"; "LV2"; "VG"; "50"];
2149        ["lvremove"; "/dev/VG"];
2150        ["lvs"]], []);
2151     InitEmpty, Always, TestOutputList (
2152       [["part_disk"; "/dev/sda"; "mbr"];
2153        ["pvcreate"; "/dev/sda1"];
2154        ["vgcreate"; "VG"; "/dev/sda1"];
2155        ["lvcreate"; "LV1"; "VG"; "50"];
2156        ["lvcreate"; "LV2"; "VG"; "50"];
2157        ["lvremove"; "/dev/VG"];
2158        ["vgs"]], ["VG"])],
2159    "remove an LVM logical volume",
2160    "\
2161 Remove an LVM logical volume C<device>, where C<device> is
2162 the path to the LV, such as C</dev/VG/LV>.
2163
2164 You can also remove all LVs in a volume group by specifying
2165 the VG name, C</dev/VG>.");
2166
2167   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2168    [InitEmpty, Always, TestOutputList (
2169       [["part_disk"; "/dev/sda"; "mbr"];
2170        ["pvcreate"; "/dev/sda1"];
2171        ["vgcreate"; "VG"; "/dev/sda1"];
2172        ["lvcreate"; "LV1"; "VG"; "50"];
2173        ["lvcreate"; "LV2"; "VG"; "50"];
2174        ["vgremove"; "VG"];
2175        ["lvs"]], []);
2176     InitEmpty, Always, TestOutputList (
2177       [["part_disk"; "/dev/sda"; "mbr"];
2178        ["pvcreate"; "/dev/sda1"];
2179        ["vgcreate"; "VG"; "/dev/sda1"];
2180        ["lvcreate"; "LV1"; "VG"; "50"];
2181        ["lvcreate"; "LV2"; "VG"; "50"];
2182        ["vgremove"; "VG"];
2183        ["vgs"]], [])],
2184    "remove an LVM volume group",
2185    "\
2186 Remove an LVM volume group C<vgname>, (for example C<VG>).
2187
2188 This also forcibly removes all logical volumes in the volume
2189 group (if any).");
2190
2191   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
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        ["lvs"]], []);
2201     InitEmpty, Always, TestOutputListOfDevices (
2202       [["part_disk"; "/dev/sda"; "mbr"];
2203        ["pvcreate"; "/dev/sda1"];
2204        ["vgcreate"; "VG"; "/dev/sda1"];
2205        ["lvcreate"; "LV1"; "VG"; "50"];
2206        ["lvcreate"; "LV2"; "VG"; "50"];
2207        ["vgremove"; "VG"];
2208        ["pvremove"; "/dev/sda1"];
2209        ["vgs"]], []);
2210     InitEmpty, Always, TestOutputListOfDevices (
2211       [["part_disk"; "/dev/sda"; "mbr"];
2212        ["pvcreate"; "/dev/sda1"];
2213        ["vgcreate"; "VG"; "/dev/sda1"];
2214        ["lvcreate"; "LV1"; "VG"; "50"];
2215        ["lvcreate"; "LV2"; "VG"; "50"];
2216        ["vgremove"; "VG"];
2217        ["pvremove"; "/dev/sda1"];
2218        ["pvs"]], [])],
2219    "remove an LVM physical volume",
2220    "\
2221 This wipes a physical volume C<device> so that LVM will no longer
2222 recognise it.
2223
2224 The implementation uses the C<pvremove> command which refuses to
2225 wipe physical volumes that contain any volume groups, so you have
2226 to remove those first.");
2227
2228   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2229    [InitBasicFS, Always, TestOutput (
2230       [["set_e2label"; "/dev/sda1"; "testlabel"];
2231        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2232    "set the ext2/3/4 filesystem label",
2233    "\
2234 This sets the ext2/3/4 filesystem label of the filesystem on
2235 C<device> to C<label>.  Filesystem labels are limited to
2236 16 characters.
2237
2238 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2239 to return the existing label on a filesystem.");
2240
2241   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2242    [],
2243    "get the ext2/3/4 filesystem label",
2244    "\
2245 This returns the ext2/3/4 filesystem label of the filesystem on
2246 C<device>.");
2247
2248   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2249    (let uuid = uuidgen () in
2250     [InitBasicFS, Always, TestOutput (
2251        [["set_e2uuid"; "/dev/sda1"; uuid];
2252         ["get_e2uuid"; "/dev/sda1"]], uuid);
2253      InitBasicFS, Always, TestOutput (
2254        [["set_e2uuid"; "/dev/sda1"; "clear"];
2255         ["get_e2uuid"; "/dev/sda1"]], "");
2256      (* We can't predict what UUIDs will be, so just check the commands run. *)
2257      InitBasicFS, Always, TestRun (
2258        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2259      InitBasicFS, Always, TestRun (
2260        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2261    "set the ext2/3/4 filesystem UUID",
2262    "\
2263 This sets the ext2/3/4 filesystem UUID of the filesystem on
2264 C<device> to C<uuid>.  The format of the UUID and alternatives
2265 such as C<clear>, C<random> and C<time> are described in the
2266 L<tune2fs(8)> manpage.
2267
2268 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2269 to return the existing UUID of a filesystem.");
2270
2271   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2272    [],
2273    "get the ext2/3/4 filesystem UUID",
2274    "\
2275 This returns the ext2/3/4 filesystem UUID of the filesystem on
2276 C<device>.");
2277
2278   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2279    [InitBasicFS, Always, TestOutputInt (
2280       [["umount"; "/dev/sda1"];
2281        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2282     InitBasicFS, Always, TestOutputInt (
2283       [["umount"; "/dev/sda1"];
2284        ["zero"; "/dev/sda1"];
2285        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2286    "run the filesystem checker",
2287    "\
2288 This runs the filesystem checker (fsck) on C<device> which
2289 should have filesystem type C<fstype>.
2290
2291 The returned integer is the status.  See L<fsck(8)> for the
2292 list of status codes from C<fsck>.
2293
2294 Notes:
2295
2296 =over 4
2297
2298 =item *
2299
2300 Multiple status codes can be summed together.
2301
2302 =item *
2303
2304 A non-zero return code can mean \"success\", for example if
2305 errors have been corrected on the filesystem.
2306
2307 =item *
2308
2309 Checking or repairing NTFS volumes is not supported
2310 (by linux-ntfs).
2311
2312 =back
2313
2314 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2315
2316   ("zero", (RErr, [Device "device"]), 85, [],
2317    [InitBasicFS, Always, TestOutput (
2318       [["umount"; "/dev/sda1"];
2319        ["zero"; "/dev/sda1"];
2320        ["file"; "/dev/sda1"]], "data")],
2321    "write zeroes to the device",
2322    "\
2323 This command writes zeroes over the first few blocks of C<device>.
2324
2325 How many blocks are zeroed isn't specified (but it's I<not> enough
2326 to securely wipe the device).  It should be sufficient to remove
2327 any partition tables, filesystem superblocks and so on.
2328
2329 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2330
2331   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2332    (* Test disabled because grub-install incompatible with virtio-blk driver.
2333     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2334     *)
2335    [InitBasicFS, Disabled, TestOutputTrue (
2336       [["grub_install"; "/"; "/dev/sda1"];
2337        ["is_dir"; "/boot"]])],
2338    "install GRUB",
2339    "\
2340 This command installs GRUB (the Grand Unified Bootloader) on
2341 C<device>, with the root directory being C<root>.");
2342
2343   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2344    [InitBasicFS, Always, TestOutput (
2345       [["write_file"; "/old"; "file content"; "0"];
2346        ["cp"; "/old"; "/new"];
2347        ["cat"; "/new"]], "file content");
2348     InitBasicFS, Always, TestOutputTrue (
2349       [["write_file"; "/old"; "file content"; "0"];
2350        ["cp"; "/old"; "/new"];
2351        ["is_file"; "/old"]]);
2352     InitBasicFS, Always, TestOutput (
2353       [["write_file"; "/old"; "file content"; "0"];
2354        ["mkdir"; "/dir"];
2355        ["cp"; "/old"; "/dir/new"];
2356        ["cat"; "/dir/new"]], "file content")],
2357    "copy a file",
2358    "\
2359 This copies a file from C<src> to C<dest> where C<dest> is
2360 either a destination filename or destination directory.");
2361
2362   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2363    [InitBasicFS, Always, TestOutput (
2364       [["mkdir"; "/olddir"];
2365        ["mkdir"; "/newdir"];
2366        ["write_file"; "/olddir/file"; "file content"; "0"];
2367        ["cp_a"; "/olddir"; "/newdir"];
2368        ["cat"; "/newdir/olddir/file"]], "file content")],
2369    "copy a file or directory recursively",
2370    "\
2371 This copies a file or directory from C<src> to C<dest>
2372 recursively using the C<cp -a> command.");
2373
2374   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2375    [InitBasicFS, Always, TestOutput (
2376       [["write_file"; "/old"; "file content"; "0"];
2377        ["mv"; "/old"; "/new"];
2378        ["cat"; "/new"]], "file content");
2379     InitBasicFS, Always, TestOutputFalse (
2380       [["write_file"; "/old"; "file content"; "0"];
2381        ["mv"; "/old"; "/new"];
2382        ["is_file"; "/old"]])],
2383    "move a file",
2384    "\
2385 This moves a file from C<src> to C<dest> where C<dest> is
2386 either a destination filename or destination directory.");
2387
2388   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2389    [InitEmpty, Always, TestRun (
2390       [["drop_caches"; "3"]])],
2391    "drop kernel page cache, dentries and inodes",
2392    "\
2393 This instructs the guest kernel to drop its page cache,
2394 and/or dentries and inode caches.  The parameter C<whattodrop>
2395 tells the kernel what precisely to drop, see
2396 L<http://linux-mm.org/Drop_Caches>
2397
2398 Setting C<whattodrop> to 3 should drop everything.
2399
2400 This automatically calls L<sync(2)> before the operation,
2401 so that the maximum guest memory is freed.");
2402
2403   ("dmesg", (RString "kmsgs", []), 91, [],
2404    [InitEmpty, Always, TestRun (
2405       [["dmesg"]])],
2406    "return kernel messages",
2407    "\
2408 This returns the kernel messages (C<dmesg> output) from
2409 the guest kernel.  This is sometimes useful for extended
2410 debugging of problems.
2411
2412 Another way to get the same information is to enable
2413 verbose messages with C<guestfs_set_verbose> or by setting
2414 the environment variable C<LIBGUESTFS_DEBUG=1> before
2415 running the program.");
2416
2417   ("ping_daemon", (RErr, []), 92, [],
2418    [InitEmpty, Always, TestRun (
2419       [["ping_daemon"]])],
2420    "ping the guest daemon",
2421    "\
2422 This is a test probe into the guestfs daemon running inside
2423 the qemu subprocess.  Calling this function checks that the
2424 daemon responds to the ping message, without affecting the daemon
2425 or attached block device(s) in any other way.");
2426
2427   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2428    [InitBasicFS, Always, TestOutputTrue (
2429       [["write_file"; "/file1"; "contents of a file"; "0"];
2430        ["cp"; "/file1"; "/file2"];
2431        ["equal"; "/file1"; "/file2"]]);
2432     InitBasicFS, Always, TestOutputFalse (
2433       [["write_file"; "/file1"; "contents of a file"; "0"];
2434        ["write_file"; "/file2"; "contents of another file"; "0"];
2435        ["equal"; "/file1"; "/file2"]]);
2436     InitBasicFS, Always, TestLastFail (
2437       [["equal"; "/file1"; "/file2"]])],
2438    "test if two files have equal contents",
2439    "\
2440 This compares the two files C<file1> and C<file2> and returns
2441 true if their content is exactly equal, or false otherwise.
2442
2443 The external L<cmp(1)> program is used for the comparison.");
2444
2445   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2446    [InitISOFS, Always, TestOutputList (
2447       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2448     InitISOFS, Always, TestOutputList (
2449       [["strings"; "/empty"]], [])],
2450    "print the printable strings in a file",
2451    "\
2452 This runs the L<strings(1)> command on a file and returns
2453 the list of printable strings found.");
2454
2455   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2456    [InitISOFS, Always, TestOutputList (
2457       [["strings_e"; "b"; "/known-5"]], []);
2458     InitBasicFS, Disabled, TestOutputList (
2459       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2460        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2461    "print the printable strings in a file",
2462    "\
2463 This is like the C<guestfs_strings> command, but allows you to
2464 specify the encoding.
2465
2466 See the L<strings(1)> manpage for the full list of encodings.
2467
2468 Commonly useful encodings are C<l> (lower case L) which will
2469 show strings inside Windows/x86 files.
2470
2471 The returned strings are transcoded to UTF-8.");
2472
2473   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2474    [InitISOFS, Always, TestOutput (
2475       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2476     (* Test for RHBZ#501888c2 regression which caused large hexdump
2477      * commands to segfault.
2478      *)
2479     InitISOFS, Always, TestRun (
2480       [["hexdump"; "/100krandom"]]);
2481     (* Test for RHBZ#579608, absolute symbolic links. *)
2482     InitISOFS, Always, TestRun (
2483       [["hexdump"; "/abssymlink"]])],
2484    "dump a file in hexadecimal",
2485    "\
2486 This runs C<hexdump -C> on the given C<path>.  The result is
2487 the human-readable, canonical hex dump of the file.");
2488
2489   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2490    [InitNone, Always, TestOutput (
2491       [["part_disk"; "/dev/sda"; "mbr"];
2492        ["mkfs"; "ext3"; "/dev/sda1"];
2493        ["mount_options"; ""; "/dev/sda1"; "/"];
2494        ["write_file"; "/new"; "test file"; "0"];
2495        ["umount"; "/dev/sda1"];
2496        ["zerofree"; "/dev/sda1"];
2497        ["mount_options"; ""; "/dev/sda1"; "/"];
2498        ["cat"; "/new"]], "test file")],
2499    "zero unused inodes and disk blocks on ext2/3 filesystem",
2500    "\
2501 This runs the I<zerofree> program on C<device>.  This program
2502 claims to zero unused inodes and disk blocks on an ext2/3
2503 filesystem, thus making it possible to compress the filesystem
2504 more effectively.
2505
2506 You should B<not> run this program if the filesystem is
2507 mounted.
2508
2509 It is possible that using this program can damage the filesystem
2510 or data on the filesystem.");
2511
2512   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2513    [],
2514    "resize an LVM physical volume",
2515    "\
2516 This resizes (expands or shrinks) an existing LVM physical
2517 volume to match the new size of the underlying device.");
2518
2519   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2520                        Int "cyls"; Int "heads"; Int "sectors";
2521                        String "line"]), 99, [DangerWillRobinson],
2522    [],
2523    "modify a single partition on a block device",
2524    "\
2525 This runs L<sfdisk(8)> option to modify just the single
2526 partition C<n> (note: C<n> counts from 1).
2527
2528 For other parameters, see C<guestfs_sfdisk>.  You should usually
2529 pass C<0> for the cyls/heads/sectors parameters.
2530
2531 See also: C<guestfs_part_add>");
2532
2533   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2534    [],
2535    "display the partition table",
2536    "\
2537 This displays the partition table on C<device>, in the
2538 human-readable output of the L<sfdisk(8)> command.  It is
2539 not intended to be parsed.
2540
2541 See also: C<guestfs_part_list>");
2542
2543   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2544    [],
2545    "display the kernel geometry",
2546    "\
2547 This displays the kernel's idea of the geometry of C<device>.
2548
2549 The result is in human-readable format, and not designed to
2550 be parsed.");
2551
2552   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2553    [],
2554    "display the disk geometry from the partition table",
2555    "\
2556 This displays the disk geometry of C<device> read from the
2557 partition table.  Especially in the case where the underlying
2558 block device has been resized, this can be different from the
2559 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2560
2561 The result is in human-readable format, and not designed to
2562 be parsed.");
2563
2564   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2565    [],
2566    "activate or deactivate all volume groups",
2567    "\
2568 This command activates or (if C<activate> is false) deactivates
2569 all logical volumes in all volume groups.
2570 If activated, then they are made known to the
2571 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2572 then those devices disappear.
2573
2574 This command is the same as running C<vgchange -a y|n>");
2575
2576   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2577    [],
2578    "activate or deactivate some volume groups",
2579    "\
2580 This command activates or (if C<activate> is false) deactivates
2581 all logical volumes in the listed volume groups C<volgroups>.
2582 If activated, then they are made known to the
2583 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2584 then those devices disappear.
2585
2586 This command is the same as running C<vgchange -a y|n volgroups...>
2587
2588 Note that if C<volgroups> is an empty list then B<all> volume groups
2589 are activated or deactivated.");
2590
2591   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2592    [InitNone, Always, TestOutput (
2593       [["part_disk"; "/dev/sda"; "mbr"];
2594        ["pvcreate"; "/dev/sda1"];
2595        ["vgcreate"; "VG"; "/dev/sda1"];
2596        ["lvcreate"; "LV"; "VG"; "10"];
2597        ["mkfs"; "ext2"; "/dev/VG/LV"];
2598        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2599        ["write_file"; "/new"; "test content"; "0"];
2600        ["umount"; "/"];
2601        ["lvresize"; "/dev/VG/LV"; "20"];
2602        ["e2fsck_f"; "/dev/VG/LV"];
2603        ["resize2fs"; "/dev/VG/LV"];
2604        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2605        ["cat"; "/new"]], "test content");
2606     InitNone, Always, TestRun (
2607       (* Make an LV smaller to test RHBZ#587484. *)
2608       [["part_disk"; "/dev/sda"; "mbr"];
2609        ["pvcreate"; "/dev/sda1"];
2610        ["vgcreate"; "VG"; "/dev/sda1"];
2611        ["lvcreate"; "LV"; "VG"; "20"];
2612        ["lvresize"; "/dev/VG/LV"; "10"]])],
2613    "resize an LVM logical volume",
2614    "\
2615 This resizes (expands or shrinks) an existing LVM logical
2616 volume to C<mbytes>.  When reducing, data in the reduced part
2617 is lost.");
2618
2619   ("resize2fs", (RErr, [Device "device"]), 106, [],
2620    [], (* lvresize tests this *)
2621    "resize an ext2/ext3 filesystem",
2622    "\
2623 This resizes an ext2 or ext3 filesystem to match the size of
2624 the underlying device.
2625
2626 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2627 on the C<device> before calling this command.  For unknown reasons
2628 C<resize2fs> sometimes gives an error about this and sometimes not.
2629 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2630 calling this function.");
2631
2632   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2633    [InitBasicFS, Always, TestOutputList (
2634       [["find"; "/"]], ["lost+found"]);
2635     InitBasicFS, Always, TestOutputList (
2636       [["touch"; "/a"];
2637        ["mkdir"; "/b"];
2638        ["touch"; "/b/c"];
2639        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2640     InitBasicFS, Always, TestOutputList (
2641       [["mkdir_p"; "/a/b/c"];
2642        ["touch"; "/a/b/c/d"];
2643        ["find"; "/a/b/"]], ["c"; "c/d"])],
2644    "find all files and directories",
2645    "\
2646 This command lists out all files and directories, recursively,
2647 starting at C<directory>.  It is essentially equivalent to
2648 running the shell command C<find directory -print> but some
2649 post-processing happens on the output, described below.
2650
2651 This returns a list of strings I<without any prefix>.  Thus
2652 if the directory structure was:
2653
2654  /tmp/a
2655  /tmp/b
2656  /tmp/c/d
2657
2658 then the returned list from C<guestfs_find> C</tmp> would be
2659 4 elements:
2660
2661  a
2662  b
2663  c
2664  c/d
2665
2666 If C<directory> is not a directory, then this command returns
2667 an error.
2668
2669 The returned list is sorted.
2670
2671 See also C<guestfs_find0>.");
2672
2673   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2674    [], (* lvresize tests this *)
2675    "check an ext2/ext3 filesystem",
2676    "\
2677 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2678 filesystem checker on C<device>, noninteractively (C<-p>),
2679 even if the filesystem appears to be clean (C<-f>).
2680
2681 This command is only needed because of C<guestfs_resize2fs>
2682 (q.v.).  Normally you should use C<guestfs_fsck>.");
2683
2684   ("sleep", (RErr, [Int "secs"]), 109, [],
2685    [InitNone, Always, TestRun (
2686       [["sleep"; "1"]])],
2687    "sleep for some seconds",
2688    "\
2689 Sleep for C<secs> seconds.");
2690
2691   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2692    [InitNone, Always, TestOutputInt (
2693       [["part_disk"; "/dev/sda"; "mbr"];
2694        ["mkfs"; "ntfs"; "/dev/sda1"];
2695        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2696     InitNone, Always, TestOutputInt (
2697       [["part_disk"; "/dev/sda"; "mbr"];
2698        ["mkfs"; "ext2"; "/dev/sda1"];
2699        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2700    "probe NTFS volume",
2701    "\
2702 This command runs the L<ntfs-3g.probe(8)> command which probes
2703 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2704 be mounted read-write, and some cannot be mounted at all).
2705
2706 C<rw> is a boolean flag.  Set it to true if you want to test
2707 if the volume can be mounted read-write.  Set it to false if
2708 you want to test if the volume can be mounted read-only.
2709
2710 The return value is an integer which C<0> if the operation
2711 would succeed, or some non-zero value documented in the
2712 L<ntfs-3g.probe(8)> manual page.");
2713
2714   ("sh", (RString "output", [String "command"]), 111, [],
2715    [], (* XXX needs tests *)
2716    "run a command via the shell",
2717    "\
2718 This call runs a command from the guest filesystem via the
2719 guest's C</bin/sh>.
2720
2721 This is like C<guestfs_command>, but passes the command to:
2722
2723  /bin/sh -c \"command\"
2724
2725 Depending on the guest's shell, this usually results in
2726 wildcards being expanded, shell expressions being interpolated
2727 and so on.
2728
2729 All the provisos about C<guestfs_command> apply to this call.");
2730
2731   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2732    [], (* XXX needs tests *)
2733    "run a command via the shell returning lines",
2734    "\
2735 This is the same as C<guestfs_sh>, but splits the result
2736 into a list of lines.
2737
2738 See also: C<guestfs_command_lines>");
2739
2740   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2741    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2742     * code in stubs.c, since all valid glob patterns must start with "/".
2743     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2744     *)
2745    [InitBasicFS, Always, TestOutputList (
2746       [["mkdir_p"; "/a/b/c"];
2747        ["touch"; "/a/b/c/d"];
2748        ["touch"; "/a/b/c/e"];
2749        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2750     InitBasicFS, Always, TestOutputList (
2751       [["mkdir_p"; "/a/b/c"];
2752        ["touch"; "/a/b/c/d"];
2753        ["touch"; "/a/b/c/e"];
2754        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2755     InitBasicFS, Always, TestOutputList (
2756       [["mkdir_p"; "/a/b/c"];
2757        ["touch"; "/a/b/c/d"];
2758        ["touch"; "/a/b/c/e"];
2759        ["glob_expand"; "/a/*/x/*"]], [])],
2760    "expand a wildcard path",
2761    "\
2762 This command searches for all the pathnames matching
2763 C<pattern> according to the wildcard expansion rules
2764 used by the shell.
2765
2766 If no paths match, then this returns an empty list
2767 (note: not an error).
2768
2769 It is just a wrapper around the C L<glob(3)> function
2770 with flags C<GLOB_MARK|GLOB_BRACE>.
2771 See that manual page for more details.");
2772
2773   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2774    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2775       [["scrub_device"; "/dev/sdc"]])],
2776    "scrub (securely wipe) a device",
2777    "\
2778 This command writes patterns over C<device> to make data retrieval
2779 more difficult.
2780
2781 It is an interface to the L<scrub(1)> program.  See that
2782 manual page for more details.");
2783
2784   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2785    [InitBasicFS, Always, TestRun (
2786       [["write_file"; "/file"; "content"; "0"];
2787        ["scrub_file"; "/file"]])],
2788    "scrub (securely wipe) a file",
2789    "\
2790 This command writes patterns over a file to make data retrieval
2791 more difficult.
2792
2793 The file is I<removed> after scrubbing.
2794
2795 It is an interface to the L<scrub(1)> program.  See that
2796 manual page for more details.");
2797
2798   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2799    [], (* XXX needs testing *)
2800    "scrub (securely wipe) free space",
2801    "\
2802 This command creates the directory C<dir> and then fills it
2803 with files until the filesystem is full, and scrubs the files
2804 as for C<guestfs_scrub_file>, and deletes them.
2805 The intention is to scrub any free space on the partition
2806 containing C<dir>.
2807
2808 It is an interface to the L<scrub(1)> program.  See that
2809 manual page for more details.");
2810
2811   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2812    [InitBasicFS, Always, TestRun (
2813       [["mkdir"; "/tmp"];
2814        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2815    "create a temporary directory",
2816    "\
2817 This command creates a temporary directory.  The
2818 C<template> parameter should be a full pathname for the
2819 temporary directory name with the final six characters being
2820 \"XXXXXX\".
2821
2822 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2823 the second one being suitable for Windows filesystems.
2824
2825 The name of the temporary directory that was created
2826 is returned.
2827
2828 The temporary directory is created with mode 0700
2829 and is owned by root.
2830
2831 The caller is responsible for deleting the temporary
2832 directory and its contents after use.
2833
2834 See also: L<mkdtemp(3)>");
2835
2836   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2837    [InitISOFS, Always, TestOutputInt (
2838       [["wc_l"; "/10klines"]], 10000)],
2839    "count lines in a file",
2840    "\
2841 This command counts the lines in a file, using the
2842 C<wc -l> external command.");
2843
2844   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2845    [InitISOFS, Always, TestOutputInt (
2846       [["wc_w"; "/10klines"]], 10000)],
2847    "count words in a file",
2848    "\
2849 This command counts the words in a file, using the
2850 C<wc -w> external command.");
2851
2852   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2853    [InitISOFS, Always, TestOutputInt (
2854       [["wc_c"; "/100kallspaces"]], 102400)],
2855    "count characters in a file",
2856    "\
2857 This command counts the characters in a file, using the
2858 C<wc -c> external command.");
2859
2860   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2861    [InitISOFS, Always, TestOutputList (
2862       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2863    "return first 10 lines of a file",
2864    "\
2865 This command returns up to the first 10 lines of a file as
2866 a list of strings.");
2867
2868   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2869    [InitISOFS, Always, TestOutputList (
2870       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2871     InitISOFS, Always, TestOutputList (
2872       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2873     InitISOFS, Always, TestOutputList (
2874       [["head_n"; "0"; "/10klines"]], [])],
2875    "return first N lines of a file",
2876    "\
2877 If the parameter C<nrlines> is a positive number, this returns the first
2878 C<nrlines> lines of the file C<path>.
2879
2880 If the parameter C<nrlines> is a negative number, this returns lines
2881 from the file C<path>, excluding the last C<nrlines> lines.
2882
2883 If the parameter C<nrlines> is zero, this returns an empty list.");
2884
2885   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2886    [InitISOFS, Always, TestOutputList (
2887       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2888    "return last 10 lines of a file",
2889    "\
2890 This command returns up to the last 10 lines of a file as
2891 a list of strings.");
2892
2893   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2894    [InitISOFS, Always, TestOutputList (
2895       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2896     InitISOFS, Always, TestOutputList (
2897       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2898     InitISOFS, Always, TestOutputList (
2899       [["tail_n"; "0"; "/10klines"]], [])],
2900    "return last N lines of a file",
2901    "\
2902 If the parameter C<nrlines> is a positive number, this returns the last
2903 C<nrlines> lines of the file C<path>.
2904
2905 If the parameter C<nrlines> is a negative number, this returns lines
2906 from the file C<path>, starting with the C<-nrlines>th line.
2907
2908 If the parameter C<nrlines> is zero, this returns an empty list.");
2909
2910   ("df", (RString "output", []), 125, [],
2911    [], (* XXX Tricky to test because it depends on the exact format
2912         * of the 'df' command and other imponderables.
2913         *)
2914    "report file system disk space usage",
2915    "\
2916 This command runs the C<df> command to report disk space used.
2917
2918 This command is mostly useful for interactive sessions.  It
2919 is I<not> intended that you try to parse the output string.
2920 Use C<statvfs> from programs.");
2921
2922   ("df_h", (RString "output", []), 126, [],
2923    [], (* XXX Tricky to test because it depends on the exact format
2924         * of the 'df' command and other imponderables.
2925         *)
2926    "report file system disk space usage (human readable)",
2927    "\
2928 This command runs the C<df -h> command to report disk space used
2929 in human-readable format.
2930
2931 This command is mostly useful for interactive sessions.  It
2932 is I<not> intended that you try to parse the output string.
2933 Use C<statvfs> from programs.");
2934
2935   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2936    [InitISOFS, Always, TestOutputInt (
2937       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2938    "estimate file space usage",
2939    "\
2940 This command runs the C<du -s> command to estimate file space
2941 usage for C<path>.
2942
2943 C<path> can be a file or a directory.  If C<path> is a directory
2944 then the estimate includes the contents of the directory and all
2945 subdirectories (recursively).
2946
2947 The result is the estimated size in I<kilobytes>
2948 (ie. units of 1024 bytes).");
2949
2950   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2951    [InitISOFS, Always, TestOutputList (
2952       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2953    "list files in an initrd",
2954    "\
2955 This command lists out files contained in an initrd.
2956
2957 The files are listed without any initial C</> character.  The
2958 files are listed in the order they appear (not necessarily
2959 alphabetical).  Directory names are listed as separate items.
2960
2961 Old Linux kernels (2.4 and earlier) used a compressed ext2
2962 filesystem as initrd.  We I<only> support the newer initramfs
2963 format (compressed cpio files).");
2964
2965   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2966    [],
2967    "mount a file using the loop device",
2968    "\
2969 This command lets you mount C<file> (a filesystem image
2970 in a file) on a mount point.  It is entirely equivalent to
2971 the command C<mount -o loop file mountpoint>.");
2972
2973   ("mkswap", (RErr, [Device "device"]), 130, [],
2974    [InitEmpty, Always, TestRun (
2975       [["part_disk"; "/dev/sda"; "mbr"];
2976        ["mkswap"; "/dev/sda1"]])],
2977    "create a swap partition",
2978    "\
2979 Create a swap partition on C<device>.");
2980
2981   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2982    [InitEmpty, Always, TestRun (
2983       [["part_disk"; "/dev/sda"; "mbr"];
2984        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2985    "create a swap partition with a label",
2986    "\
2987 Create a swap partition on C<device> with label C<label>.
2988
2989 Note that you cannot attach a swap label to a block device
2990 (eg. C</dev/sda>), just to a partition.  This appears to be
2991 a limitation of the kernel or swap tools.");
2992
2993   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2994    (let uuid = uuidgen () in
2995     [InitEmpty, Always, TestRun (
2996        [["part_disk"; "/dev/sda"; "mbr"];
2997         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2998    "create a swap partition with an explicit UUID",
2999    "\
3000 Create a swap partition on C<device> with UUID C<uuid>.");
3001
3002   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3003    [InitBasicFS, Always, TestOutputStruct (
3004       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3005        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3006        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3007     InitBasicFS, Always, TestOutputStruct (
3008       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3009        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3010    "make block, character or FIFO devices",
3011    "\
3012 This call creates block or character special devices, or
3013 named pipes (FIFOs).
3014
3015 The C<mode> parameter should be the mode, using the standard
3016 constants.  C<devmajor> and C<devminor> are the
3017 device major and minor numbers, only used when creating block
3018 and character special devices.
3019
3020 Note that, just like L<mknod(2)>, the mode must be bitwise
3021 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3022 just creates a regular file).  These constants are
3023 available in the standard Linux header files, or you can use
3024 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3025 which are wrappers around this command which bitwise OR
3026 in the appropriate constant for you.
3027
3028 The mode actually set is affected by the umask.");
3029
3030   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3031    [InitBasicFS, Always, TestOutputStruct (
3032       [["mkfifo"; "0o777"; "/node"];
3033        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3034    "make FIFO (named pipe)",
3035    "\
3036 This call creates a FIFO (named pipe) called C<path> with
3037 mode C<mode>.  It is just a convenient wrapper around
3038 C<guestfs_mknod>.
3039
3040 The mode actually set is affected by the umask.");
3041
3042   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3043    [InitBasicFS, Always, TestOutputStruct (
3044       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3045        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3046    "make block device node",
3047    "\
3048 This call creates a block device node called C<path> with
3049 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3050 It is just a convenient wrapper around C<guestfs_mknod>.
3051
3052 The mode actually set is affected by the umask.");
3053
3054   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3055    [InitBasicFS, Always, TestOutputStruct (
3056       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3057        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3058    "make char device node",
3059    "\
3060 This call creates a char device node called C<path> with
3061 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3062 It is just a convenient wrapper around C<guestfs_mknod>.
3063
3064 The mode actually set is affected by the umask.");
3065
3066   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3067    [InitEmpty, Always, TestOutputInt (
3068       [["umask"; "0o22"]], 0o22)],
3069    "set file mode creation mask (umask)",
3070    "\
3071 This function sets the mask used for creating new files and
3072 device nodes to C<mask & 0777>.
3073
3074 Typical umask values would be C<022> which creates new files
3075 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3076 C<002> which creates new files with permissions like
3077 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3078
3079 The default umask is C<022>.  This is important because it
3080 means that directories and device nodes will be created with
3081 C<0644> or C<0755> mode even if you specify C<0777>.
3082
3083 See also C<guestfs_get_umask>,
3084 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3085
3086 This call returns the previous umask.");
3087
3088   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3089    [],
3090    "read directories entries",
3091    "\
3092 This returns the list of directory entries in directory C<dir>.
3093
3094 All entries in the directory are returned, including C<.> and
3095 C<..>.  The entries are I<not> sorted, but returned in the same
3096 order as the underlying filesystem.
3097
3098 Also this call returns basic file type information about each
3099 file.  The C<ftyp> field will contain one of the following characters:
3100
3101 =over 4
3102
3103 =item 'b'
3104
3105 Block special
3106
3107 =item 'c'
3108
3109 Char special
3110
3111 =item 'd'
3112
3113 Directory
3114
3115 =item 'f'
3116
3117 FIFO (named pipe)
3118
3119 =item 'l'
3120
3121 Symbolic link
3122
3123 =item 'r'
3124
3125 Regular file
3126
3127 =item 's'
3128
3129 Socket
3130
3131 =item 'u'
3132
3133 Unknown file type
3134
3135 =item '?'
3136
3137 The L<readdir(3)> returned a C<d_type> field with an
3138 unexpected value
3139
3140 =back
3141
3142 This function is primarily intended for use by programs.  To
3143 get a simple list of names, use C<guestfs_ls>.  To get a printable
3144 directory for human consumption, use C<guestfs_ll>.");
3145
3146   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3147    [],
3148    "create partitions on a block device",
3149    "\
3150 This is a simplified interface to the C<guestfs_sfdisk>
3151 command, where partition sizes are specified in megabytes
3152 only (rounded to the nearest cylinder) and you don't need
3153 to specify the cyls, heads and sectors parameters which
3154 were rarely if ever used anyway.
3155
3156 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3157 and C<guestfs_part_disk>");
3158
3159   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3160    [],
3161    "determine file type inside a compressed file",
3162    "\
3163 This command runs C<file> after first decompressing C<path>
3164 using C<method>.
3165
3166 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3167
3168 Since 1.0.63, use C<guestfs_file> instead which can now
3169 process compressed files.");
3170
3171   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3172    [],
3173    "list extended attributes of a file or directory",
3174    "\
3175 This call lists the extended attributes of the file or directory
3176 C<path>.
3177
3178 At the system call level, this is a combination of the
3179 L<listxattr(2)> and L<getxattr(2)> calls.
3180
3181 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3182
3183   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3184    [],
3185    "list extended attributes of a file or directory",
3186    "\
3187 This is the same as C<guestfs_getxattrs>, but if C<path>
3188 is a symbolic link, then it returns the extended attributes
3189 of the link itself.");
3190
3191   ("setxattr", (RErr, [String "xattr";
3192                        String "val"; Int "vallen"; (* will be BufferIn *)
3193                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3194    [],
3195    "set extended attribute of a file or directory",
3196    "\
3197 This call sets the extended attribute named C<xattr>
3198 of the file C<path> to the value C<val> (of length C<vallen>).
3199 The value is arbitrary 8 bit data.
3200
3201 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3202
3203   ("lsetxattr", (RErr, [String "xattr";
3204                         String "val"; Int "vallen"; (* will be BufferIn *)
3205                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3206    [],
3207    "set extended attribute of a file or directory",
3208    "\
3209 This is the same as C<guestfs_setxattr>, but if C<path>
3210 is a symbolic link, then it sets an extended attribute
3211 of the link itself.");
3212
3213   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3214    [],
3215    "remove extended attribute of a file or directory",
3216    "\
3217 This call removes the extended attribute named C<xattr>
3218 of the file C<path>.
3219
3220 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3221
3222   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3223    [],
3224    "remove extended attribute of a file or directory",
3225    "\
3226 This is the same as C<guestfs_removexattr>, but if C<path>
3227 is a symbolic link, then it removes an extended attribute
3228 of the link itself.");
3229
3230   ("mountpoints", (RHashtable "mps", []), 147, [],
3231    [],
3232    "show mountpoints",
3233    "\
3234 This call is similar to C<guestfs_mounts>.  That call returns
3235 a list of devices.  This one returns a hash table (map) of
3236 device name to directory where the device is mounted.");
3237
3238   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3239    (* This is a special case: while you would expect a parameter
3240     * of type "Pathname", that doesn't work, because it implies
3241     * NEED_ROOT in the generated calling code in stubs.c, and
3242     * this function cannot use NEED_ROOT.
3243     *)
3244    [],
3245    "create a mountpoint",
3246    "\
3247 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3248 specialized calls that can be used to create extra mountpoints
3249 before mounting the first filesystem.
3250
3251 These calls are I<only> necessary in some very limited circumstances,
3252 mainly the case where you want to mount a mix of unrelated and/or
3253 read-only filesystems together.
3254
3255 For example, live CDs often contain a \"Russian doll\" nest of
3256 filesystems, an ISO outer layer, with a squashfs image inside, with
3257 an ext2/3 image inside that.  You can unpack this as follows
3258 in guestfish:
3259
3260  add-ro Fedora-11-i686-Live.iso
3261  run
3262  mkmountpoint /cd
3263  mkmountpoint /squash
3264  mkmountpoint /ext3
3265  mount /dev/sda /cd
3266  mount-loop /cd/LiveOS/squashfs.img /squash
3267  mount-loop /squash/LiveOS/ext3fs.img /ext3
3268
3269 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3270
3271   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3272    [],
3273    "remove a mountpoint",
3274    "\
3275 This calls removes a mountpoint that was previously created
3276 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3277 for full details.");
3278
3279   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3280    [InitISOFS, Always, TestOutputBuffer (
3281       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3282    "read a file",
3283    "\
3284 This calls returns the contents of the file C<path> as a
3285 buffer.
3286
3287 Unlike C<guestfs_cat>, this function can correctly
3288 handle files that contain embedded ASCII NUL characters.
3289 However unlike C<guestfs_download>, this function is limited
3290 in the total size of file that can be handled.");
3291
3292   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3293    [InitISOFS, Always, TestOutputList (
3294       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3295     InitISOFS, Always, TestOutputList (
3296       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3297     (* Test for RHBZ#579608, absolute symbolic links. *)
3298     InitISOFS, Always, TestOutputList (
3299       [["grep"; "nomatch"; "/abssymlink"]], [])],
3300    "return lines matching a pattern",
3301    "\
3302 This calls the external C<grep> program and returns the
3303 matching lines.");
3304
3305   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3306    [InitISOFS, Always, TestOutputList (
3307       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3308    "return lines matching a pattern",
3309    "\
3310 This calls the external C<egrep> program and returns the
3311 matching lines.");
3312
3313   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3314    [InitISOFS, Always, TestOutputList (
3315       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3316    "return lines matching a pattern",
3317    "\
3318 This calls the external C<fgrep> program and returns the
3319 matching lines.");
3320
3321   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3322    [InitISOFS, Always, TestOutputList (
3323       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3324    "return lines matching a pattern",
3325    "\
3326 This calls the external C<grep -i> program and returns the
3327 matching lines.");
3328
3329   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3330    [InitISOFS, Always, TestOutputList (
3331       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3332    "return lines matching a pattern",
3333    "\
3334 This calls the external C<egrep -i> program and returns the
3335 matching lines.");
3336
3337   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3338    [InitISOFS, Always, TestOutputList (
3339       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3340    "return lines matching a pattern",
3341    "\
3342 This calls the external C<fgrep -i> program and returns the
3343 matching lines.");
3344
3345   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3346    [InitISOFS, Always, TestOutputList (
3347       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3348    "return lines matching a pattern",
3349    "\
3350 This calls the external C<zgrep> program and returns the
3351 matching lines.");
3352
3353   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3354    [InitISOFS, Always, TestOutputList (
3355       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3356    "return lines matching a pattern",
3357    "\
3358 This calls the external C<zegrep> program and returns the
3359 matching lines.");
3360
3361   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3362    [InitISOFS, Always, TestOutputList (
3363       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3364    "return lines matching a pattern",
3365    "\
3366 This calls the external C<zfgrep> program and returns the
3367 matching lines.");
3368
3369   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3370    [InitISOFS, Always, TestOutputList (
3371       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3372    "return lines matching a pattern",
3373    "\
3374 This calls the external C<zgrep -i> program and returns the
3375 matching lines.");
3376
3377   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3378    [InitISOFS, Always, TestOutputList (
3379       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3380    "return lines matching a pattern",
3381    "\
3382 This calls the external C<zegrep -i> program and returns the
3383 matching lines.");
3384
3385   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3386    [InitISOFS, Always, TestOutputList (
3387       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3388    "return lines matching a pattern",
3389    "\
3390 This calls the external C<zfgrep -i> program and returns the
3391 matching lines.");
3392
3393   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3394    [InitISOFS, Always, TestOutput (
3395       [["realpath"; "/../directory"]], "/directory")],
3396    "canonicalized absolute pathname",
3397    "\
3398 Return the canonicalized absolute pathname of C<path>.  The
3399 returned path has no C<.>, C<..> or symbolic link path elements.");
3400
3401   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3402    [InitBasicFS, Always, TestOutputStruct (
3403       [["touch"; "/a"];
3404        ["ln"; "/a"; "/b"];
3405        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3406    "create a hard link",
3407    "\
3408 This command creates a hard link using the C<ln> command.");
3409
3410   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3411    [InitBasicFS, Always, TestOutputStruct (
3412       [["touch"; "/a"];
3413        ["touch"; "/b"];
3414        ["ln_f"; "/a"; "/b"];
3415        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3416    "create a hard link",
3417    "\
3418 This command creates a hard link using the C<ln -f> command.
3419 The C<-f> option removes the link (C<linkname>) if it exists already.");
3420
3421   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3422    [InitBasicFS, Always, TestOutputStruct (
3423       [["touch"; "/a"];
3424        ["ln_s"; "a"; "/b"];
3425        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3426    "create a symbolic link",
3427    "\
3428 This command creates a symbolic link using the C<ln -s> command.");
3429
3430   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3431    [InitBasicFS, Always, TestOutput (
3432       [["mkdir_p"; "/a/b"];
3433        ["touch"; "/a/b/c"];
3434        ["ln_sf"; "../d"; "/a/b/c"];
3435        ["readlink"; "/a/b/c"]], "../d")],
3436    "create a symbolic link",
3437    "\
3438 This command creates a symbolic link using the C<ln -sf> command,
3439 The C<-f> option removes the link (C<linkname>) if it exists already.");
3440
3441   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3442    [] (* XXX tested above *),
3443    "read the target of a symbolic link",
3444    "\
3445 This command reads the target of a symbolic link.");
3446
3447   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3448    [InitBasicFS, Always, TestOutputStruct (
3449       [["fallocate"; "/a"; "1000000"];
3450        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3451    "preallocate a file in the guest filesystem",
3452    "\
3453 This command preallocates a file (containing zero bytes) named
3454 C<path> of size C<len> bytes.  If the file exists already, it
3455 is overwritten.
3456
3457 Do not confuse this with the guestfish-specific
3458 C<alloc> command which allocates a file in the host and
3459 attaches it as a device.");
3460
3461   ("swapon_device", (RErr, [Device "device"]), 170, [],
3462    [InitPartition, Always, TestRun (
3463       [["mkswap"; "/dev/sda1"];
3464        ["swapon_device"; "/dev/sda1"];
3465        ["swapoff_device"; "/dev/sda1"]])],
3466    "enable swap on device",
3467    "\
3468 This command enables the libguestfs appliance to use the
3469 swap device or partition named C<device>.  The increased
3470 memory is made available for all commands, for example
3471 those run using C<guestfs_command> or C<guestfs_sh>.
3472
3473 Note that you should not swap to existing guest swap
3474 partitions unless you know what you are doing.  They may
3475 contain hibernation information, or other information that
3476 the guest doesn't want you to trash.  You also risk leaking
3477 information about the host to the guest this way.  Instead,
3478 attach a new host device to the guest and swap on that.");
3479
3480   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3481    [], (* XXX tested by swapon_device *)
3482    "disable swap on device",
3483    "\
3484 This command disables the libguestfs appliance swap
3485 device or partition named C<device>.
3486 See C<guestfs_swapon_device>.");
3487
3488   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3489    [InitBasicFS, Always, TestRun (
3490       [["fallocate"; "/swap"; "8388608"];
3491        ["mkswap_file"; "/swap"];
3492        ["swapon_file"; "/swap"];
3493        ["swapoff_file"; "/swap"]])],
3494    "enable swap on file",
3495    "\
3496 This command enables swap to a file.
3497 See C<guestfs_swapon_device> for other notes.");
3498
3499   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3500    [], (* XXX tested by swapon_file *)
3501    "disable swap on file",
3502    "\
3503 This command disables the libguestfs appliance swap on file.");
3504
3505   ("swapon_label", (RErr, [String "label"]), 174, [],
3506    [InitEmpty, Always, TestRun (
3507       [["part_disk"; "/dev/sdb"; "mbr"];
3508        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3509        ["swapon_label"; "swapit"];
3510        ["swapoff_label"; "swapit"];
3511        ["zero"; "/dev/sdb"];
3512        ["blockdev_rereadpt"; "/dev/sdb"]])],
3513    "enable swap on labeled swap partition",
3514    "\
3515 This command enables swap to a labeled swap partition.
3516 See C<guestfs_swapon_device> for other notes.");
3517
3518   ("swapoff_label", (RErr, [String "label"]), 175, [],
3519    [], (* XXX tested by swapon_label *)
3520    "disable swap on labeled swap partition",
3521    "\
3522 This command disables the libguestfs appliance swap on
3523 labeled swap partition.");
3524
3525   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3526    (let uuid = uuidgen () in
3527     [InitEmpty, Always, TestRun (
3528        [["mkswap_U"; uuid; "/dev/sdb"];
3529         ["swapon_uuid"; uuid];
3530         ["swapoff_uuid"; uuid]])]),
3531    "enable swap on swap partition by UUID",
3532    "\
3533 This command enables swap to a swap partition with the given UUID.
3534 See C<guestfs_swapon_device> for other notes.");
3535
3536   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3537    [], (* XXX tested by swapon_uuid *)
3538    "disable swap on swap partition by UUID",
3539    "\
3540 This command disables the libguestfs appliance swap partition
3541 with the given UUID.");
3542
3543   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3544    [InitBasicFS, Always, TestRun (
3545       [["fallocate"; "/swap"; "8388608"];
3546        ["mkswap_file"; "/swap"]])],
3547    "create a swap file",
3548    "\
3549 Create a swap file.
3550
3551 This command just writes a swap file signature to an existing
3552 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3553
3554   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3555    [InitISOFS, Always, TestRun (
3556       [["inotify_init"; "0"]])],
3557    "create an inotify handle",
3558    "\
3559 This command creates a new inotify handle.
3560 The inotify subsystem can be used to notify events which happen to
3561 objects in the guest filesystem.
3562
3563 C<maxevents> is the maximum number of events which will be
3564 queued up between calls to C<guestfs_inotify_read> or
3565 C<guestfs_inotify_files>.
3566 If this is passed as C<0>, then the kernel (or previously set)
3567 default is used.  For Linux 2.6.29 the default was 16384 events.
3568 Beyond this limit, the kernel throws away events, but records
3569 the fact that it threw them away by setting a flag
3570 C<IN_Q_OVERFLOW> in the returned structure list (see
3571 C<guestfs_inotify_read>).
3572
3573 Before any events are generated, you have to add some
3574 watches to the internal watch list.  See:
3575 C<guestfs_inotify_add_watch>,
3576 C<guestfs_inotify_rm_watch> and
3577 C<guestfs_inotify_watch_all>.
3578
3579 Queued up events should be read periodically by calling
3580 C<guestfs_inotify_read>
3581 (or C<guestfs_inotify_files> which is just a helpful
3582 wrapper around C<guestfs_inotify_read>).  If you don't
3583 read the events out often enough then you risk the internal
3584 queue overflowing.
3585
3586 The handle should be closed after use by calling
3587 C<guestfs_inotify_close>.  This also removes any
3588 watches automatically.
3589
3590 See also L<inotify(7)> for an overview of the inotify interface
3591 as exposed by the Linux kernel, which is roughly what we expose
3592 via libguestfs.  Note that there is one global inotify handle
3593 per libguestfs instance.");
3594
3595   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3596    [InitBasicFS, Always, TestOutputList (
3597       [["inotify_init"; "0"];
3598        ["inotify_add_watch"; "/"; "1073741823"];
3599        ["touch"; "/a"];
3600        ["touch"; "/b"];
3601        ["inotify_files"]], ["a"; "b"])],
3602    "add an inotify watch",
3603    "\
3604 Watch C<path> for the events listed in C<mask>.
3605
3606 Note that if C<path> is a directory then events within that
3607 directory are watched, but this does I<not> happen recursively
3608 (in subdirectories).
3609
3610 Note for non-C or non-Linux callers: the inotify events are
3611 defined by the Linux kernel ABI and are listed in
3612 C</usr/include/sys/inotify.h>.");
3613
3614   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3615    [],
3616    "remove an inotify watch",
3617    "\
3618 Remove a previously defined inotify watch.
3619 See C<guestfs_inotify_add_watch>.");
3620
3621   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3622    [],
3623    "return list of inotify events",
3624    "\
3625 Return the complete queue of events that have happened
3626 since the previous read call.
3627
3628 If no events have happened, this returns an empty list.
3629
3630 I<Note>: In order to make sure that all events have been
3631 read, you must call this function repeatedly until it
3632 returns an empty list.  The reason is that the call will
3633 read events up to the maximum appliance-to-host message
3634 size and leave remaining events in the queue.");
3635
3636   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3637    [],
3638    "return list of watched files that had events",
3639    "\
3640 This function is a helpful wrapper around C<guestfs_inotify_read>
3641 which just returns a list of pathnames of objects that were
3642 touched.  The returned pathnames are sorted and deduplicated.");
3643
3644   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3645    [],
3646    "close the inotify handle",
3647    "\
3648 This closes the inotify handle which was previously
3649 opened by inotify_init.  It removes all watches, throws
3650 away any pending events, and deallocates all resources.");
3651
3652   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3653    [],
3654    "set SELinux security context",
3655    "\
3656 This sets the SELinux security context of the daemon
3657 to the string C<context>.
3658
3659 See the documentation about SELINUX in L<guestfs(3)>.");
3660
3661   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3662    [],
3663    "get SELinux security context",
3664    "\
3665 This gets the SELinux security context of the daemon.
3666
3667 See the documentation about SELINUX in L<guestfs(3)>,
3668 and C<guestfs_setcon>");
3669
3670   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3671    [InitEmpty, Always, TestOutput (
3672       [["part_disk"; "/dev/sda"; "mbr"];
3673        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3674        ["mount_options"; ""; "/dev/sda1"; "/"];
3675        ["write_file"; "/new"; "new file contents"; "0"];
3676        ["cat"; "/new"]], "new file contents")],
3677    "make a filesystem with block size",
3678    "\
3679 This call is similar to C<guestfs_mkfs>, but it allows you to
3680 control the block size of the resulting filesystem.  Supported
3681 block sizes depend on the filesystem type, but typically they
3682 are C<1024>, C<2048> or C<4096> only.");
3683
3684   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3685    [InitEmpty, Always, TestOutput (
3686       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3687        ["mke2journal"; "4096"; "/dev/sda1"];
3688        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3689        ["mount_options"; ""; "/dev/sda2"; "/"];
3690        ["write_file"; "/new"; "new file contents"; "0"];
3691        ["cat"; "/new"]], "new file contents")],
3692    "make ext2/3/4 external journal",
3693    "\
3694 This creates an ext2 external journal on C<device>.  It is equivalent
3695 to the command:
3696
3697  mke2fs -O journal_dev -b blocksize device");
3698
3699   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3700    [InitEmpty, Always, TestOutput (
3701       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3702        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3703        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3704        ["mount_options"; ""; "/dev/sda2"; "/"];
3705        ["write_file"; "/new"; "new file contents"; "0"];
3706        ["cat"; "/new"]], "new file contents")],
3707    "make ext2/3/4 external journal with label",
3708    "\
3709 This creates an ext2 external journal on C<device> with label C<label>.");
3710
3711   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3712    (let uuid = uuidgen () in
3713     [InitEmpty, Always, TestOutput (
3714        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3715         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3716         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3717         ["mount_options"; ""; "/dev/sda2"; "/"];
3718         ["write_file"; "/new"; "new file contents"; "0"];
3719         ["cat"; "/new"]], "new file contents")]),
3720    "make ext2/3/4 external journal with UUID",
3721    "\
3722 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3723
3724   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3725    [],
3726    "make ext2/3/4 filesystem with external journal",
3727    "\
3728 This creates an ext2/3/4 filesystem on C<device> with
3729 an external journal on C<journal>.  It is equivalent
3730 to the command:
3731
3732  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3733
3734 See also C<guestfs_mke2journal>.");
3735
3736   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3737    [],
3738    "make ext2/3/4 filesystem with external journal",
3739    "\
3740 This creates an ext2/3/4 filesystem on C<device> with
3741 an external journal on the journal labeled C<label>.
3742
3743 See also C<guestfs_mke2journal_L>.");
3744
3745   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3746    [],
3747    "make ext2/3/4 filesystem with external journal",
3748    "\
3749 This creates an ext2/3/4 filesystem on C<device> with
3750 an external journal on the journal with UUID C<uuid>.
3751
3752 See also C<guestfs_mke2journal_U>.");
3753
3754   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3755    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3756    "load a kernel module",
3757    "\
3758 This loads a kernel module in the appliance.
3759
3760 The kernel module must have been whitelisted when libguestfs
3761 was built (see C<appliance/kmod.whitelist.in> in the source).");
3762
3763   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3764    [InitNone, Always, TestOutput (
3765       [["echo_daemon"; "This is a test"]], "This is a test"
3766     )],
3767    "echo arguments back to the client",
3768    "\
3769 This command concatenate the list of C<words> passed with single spaces between
3770 them and returns the resulting string.
3771
3772 You can use this command to test the connection through to the daemon.
3773
3774 See also C<guestfs_ping_daemon>.");
3775
3776   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3777    [], (* There is a regression test for this. *)
3778    "find all files and directories, returning NUL-separated list",
3779    "\
3780 This command lists out all files and directories, recursively,
3781 starting at C<directory>, placing the resulting list in the
3782 external file called C<files>.
3783
3784 This command works the same way as C<guestfs_find> with the
3785 following exceptions:
3786
3787 =over 4
3788
3789 =item *
3790
3791 The resulting list is written to an external file.
3792
3793 =item *
3794
3795 Items (filenames) in the result are separated
3796 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3797
3798 =item *
3799
3800 This command is not limited in the number of names that it
3801 can return.
3802
3803 =item *
3804
3805 The result list is not sorted.
3806
3807 =back");
3808
3809   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3810    [InitISOFS, Always, TestOutput (
3811       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3812     InitISOFS, Always, TestOutput (
3813       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3814     InitISOFS, Always, TestOutput (
3815       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3816     InitISOFS, Always, TestLastFail (
3817       [["case_sensitive_path"; "/Known-1/"]]);
3818     InitBasicFS, Always, TestOutput (
3819       [["mkdir"; "/a"];
3820        ["mkdir"; "/a/bbb"];
3821        ["touch"; "/a/bbb/c"];
3822        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3823     InitBasicFS, Always, TestOutput (
3824       [["mkdir"; "/a"];
3825        ["mkdir"; "/a/bbb"];
3826        ["touch"; "/a/bbb/c"];
3827        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3828     InitBasicFS, Always, TestLastFail (
3829       [["mkdir"; "/a"];
3830        ["mkdir"; "/a/bbb"];
3831        ["touch"; "/a/bbb/c"];
3832        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3833    "return true path on case-insensitive filesystem",
3834    "\
3835 This can be used to resolve case insensitive paths on
3836 a filesystem which is case sensitive.  The use case is
3837 to resolve paths which you have read from Windows configuration
3838 files or the Windows Registry, to the true path.
3839
3840 The command handles a peculiarity of the Linux ntfs-3g
3841 filesystem driver (and probably others), which is that although
3842 the underlying filesystem is case-insensitive, the driver
3843 exports the filesystem to Linux as case-sensitive.
3844
3845 One consequence of this is that special directories such
3846 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3847 (or other things) depending on the precise details of how
3848 they were created.  In Windows itself this would not be
3849 a problem.
3850
3851 Bug or feature?  You decide:
3852 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3853
3854 This function resolves the true case of each element in the
3855 path and returns the case-sensitive path.
3856
3857 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3858 might return C<\"/WINDOWS/system32\"> (the exact return value
3859 would depend on details of how the directories were originally
3860 created under Windows).
3861
3862 I<Note>:
3863 This function does not handle drive names, backslashes etc.
3864
3865 See also C<guestfs_realpath>.");
3866
3867   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3868    [InitBasicFS, Always, TestOutput (
3869       [["vfs_type"; "/dev/sda1"]], "ext2")],
3870    "get the Linux VFS type corresponding to a mounted device",
3871    "\
3872 This command gets the block device type corresponding to
3873 a mounted device called C<device>.
3874
3875 Usually the result is the name of the Linux VFS module that
3876 is used to mount this device (probably determined automatically
3877 if you used the C<guestfs_mount> call).");
3878
3879   ("truncate", (RErr, [Pathname "path"]), 199, [],
3880    [InitBasicFS, Always, TestOutputStruct (
3881       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3882        ["truncate"; "/test"];
3883        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3884    "truncate a file to zero size",
3885    "\
3886 This command truncates C<path> to a zero-length file.  The
3887 file must exist already.");
3888
3889   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3890    [InitBasicFS, Always, TestOutputStruct (
3891       [["touch"; "/test"];
3892        ["truncate_size"; "/test"; "1000"];
3893        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3894    "truncate a file to a particular size",
3895    "\
3896 This command truncates C<path> to size C<size> bytes.  The file
3897 must exist already.  If the file is smaller than C<size> then
3898 the file is extended to the required size with null bytes.");
3899
3900   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3901    [InitBasicFS, Always, TestOutputStruct (
3902       [["touch"; "/test"];
3903        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3904        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3905    "set timestamp of a file with nanosecond precision",
3906    "\
3907 This command sets the timestamps of a file with nanosecond
3908 precision.
3909
3910 C<atsecs, atnsecs> are the last access time (atime) in secs and
3911 nanoseconds from the epoch.
3912
3913 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3914 secs and nanoseconds from the epoch.
3915
3916 If the C<*nsecs> field contains the special value C<-1> then
3917 the corresponding timestamp is set to the current time.  (The
3918 C<*secs> field is ignored in this case).
3919
3920 If the C<*nsecs> field contains the special value C<-2> then
3921 the corresponding timestamp is left unchanged.  (The
3922 C<*secs> field is ignored in this case).");
3923
3924   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3925    [InitBasicFS, Always, TestOutputStruct (
3926       [["mkdir_mode"; "/test"; "0o111"];
3927        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3928    "create a directory with a particular mode",
3929    "\
3930 This command creates a directory, setting the initial permissions
3931 of the directory to C<mode>.
3932
3933 For common Linux filesystems, the actual mode which is set will
3934 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3935 interpret the mode in other ways.
3936
3937 See also C<guestfs_mkdir>, C<guestfs_umask>");
3938
3939   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3940    [], (* XXX *)
3941    "change file owner and group",
3942    "\
3943 Change the file owner to C<owner> and group to C<group>.
3944 This is like C<guestfs_chown> but if C<path> is a symlink then
3945 the link itself is changed, not the target.
3946
3947 Only numeric uid and gid are supported.  If you want to use
3948 names, you will need to locate and parse the password file
3949 yourself (Augeas support makes this relatively easy).");
3950
3951   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3952    [], (* XXX *)
3953    "lstat on multiple files",
3954    "\
3955 This call allows you to perform the C<guestfs_lstat> operation
3956 on multiple files, where all files are in the directory C<path>.
3957 C<names> is the list of files from this directory.
3958
3959 On return you get a list of stat structs, with a one-to-one
3960 correspondence to the C<names> list.  If any name did not exist
3961 or could not be lstat'd, then the C<ino> field of that structure
3962 is set to C<-1>.
3963
3964 This call is intended for programs that want to efficiently
3965 list a directory contents without making many round-trips.
3966 See also C<guestfs_lxattrlist> for a similarly efficient call
3967 for getting extended attributes.  Very long directory listings
3968 might cause the protocol message size to be exceeded, causing
3969 this call to fail.  The caller must split up such requests
3970 into smaller groups of names.");
3971
3972   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3973    [], (* XXX *)
3974    "lgetxattr on multiple files",
3975    "\
3976 This call allows you to get the extended attributes
3977 of multiple files, where all files are in the directory C<path>.
3978 C<names> is the list of files from this directory.
3979
3980 On return you get a flat list of xattr structs which must be
3981 interpreted sequentially.  The first xattr struct always has a zero-length
3982 C<attrname>.  C<attrval> in this struct is zero-length
3983 to indicate there was an error doing C<lgetxattr> for this
3984 file, I<or> is a C string which is a decimal number
3985 (the number of following attributes for this file, which could
3986 be C<\"0\">).  Then after the first xattr struct are the
3987 zero or more attributes for the first named file.
3988 This repeats for the second and subsequent files.
3989
3990 This call is intended for programs that want to efficiently
3991 list a directory contents without making many round-trips.
3992 See also C<guestfs_lstatlist> for a similarly efficient call
3993 for getting standard stats.  Very long directory listings
3994 might cause the protocol message size to be exceeded, causing
3995 this call to fail.  The caller must split up such requests
3996 into smaller groups of names.");
3997
3998   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3999    [], (* XXX *)
4000    "readlink on multiple files",
4001    "\
4002 This call allows you to do a C<readlink> operation
4003 on multiple files, where all files are in the directory C<path>.
4004 C<names> is the list of files from this directory.
4005
4006 On return you get a list of strings, with a one-to-one
4007 correspondence to the C<names> list.  Each string is the
4008 value of the symbol link.
4009
4010 If the C<readlink(2)> operation fails on any name, then
4011 the corresponding result string is the empty string C<\"\">.
4012 However the whole operation is completed even if there
4013 were C<readlink(2)> errors, and so you can call this
4014 function with names where you don't know if they are
4015 symbolic links already (albeit slightly less efficient).
4016
4017 This call is intended for programs that want to efficiently
4018 list a directory contents without making many round-trips.
4019 Very long directory listings might cause the protocol
4020 message size to be exceeded, causing
4021 this call to fail.  The caller must split up such requests
4022 into smaller groups of names.");
4023
4024   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4025    [InitISOFS, Always, TestOutputBuffer (
4026       [["pread"; "/known-4"; "1"; "3"]], "\n");
4027     InitISOFS, Always, TestOutputBuffer (
4028       [["pread"; "/empty"; "0"; "100"]], "")],
4029    "read part of a file",
4030    "\
4031 This command lets you read part of a file.  It reads C<count>
4032 bytes of the file, starting at C<offset>, from file C<path>.
4033
4034 This may read fewer bytes than requested.  For further details
4035 see the L<pread(2)> system call.");
4036
4037   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4038    [InitEmpty, Always, TestRun (
4039       [["part_init"; "/dev/sda"; "gpt"]])],
4040    "create an empty partition table",
4041    "\
4042 This creates an empty partition table on C<device> of one of the
4043 partition types listed below.  Usually C<parttype> should be
4044 either C<msdos> or C<gpt> (for large disks).
4045
4046 Initially there are no partitions.  Following this, you should
4047 call C<guestfs_part_add> for each partition required.
4048
4049 Possible values for C<parttype> are:
4050
4051 =over 4
4052
4053 =item B<efi> | B<gpt>
4054
4055 Intel EFI / GPT partition table.
4056
4057 This is recommended for >= 2 TB partitions that will be accessed
4058 from Linux and Intel-based Mac OS X.  It also has limited backwards
4059 compatibility with the C<mbr> format.
4060
4061 =item B<mbr> | B<msdos>
4062
4063 The standard PC \"Master Boot Record\" (MBR) format used
4064 by MS-DOS and Windows.  This partition type will B<only> work
4065 for device sizes up to 2 TB.  For large disks we recommend
4066 using C<gpt>.
4067
4068 =back
4069
4070 Other partition table types that may work but are not
4071 supported include:
4072
4073 =over 4
4074
4075 =item B<aix>
4076
4077 AIX disk labels.
4078
4079 =item B<amiga> | B<rdb>
4080
4081 Amiga \"Rigid Disk Block\" format.
4082
4083 =item B<bsd>
4084
4085 BSD disk labels.
4086
4087 =item B<dasd>
4088
4089 DASD, used on IBM mainframes.
4090
4091 =item B<dvh>
4092
4093 MIPS/SGI volumes.
4094
4095 =item B<mac>
4096
4097 Old Mac partition format.  Modern Macs use C<gpt>.
4098
4099 =item B<pc98>
4100
4101 NEC PC-98 format, common in Japan apparently.
4102
4103 =item B<sun>
4104
4105 Sun disk labels.
4106
4107 =back");
4108
4109   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4110    [InitEmpty, Always, TestRun (
4111       [["part_init"; "/dev/sda"; "mbr"];
4112        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4113     InitEmpty, Always, TestRun (
4114       [["part_init"; "/dev/sda"; "gpt"];
4115        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4116        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4117     InitEmpty, Always, TestRun (
4118       [["part_init"; "/dev/sda"; "mbr"];
4119        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4120        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4121        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4122        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4123    "add a partition to the device",
4124    "\
4125 This command adds a partition to C<device>.  If there is no partition
4126 table on the device, call C<guestfs_part_init> first.
4127
4128 The C<prlogex> parameter is the type of partition.  Normally you
4129 should pass C<p> or C<primary> here, but MBR partition tables also
4130 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4131 types.
4132
4133 C<startsect> and C<endsect> are the start and end of the partition
4134 in I<sectors>.  C<endsect> may be negative, which means it counts
4135 backwards from the end of the disk (C<-1> is the last sector).
4136
4137 Creating a partition which covers the whole disk is not so easy.
4138 Use C<guestfs_part_disk> to do that.");
4139
4140   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4141    [InitEmpty, Always, TestRun (
4142       [["part_disk"; "/dev/sda"; "mbr"]]);
4143     InitEmpty, Always, TestRun (
4144       [["part_disk"; "/dev/sda"; "gpt"]])],
4145    "partition whole disk with a single primary partition",
4146    "\
4147 This command is simply a combination of C<guestfs_part_init>
4148 followed by C<guestfs_part_add> to create a single primary partition
4149 covering the whole disk.
4150
4151 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4152 but other possible values are described in C<guestfs_part_init>.");
4153
4154   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4155    [InitEmpty, Always, TestRun (
4156       [["part_disk"; "/dev/sda"; "mbr"];
4157        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4158    "make a partition bootable",
4159    "\
4160 This sets the bootable flag on partition numbered C<partnum> on
4161 device C<device>.  Note that partitions are numbered from 1.
4162
4163 The bootable flag is used by some operating systems (notably
4164 Windows) to determine which partition to boot from.  It is by
4165 no means universally recognized.");
4166
4167   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4168    [InitEmpty, Always, TestRun (
4169       [["part_disk"; "/dev/sda"; "gpt"];
4170        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4171    "set partition name",
4172    "\
4173 This sets the partition name on partition numbered C<partnum> on
4174 device C<device>.  Note that partitions are numbered from 1.
4175
4176 The partition name can only be set on certain types of partition
4177 table.  This works on C<gpt> but not on C<mbr> partitions.");
4178
4179   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4180    [], (* XXX Add a regression test for this. *)
4181    "list partitions on a device",
4182    "\
4183 This command parses the partition table on C<device> and
4184 returns the list of partitions found.
4185
4186 The fields in the returned structure are:
4187
4188 =over 4
4189
4190 =item B<part_num>
4191
4192 Partition number, counting from 1.
4193
4194 =item B<part_start>
4195
4196 Start of the partition I<in bytes>.  To get sectors you have to
4197 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4198
4199 =item B<part_end>
4200
4201 End of the partition in bytes.
4202
4203 =item B<part_size>
4204
4205 Size of the partition in bytes.
4206
4207 =back");
4208
4209   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4210    [InitEmpty, Always, TestOutput (
4211       [["part_disk"; "/dev/sda"; "gpt"];
4212        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4213    "get the partition table type",
4214    "\
4215 This command examines the partition table on C<device> and
4216 returns the partition table type (format) being used.
4217
4218 Common return values include: C<msdos> (a DOS/Windows style MBR
4219 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4220 values are possible, although unusual.  See C<guestfs_part_init>
4221 for a full list.");
4222
4223   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4224    [InitBasicFS, Always, TestOutputBuffer (
4225       [["fill"; "0x63"; "10"; "/test"];
4226        ["read_file"; "/test"]], "cccccccccc")],
4227    "fill a file with octets",
4228    "\
4229 This command creates a new file called C<path>.  The initial
4230 content of the file is C<len> octets of C<c>, where C<c>
4231 must be a number in the range C<[0..255]>.
4232
4233 To fill a file with zero bytes (sparsely), it is
4234 much more efficient to use C<guestfs_truncate_size>.");
4235
4236   ("available", (RErr, [StringList "groups"]), 216, [],
4237    [InitNone, Always, TestRun [["available"; ""]]],
4238    "test availability of some parts of the API",
4239    "\
4240 This command is used to check the availability of some
4241 groups of functionality in the appliance, which not all builds of
4242 the libguestfs appliance will be able to provide.
4243
4244 The libguestfs groups, and the functions that those
4245 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4246
4247 The argument C<groups> is a list of group names, eg:
4248 C<[\"inotify\", \"augeas\"]> would check for the availability of
4249 the Linux inotify functions and Augeas (configuration file
4250 editing) functions.
4251
4252 The command returns no error if I<all> requested groups are available.
4253
4254 It fails with an error if one or more of the requested
4255 groups is unavailable in the appliance.
4256
4257 If an unknown group name is included in the
4258 list of groups then an error is always returned.
4259
4260 I<Notes:>
4261
4262 =over 4
4263
4264 =item *
4265
4266 You must call C<guestfs_launch> before calling this function.
4267
4268 The reason is because we don't know what groups are
4269 supported by the appliance/daemon until it is running and can
4270 be queried.
4271
4272 =item *
4273
4274 If a group of functions is available, this does not necessarily
4275 mean that they will work.  You still have to check for errors
4276 when calling individual API functions even if they are
4277 available.
4278
4279 =item *
4280
4281 It is usually the job of distro packagers to build
4282 complete functionality into the libguestfs appliance.
4283 Upstream libguestfs, if built from source with all
4284 requirements satisfied, will support everything.
4285
4286 =item *
4287
4288 This call was added in version C<1.0.80>.  In previous
4289 versions of libguestfs all you could do would be to speculatively
4290 execute a command to find out if the daemon implemented it.
4291 See also C<guestfs_version>.
4292
4293 =back");
4294
4295   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4296    [InitBasicFS, Always, TestOutputBuffer (
4297       [["write_file"; "/src"; "hello, world"; "0"];
4298        ["dd"; "/src"; "/dest"];
4299        ["read_file"; "/dest"]], "hello, world")],
4300    "copy from source to destination using dd",
4301    "\
4302 This command copies from one source device or file C<src>
4303 to another destination device or file C<dest>.  Normally you
4304 would use this to copy to or from a device or partition, for
4305 example to duplicate a filesystem.
4306
4307 If the destination is a device, it must be as large or larger
4308 than the source file or device, otherwise the copy will fail.
4309 This command cannot do partial copies (see C<guestfs_copy_size>).");
4310
4311   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4312    [InitBasicFS, Always, TestOutputInt (
4313       [["write_file"; "/file"; "hello, world"; "0"];
4314        ["filesize"; "/file"]], 12)],
4315    "return the size of the file in bytes",
4316    "\
4317 This command returns the size of C<file> in bytes.
4318
4319 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4320 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4321 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4322
4323   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4324    [InitBasicFSonLVM, Always, TestOutputList (
4325       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4326        ["lvs"]], ["/dev/VG/LV2"])],
4327    "rename an LVM logical volume",
4328    "\
4329 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4330
4331   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4332    [InitBasicFSonLVM, Always, TestOutputList (
4333       [["umount"; "/"];
4334        ["vg_activate"; "false"; "VG"];
4335        ["vgrename"; "VG"; "VG2"];
4336        ["vg_activate"; "true"; "VG2"];
4337        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4338        ["vgs"]], ["VG2"])],
4339    "rename an LVM volume group",
4340    "\
4341 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4342
4343   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4344    [InitISOFS, Always, TestOutputBuffer (
4345       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4346    "list the contents of a single file in an initrd",
4347    "\
4348 This command unpacks the file C<filename> from the initrd file
4349 called C<initrdpath>.  The filename must be given I<without> the
4350 initial C</> character.
4351
4352 For example, in guestfish you could use the following command
4353 to examine the boot script (usually called C</init>)
4354 contained in a Linux initrd or initramfs image:
4355
4356  initrd-cat /boot/initrd-<version>.img init
4357
4358 See also C<guestfs_initrd_list>.");
4359
4360   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4361    [],
4362    "get the UUID of a physical volume",
4363    "\
4364 This command returns the UUID of the LVM PV C<device>.");
4365
4366   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4367    [],
4368    "get the UUID of a volume group",
4369    "\
4370 This command returns the UUID of the LVM VG named C<vgname>.");
4371
4372   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4373    [],
4374    "get the UUID of a logical volume",
4375    "\
4376 This command returns the UUID of the LVM LV C<device>.");
4377
4378   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4379    [],
4380    "get the PV UUIDs containing the volume group",
4381    "\
4382 Given a VG called C<vgname>, this returns the UUIDs of all
4383 the physical volumes that this volume group resides on.
4384
4385 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4386 calls to associate physical volumes and volume groups.
4387
4388 See also C<guestfs_vglvuuids>.");
4389
4390   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4391    [],
4392    "get the LV UUIDs of all LVs in the volume group",
4393    "\
4394 Given a VG called C<vgname>, this returns the UUIDs of all
4395 the logical volumes created in this volume group.
4396
4397 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4398 calls to associate logical volumes and volume groups.
4399
4400 See also C<guestfs_vgpvuuids>.");
4401
4402   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4403    [InitBasicFS, Always, TestOutputBuffer (
4404       [["write_file"; "/src"; "hello, world"; "0"];
4405        ["copy_size"; "/src"; "/dest"; "5"];
4406        ["read_file"; "/dest"]], "hello")],
4407    "copy size bytes from source to destination using dd",
4408    "\
4409 This command copies exactly C<size> bytes from one source device
4410 or file C<src> to another destination device or file C<dest>.
4411
4412 Note this will fail if the source is too short or if the destination
4413 is not large enough.");
4414
4415   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4416    [InitBasicFSonLVM, Always, TestRun (
4417       [["zero_device"; "/dev/VG/LV"]])],
4418    "write zeroes to an entire device",
4419    "\
4420 This command writes zeroes over the entire C<device>.  Compare
4421 with C<guestfs_zero> which just zeroes the first few blocks of
4422 a device.");
4423
4424   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4425    [InitBasicFS, Always, TestOutput (
4426       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4427        ["cat"; "/hello"]], "hello\n")],
4428    "unpack compressed tarball to directory",
4429    "\
4430 This command uploads and unpacks local file C<tarball> (an
4431 I<xz compressed> tar file) into C<directory>.");
4432
4433   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4434    [],
4435    "pack directory into compressed tarball",
4436    "\
4437 This command packs the contents of C<directory> and downloads
4438 it to local file C<tarball> (as an xz compressed tar archive).");
4439
4440   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4441    [],
4442    "resize an NTFS filesystem",
4443    "\
4444 This command resizes an NTFS filesystem, expanding or
4445 shrinking it to the size of the underlying device.
4446 See also L<ntfsresize(8)>.");
4447
4448   ("vgscan", (RErr, []), 232, [],
4449    [InitEmpty, Always, TestRun (
4450       [["vgscan"]])],
4451    "rescan for LVM physical volumes, volume groups and logical volumes",
4452    "\
4453 This rescans all block devices and rebuilds the list of LVM
4454 physical volumes, volume groups and logical volumes.");
4455
4456   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4457    [InitEmpty, Always, TestRun (
4458       [["part_init"; "/dev/sda"; "mbr"];
4459        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4460        ["part_del"; "/dev/sda"; "1"]])],
4461    "delete a partition",
4462    "\
4463 This command deletes the partition numbered C<partnum> on C<device>.
4464
4465 Note that in the case of MBR partitioning, deleting an
4466 extended partition also deletes any logical partitions
4467 it contains.");
4468
4469   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4470    [InitEmpty, Always, TestOutputTrue (
4471       [["part_init"; "/dev/sda"; "mbr"];
4472        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4473        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4474        ["part_get_bootable"; "/dev/sda"; "1"]])],
4475    "return true if a partition is bootable",
4476    "\
4477 This command returns true if the partition C<partnum> on
4478 C<device> has the bootable flag set.
4479
4480 See also C<guestfs_part_set_bootable>.");
4481
4482   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4483    [InitEmpty, Always, TestOutputInt (
4484       [["part_init"; "/dev/sda"; "mbr"];
4485        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4486        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4487        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4488    "get the MBR type byte (ID byte) from a partition",
4489    "\
4490 Returns the MBR type byte (also known as the ID byte) from
4491 the numbered partition C<partnum>.
4492
4493 Note that only MBR (old DOS-style) partitions have type bytes.
4494 You will get undefined results for other partition table
4495 types (see C<guestfs_part_get_parttype>).");
4496
4497   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4498    [], (* tested by part_get_mbr_id *)
4499    "set the MBR type byte (ID byte) of a partition",
4500    "\
4501 Sets the MBR type byte (also known as the ID byte) of
4502 the numbered partition C<partnum> to C<idbyte>.  Note
4503 that the type bytes quoted in most documentation are
4504 in fact hexadecimal numbers, but usually documented
4505 without any leading \"0x\" which might be confusing.
4506
4507 Note that only MBR (old DOS-style) partitions have type bytes.
4508 You will get undefined results for other partition table
4509 types (see C<guestfs_part_get_parttype>).");
4510
4511   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4512    [InitISOFS, Always, TestOutput (
4513       [["checksum_device"; "md5"; "/dev/sdd"]],
4514       (Digest.to_hex (Digest.file "images/test.iso")))],
4515    "compute MD5, SHAx or CRC checksum of the contents of a device",
4516    "\
4517 This call computes the MD5, SHAx or CRC checksum of the
4518 contents of the device named C<device>.  For the types of
4519 checksums supported see the C<guestfs_checksum> command.");
4520
4521   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4522    [InitNone, Always, TestRun (
4523       [["part_disk"; "/dev/sda"; "mbr"];
4524        ["pvcreate"; "/dev/sda1"];
4525        ["vgcreate"; "VG"; "/dev/sda1"];
4526        ["lvcreate"; "LV"; "VG"; "10"];
4527        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4528    "expand an LV to fill free space",
4529    "\
4530 This expands an existing logical volume C<lv> so that it fills
4531 C<pc>% of the remaining free space in the volume group.  Commonly
4532 you would call this with pc = 100 which expands the logical volume
4533 as much as possible, using all remaining free space in the volume
4534 group.");
4535
4536   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4537    [], (* XXX Augeas code needs tests. *)
4538    "clear Augeas path",
4539    "\
4540 Set the value associated with C<path> to C<NULL>.  This
4541 is the same as the L<augtool(1)> C<clear> command.");
4542
4543   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4544    [InitEmpty, Always, TestOutputInt (
4545       [["get_umask"]], 0o22)],
4546    "get the current umask",
4547    "\
4548 Return the current umask.  By default the umask is C<022>
4549 unless it has been set by calling C<guestfs_umask>.");
4550
4551   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4552    [],
4553    "upload a file to the appliance (internal use only)",
4554    "\
4555 The C<guestfs_debug_upload> command uploads a file to
4556 the libguestfs appliance.
4557
4558 There is no comprehensive help for this command.  You have
4559 to look at the file C<daemon/debug.c> in the libguestfs source
4560 to find out what it is for.");
4561
4562   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4563    [InitBasicFS, Always, TestOutput (
4564       [["base64_in"; "../images/hello.b64"; "/hello"];
4565        ["cat"; "/hello"]], "hello\n")],
4566    "upload base64-encoded data to file",
4567    "\
4568 This command uploads base64-encoded data from C<base64file>
4569 to C<filename>.");
4570
4571   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4572    [],
4573    "download file and encode as base64",
4574    "\
4575 This command downloads the contents of C<filename>, writing
4576 it out to local file C<base64file> encoded as base64.");
4577
4578   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4579    [],
4580    "compute MD5, SHAx or CRC checksum of files in a directory",
4581    "\
4582 This command computes the checksums of all regular files in
4583 C<directory> and then emits a list of those checksums to
4584 the local output file C<sumsfile>.
4585
4586 This can be used for verifying the integrity of a virtual
4587 machine.  However to be properly secure you should pay
4588 attention to the output of the checksum command (it uses
4589 the ones from GNU coreutils).  In particular when the
4590 filename is not printable, coreutils uses a special
4591 backslash syntax.  For more information, see the GNU
4592 coreutils info file.");
4593
4594 ]
4595
4596 let all_functions = non_daemon_functions @ daemon_functions
4597
4598 (* In some places we want the functions to be displayed sorted
4599  * alphabetically, so this is useful:
4600  *)
4601 let all_functions_sorted =
4602   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4603                compare n1 n2) all_functions
4604
4605 (* Field types for structures. *)
4606 type field =
4607   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4608   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4609   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4610   | FUInt32
4611   | FInt32
4612   | FUInt64
4613   | FInt64
4614   | FBytes                      (* Any int measure that counts bytes. *)
4615   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4616   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4617
4618 (* Because we generate extra parsing code for LVM command line tools,
4619  * we have to pull out the LVM columns separately here.
4620  *)
4621 let lvm_pv_cols = [
4622   "pv_name", FString;
4623   "pv_uuid", FUUID;
4624   "pv_fmt", FString;
4625   "pv_size", FBytes;
4626   "dev_size", FBytes;
4627   "pv_free", FBytes;
4628   "pv_used", FBytes;
4629   "pv_attr", FString (* XXX *);
4630   "pv_pe_count", FInt64;
4631   "pv_pe_alloc_count", FInt64;
4632   "pv_tags", FString;
4633   "pe_start", FBytes;
4634   "pv_mda_count", FInt64;
4635   "pv_mda_free", FBytes;
4636   (* Not in Fedora 10:
4637      "pv_mda_size", FBytes;
4638   *)
4639 ]
4640 let lvm_vg_cols = [
4641   "vg_name", FString;
4642   "vg_uuid", FUUID;
4643   "vg_fmt", FString;
4644   "vg_attr", FString (* XXX *);
4645   "vg_size", FBytes;
4646   "vg_free", FBytes;
4647   "vg_sysid", FString;
4648   "vg_extent_size", FBytes;
4649   "vg_extent_count", FInt64;
4650   "vg_free_count", FInt64;
4651   "max_lv", FInt64;
4652   "max_pv", FInt64;
4653   "pv_count", FInt64;
4654   "lv_count", FInt64;
4655   "snap_count", FInt64;
4656   "vg_seqno", FInt64;
4657   "vg_tags", FString;
4658   "vg_mda_count", FInt64;
4659   "vg_mda_free", FBytes;
4660   (* Not in Fedora 10:
4661      "vg_mda_size", FBytes;
4662   *)
4663 ]
4664 let lvm_lv_cols = [
4665   "lv_name", FString;
4666   "lv_uuid", FUUID;
4667   "lv_attr", FString (* XXX *);
4668   "lv_major", FInt64;
4669   "lv_minor", FInt64;
4670   "lv_kernel_major", FInt64;
4671   "lv_kernel_minor", FInt64;
4672   "lv_size", FBytes;
4673   "seg_count", FInt64;
4674   "origin", FString;
4675   "snap_percent", FOptPercent;
4676   "copy_percent", FOptPercent;
4677   "move_pv", FString;
4678   "lv_tags", FString;
4679   "mirror_log", FString;
4680   "modules", FString;
4681 ]
4682
4683 (* Names and fields in all structures (in RStruct and RStructList)
4684  * that we support.
4685  *)
4686 let structs = [
4687   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4688    * not use this struct in any new code.
4689    *)
4690   "int_bool", [
4691     "i", FInt32;                (* for historical compatibility *)
4692     "b", FInt32;                (* for historical compatibility *)
4693   ];
4694
4695   (* LVM PVs, VGs, LVs. *)
4696   "lvm_pv", lvm_pv_cols;
4697   "lvm_vg", lvm_vg_cols;
4698   "lvm_lv", lvm_lv_cols;
4699
4700   (* Column names and types from stat structures.
4701    * NB. Can't use things like 'st_atime' because glibc header files
4702    * define some of these as macros.  Ugh.
4703    *)
4704   "stat", [
4705     "dev", FInt64;
4706     "ino", FInt64;
4707     "mode", FInt64;
4708     "nlink", FInt64;
4709     "uid", FInt64;
4710     "gid", FInt64;
4711     "rdev", FInt64;
4712     "size", FInt64;
4713     "blksize", FInt64;
4714     "blocks", FInt64;
4715     "atime", FInt64;
4716     "mtime", FInt64;
4717     "ctime", FInt64;
4718   ];
4719   "statvfs", [
4720     "bsize", FInt64;
4721     "frsize", FInt64;
4722     "blocks", FInt64;
4723     "bfree", FInt64;
4724     "bavail", FInt64;
4725     "files", FInt64;
4726     "ffree", FInt64;
4727     "favail", FInt64;
4728     "fsid", FInt64;
4729     "flag", FInt64;
4730     "namemax", FInt64;
4731   ];
4732
4733   (* Column names in dirent structure. *)
4734   "dirent", [
4735     "ino", FInt64;
4736     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4737     "ftyp", FChar;
4738     "name", FString;
4739   ];
4740
4741   (* Version numbers. *)
4742   "version", [
4743     "major", FInt64;
4744     "minor", FInt64;
4745     "release", FInt64;
4746     "extra", FString;
4747   ];
4748
4749   (* Extended attribute. *)
4750   "xattr", [
4751     "attrname", FString;
4752     "attrval", FBuffer;
4753   ];
4754
4755   (* Inotify events. *)
4756   "inotify_event", [
4757     "in_wd", FInt64;
4758     "in_mask", FUInt32;
4759     "in_cookie", FUInt32;
4760     "in_name", FString;
4761   ];
4762
4763   (* Partition table entry. *)
4764   "partition", [
4765     "part_num", FInt32;
4766     "part_start", FBytes;
4767     "part_end", FBytes;
4768     "part_size", FBytes;
4769   ];
4770 ] (* end of structs *)
4771
4772 (* Ugh, Java has to be different ..
4773  * These names are also used by the Haskell bindings.
4774  *)
4775 let java_structs = [
4776   "int_bool", "IntBool";
4777   "lvm_pv", "PV";
4778   "lvm_vg", "VG";
4779   "lvm_lv", "LV";
4780   "stat", "Stat";
4781   "statvfs", "StatVFS";
4782   "dirent", "Dirent";
4783   "version", "Version";
4784   "xattr", "XAttr";
4785   "inotify_event", "INotifyEvent";
4786   "partition", "Partition";
4787 ]
4788
4789 (* What structs are actually returned. *)
4790 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4791
4792 (* Returns a list of RStruct/RStructList structs that are returned
4793  * by any function.  Each element of returned list is a pair:
4794  *
4795  * (structname, RStructOnly)
4796  *    == there exists function which returns RStruct (_, structname)
4797  * (structname, RStructListOnly)
4798  *    == there exists function which returns RStructList (_, structname)
4799  * (structname, RStructAndList)
4800  *    == there are functions returning both RStruct (_, structname)
4801  *                                      and RStructList (_, structname)
4802  *)
4803 let rstructs_used_by functions =
4804   (* ||| is a "logical OR" for rstructs_used_t *)
4805   let (|||) a b =
4806     match a, b with
4807     | RStructAndList, _
4808     | _, RStructAndList -> RStructAndList
4809     | RStructOnly, RStructListOnly
4810     | RStructListOnly, RStructOnly -> RStructAndList
4811     | RStructOnly, RStructOnly -> RStructOnly
4812     | RStructListOnly, RStructListOnly -> RStructListOnly
4813   in
4814
4815   let h = Hashtbl.create 13 in
4816
4817   (* if elem->oldv exists, update entry using ||| operator,
4818    * else just add elem->newv to the hash
4819    *)
4820   let update elem newv =
4821     try  let oldv = Hashtbl.find h elem in
4822          Hashtbl.replace h elem (newv ||| oldv)
4823     with Not_found -> Hashtbl.add h elem newv
4824   in
4825
4826   List.iter (
4827     fun (_, style, _, _, _, _, _) ->
4828       match fst style with
4829       | RStruct (_, structname) -> update structname RStructOnly
4830       | RStructList (_, structname) -> update structname RStructListOnly
4831       | _ -> ()
4832   ) functions;
4833
4834   (* return key->values as a list of (key,value) *)
4835   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4836
4837 (* Used for testing language bindings. *)
4838 type callt =
4839   | CallString of string
4840   | CallOptString of string option
4841   | CallStringList of string list
4842   | CallInt of int
4843   | CallInt64 of int64
4844   | CallBool of bool
4845
4846 (* Used to memoize the result of pod2text. *)
4847 let pod2text_memo_filename = "src/.pod2text.data"
4848 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4849   try
4850     let chan = open_in pod2text_memo_filename in
4851     let v = input_value chan in
4852     close_in chan;
4853     v
4854   with
4855     _ -> Hashtbl.create 13
4856 let pod2text_memo_updated () =
4857   let chan = open_out pod2text_memo_filename in
4858   output_value chan pod2text_memo;
4859   close_out chan
4860
4861 (* Useful functions.
4862  * Note we don't want to use any external OCaml libraries which
4863  * makes this a bit harder than it should be.
4864  *)
4865 module StringMap = Map.Make (String)
4866
4867 let failwithf fs = ksprintf failwith fs
4868
4869 let unique = let i = ref 0 in fun () -> incr i; !i
4870
4871 let replace_char s c1 c2 =
4872   let s2 = String.copy s in
4873   let r = ref false in
4874   for i = 0 to String.length s2 - 1 do
4875     if String.unsafe_get s2 i = c1 then (
4876       String.unsafe_set s2 i c2;
4877       r := true
4878     )
4879   done;
4880   if not !r then s else s2
4881
4882 let isspace c =
4883   c = ' '
4884   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4885
4886 let triml ?(test = isspace) str =
4887   let i = ref 0 in
4888   let n = ref (String.length str) in
4889   while !n > 0 && test str.[!i]; do
4890     decr n;
4891     incr i
4892   done;
4893   if !i = 0 then str
4894   else String.sub str !i !n
4895
4896 let trimr ?(test = isspace) str =
4897   let n = ref (String.length str) in
4898   while !n > 0 && test str.[!n-1]; do
4899     decr n
4900   done;
4901   if !n = String.length str then str
4902   else String.sub str 0 !n
4903
4904 let trim ?(test = isspace) str =
4905   trimr ~test (triml ~test str)
4906
4907 let rec find s sub =
4908   let len = String.length s in
4909   let sublen = String.length sub in
4910   let rec loop i =
4911     if i <= len-sublen then (
4912       let rec loop2 j =
4913         if j < sublen then (
4914           if s.[i+j] = sub.[j] then loop2 (j+1)
4915           else -1
4916         ) else
4917           i (* found *)
4918       in
4919       let r = loop2 0 in
4920       if r = -1 then loop (i+1) else r
4921     ) else
4922       -1 (* not found *)
4923   in
4924   loop 0
4925
4926 let rec replace_str s s1 s2 =
4927   let len = String.length s in
4928   let sublen = String.length s1 in
4929   let i = find s s1 in
4930   if i = -1 then s
4931   else (
4932     let s' = String.sub s 0 i in
4933     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4934     s' ^ s2 ^ replace_str s'' s1 s2
4935   )
4936
4937 let rec string_split sep str =
4938   let len = String.length str in
4939   let seplen = String.length sep in
4940   let i = find str sep in
4941   if i = -1 then [str]
4942   else (
4943     let s' = String.sub str 0 i in
4944     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4945     s' :: string_split sep s''
4946   )
4947
4948 let files_equal n1 n2 =
4949   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4950   match Sys.command cmd with
4951   | 0 -> true
4952   | 1 -> false
4953   | i -> failwithf "%s: failed with error code %d" cmd i
4954
4955 let rec filter_map f = function
4956   | [] -> []
4957   | x :: xs ->
4958       match f x with
4959       | Some y -> y :: filter_map f xs
4960       | None -> filter_map f xs
4961
4962 let rec find_map f = function
4963   | [] -> raise Not_found
4964   | x :: xs ->
4965       match f x with
4966       | Some y -> y
4967       | None -> find_map f xs
4968
4969 let iteri f xs =
4970   let rec loop i = function
4971     | [] -> ()
4972     | x :: xs -> f i x; loop (i+1) xs
4973   in
4974   loop 0 xs
4975
4976 let mapi f xs =
4977   let rec loop i = function
4978     | [] -> []
4979     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4980   in
4981   loop 0 xs
4982
4983 let count_chars c str =
4984   let count = ref 0 in
4985   for i = 0 to String.length str - 1 do
4986     if c = String.unsafe_get str i then incr count
4987   done;
4988   !count
4989
4990 let name_of_argt = function
4991   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4992   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4993   | FileIn n | FileOut n -> n
4994
4995 let java_name_of_struct typ =
4996   try List.assoc typ java_structs
4997   with Not_found ->
4998     failwithf
4999       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5000
5001 let cols_of_struct typ =
5002   try List.assoc typ structs
5003   with Not_found ->
5004     failwithf "cols_of_struct: unknown struct %s" typ
5005
5006 let seq_of_test = function
5007   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5008   | TestOutputListOfDevices (s, _)
5009   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5010   | TestOutputTrue s | TestOutputFalse s
5011   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5012   | TestOutputStruct (s, _)
5013   | TestLastFail s -> s
5014
5015 (* Handling for function flags. *)
5016 let protocol_limit_warning =
5017   "Because of the message protocol, there is a transfer limit
5018 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5019
5020 let danger_will_robinson =
5021   "B<This command is dangerous.  Without careful use you
5022 can easily destroy all your data>."
5023
5024 let deprecation_notice flags =
5025   try
5026     let alt =
5027       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5028     let txt =
5029       sprintf "This function is deprecated.
5030 In new code, use the C<%s> call instead.
5031
5032 Deprecated functions will not be removed from the API, but the
5033 fact that they are deprecated indicates that there are problems
5034 with correct use of these functions." alt in
5035     Some txt
5036   with
5037     Not_found -> None
5038
5039 (* Create list of optional groups. *)
5040 let optgroups =
5041   let h = Hashtbl.create 13 in
5042   List.iter (
5043     fun (name, _, _, flags, _, _, _) ->
5044       List.iter (
5045         function
5046         | Optional group ->
5047             let names = try Hashtbl.find h group with Not_found -> [] in
5048             Hashtbl.replace h group (name :: names)
5049         | _ -> ()
5050       ) flags
5051   ) daemon_functions;
5052   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5053   let groups =
5054     List.map (
5055       fun group -> group, List.sort compare (Hashtbl.find h group)
5056     ) groups in
5057   List.sort (fun x y -> compare (fst x) (fst y)) groups
5058
5059 (* Check function names etc. for consistency. *)
5060 let check_functions () =
5061   let contains_uppercase str =
5062     let len = String.length str in
5063     let rec loop i =
5064       if i >= len then false
5065       else (
5066         let c = str.[i] in
5067         if c >= 'A' && c <= 'Z' then true
5068         else loop (i+1)
5069       )
5070     in
5071     loop 0
5072   in
5073
5074   (* Check function names. *)
5075   List.iter (
5076     fun (name, _, _, _, _, _, _) ->
5077       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5078         failwithf "function name %s does not need 'guestfs' prefix" name;
5079       if name = "" then
5080         failwithf "function name is empty";
5081       if name.[0] < 'a' || name.[0] > 'z' then
5082         failwithf "function name %s must start with lowercase a-z" name;
5083       if String.contains name '-' then
5084         failwithf "function name %s should not contain '-', use '_' instead."
5085           name
5086   ) all_functions;
5087
5088   (* Check function parameter/return names. *)
5089   List.iter (
5090     fun (name, style, _, _, _, _, _) ->
5091       let check_arg_ret_name n =
5092         if contains_uppercase n then
5093           failwithf "%s param/ret %s should not contain uppercase chars"
5094             name n;
5095         if String.contains n '-' || String.contains n '_' then
5096           failwithf "%s param/ret %s should not contain '-' or '_'"
5097             name n;
5098         if n = "value" then
5099           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;
5100         if n = "int" || n = "char" || n = "short" || n = "long" then
5101           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5102         if n = "i" || n = "n" then
5103           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5104         if n = "argv" || n = "args" then
5105           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5106
5107         (* List Haskell, OCaml and C keywords here.
5108          * http://www.haskell.org/haskellwiki/Keywords
5109          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5110          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5111          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5112          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5113          * Omitting _-containing words, since they're handled above.
5114          * Omitting the OCaml reserved word, "val", is ok,
5115          * and saves us from renaming several parameters.
5116          *)
5117         let reserved = [
5118           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5119           "char"; "class"; "const"; "constraint"; "continue"; "data";
5120           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5121           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5122           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5123           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5124           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5125           "interface";
5126           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5127           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5128           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5129           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5130           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5131           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5132           "volatile"; "when"; "where"; "while";
5133           ] in
5134         if List.mem n reserved then
5135           failwithf "%s has param/ret using reserved word %s" name n;
5136       in
5137
5138       (match fst style with
5139        | RErr -> ()
5140        | RInt n | RInt64 n | RBool n
5141        | RConstString n | RConstOptString n | RString n
5142        | RStringList n | RStruct (n, _) | RStructList (n, _)
5143        | RHashtable n | RBufferOut n ->
5144            check_arg_ret_name n
5145       );
5146       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5147   ) all_functions;
5148
5149   (* Check short descriptions. *)
5150   List.iter (
5151     fun (name, _, _, _, _, shortdesc, _) ->
5152       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5153         failwithf "short description of %s should begin with lowercase." name;
5154       let c = shortdesc.[String.length shortdesc-1] in
5155       if c = '\n' || c = '.' then
5156         failwithf "short description of %s should not end with . or \\n." name
5157   ) all_functions;
5158
5159   (* Check long descriptions. *)
5160   List.iter (
5161     fun (name, _, _, _, _, _, longdesc) ->
5162       if longdesc.[String.length longdesc-1] = '\n' then
5163         failwithf "long description of %s should not end with \\n." name
5164   ) all_functions;
5165
5166   (* Check proc_nrs. *)
5167   List.iter (
5168     fun (name, _, proc_nr, _, _, _, _) ->
5169       if proc_nr <= 0 then
5170         failwithf "daemon function %s should have proc_nr > 0" name
5171   ) daemon_functions;
5172
5173   List.iter (
5174     fun (name, _, proc_nr, _, _, _, _) ->
5175       if proc_nr <> -1 then
5176         failwithf "non-daemon function %s should have proc_nr -1" name
5177   ) non_daemon_functions;
5178
5179   let proc_nrs =
5180     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5181       daemon_functions in
5182   let proc_nrs =
5183     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5184   let rec loop = function
5185     | [] -> ()
5186     | [_] -> ()
5187     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5188         loop rest
5189     | (name1,nr1) :: (name2,nr2) :: _ ->
5190         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5191           name1 name2 nr1 nr2
5192   in
5193   loop proc_nrs;
5194
5195   (* Check tests. *)
5196   List.iter (
5197     function
5198       (* Ignore functions that have no tests.  We generate a
5199        * warning when the user does 'make check' instead.
5200        *)
5201     | name, _, _, _, [], _, _ -> ()
5202     | name, _, _, _, tests, _, _ ->
5203         let funcs =
5204           List.map (
5205             fun (_, _, test) ->
5206               match seq_of_test test with
5207               | [] ->
5208                   failwithf "%s has a test containing an empty sequence" name
5209               | cmds -> List.map List.hd cmds
5210           ) tests in
5211         let funcs = List.flatten funcs in
5212
5213         let tested = List.mem name funcs in
5214
5215         if not tested then
5216           failwithf "function %s has tests but does not test itself" name
5217   ) all_functions
5218
5219 (* 'pr' prints to the current output file. *)
5220 let chan = ref Pervasives.stdout
5221 let lines = ref 0
5222 let pr fs =
5223   ksprintf
5224     (fun str ->
5225        let i = count_chars '\n' str in
5226        lines := !lines + i;
5227        output_string !chan str
5228     ) fs
5229
5230 let copyright_years =
5231   let this_year = 1900 + (localtime (time ())).tm_year in
5232   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5233
5234 (* Generate a header block in a number of standard styles. *)
5235 type comment_style =
5236     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5237 type license = GPLv2plus | LGPLv2plus
5238
5239 let generate_header ?(extra_inputs = []) comment license =
5240   let inputs = "src/generator.ml" :: extra_inputs in
5241   let c = match comment with
5242     | CStyle ->         pr "/* "; " *"
5243     | CPlusPlusStyle -> pr "// "; "//"
5244     | HashStyle ->      pr "# ";  "#"
5245     | OCamlStyle ->     pr "(* "; " *"
5246     | HaskellStyle ->   pr "{- "; "  " in
5247   pr "libguestfs generated file\n";
5248   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5249   List.iter (pr "%s   %s\n" c) inputs;
5250   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5251   pr "%s\n" c;
5252   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5253   pr "%s\n" c;
5254   (match license with
5255    | GPLv2plus ->
5256        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5257        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5258        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5259        pr "%s (at your option) any later version.\n" c;
5260        pr "%s\n" c;
5261        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5262        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5263        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5264        pr "%s GNU General Public License for more details.\n" c;
5265        pr "%s\n" c;
5266        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5267        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5268        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5269
5270    | LGPLv2plus ->
5271        pr "%s This library is free software; you can redistribute it and/or\n" c;
5272        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5273        pr "%s License as published by the Free Software Foundation; either\n" c;
5274        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5275        pr "%s\n" c;
5276        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5277        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5278        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5279        pr "%s Lesser General Public License for more details.\n" c;
5280        pr "%s\n" c;
5281        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5282        pr "%s License along with this library; if not, write to the Free Software\n" c;
5283        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5284   );
5285   (match comment with
5286    | CStyle -> pr " */\n"
5287    | CPlusPlusStyle
5288    | HashStyle -> ()
5289    | OCamlStyle -> pr " *)\n"
5290    | HaskellStyle -> pr "-}\n"
5291   );
5292   pr "\n"
5293
5294 (* Start of main code generation functions below this line. *)
5295
5296 (* Generate the pod documentation for the C API. *)
5297 let rec generate_actions_pod () =
5298   List.iter (
5299     fun (shortname, style, _, flags, _, _, longdesc) ->
5300       if not (List.mem NotInDocs flags) then (
5301         let name = "guestfs_" ^ shortname in
5302         pr "=head2 %s\n\n" name;
5303         pr " ";
5304         generate_prototype ~extern:false ~handle:"g" name style;
5305         pr "\n\n";
5306         pr "%s\n\n" longdesc;
5307         (match fst style with
5308          | RErr ->
5309              pr "This function returns 0 on success or -1 on error.\n\n"
5310          | RInt _ ->
5311              pr "On error this function returns -1.\n\n"
5312          | RInt64 _ ->
5313              pr "On error this function returns -1.\n\n"
5314          | RBool _ ->
5315              pr "This function returns a C truth value on success or -1 on error.\n\n"
5316          | RConstString _ ->
5317              pr "This function returns a string, or NULL on error.
5318 The string is owned by the guest handle and must I<not> be freed.\n\n"
5319          | RConstOptString _ ->
5320              pr "This function returns a string which may be NULL.
5321 There is way to return an error from this function.
5322 The string is owned by the guest handle and must I<not> be freed.\n\n"
5323          | RString _ ->
5324              pr "This function returns a string, or NULL on error.
5325 I<The caller must free the returned string after use>.\n\n"
5326          | RStringList _ ->
5327              pr "This function returns a NULL-terminated array of strings
5328 (like L<environ(3)>), or NULL if there was an error.
5329 I<The caller must free the strings and the array after use>.\n\n"
5330          | RStruct (_, typ) ->
5331              pr "This function returns a C<struct guestfs_%s *>,
5332 or NULL if there was an error.
5333 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5334          | RStructList (_, typ) ->
5335              pr "This function returns a C<struct guestfs_%s_list *>
5336 (see E<lt>guestfs-structs.hE<gt>),
5337 or NULL if there was an error.
5338 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5339          | RHashtable _ ->
5340              pr "This function returns a NULL-terminated array of
5341 strings, or NULL if there was an error.
5342 The array of strings will always have length C<2n+1>, where
5343 C<n> keys and values alternate, followed by the trailing NULL entry.
5344 I<The caller must free the strings and the array after use>.\n\n"
5345          | RBufferOut _ ->
5346              pr "This function returns a buffer, or NULL on error.
5347 The size of the returned buffer is written to C<*size_r>.
5348 I<The caller must free the returned buffer after use>.\n\n"
5349         );
5350         if List.mem ProtocolLimitWarning flags then
5351           pr "%s\n\n" protocol_limit_warning;
5352         if List.mem DangerWillRobinson flags then
5353           pr "%s\n\n" danger_will_robinson;
5354         match deprecation_notice flags with
5355         | None -> ()
5356         | Some txt -> pr "%s\n\n" txt
5357       )
5358   ) all_functions_sorted
5359
5360 and generate_structs_pod () =
5361   (* Structs documentation. *)
5362   List.iter (
5363     fun (typ, cols) ->
5364       pr "=head2 guestfs_%s\n" typ;
5365       pr "\n";
5366       pr " struct guestfs_%s {\n" typ;
5367       List.iter (
5368         function
5369         | name, FChar -> pr "   char %s;\n" name
5370         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5371         | name, FInt32 -> pr "   int32_t %s;\n" name
5372         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5373         | name, FInt64 -> pr "   int64_t %s;\n" name
5374         | name, FString -> pr "   char *%s;\n" name
5375         | name, FBuffer ->
5376             pr "   /* The next two fields describe a byte array. */\n";
5377             pr "   uint32_t %s_len;\n" name;
5378             pr "   char *%s;\n" name
5379         | name, FUUID ->
5380             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5381             pr "   char %s[32];\n" name
5382         | name, FOptPercent ->
5383             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5384             pr "   float %s;\n" name
5385       ) cols;
5386       pr " };\n";
5387       pr " \n";
5388       pr " struct guestfs_%s_list {\n" typ;
5389       pr "   uint32_t len; /* Number of elements in list. */\n";
5390       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5391       pr " };\n";
5392       pr " \n";
5393       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5394       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5395         typ typ;
5396       pr "\n"
5397   ) structs
5398
5399 and generate_availability_pod () =
5400   (* Availability documentation. *)
5401   pr "=over 4\n";
5402   pr "\n";
5403   List.iter (
5404     fun (group, functions) ->
5405       pr "=item B<%s>\n" group;
5406       pr "\n";
5407       pr "The following functions:\n";
5408       List.iter (pr "L</guestfs_%s>\n") functions;
5409       pr "\n"
5410   ) optgroups;
5411   pr "=back\n";
5412   pr "\n"
5413
5414 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5415  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5416  *
5417  * We have to use an underscore instead of a dash because otherwise
5418  * rpcgen generates incorrect code.
5419  *
5420  * This header is NOT exported to clients, but see also generate_structs_h.
5421  *)
5422 and generate_xdr () =
5423   generate_header CStyle LGPLv2plus;
5424
5425   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5426   pr "typedef string str<>;\n";
5427   pr "\n";
5428
5429   (* Internal structures. *)
5430   List.iter (
5431     function
5432     | typ, cols ->
5433         pr "struct guestfs_int_%s {\n" typ;
5434         List.iter (function
5435                    | name, FChar -> pr "  char %s;\n" name
5436                    | name, FString -> pr "  string %s<>;\n" name
5437                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5438                    | name, FUUID -> pr "  opaque %s[32];\n" name
5439                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5440                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5441                    | name, FOptPercent -> pr "  float %s;\n" name
5442                   ) cols;
5443         pr "};\n";
5444         pr "\n";
5445         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5446         pr "\n";
5447   ) structs;
5448
5449   List.iter (
5450     fun (shortname, style, _, _, _, _, _) ->
5451       let name = "guestfs_" ^ shortname in
5452
5453       (match snd style with
5454        | [] -> ()
5455        | args ->
5456            pr "struct %s_args {\n" name;
5457            List.iter (
5458              function
5459              | Pathname n | Device n | Dev_or_Path n | String n ->
5460                  pr "  string %s<>;\n" n
5461              | OptString n -> pr "  str *%s;\n" n
5462              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5463              | Bool n -> pr "  bool %s;\n" n
5464              | Int n -> pr "  int %s;\n" n
5465              | Int64 n -> pr "  hyper %s;\n" n
5466              | FileIn _ | FileOut _ -> ()
5467            ) args;
5468            pr "};\n\n"
5469       );
5470       (match fst style with
5471        | RErr -> ()
5472        | RInt n ->
5473            pr "struct %s_ret {\n" name;
5474            pr "  int %s;\n" n;
5475            pr "};\n\n"
5476        | RInt64 n ->
5477            pr "struct %s_ret {\n" name;
5478            pr "  hyper %s;\n" n;
5479            pr "};\n\n"
5480        | RBool n ->
5481            pr "struct %s_ret {\n" name;
5482            pr "  bool %s;\n" n;
5483            pr "};\n\n"
5484        | RConstString _ | RConstOptString _ ->
5485            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5486        | RString n ->
5487            pr "struct %s_ret {\n" name;
5488            pr "  string %s<>;\n" n;
5489            pr "};\n\n"
5490        | RStringList n ->
5491            pr "struct %s_ret {\n" name;
5492            pr "  str %s<>;\n" n;
5493            pr "};\n\n"
5494        | RStruct (n, typ) ->
5495            pr "struct %s_ret {\n" name;
5496            pr "  guestfs_int_%s %s;\n" typ n;
5497            pr "};\n\n"
5498        | RStructList (n, typ) ->
5499            pr "struct %s_ret {\n" name;
5500            pr "  guestfs_int_%s_list %s;\n" typ n;
5501            pr "};\n\n"
5502        | RHashtable n ->
5503            pr "struct %s_ret {\n" name;
5504            pr "  str %s<>;\n" n;
5505            pr "};\n\n"
5506        | RBufferOut n ->
5507            pr "struct %s_ret {\n" name;
5508            pr "  opaque %s<>;\n" n;
5509            pr "};\n\n"
5510       );
5511   ) daemon_functions;
5512
5513   (* Table of procedure numbers. *)
5514   pr "enum guestfs_procedure {\n";
5515   List.iter (
5516     fun (shortname, _, proc_nr, _, _, _, _) ->
5517       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5518   ) daemon_functions;
5519   pr "  GUESTFS_PROC_NR_PROCS\n";
5520   pr "};\n";
5521   pr "\n";
5522
5523   (* Having to choose a maximum message size is annoying for several
5524    * reasons (it limits what we can do in the API), but it (a) makes
5525    * the protocol a lot simpler, and (b) provides a bound on the size
5526    * of the daemon which operates in limited memory space.
5527    *)
5528   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5529   pr "\n";
5530
5531   (* Message header, etc. *)
5532   pr "\
5533 /* The communication protocol is now documented in the guestfs(3)
5534  * manpage.
5535  */
5536
5537 const GUESTFS_PROGRAM = 0x2000F5F5;
5538 const GUESTFS_PROTOCOL_VERSION = 1;
5539
5540 /* These constants must be larger than any possible message length. */
5541 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5542 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5543
5544 enum guestfs_message_direction {
5545   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5546   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5547 };
5548
5549 enum guestfs_message_status {
5550   GUESTFS_STATUS_OK = 0,
5551   GUESTFS_STATUS_ERROR = 1
5552 };
5553
5554 const GUESTFS_ERROR_LEN = 256;
5555
5556 struct guestfs_message_error {
5557   string error_message<GUESTFS_ERROR_LEN>;
5558 };
5559
5560 struct guestfs_message_header {
5561   unsigned prog;                     /* GUESTFS_PROGRAM */
5562   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5563   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5564   guestfs_message_direction direction;
5565   unsigned serial;                   /* message serial number */
5566   guestfs_message_status status;
5567 };
5568
5569 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5570
5571 struct guestfs_chunk {
5572   int cancel;                        /* if non-zero, transfer is cancelled */
5573   /* data size is 0 bytes if the transfer has finished successfully */
5574   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5575 };
5576 "
5577
5578 (* Generate the guestfs-structs.h file. *)
5579 and generate_structs_h () =
5580   generate_header CStyle LGPLv2plus;
5581
5582   (* This is a public exported header file containing various
5583    * structures.  The structures are carefully written to have
5584    * exactly the same in-memory format as the XDR structures that
5585    * we use on the wire to the daemon.  The reason for creating
5586    * copies of these structures here is just so we don't have to
5587    * export the whole of guestfs_protocol.h (which includes much
5588    * unrelated and XDR-dependent stuff that we don't want to be
5589    * public, or required by clients).
5590    *
5591    * To reiterate, we will pass these structures to and from the
5592    * client with a simple assignment or memcpy, so the format
5593    * must be identical to what rpcgen / the RFC defines.
5594    *)
5595
5596   (* Public structures. *)
5597   List.iter (
5598     fun (typ, cols) ->
5599       pr "struct guestfs_%s {\n" typ;
5600       List.iter (
5601         function
5602         | name, FChar -> pr "  char %s;\n" name
5603         | name, FString -> pr "  char *%s;\n" name
5604         | name, FBuffer ->
5605             pr "  uint32_t %s_len;\n" name;
5606             pr "  char *%s;\n" name
5607         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5608         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5609         | name, FInt32 -> pr "  int32_t %s;\n" name
5610         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5611         | name, FInt64 -> pr "  int64_t %s;\n" name
5612         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5613       ) cols;
5614       pr "};\n";
5615       pr "\n";
5616       pr "struct guestfs_%s_list {\n" typ;
5617       pr "  uint32_t len;\n";
5618       pr "  struct guestfs_%s *val;\n" typ;
5619       pr "};\n";
5620       pr "\n";
5621       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5622       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5623       pr "\n"
5624   ) structs
5625
5626 (* Generate the guestfs-actions.h file. *)
5627 and generate_actions_h () =
5628   generate_header CStyle LGPLv2plus;
5629   List.iter (
5630     fun (shortname, style, _, _, _, _, _) ->
5631       let name = "guestfs_" ^ shortname in
5632       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5633         name style
5634   ) all_functions
5635
5636 (* Generate the guestfs-internal-actions.h file. *)
5637 and generate_internal_actions_h () =
5638   generate_header CStyle LGPLv2plus;
5639   List.iter (
5640     fun (shortname, style, _, _, _, _, _) ->
5641       let name = "guestfs__" ^ shortname in
5642       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5643         name style
5644   ) non_daemon_functions
5645
5646 (* Generate the client-side dispatch stubs. *)
5647 and generate_client_actions () =
5648   generate_header CStyle LGPLv2plus;
5649
5650   pr "\
5651 #include <stdio.h>
5652 #include <stdlib.h>
5653 #include <stdint.h>
5654 #include <string.h>
5655 #include <inttypes.h>
5656
5657 #include \"guestfs.h\"
5658 #include \"guestfs-internal.h\"
5659 #include \"guestfs-internal-actions.h\"
5660 #include \"guestfs_protocol.h\"
5661
5662 #define error guestfs_error
5663 //#define perrorf guestfs_perrorf
5664 #define safe_malloc guestfs_safe_malloc
5665 #define safe_realloc guestfs_safe_realloc
5666 //#define safe_strdup guestfs_safe_strdup
5667 #define safe_memdup guestfs_safe_memdup
5668
5669 /* Check the return message from a call for validity. */
5670 static int
5671 check_reply_header (guestfs_h *g,
5672                     const struct guestfs_message_header *hdr,
5673                     unsigned int proc_nr, unsigned int serial)
5674 {
5675   if (hdr->prog != GUESTFS_PROGRAM) {
5676     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5677     return -1;
5678   }
5679   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5680     error (g, \"wrong protocol version (%%d/%%d)\",
5681            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5682     return -1;
5683   }
5684   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5685     error (g, \"unexpected message direction (%%d/%%d)\",
5686            hdr->direction, GUESTFS_DIRECTION_REPLY);
5687     return -1;
5688   }
5689   if (hdr->proc != proc_nr) {
5690     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5691     return -1;
5692   }
5693   if (hdr->serial != serial) {
5694     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5695     return -1;
5696   }
5697
5698   return 0;
5699 }
5700
5701 /* Check we are in the right state to run a high-level action. */
5702 static int
5703 check_state (guestfs_h *g, const char *caller)
5704 {
5705   if (!guestfs__is_ready (g)) {
5706     if (guestfs__is_config (g) || guestfs__is_launching (g))
5707       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5708         caller);
5709     else
5710       error (g, \"%%s called from the wrong state, %%d != READY\",
5711         caller, guestfs__get_state (g));
5712     return -1;
5713   }
5714   return 0;
5715 }
5716
5717 ";
5718
5719   (* Generate code to generate guestfish call traces. *)
5720   let trace_call shortname style =
5721     pr "  if (guestfs__get_trace (g)) {\n";
5722
5723     let needs_i =
5724       List.exists (function
5725                    | StringList _ | DeviceList _ -> true
5726                    | _ -> false) (snd style) in
5727     if needs_i then (
5728       pr "    int i;\n";
5729       pr "\n"
5730     );
5731
5732     pr "    printf (\"%s\");\n" shortname;
5733     List.iter (
5734       function
5735       | String n                        (* strings *)
5736       | Device n
5737       | Pathname n
5738       | Dev_or_Path n
5739       | FileIn n
5740       | FileOut n ->
5741           (* guestfish doesn't support string escaping, so neither do we *)
5742           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5743       | OptString n ->                  (* string option *)
5744           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5745           pr "    else printf (\" null\");\n"
5746       | StringList n
5747       | DeviceList n ->                 (* string list *)
5748           pr "    putchar (' ');\n";
5749           pr "    putchar ('\"');\n";
5750           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5751           pr "      if (i > 0) putchar (' ');\n";
5752           pr "      fputs (%s[i], stdout);\n" n;
5753           pr "    }\n";
5754           pr "    putchar ('\"');\n";
5755       | Bool n ->                       (* boolean *)
5756           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5757       | Int n ->                        (* int *)
5758           pr "    printf (\" %%d\", %s);\n" n
5759       | Int64 n ->
5760           pr "    printf (\" %%\" PRIi64, %s);\n" n
5761     ) (snd style);
5762     pr "    putchar ('\\n');\n";
5763     pr "  }\n";
5764     pr "\n";
5765   in
5766
5767   (* For non-daemon functions, generate a wrapper around each function. *)
5768   List.iter (
5769     fun (shortname, style, _, _, _, _, _) ->
5770       let name = "guestfs_" ^ shortname in
5771
5772       generate_prototype ~extern:false ~semicolon:false ~newline:true
5773         ~handle:"g" name style;
5774       pr "{\n";
5775       trace_call shortname style;
5776       pr "  return guestfs__%s " shortname;
5777       generate_c_call_args ~handle:"g" style;
5778       pr ";\n";
5779       pr "}\n";
5780       pr "\n"
5781   ) non_daemon_functions;
5782
5783   (* Client-side stubs for each function. *)
5784   List.iter (
5785     fun (shortname, style, _, _, _, _, _) ->
5786       let name = "guestfs_" ^ shortname in
5787
5788       (* Generate the action stub. *)
5789       generate_prototype ~extern:false ~semicolon:false ~newline:true
5790         ~handle:"g" name style;
5791
5792       let error_code =
5793         match fst style with
5794         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5795         | RConstString _ | RConstOptString _ ->
5796             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5797         | RString _ | RStringList _
5798         | RStruct _ | RStructList _
5799         | RHashtable _ | RBufferOut _ ->
5800             "NULL" in
5801
5802       pr "{\n";
5803
5804       (match snd style with
5805        | [] -> ()
5806        | _ -> pr "  struct %s_args args;\n" name
5807       );
5808
5809       pr "  guestfs_message_header hdr;\n";
5810       pr "  guestfs_message_error err;\n";
5811       let has_ret =
5812         match fst style with
5813         | RErr -> false
5814         | RConstString _ | RConstOptString _ ->
5815             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5816         | RInt _ | RInt64 _
5817         | RBool _ | RString _ | RStringList _
5818         | RStruct _ | RStructList _
5819         | RHashtable _ | RBufferOut _ ->
5820             pr "  struct %s_ret ret;\n" name;
5821             true in
5822
5823       pr "  int serial;\n";
5824       pr "  int r;\n";
5825       pr "\n";
5826       trace_call shortname style;
5827       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5828         shortname error_code;
5829       pr "  guestfs___set_busy (g);\n";
5830       pr "\n";
5831
5832       (* Send the main header and arguments. *)
5833       (match snd style with
5834        | [] ->
5835            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5836              (String.uppercase shortname)
5837        | args ->
5838            List.iter (
5839              function
5840              | Pathname n | Device n | Dev_or_Path n | String n ->
5841                  pr "  args.%s = (char *) %s;\n" n n
5842              | OptString n ->
5843                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5844              | StringList n | DeviceList n ->
5845                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5846                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5847              | Bool n ->
5848                  pr "  args.%s = %s;\n" n n
5849              | Int n ->
5850                  pr "  args.%s = %s;\n" n n
5851              | Int64 n ->
5852                  pr "  args.%s = %s;\n" n n
5853              | FileIn _ | FileOut _ -> ()
5854            ) args;
5855            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5856              (String.uppercase shortname);
5857            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5858              name;
5859       );
5860       pr "  if (serial == -1) {\n";
5861       pr "    guestfs___end_busy (g);\n";
5862       pr "    return %s;\n" error_code;
5863       pr "  }\n";
5864       pr "\n";
5865
5866       (* Send any additional files (FileIn) requested. *)
5867       let need_read_reply_label = ref false in
5868       List.iter (
5869         function
5870         | FileIn n ->
5871             pr "  r = guestfs___send_file (g, %s);\n" n;
5872             pr "  if (r == -1) {\n";
5873             pr "    guestfs___end_busy (g);\n";
5874             pr "    return %s;\n" error_code;
5875             pr "  }\n";
5876             pr "  if (r == -2) /* daemon cancelled */\n";
5877             pr "    goto read_reply;\n";
5878             need_read_reply_label := true;
5879             pr "\n";
5880         | _ -> ()
5881       ) (snd style);
5882
5883       (* Wait for the reply from the remote end. *)
5884       if !need_read_reply_label then pr " read_reply:\n";
5885       pr "  memset (&hdr, 0, sizeof hdr);\n";
5886       pr "  memset (&err, 0, sizeof err);\n";
5887       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5888       pr "\n";
5889       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5890       if not has_ret then
5891         pr "NULL, NULL"
5892       else
5893         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5894       pr ");\n";
5895
5896       pr "  if (r == -1) {\n";
5897       pr "    guestfs___end_busy (g);\n";
5898       pr "    return %s;\n" error_code;
5899       pr "  }\n";
5900       pr "\n";
5901
5902       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5903         (String.uppercase shortname);
5904       pr "    guestfs___end_busy (g);\n";
5905       pr "    return %s;\n" error_code;
5906       pr "  }\n";
5907       pr "\n";
5908
5909       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5910       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5911       pr "    free (err.error_message);\n";
5912       pr "    guestfs___end_busy (g);\n";
5913       pr "    return %s;\n" error_code;
5914       pr "  }\n";
5915       pr "\n";
5916
5917       (* Expecting to receive further files (FileOut)? *)
5918       List.iter (
5919         function
5920         | FileOut n ->
5921             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5922             pr "    guestfs___end_busy (g);\n";
5923             pr "    return %s;\n" error_code;
5924             pr "  }\n";
5925             pr "\n";
5926         | _ -> ()
5927       ) (snd style);
5928
5929       pr "  guestfs___end_busy (g);\n";
5930
5931       (match fst style with
5932        | RErr -> pr "  return 0;\n"
5933        | RInt n | RInt64 n | RBool n ->
5934            pr "  return ret.%s;\n" n
5935        | RConstString _ | RConstOptString _ ->
5936            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5937        | RString n ->
5938            pr "  return ret.%s; /* caller will free */\n" n
5939        | RStringList n | RHashtable n ->
5940            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5941            pr "  ret.%s.%s_val =\n" n n;
5942            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5943            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5944              n n;
5945            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5946            pr "  return ret.%s.%s_val;\n" n n
5947        | RStruct (n, _) ->
5948            pr "  /* caller will free this */\n";
5949            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5950        | RStructList (n, _) ->
5951            pr "  /* caller will free this */\n";
5952            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5953        | RBufferOut n ->
5954            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5955            pr "   * _val might be NULL here.  To make the API saner for\n";
5956            pr "   * callers, we turn this case into a unique pointer (using\n";
5957            pr "   * malloc(1)).\n";
5958            pr "   */\n";
5959            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5960            pr "    *size_r = ret.%s.%s_len;\n" n n;
5961            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5962            pr "  } else {\n";
5963            pr "    free (ret.%s.%s_val);\n" n n;
5964            pr "    char *p = safe_malloc (g, 1);\n";
5965            pr "    *size_r = ret.%s.%s_len;\n" n n;
5966            pr "    return p;\n";
5967            pr "  }\n";
5968       );
5969
5970       pr "}\n\n"
5971   ) daemon_functions;
5972
5973   (* Functions to free structures. *)
5974   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5975   pr " * structure format is identical to the XDR format.  See note in\n";
5976   pr " * generator.ml.\n";
5977   pr " */\n";
5978   pr "\n";
5979
5980   List.iter (
5981     fun (typ, _) ->
5982       pr "void\n";
5983       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5984       pr "{\n";
5985       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5986       pr "  free (x);\n";
5987       pr "}\n";
5988       pr "\n";
5989
5990       pr "void\n";
5991       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5992       pr "{\n";
5993       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5994       pr "  free (x);\n";
5995       pr "}\n";
5996       pr "\n";
5997
5998   ) structs;
5999
6000 (* Generate daemon/actions.h. *)
6001 and generate_daemon_actions_h () =
6002   generate_header CStyle GPLv2plus;
6003
6004   pr "#include \"../src/guestfs_protocol.h\"\n";
6005   pr "\n";
6006
6007   List.iter (
6008     fun (name, style, _, _, _, _, _) ->
6009       generate_prototype
6010         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6011         name style;
6012   ) daemon_functions
6013
6014 (* Generate the linker script which controls the visibility of
6015  * symbols in the public ABI and ensures no other symbols get
6016  * exported accidentally.
6017  *)
6018 and generate_linker_script () =
6019   generate_header HashStyle GPLv2plus;
6020
6021   let globals = [
6022     "guestfs_create";
6023     "guestfs_close";
6024     "guestfs_get_error_handler";
6025     "guestfs_get_out_of_memory_handler";
6026     "guestfs_last_error";
6027     "guestfs_set_error_handler";
6028     "guestfs_set_launch_done_callback";
6029     "guestfs_set_log_message_callback";
6030     "guestfs_set_out_of_memory_handler";
6031     "guestfs_set_subprocess_quit_callback";
6032
6033     (* Unofficial parts of the API: the bindings code use these
6034      * functions, so it is useful to export them.
6035      *)
6036     "guestfs_safe_calloc";
6037     "guestfs_safe_malloc";
6038   ] in
6039   let functions =
6040     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6041       all_functions in
6042   let structs =
6043     List.concat (
6044       List.map (fun (typ, _) ->
6045                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6046         structs
6047     ) in
6048   let globals = List.sort compare (globals @ functions @ structs) in
6049
6050   pr "{\n";
6051   pr "    global:\n";
6052   List.iter (pr "        %s;\n") globals;
6053   pr "\n";
6054
6055   pr "    local:\n";
6056   pr "        *;\n";
6057   pr "};\n"
6058
6059 (* Generate the server-side stubs. *)
6060 and generate_daemon_actions () =
6061   generate_header CStyle GPLv2plus;
6062
6063   pr "#include <config.h>\n";
6064   pr "\n";
6065   pr "#include <stdio.h>\n";
6066   pr "#include <stdlib.h>\n";
6067   pr "#include <string.h>\n";
6068   pr "#include <inttypes.h>\n";
6069   pr "#include <rpc/types.h>\n";
6070   pr "#include <rpc/xdr.h>\n";
6071   pr "\n";
6072   pr "#include \"daemon.h\"\n";
6073   pr "#include \"c-ctype.h\"\n";
6074   pr "#include \"../src/guestfs_protocol.h\"\n";
6075   pr "#include \"actions.h\"\n";
6076   pr "\n";
6077
6078   List.iter (
6079     fun (name, style, _, _, _, _, _) ->
6080       (* Generate server-side stubs. *)
6081       pr "static void %s_stub (XDR *xdr_in)\n" name;
6082       pr "{\n";
6083       let error_code =
6084         match fst style with
6085         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6086         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6087         | RBool _ -> pr "  int r;\n"; "-1"
6088         | RConstString _ | RConstOptString _ ->
6089             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6090         | RString _ -> pr "  char *r;\n"; "NULL"
6091         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6092         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6093         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6094         | RBufferOut _ ->
6095             pr "  size_t size = 1;\n";
6096             pr "  char *r;\n";
6097             "NULL" in
6098
6099       (match snd style with
6100        | [] -> ()
6101        | args ->
6102            pr "  struct guestfs_%s_args args;\n" name;
6103            List.iter (
6104              function
6105              | Device n | Dev_or_Path n
6106              | Pathname n
6107              | String n -> ()
6108              | OptString n -> pr "  char *%s;\n" n
6109              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6110              | Bool n -> pr "  int %s;\n" n
6111              | Int n -> pr "  int %s;\n" n
6112              | Int64 n -> pr "  int64_t %s;\n" n
6113              | FileIn _ | FileOut _ -> ()
6114            ) args
6115       );
6116       pr "\n";
6117
6118       let is_filein =
6119         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6120
6121       (match snd style with
6122        | [] -> ()
6123        | args ->
6124            pr "  memset (&args, 0, sizeof args);\n";
6125            pr "\n";
6126            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6127            if is_filein then
6128              pr "    cancel_receive ();\n";
6129            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6130            pr "    goto done;\n";
6131            pr "  }\n";
6132            let pr_args n =
6133              pr "  char *%s = args.%s;\n" n n
6134            in
6135            let pr_list_handling_code n =
6136              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6137              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6138              pr "  if (%s == NULL) {\n" n;
6139              if is_filein then
6140                pr "    cancel_receive ();\n";
6141              pr "    reply_with_perror (\"realloc\");\n";
6142              pr "    goto done;\n";
6143              pr "  }\n";
6144              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6145              pr "  args.%s.%s_val = %s;\n" n n n;
6146            in
6147            List.iter (
6148              function
6149              | Pathname n ->
6150                  pr_args n;
6151                  pr "  ABS_PATH (%s, %s, goto done);\n"
6152                    n (if is_filein then "cancel_receive ()" else "");
6153              | Device n ->
6154                  pr_args n;
6155                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6156                    n (if is_filein then "cancel_receive ()" else "");
6157              | Dev_or_Path n ->
6158                  pr_args n;
6159                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6160                    n (if is_filein then "cancel_receive ()" else "");
6161              | String n -> pr_args n
6162              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6163              | StringList n ->
6164                  pr_list_handling_code n;
6165              | DeviceList n ->
6166                  pr_list_handling_code n;
6167                  pr "  /* Ensure that each is a device,\n";
6168                  pr "   * and perform device name translation. */\n";
6169                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6170                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6171                    (if is_filein then "cancel_receive ()" else "");
6172                  pr "  }\n";
6173              | Bool n -> pr "  %s = args.%s;\n" n n
6174              | Int n -> pr "  %s = args.%s;\n" n n
6175              | Int64 n -> pr "  %s = args.%s;\n" n n
6176              | FileIn _ | FileOut _ -> ()
6177            ) args;
6178            pr "\n"
6179       );
6180
6181
6182       (* this is used at least for do_equal *)
6183       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6184         (* Emit NEED_ROOT just once, even when there are two or
6185            more Pathname args *)
6186         pr "  NEED_ROOT (%s, goto done);\n"
6187           (if is_filein then "cancel_receive ()" else "");
6188       );
6189
6190       (* Don't want to call the impl with any FileIn or FileOut
6191        * parameters, since these go "outside" the RPC protocol.
6192        *)
6193       let args' =
6194         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6195           (snd style) in
6196       pr "  r = do_%s " name;
6197       generate_c_call_args (fst style, args');
6198       pr ";\n";
6199
6200       (match fst style with
6201        | RErr | RInt _ | RInt64 _ | RBool _
6202        | RConstString _ | RConstOptString _
6203        | RString _ | RStringList _ | RHashtable _
6204        | RStruct (_, _) | RStructList (_, _) ->
6205            pr "  if (r == %s)\n" error_code;
6206            pr "    /* do_%s has already called reply_with_error */\n" name;
6207            pr "    goto done;\n";
6208            pr "\n"
6209        | RBufferOut _ ->
6210            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6211            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6212            pr "   */\n";
6213            pr "  if (size == 1 && r == %s)\n" error_code;
6214            pr "    /* do_%s has already called reply_with_error */\n" name;
6215            pr "    goto done;\n";
6216            pr "\n"
6217       );
6218
6219       (* If there are any FileOut parameters, then the impl must
6220        * send its own reply.
6221        *)
6222       let no_reply =
6223         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6224       if no_reply then
6225         pr "  /* do_%s has already sent a reply */\n" name
6226       else (
6227         match fst style with
6228         | RErr -> pr "  reply (NULL, NULL);\n"
6229         | RInt n | RInt64 n | RBool n ->
6230             pr "  struct guestfs_%s_ret ret;\n" name;
6231             pr "  ret.%s = r;\n" n;
6232             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6233               name
6234         | RConstString _ | RConstOptString _ ->
6235             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6236         | RString n ->
6237             pr "  struct guestfs_%s_ret ret;\n" name;
6238             pr "  ret.%s = r;\n" n;
6239             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6240               name;
6241             pr "  free (r);\n"
6242         | RStringList n | RHashtable n ->
6243             pr "  struct guestfs_%s_ret ret;\n" name;
6244             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6245             pr "  ret.%s.%s_val = r;\n" n n;
6246             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6247               name;
6248             pr "  free_strings (r);\n"
6249         | RStruct (n, _) ->
6250             pr "  struct guestfs_%s_ret ret;\n" name;
6251             pr "  ret.%s = *r;\n" n;
6252             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6253               name;
6254             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6255               name
6256         | RStructList (n, _) ->
6257             pr "  struct guestfs_%s_ret ret;\n" name;
6258             pr "  ret.%s = *r;\n" n;
6259             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6260               name;
6261             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6262               name
6263         | RBufferOut n ->
6264             pr "  struct guestfs_%s_ret ret;\n" name;
6265             pr "  ret.%s.%s_val = r;\n" n n;
6266             pr "  ret.%s.%s_len = size;\n" n n;
6267             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6268               name;
6269             pr "  free (r);\n"
6270       );
6271
6272       (* Free the args. *)
6273       pr "done:\n";
6274       (match snd style with
6275        | [] -> ()
6276        | _ ->
6277            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6278              name
6279       );
6280       pr "  return;\n";
6281       pr "}\n\n";
6282   ) daemon_functions;
6283
6284   (* Dispatch function. *)
6285   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6286   pr "{\n";
6287   pr "  switch (proc_nr) {\n";
6288
6289   List.iter (
6290     fun (name, style, _, _, _, _, _) ->
6291       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6292       pr "      %s_stub (xdr_in);\n" name;
6293       pr "      break;\n"
6294   ) daemon_functions;
6295
6296   pr "    default:\n";
6297   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";
6298   pr "  }\n";
6299   pr "}\n";
6300   pr "\n";
6301
6302   (* LVM columns and tokenization functions. *)
6303   (* XXX This generates crap code.  We should rethink how we
6304    * do this parsing.
6305    *)
6306   List.iter (
6307     function
6308     | typ, cols ->
6309         pr "static const char *lvm_%s_cols = \"%s\";\n"
6310           typ (String.concat "," (List.map fst cols));
6311         pr "\n";
6312
6313         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6314         pr "{\n";
6315         pr "  char *tok, *p, *next;\n";
6316         pr "  int i, j;\n";
6317         pr "\n";
6318         (*
6319           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6320           pr "\n";
6321         *)
6322         pr "  if (!str) {\n";
6323         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6324         pr "    return -1;\n";
6325         pr "  }\n";
6326         pr "  if (!*str || c_isspace (*str)) {\n";
6327         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6328         pr "    return -1;\n";
6329         pr "  }\n";
6330         pr "  tok = str;\n";
6331         List.iter (
6332           fun (name, coltype) ->
6333             pr "  if (!tok) {\n";
6334             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6335             pr "    return -1;\n";
6336             pr "  }\n";
6337             pr "  p = strchrnul (tok, ',');\n";
6338             pr "  if (*p) next = p+1; else next = NULL;\n";
6339             pr "  *p = '\\0';\n";
6340             (match coltype with
6341              | FString ->
6342                  pr "  r->%s = strdup (tok);\n" name;
6343                  pr "  if (r->%s == NULL) {\n" name;
6344                  pr "    perror (\"strdup\");\n";
6345                  pr "    return -1;\n";
6346                  pr "  }\n"
6347              | FUUID ->
6348                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6349                  pr "    if (tok[j] == '\\0') {\n";
6350                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6351                  pr "      return -1;\n";
6352                  pr "    } else if (tok[j] != '-')\n";
6353                  pr "      r->%s[i++] = tok[j];\n" name;
6354                  pr "  }\n";
6355              | FBytes ->
6356                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6357                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6358                  pr "    return -1;\n";
6359                  pr "  }\n";
6360              | FInt64 ->
6361                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6362                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6363                  pr "    return -1;\n";
6364                  pr "  }\n";
6365              | FOptPercent ->
6366                  pr "  if (tok[0] == '\\0')\n";
6367                  pr "    r->%s = -1;\n" name;
6368                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6369                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6370                  pr "    return -1;\n";
6371                  pr "  }\n";
6372              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6373                  assert false (* can never be an LVM column *)
6374             );
6375             pr "  tok = next;\n";
6376         ) cols;
6377
6378         pr "  if (tok != NULL) {\n";
6379         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6380         pr "    return -1;\n";
6381         pr "  }\n";
6382         pr "  return 0;\n";
6383         pr "}\n";
6384         pr "\n";
6385
6386         pr "guestfs_int_lvm_%s_list *\n" typ;
6387         pr "parse_command_line_%ss (void)\n" typ;
6388         pr "{\n";
6389         pr "  char *out, *err;\n";
6390         pr "  char *p, *pend;\n";
6391         pr "  int r, i;\n";
6392         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6393         pr "  void *newp;\n";
6394         pr "\n";
6395         pr "  ret = malloc (sizeof *ret);\n";
6396         pr "  if (!ret) {\n";
6397         pr "    reply_with_perror (\"malloc\");\n";
6398         pr "    return NULL;\n";
6399         pr "  }\n";
6400         pr "\n";
6401         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6402         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6403         pr "\n";
6404         pr "  r = command (&out, &err,\n";
6405         pr "           \"lvm\", \"%ss\",\n" typ;
6406         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6407         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6408         pr "  if (r == -1) {\n";
6409         pr "    reply_with_error (\"%%s\", err);\n";
6410         pr "    free (out);\n";
6411         pr "    free (err);\n";
6412         pr "    free (ret);\n";
6413         pr "    return NULL;\n";
6414         pr "  }\n";
6415         pr "\n";
6416         pr "  free (err);\n";
6417         pr "\n";
6418         pr "  /* Tokenize each line of the output. */\n";
6419         pr "  p = out;\n";
6420         pr "  i = 0;\n";
6421         pr "  while (p) {\n";
6422         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6423         pr "    if (pend) {\n";
6424         pr "      *pend = '\\0';\n";
6425         pr "      pend++;\n";
6426         pr "    }\n";
6427         pr "\n";
6428         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6429         pr "      p++;\n";
6430         pr "\n";
6431         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6432         pr "      p = pend;\n";
6433         pr "      continue;\n";
6434         pr "    }\n";
6435         pr "\n";
6436         pr "    /* Allocate some space to store this next entry. */\n";
6437         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6438         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6439         pr "    if (newp == NULL) {\n";
6440         pr "      reply_with_perror (\"realloc\");\n";
6441         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6442         pr "      free (ret);\n";
6443         pr "      free (out);\n";
6444         pr "      return NULL;\n";
6445         pr "    }\n";
6446         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6447         pr "\n";
6448         pr "    /* Tokenize the next entry. */\n";
6449         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6450         pr "    if (r == -1) {\n";
6451         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6452         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6453         pr "      free (ret);\n";
6454         pr "      free (out);\n";
6455         pr "      return NULL;\n";
6456         pr "    }\n";
6457         pr "\n";
6458         pr "    ++i;\n";
6459         pr "    p = pend;\n";
6460         pr "  }\n";
6461         pr "\n";
6462         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6463         pr "\n";
6464         pr "  free (out);\n";
6465         pr "  return ret;\n";
6466         pr "}\n"
6467
6468   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6469
6470 (* Generate a list of function names, for debugging in the daemon.. *)
6471 and generate_daemon_names () =
6472   generate_header CStyle GPLv2plus;
6473
6474   pr "#include <config.h>\n";
6475   pr "\n";
6476   pr "#include \"daemon.h\"\n";
6477   pr "\n";
6478
6479   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6480   pr "const char *function_names[] = {\n";
6481   List.iter (
6482     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6483   ) daemon_functions;
6484   pr "};\n";
6485
6486 (* Generate the optional groups for the daemon to implement
6487  * guestfs_available.
6488  *)
6489 and generate_daemon_optgroups_c () =
6490   generate_header CStyle GPLv2plus;
6491
6492   pr "#include <config.h>\n";
6493   pr "\n";
6494   pr "#include \"daemon.h\"\n";
6495   pr "#include \"optgroups.h\"\n";
6496   pr "\n";
6497
6498   pr "struct optgroup optgroups[] = {\n";
6499   List.iter (
6500     fun (group, _) ->
6501       pr "  { \"%s\", optgroup_%s_available },\n" group group
6502   ) optgroups;
6503   pr "  { NULL, NULL }\n";
6504   pr "};\n"
6505
6506 and generate_daemon_optgroups_h () =
6507   generate_header CStyle GPLv2plus;
6508
6509   List.iter (
6510     fun (group, _) ->
6511       pr "extern int optgroup_%s_available (void);\n" group
6512   ) optgroups
6513
6514 (* Generate the tests. *)
6515 and generate_tests () =
6516   generate_header CStyle GPLv2plus;
6517
6518   pr "\
6519 #include <stdio.h>
6520 #include <stdlib.h>
6521 #include <string.h>
6522 #include <unistd.h>
6523 #include <sys/types.h>
6524 #include <fcntl.h>
6525
6526 #include \"guestfs.h\"
6527 #include \"guestfs-internal.h\"
6528
6529 static guestfs_h *g;
6530 static int suppress_error = 0;
6531
6532 static void print_error (guestfs_h *g, void *data, const char *msg)
6533 {
6534   if (!suppress_error)
6535     fprintf (stderr, \"%%s\\n\", msg);
6536 }
6537
6538 /* FIXME: nearly identical code appears in fish.c */
6539 static void print_strings (char *const *argv)
6540 {
6541   int argc;
6542
6543   for (argc = 0; argv[argc] != NULL; ++argc)
6544     printf (\"\\t%%s\\n\", argv[argc]);
6545 }
6546
6547 /*
6548 static void print_table (char const *const *argv)
6549 {
6550   int i;
6551
6552   for (i = 0; argv[i] != NULL; i += 2)
6553     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6554 }
6555 */
6556
6557 ";
6558
6559   (* Generate a list of commands which are not tested anywhere. *)
6560   pr "static void no_test_warnings (void)\n";
6561   pr "{\n";
6562
6563   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6564   List.iter (
6565     fun (_, _, _, _, tests, _, _) ->
6566       let tests = filter_map (
6567         function
6568         | (_, (Always|If _|Unless _), test) -> Some test
6569         | (_, Disabled, _) -> None
6570       ) tests in
6571       let seq = List.concat (List.map seq_of_test tests) in
6572       let cmds_tested = List.map List.hd seq in
6573       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6574   ) all_functions;
6575
6576   List.iter (
6577     fun (name, _, _, _, _, _, _) ->
6578       if not (Hashtbl.mem hash name) then
6579         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6580   ) all_functions;
6581
6582   pr "}\n";
6583   pr "\n";
6584
6585   (* Generate the actual tests.  Note that we generate the tests
6586    * in reverse order, deliberately, so that (in general) the
6587    * newest tests run first.  This makes it quicker and easier to
6588    * debug them.
6589    *)
6590   let test_names =
6591     List.map (
6592       fun (name, _, _, flags, tests, _, _) ->
6593         mapi (generate_one_test name flags) tests
6594     ) (List.rev all_functions) in
6595   let test_names = List.concat test_names in
6596   let nr_tests = List.length test_names in
6597
6598   pr "\
6599 int main (int argc, char *argv[])
6600 {
6601   char c = 0;
6602   unsigned long int n_failed = 0;
6603   const char *filename;
6604   int fd;
6605   int nr_tests, test_num = 0;
6606
6607   setbuf (stdout, NULL);
6608
6609   no_test_warnings ();
6610
6611   g = guestfs_create ();
6612   if (g == NULL) {
6613     printf (\"guestfs_create FAILED\\n\");
6614     exit (EXIT_FAILURE);
6615   }
6616
6617   guestfs_set_error_handler (g, print_error, NULL);
6618
6619   guestfs_set_path (g, \"../appliance\");
6620
6621   filename = \"test1.img\";
6622   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6623   if (fd == -1) {
6624     perror (filename);
6625     exit (EXIT_FAILURE);
6626   }
6627   if (lseek (fd, %d, SEEK_SET) == -1) {
6628     perror (\"lseek\");
6629     close (fd);
6630     unlink (filename);
6631     exit (EXIT_FAILURE);
6632   }
6633   if (write (fd, &c, 1) == -1) {
6634     perror (\"write\");
6635     close (fd);
6636     unlink (filename);
6637     exit (EXIT_FAILURE);
6638   }
6639   if (close (fd) == -1) {
6640     perror (filename);
6641     unlink (filename);
6642     exit (EXIT_FAILURE);
6643   }
6644   if (guestfs_add_drive (g, filename) == -1) {
6645     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6646     exit (EXIT_FAILURE);
6647   }
6648
6649   filename = \"test2.img\";
6650   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6651   if (fd == -1) {
6652     perror (filename);
6653     exit (EXIT_FAILURE);
6654   }
6655   if (lseek (fd, %d, SEEK_SET) == -1) {
6656     perror (\"lseek\");
6657     close (fd);
6658     unlink (filename);
6659     exit (EXIT_FAILURE);
6660   }
6661   if (write (fd, &c, 1) == -1) {
6662     perror (\"write\");
6663     close (fd);
6664     unlink (filename);
6665     exit (EXIT_FAILURE);
6666   }
6667   if (close (fd) == -1) {
6668     perror (filename);
6669     unlink (filename);
6670     exit (EXIT_FAILURE);
6671   }
6672   if (guestfs_add_drive (g, filename) == -1) {
6673     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6674     exit (EXIT_FAILURE);
6675   }
6676
6677   filename = \"test3.img\";
6678   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6679   if (fd == -1) {
6680     perror (filename);
6681     exit (EXIT_FAILURE);
6682   }
6683   if (lseek (fd, %d, SEEK_SET) == -1) {
6684     perror (\"lseek\");
6685     close (fd);
6686     unlink (filename);
6687     exit (EXIT_FAILURE);
6688   }
6689   if (write (fd, &c, 1) == -1) {
6690     perror (\"write\");
6691     close (fd);
6692     unlink (filename);
6693     exit (EXIT_FAILURE);
6694   }
6695   if (close (fd) == -1) {
6696     perror (filename);
6697     unlink (filename);
6698     exit (EXIT_FAILURE);
6699   }
6700   if (guestfs_add_drive (g, filename) == -1) {
6701     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6702     exit (EXIT_FAILURE);
6703   }
6704
6705   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6706     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6707     exit (EXIT_FAILURE);
6708   }
6709
6710   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6711   alarm (600);
6712
6713   if (guestfs_launch (g) == -1) {
6714     printf (\"guestfs_launch FAILED\\n\");
6715     exit (EXIT_FAILURE);
6716   }
6717
6718   /* Cancel previous alarm. */
6719   alarm (0);
6720
6721   nr_tests = %d;
6722
6723 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6724
6725   iteri (
6726     fun i test_name ->
6727       pr "  test_num++;\n";
6728       pr "  if (guestfs_get_verbose (g))\n";
6729       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6730       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6731       pr "  if (%s () == -1) {\n" test_name;
6732       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6733       pr "    n_failed++;\n";
6734       pr "  }\n";
6735   ) test_names;
6736   pr "\n";
6737
6738   pr "  guestfs_close (g);\n";
6739   pr "  unlink (\"test1.img\");\n";
6740   pr "  unlink (\"test2.img\");\n";
6741   pr "  unlink (\"test3.img\");\n";
6742   pr "\n";
6743
6744   pr "  if (n_failed > 0) {\n";
6745   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6746   pr "    exit (EXIT_FAILURE);\n";
6747   pr "  }\n";
6748   pr "\n";
6749
6750   pr "  exit (EXIT_SUCCESS);\n";
6751   pr "}\n"
6752
6753 and generate_one_test name flags i (init, prereq, test) =
6754   let test_name = sprintf "test_%s_%d" name i in
6755
6756   pr "\
6757 static int %s_skip (void)
6758 {
6759   const char *str;
6760
6761   str = getenv (\"TEST_ONLY\");
6762   if (str)
6763     return strstr (str, \"%s\") == NULL;
6764   str = getenv (\"SKIP_%s\");
6765   if (str && STREQ (str, \"1\")) return 1;
6766   str = getenv (\"SKIP_TEST_%s\");
6767   if (str && STREQ (str, \"1\")) return 1;
6768   return 0;
6769 }
6770
6771 " test_name name (String.uppercase test_name) (String.uppercase name);
6772
6773   (match prereq with
6774    | Disabled | Always -> ()
6775    | If code | Unless code ->
6776        pr "static int %s_prereq (void)\n" test_name;
6777        pr "{\n";
6778        pr "  %s\n" code;
6779        pr "}\n";
6780        pr "\n";
6781   );
6782
6783   pr "\
6784 static int %s (void)
6785 {
6786   if (%s_skip ()) {
6787     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6788     return 0;
6789   }
6790
6791 " test_name test_name test_name;
6792
6793   (* Optional functions should only be tested if the relevant
6794    * support is available in the daemon.
6795    *)
6796   List.iter (
6797     function
6798     | Optional group ->
6799         pr "  {\n";
6800         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6801         pr "    int r;\n";
6802         pr "    suppress_error = 1;\n";
6803         pr "    r = guestfs_available (g, (char **) groups);\n";
6804         pr "    suppress_error = 0;\n";
6805         pr "    if (r == -1) {\n";
6806         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6807         pr "      return 0;\n";
6808         pr "    }\n";
6809         pr "  }\n";
6810     | _ -> ()
6811   ) flags;
6812
6813   (match prereq with
6814    | Disabled ->
6815        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6816    | If _ ->
6817        pr "  if (! %s_prereq ()) {\n" test_name;
6818        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6819        pr "    return 0;\n";
6820        pr "  }\n";
6821        pr "\n";
6822        generate_one_test_body name i test_name init test;
6823    | Unless _ ->
6824        pr "  if (%s_prereq ()) {\n" test_name;
6825        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6826        pr "    return 0;\n";
6827        pr "  }\n";
6828        pr "\n";
6829        generate_one_test_body name i test_name init test;
6830    | Always ->
6831        generate_one_test_body name i test_name init test
6832   );
6833
6834   pr "  return 0;\n";
6835   pr "}\n";
6836   pr "\n";
6837   test_name
6838
6839 and generate_one_test_body name i test_name init test =
6840   (match init with
6841    | InitNone (* XXX at some point, InitNone and InitEmpty became
6842                * folded together as the same thing.  Really we should
6843                * make InitNone do nothing at all, but the tests may
6844                * need to be checked to make sure this is OK.
6845                *)
6846    | InitEmpty ->
6847        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6848        List.iter (generate_test_command_call test_name)
6849          [["blockdev_setrw"; "/dev/sda"];
6850           ["umount_all"];
6851           ["lvm_remove_all"]]
6852    | InitPartition ->
6853        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6854        List.iter (generate_test_command_call test_name)
6855          [["blockdev_setrw"; "/dev/sda"];
6856           ["umount_all"];
6857           ["lvm_remove_all"];
6858           ["part_disk"; "/dev/sda"; "mbr"]]
6859    | InitBasicFS ->
6860        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6861        List.iter (generate_test_command_call test_name)
6862          [["blockdev_setrw"; "/dev/sda"];
6863           ["umount_all"];
6864           ["lvm_remove_all"];
6865           ["part_disk"; "/dev/sda"; "mbr"];
6866           ["mkfs"; "ext2"; "/dev/sda1"];
6867           ["mount_options"; ""; "/dev/sda1"; "/"]]
6868    | InitBasicFSonLVM ->
6869        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6870          test_name;
6871        List.iter (generate_test_command_call test_name)
6872          [["blockdev_setrw"; "/dev/sda"];
6873           ["umount_all"];
6874           ["lvm_remove_all"];
6875           ["part_disk"; "/dev/sda"; "mbr"];
6876           ["pvcreate"; "/dev/sda1"];
6877           ["vgcreate"; "VG"; "/dev/sda1"];
6878           ["lvcreate"; "LV"; "VG"; "8"];
6879           ["mkfs"; "ext2"; "/dev/VG/LV"];
6880           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6881    | InitISOFS ->
6882        pr "  /* InitISOFS for %s */\n" test_name;
6883        List.iter (generate_test_command_call test_name)
6884          [["blockdev_setrw"; "/dev/sda"];
6885           ["umount_all"];
6886           ["lvm_remove_all"];
6887           ["mount_ro"; "/dev/sdd"; "/"]]
6888   );
6889
6890   let get_seq_last = function
6891     | [] ->
6892         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6893           test_name
6894     | seq ->
6895         let seq = List.rev seq in
6896         List.rev (List.tl seq), List.hd seq
6897   in
6898
6899   match test with
6900   | TestRun seq ->
6901       pr "  /* TestRun for %s (%d) */\n" name i;
6902       List.iter (generate_test_command_call test_name) seq
6903   | TestOutput (seq, expected) ->
6904       pr "  /* TestOutput for %s (%d) */\n" name i;
6905       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6906       let seq, last = get_seq_last seq in
6907       let test () =
6908         pr "    if (STRNEQ (r, expected)) {\n";
6909         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6910         pr "      return -1;\n";
6911         pr "    }\n"
6912       in
6913       List.iter (generate_test_command_call test_name) seq;
6914       generate_test_command_call ~test test_name last
6915   | TestOutputList (seq, expected) ->
6916       pr "  /* TestOutputList for %s (%d) */\n" name i;
6917       let seq, last = get_seq_last seq in
6918       let test () =
6919         iteri (
6920           fun i str ->
6921             pr "    if (!r[%d]) {\n" i;
6922             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6923             pr "      print_strings (r);\n";
6924             pr "      return -1;\n";
6925             pr "    }\n";
6926             pr "    {\n";
6927             pr "      const char *expected = \"%s\";\n" (c_quote str);
6928             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6929             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6930             pr "        return -1;\n";
6931             pr "      }\n";
6932             pr "    }\n"
6933         ) expected;
6934         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6935         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6936           test_name;
6937         pr "      print_strings (r);\n";
6938         pr "      return -1;\n";
6939         pr "    }\n"
6940       in
6941       List.iter (generate_test_command_call test_name) seq;
6942       generate_test_command_call ~test test_name last
6943   | TestOutputListOfDevices (seq, expected) ->
6944       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6945       let seq, last = get_seq_last seq in
6946       let test () =
6947         iteri (
6948           fun i str ->
6949             pr "    if (!r[%d]) {\n" i;
6950             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6951             pr "      print_strings (r);\n";
6952             pr "      return -1;\n";
6953             pr "    }\n";
6954             pr "    {\n";
6955             pr "      const char *expected = \"%s\";\n" (c_quote str);
6956             pr "      r[%d][5] = 's';\n" i;
6957             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6958             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6959             pr "        return -1;\n";
6960             pr "      }\n";
6961             pr "    }\n"
6962         ) expected;
6963         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6964         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6965           test_name;
6966         pr "      print_strings (r);\n";
6967         pr "      return -1;\n";
6968         pr "    }\n"
6969       in
6970       List.iter (generate_test_command_call test_name) seq;
6971       generate_test_command_call ~test test_name last
6972   | TestOutputInt (seq, expected) ->
6973       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6974       let seq, last = get_seq_last seq in
6975       let test () =
6976         pr "    if (r != %d) {\n" expected;
6977         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6978           test_name expected;
6979         pr "               (int) r);\n";
6980         pr "      return -1;\n";
6981         pr "    }\n"
6982       in
6983       List.iter (generate_test_command_call test_name) seq;
6984       generate_test_command_call ~test test_name last
6985   | TestOutputIntOp (seq, op, expected) ->
6986       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6987       let seq, last = get_seq_last seq in
6988       let test () =
6989         pr "    if (! (r %s %d)) {\n" op expected;
6990         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6991           test_name op expected;
6992         pr "               (int) r);\n";
6993         pr "      return -1;\n";
6994         pr "    }\n"
6995       in
6996       List.iter (generate_test_command_call test_name) seq;
6997       generate_test_command_call ~test test_name last
6998   | TestOutputTrue seq ->
6999       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7000       let seq, last = get_seq_last seq in
7001       let test () =
7002         pr "    if (!r) {\n";
7003         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7004           test_name;
7005         pr "      return -1;\n";
7006         pr "    }\n"
7007       in
7008       List.iter (generate_test_command_call test_name) seq;
7009       generate_test_command_call ~test test_name last
7010   | TestOutputFalse seq ->
7011       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7012       let seq, last = get_seq_last seq in
7013       let test () =
7014         pr "    if (r) {\n";
7015         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7016           test_name;
7017         pr "      return -1;\n";
7018         pr "    }\n"
7019       in
7020       List.iter (generate_test_command_call test_name) seq;
7021       generate_test_command_call ~test test_name last
7022   | TestOutputLength (seq, expected) ->
7023       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7024       let seq, last = get_seq_last seq in
7025       let test () =
7026         pr "    int j;\n";
7027         pr "    for (j = 0; j < %d; ++j)\n" expected;
7028         pr "      if (r[j] == NULL) {\n";
7029         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7030           test_name;
7031         pr "        print_strings (r);\n";
7032         pr "        return -1;\n";
7033         pr "      }\n";
7034         pr "    if (r[j] != NULL) {\n";
7035         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7036           test_name;
7037         pr "      print_strings (r);\n";
7038         pr "      return -1;\n";
7039         pr "    }\n"
7040       in
7041       List.iter (generate_test_command_call test_name) seq;
7042       generate_test_command_call ~test test_name last
7043   | TestOutputBuffer (seq, expected) ->
7044       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7045       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7046       let seq, last = get_seq_last seq in
7047       let len = String.length expected in
7048       let test () =
7049         pr "    if (size != %d) {\n" len;
7050         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7051         pr "      return -1;\n";
7052         pr "    }\n";
7053         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7054         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7055         pr "      return -1;\n";
7056         pr "    }\n"
7057       in
7058       List.iter (generate_test_command_call test_name) seq;
7059       generate_test_command_call ~test test_name last
7060   | TestOutputStruct (seq, checks) ->
7061       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7062       let seq, last = get_seq_last seq in
7063       let test () =
7064         List.iter (
7065           function
7066           | CompareWithInt (field, expected) ->
7067               pr "    if (r->%s != %d) {\n" field expected;
7068               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7069                 test_name field expected;
7070               pr "               (int) r->%s);\n" field;
7071               pr "      return -1;\n";
7072               pr "    }\n"
7073           | CompareWithIntOp (field, op, expected) ->
7074               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7075               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7076                 test_name field op expected;
7077               pr "               (int) r->%s);\n" field;
7078               pr "      return -1;\n";
7079               pr "    }\n"
7080           | CompareWithString (field, expected) ->
7081               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7082               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7083                 test_name field expected;
7084               pr "               r->%s);\n" field;
7085               pr "      return -1;\n";
7086               pr "    }\n"
7087           | CompareFieldsIntEq (field1, field2) ->
7088               pr "    if (r->%s != r->%s) {\n" field1 field2;
7089               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7090                 test_name field1 field2;
7091               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7092               pr "      return -1;\n";
7093               pr "    }\n"
7094           | CompareFieldsStrEq (field1, field2) ->
7095               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7096               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7097                 test_name field1 field2;
7098               pr "               r->%s, r->%s);\n" field1 field2;
7099               pr "      return -1;\n";
7100               pr "    }\n"
7101         ) checks
7102       in
7103       List.iter (generate_test_command_call test_name) seq;
7104       generate_test_command_call ~test test_name last
7105   | TestLastFail seq ->
7106       pr "  /* TestLastFail for %s (%d) */\n" name i;
7107       let seq, last = get_seq_last seq in
7108       List.iter (generate_test_command_call test_name) seq;
7109       generate_test_command_call test_name ~expect_error:true last
7110
7111 (* Generate the code to run a command, leaving the result in 'r'.
7112  * If you expect to get an error then you should set expect_error:true.
7113  *)
7114 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7115   match cmd with
7116   | [] -> assert false
7117   | name :: args ->
7118       (* Look up the command to find out what args/ret it has. *)
7119       let style =
7120         try
7121           let _, style, _, _, _, _, _ =
7122             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7123           style
7124         with Not_found ->
7125           failwithf "%s: in test, command %s was not found" test_name name in
7126
7127       if List.length (snd style) <> List.length args then
7128         failwithf "%s: in test, wrong number of args given to %s"
7129           test_name name;
7130
7131       pr "  {\n";
7132
7133       List.iter (
7134         function
7135         | OptString n, "NULL" -> ()
7136         | Pathname n, arg
7137         | Device n, arg
7138         | Dev_or_Path n, arg
7139         | String n, arg
7140         | OptString n, arg ->
7141             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7142         | Int _, _
7143         | Int64 _, _
7144         | Bool _, _
7145         | FileIn _, _ | FileOut _, _ -> ()
7146         | StringList n, "" | DeviceList n, "" ->
7147             pr "    const char *const %s[1] = { NULL };\n" n
7148         | StringList n, arg | DeviceList n, arg ->
7149             let strs = string_split " " arg in
7150             iteri (
7151               fun i str ->
7152                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7153             ) strs;
7154             pr "    const char *const %s[] = {\n" n;
7155             iteri (
7156               fun i _ -> pr "      %s_%d,\n" n i
7157             ) strs;
7158             pr "      NULL\n";
7159             pr "    };\n";
7160       ) (List.combine (snd style) args);
7161
7162       let error_code =
7163         match fst style with
7164         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7165         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7166         | RConstString _ | RConstOptString _ ->
7167             pr "    const char *r;\n"; "NULL"
7168         | RString _ -> pr "    char *r;\n"; "NULL"
7169         | RStringList _ | RHashtable _ ->
7170             pr "    char **r;\n";
7171             pr "    int i;\n";
7172             "NULL"
7173         | RStruct (_, typ) ->
7174             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7175         | RStructList (_, typ) ->
7176             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7177         | RBufferOut _ ->
7178             pr "    char *r;\n";
7179             pr "    size_t size;\n";
7180             "NULL" in
7181
7182       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7183       pr "    r = guestfs_%s (g" name;
7184
7185       (* Generate the parameters. *)
7186       List.iter (
7187         function
7188         | OptString _, "NULL" -> pr ", NULL"
7189         | Pathname n, _
7190         | Device n, _ | Dev_or_Path n, _
7191         | String n, _
7192         | OptString n, _ ->
7193             pr ", %s" n
7194         | FileIn _, arg | FileOut _, arg ->
7195             pr ", \"%s\"" (c_quote arg)
7196         | StringList n, _ | DeviceList n, _ ->
7197             pr ", (char **) %s" n
7198         | Int _, arg ->
7199             let i =
7200               try int_of_string arg
7201               with Failure "int_of_string" ->
7202                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7203             pr ", %d" i
7204         | Int64 _, arg ->
7205             let i =
7206               try Int64.of_string arg
7207               with Failure "int_of_string" ->
7208                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7209             pr ", %Ld" i
7210         | Bool _, arg ->
7211             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7212       ) (List.combine (snd style) args);
7213
7214       (match fst style with
7215        | RBufferOut _ -> pr ", &size"
7216        | _ -> ()
7217       );
7218
7219       pr ");\n";
7220
7221       if not expect_error then
7222         pr "    if (r == %s)\n" error_code
7223       else
7224         pr "    if (r != %s)\n" error_code;
7225       pr "      return -1;\n";
7226
7227       (* Insert the test code. *)
7228       (match test with
7229        | None -> ()
7230        | Some f -> f ()
7231       );
7232
7233       (match fst style with
7234        | RErr | RInt _ | RInt64 _ | RBool _
7235        | RConstString _ | RConstOptString _ -> ()
7236        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7237        | RStringList _ | RHashtable _ ->
7238            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7239            pr "      free (r[i]);\n";
7240            pr "    free (r);\n"
7241        | RStruct (_, typ) ->
7242            pr "    guestfs_free_%s (r);\n" typ
7243        | RStructList (_, typ) ->
7244            pr "    guestfs_free_%s_list (r);\n" typ
7245       );
7246
7247       pr "  }\n"
7248
7249 and c_quote str =
7250   let str = replace_str str "\r" "\\r" in
7251   let str = replace_str str "\n" "\\n" in
7252   let str = replace_str str "\t" "\\t" in
7253   let str = replace_str str "\000" "\\0" in
7254   str
7255
7256 (* Generate a lot of different functions for guestfish. *)
7257 and generate_fish_cmds () =
7258   generate_header CStyle GPLv2plus;
7259
7260   let all_functions =
7261     List.filter (
7262       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7263     ) all_functions in
7264   let all_functions_sorted =
7265     List.filter (
7266       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7267     ) all_functions_sorted in
7268
7269   pr "#include <config.h>\n";
7270   pr "\n";
7271   pr "#include <stdio.h>\n";
7272   pr "#include <stdlib.h>\n";
7273   pr "#include <string.h>\n";
7274   pr "#include <inttypes.h>\n";
7275   pr "\n";
7276   pr "#include <guestfs.h>\n";
7277   pr "#include \"c-ctype.h\"\n";
7278   pr "#include \"full-write.h\"\n";
7279   pr "#include \"xstrtol.h\"\n";
7280   pr "#include \"fish.h\"\n";
7281   pr "\n";
7282
7283   (* list_commands function, which implements guestfish -h *)
7284   pr "void list_commands (void)\n";
7285   pr "{\n";
7286   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7287   pr "  list_builtin_commands ();\n";
7288   List.iter (
7289     fun (name, _, _, flags, _, shortdesc, _) ->
7290       let name = replace_char name '_' '-' in
7291       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7292         name shortdesc
7293   ) all_functions_sorted;
7294   pr "  printf (\"    %%s\\n\",";
7295   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7296   pr "}\n";
7297   pr "\n";
7298
7299   (* display_command function, which implements guestfish -h cmd *)
7300   pr "void display_command (const char *cmd)\n";
7301   pr "{\n";
7302   List.iter (
7303     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7304       let name2 = replace_char name '_' '-' in
7305       let alias =
7306         try find_map (function FishAlias n -> Some n | _ -> None) flags
7307         with Not_found -> name in
7308       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7309       let synopsis =
7310         match snd style with
7311         | [] -> name2
7312         | args ->
7313             sprintf "%s %s"
7314               name2 (String.concat " " (List.map name_of_argt args)) in
7315
7316       let warnings =
7317         if List.mem ProtocolLimitWarning flags then
7318           ("\n\n" ^ protocol_limit_warning)
7319         else "" in
7320
7321       (* For DangerWillRobinson commands, we should probably have
7322        * guestfish prompt before allowing you to use them (especially
7323        * in interactive mode). XXX
7324        *)
7325       let warnings =
7326         warnings ^
7327           if List.mem DangerWillRobinson flags then
7328             ("\n\n" ^ danger_will_robinson)
7329           else "" in
7330
7331       let warnings =
7332         warnings ^
7333           match deprecation_notice flags with
7334           | None -> ""
7335           | Some txt -> "\n\n" ^ txt in
7336
7337       let describe_alias =
7338         if name <> alias then
7339           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7340         else "" in
7341
7342       pr "  if (";
7343       pr "STRCASEEQ (cmd, \"%s\")" name;
7344       if name <> name2 then
7345         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7346       if name <> alias then
7347         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7348       pr ")\n";
7349       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7350         name2 shortdesc
7351         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7352          "=head1 DESCRIPTION\n\n" ^
7353          longdesc ^ warnings ^ describe_alias);
7354       pr "  else\n"
7355   ) all_functions;
7356   pr "    display_builtin_command (cmd);\n";
7357   pr "}\n";
7358   pr "\n";
7359
7360   let emit_print_list_function typ =
7361     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7362       typ typ typ;
7363     pr "{\n";
7364     pr "  unsigned int i;\n";
7365     pr "\n";
7366     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7367     pr "    printf (\"[%%d] = {\\n\", i);\n";
7368     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7369     pr "    printf (\"}\\n\");\n";
7370     pr "  }\n";
7371     pr "}\n";
7372     pr "\n";
7373   in
7374
7375   (* print_* functions *)
7376   List.iter (
7377     fun (typ, cols) ->
7378       let needs_i =
7379         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7380
7381       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7382       pr "{\n";
7383       if needs_i then (
7384         pr "  unsigned int i;\n";
7385         pr "\n"
7386       );
7387       List.iter (
7388         function
7389         | name, FString ->
7390             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7391         | name, FUUID ->
7392             pr "  printf (\"%%s%s: \", indent);\n" name;
7393             pr "  for (i = 0; i < 32; ++i)\n";
7394             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7395             pr "  printf (\"\\n\");\n"
7396         | name, FBuffer ->
7397             pr "  printf (\"%%s%s: \", indent);\n" name;
7398             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7399             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7400             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7401             pr "    else\n";
7402             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7403             pr "  printf (\"\\n\");\n"
7404         | name, (FUInt64|FBytes) ->
7405             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7406               name typ name
7407         | name, FInt64 ->
7408             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7409               name typ name
7410         | name, FUInt32 ->
7411             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7412               name typ name
7413         | name, FInt32 ->
7414             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7415               name typ name
7416         | name, FChar ->
7417             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7418               name typ name
7419         | name, FOptPercent ->
7420             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7421               typ name name typ name;
7422             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7423       ) cols;
7424       pr "}\n";
7425       pr "\n";
7426   ) structs;
7427
7428   (* Emit a print_TYPE_list function definition only if that function is used. *)
7429   List.iter (
7430     function
7431     | typ, (RStructListOnly | RStructAndList) ->
7432         (* generate the function for typ *)
7433         emit_print_list_function typ
7434     | typ, _ -> () (* empty *)
7435   ) (rstructs_used_by all_functions);
7436
7437   (* Emit a print_TYPE function definition only if that function is used. *)
7438   List.iter (
7439     function
7440     | typ, (RStructOnly | RStructAndList) ->
7441         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7442         pr "{\n";
7443         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7444         pr "}\n";
7445         pr "\n";
7446     | typ, _ -> () (* empty *)
7447   ) (rstructs_used_by all_functions);
7448
7449   (* run_<action> actions *)
7450   List.iter (
7451     fun (name, style, _, flags, _, _, _) ->
7452       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7453       pr "{\n";
7454       (match fst style with
7455        | RErr
7456        | RInt _
7457        | RBool _ -> pr "  int r;\n"
7458        | RInt64 _ -> pr "  int64_t r;\n"
7459        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7460        | RString _ -> pr "  char *r;\n"
7461        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7462        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7463        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7464        | RBufferOut _ ->
7465            pr "  char *r;\n";
7466            pr "  size_t size;\n";
7467       );
7468       List.iter (
7469         function
7470         | Device n
7471         | String n
7472         | OptString n -> pr "  const char *%s;\n" n
7473         | Pathname n
7474         | Dev_or_Path n
7475         | FileIn n
7476         | FileOut n -> pr "  char *%s;\n" n
7477         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7478         | Bool n -> pr "  int %s;\n" n
7479         | Int n -> pr "  int %s;\n" n
7480         | Int64 n -> pr "  int64_t %s;\n" n
7481       ) (snd style);
7482
7483       (* Check and convert parameters. *)
7484       let argc_expected = List.length (snd style) in
7485       pr "  if (argc != %d) {\n" argc_expected;
7486       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7487         argc_expected;
7488       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7489       pr "    return -1;\n";
7490       pr "  }\n";
7491
7492       let parse_integer fn fntyp rtyp range name i =
7493         pr "  {\n";
7494         pr "    strtol_error xerr;\n";
7495         pr "    %s r;\n" fntyp;
7496         pr "\n";
7497         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7498         pr "    if (xerr != LONGINT_OK) {\n";
7499         pr "      fprintf (stderr,\n";
7500         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7501         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7502         pr "      return -1;\n";
7503         pr "    }\n";
7504         (match range with
7505          | None -> ()
7506          | Some (min, max, comment) ->
7507              pr "    /* %s */\n" comment;
7508              pr "    if (r < %s || r > %s) {\n" min max;
7509              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7510                name;
7511              pr "      return -1;\n";
7512              pr "    }\n";
7513              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7514         );
7515         pr "    %s = r;\n" name;
7516         pr "  }\n";
7517       in
7518
7519       iteri (
7520         fun i ->
7521           function
7522           | Device name
7523           | String name ->
7524               pr "  %s = argv[%d];\n" name i
7525           | Pathname name
7526           | Dev_or_Path name ->
7527               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7528               pr "  if (%s == NULL) return -1;\n" name
7529           | OptString name ->
7530               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7531                 name i i
7532           | FileIn name ->
7533               pr "  %s = file_in (argv[%d]);\n" name i;
7534               pr "  if (%s == NULL) return -1;\n" name
7535           | FileOut name ->
7536               pr "  %s = file_out (argv[%d]);\n" name i;
7537               pr "  if (%s == NULL) return -1;\n" name
7538           | StringList name | DeviceList name ->
7539               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7540               pr "  if (%s == NULL) return -1;\n" name;
7541           | Bool name ->
7542               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7543           | Int name ->
7544               let range =
7545                 let min = "(-(2LL<<30))"
7546                 and max = "((2LL<<30)-1)"
7547                 and comment =
7548                   "The Int type in the generator is a signed 31 bit int." in
7549                 Some (min, max, comment) in
7550               parse_integer "xstrtoll" "long long" "int" range name i
7551           | Int64 name ->
7552               parse_integer "xstrtoll" "long long" "int64_t" None name i
7553       ) (snd style);
7554
7555       (* Call C API function. *)
7556       let fn =
7557         try find_map (function FishAction n -> Some n | _ -> None) flags
7558         with Not_found -> sprintf "guestfs_%s" name in
7559       pr "  r = %s " fn;
7560       generate_c_call_args ~handle:"g" style;
7561       pr ";\n";
7562
7563       List.iter (
7564         function
7565         | Device name | String name
7566         | OptString name | Bool name
7567         | Int name | Int64 name -> ()
7568         | Pathname name | Dev_or_Path name | FileOut name ->
7569             pr "  free (%s);\n" name
7570         | FileIn name ->
7571             pr "  free_file_in (%s);\n" name
7572         | StringList name | DeviceList name ->
7573             pr "  free_strings (%s);\n" name
7574       ) (snd style);
7575
7576       (* Any output flags? *)
7577       let fish_output =
7578         let flags = filter_map (
7579           function FishOutput flag -> Some flag | _ -> None
7580         ) flags in
7581         match flags with
7582         | [] -> None
7583         | [f] -> Some f
7584         | _ ->
7585             failwithf "%s: more than one FishOutput flag is not allowed" name in
7586
7587       (* Check return value for errors and display command results. *)
7588       (match fst style with
7589        | RErr -> pr "  return r;\n"
7590        | RInt _ ->
7591            pr "  if (r == -1) return -1;\n";
7592            (match fish_output with
7593             | None ->
7594                 pr "  printf (\"%%d\\n\", r);\n";
7595             | Some FishOutputOctal ->
7596                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7597             | Some FishOutputHexadecimal ->
7598                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7599            pr "  return 0;\n"
7600        | RInt64 _ ->
7601            pr "  if (r == -1) return -1;\n";
7602            (match fish_output with
7603             | None ->
7604                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7605             | Some FishOutputOctal ->
7606                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7607             | Some FishOutputHexadecimal ->
7608                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7609            pr "  return 0;\n"
7610        | RBool _ ->
7611            pr "  if (r == -1) return -1;\n";
7612            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7613            pr "  return 0;\n"
7614        | RConstString _ ->
7615            pr "  if (r == NULL) return -1;\n";
7616            pr "  printf (\"%%s\\n\", r);\n";
7617            pr "  return 0;\n"
7618        | RConstOptString _ ->
7619            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7620            pr "  return 0;\n"
7621        | RString _ ->
7622            pr "  if (r == NULL) return -1;\n";
7623            pr "  printf (\"%%s\\n\", r);\n";
7624            pr "  free (r);\n";
7625            pr "  return 0;\n"
7626        | RStringList _ ->
7627            pr "  if (r == NULL) return -1;\n";
7628            pr "  print_strings (r);\n";
7629            pr "  free_strings (r);\n";
7630            pr "  return 0;\n"
7631        | RStruct (_, typ) ->
7632            pr "  if (r == NULL) return -1;\n";
7633            pr "  print_%s (r);\n" typ;
7634            pr "  guestfs_free_%s (r);\n" typ;
7635            pr "  return 0;\n"
7636        | RStructList (_, typ) ->
7637            pr "  if (r == NULL) return -1;\n";
7638            pr "  print_%s_list (r);\n" typ;
7639            pr "  guestfs_free_%s_list (r);\n" typ;
7640            pr "  return 0;\n"
7641        | RHashtable _ ->
7642            pr "  if (r == NULL) return -1;\n";
7643            pr "  print_table (r);\n";
7644            pr "  free_strings (r);\n";
7645            pr "  return 0;\n"
7646        | RBufferOut _ ->
7647            pr "  if (r == NULL) return -1;\n";
7648            pr "  if (full_write (1, r, size) != size) {\n";
7649            pr "    perror (\"write\");\n";
7650            pr "    free (r);\n";
7651            pr "    return -1;\n";
7652            pr "  }\n";
7653            pr "  free (r);\n";
7654            pr "  return 0;\n"
7655       );
7656       pr "}\n";
7657       pr "\n"
7658   ) all_functions;
7659
7660   (* run_action function *)
7661   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7662   pr "{\n";
7663   List.iter (
7664     fun (name, _, _, flags, _, _, _) ->
7665       let name2 = replace_char name '_' '-' in
7666       let alias =
7667         try find_map (function FishAlias n -> Some n | _ -> None) flags
7668         with Not_found -> name in
7669       pr "  if (";
7670       pr "STRCASEEQ (cmd, \"%s\")" name;
7671       if name <> name2 then
7672         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7673       if name <> alias then
7674         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7675       pr ")\n";
7676       pr "    return run_%s (cmd, argc, argv);\n" name;
7677       pr "  else\n";
7678   ) all_functions;
7679   pr "    {\n";
7680   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7681   pr "      if (command_num == 1)\n";
7682   pr "        extended_help_message ();\n";
7683   pr "      return -1;\n";
7684   pr "    }\n";
7685   pr "  return 0;\n";
7686   pr "}\n";
7687   pr "\n"
7688
7689 (* Readline completion for guestfish. *)
7690 and generate_fish_completion () =
7691   generate_header CStyle GPLv2plus;
7692
7693   let all_functions =
7694     List.filter (
7695       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7696     ) all_functions in
7697
7698   pr "\
7699 #include <config.h>
7700
7701 #include <stdio.h>
7702 #include <stdlib.h>
7703 #include <string.h>
7704
7705 #ifdef HAVE_LIBREADLINE
7706 #include <readline/readline.h>
7707 #endif
7708
7709 #include \"fish.h\"
7710
7711 #ifdef HAVE_LIBREADLINE
7712
7713 static const char *const commands[] = {
7714   BUILTIN_COMMANDS_FOR_COMPLETION,
7715 ";
7716
7717   (* Get the commands, including the aliases.  They don't need to be
7718    * sorted - the generator() function just does a dumb linear search.
7719    *)
7720   let commands =
7721     List.map (
7722       fun (name, _, _, flags, _, _, _) ->
7723         let name2 = replace_char name '_' '-' in
7724         let alias =
7725           try find_map (function FishAlias n -> Some n | _ -> None) flags
7726           with Not_found -> name in
7727
7728         if name <> alias then [name2; alias] else [name2]
7729     ) all_functions in
7730   let commands = List.flatten commands in
7731
7732   List.iter (pr "  \"%s\",\n") commands;
7733
7734   pr "  NULL
7735 };
7736
7737 static char *
7738 generator (const char *text, int state)
7739 {
7740   static int index, len;
7741   const char *name;
7742
7743   if (!state) {
7744     index = 0;
7745     len = strlen (text);
7746   }
7747
7748   rl_attempted_completion_over = 1;
7749
7750   while ((name = commands[index]) != NULL) {
7751     index++;
7752     if (STRCASEEQLEN (name, text, len))
7753       return strdup (name);
7754   }
7755
7756   return NULL;
7757 }
7758
7759 #endif /* HAVE_LIBREADLINE */
7760
7761 #ifdef HAVE_RL_COMPLETION_MATCHES
7762 #define RL_COMPLETION_MATCHES rl_completion_matches
7763 #else
7764 #ifdef HAVE_COMPLETION_MATCHES
7765 #define RL_COMPLETION_MATCHES completion_matches
7766 #endif
7767 #endif /* else just fail if we don't have either symbol */
7768
7769 char **
7770 do_completion (const char *text, int start, int end)
7771 {
7772   char **matches = NULL;
7773
7774 #ifdef HAVE_LIBREADLINE
7775   rl_completion_append_character = ' ';
7776
7777   if (start == 0)
7778     matches = RL_COMPLETION_MATCHES (text, generator);
7779   else if (complete_dest_paths)
7780     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7781 #endif
7782
7783   return matches;
7784 }
7785 ";
7786
7787 (* Generate the POD documentation for guestfish. *)
7788 and generate_fish_actions_pod () =
7789   let all_functions_sorted =
7790     List.filter (
7791       fun (_, _, _, flags, _, _, _) ->
7792         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7793     ) all_functions_sorted in
7794
7795   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7796
7797   List.iter (
7798     fun (name, style, _, flags, _, _, longdesc) ->
7799       let longdesc =
7800         Str.global_substitute rex (
7801           fun s ->
7802             let sub =
7803               try Str.matched_group 1 s
7804               with Not_found ->
7805                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7806             "C<" ^ replace_char sub '_' '-' ^ ">"
7807         ) longdesc in
7808       let name = replace_char name '_' '-' in
7809       let alias =
7810         try find_map (function FishAlias n -> Some n | _ -> None) flags
7811         with Not_found -> name in
7812
7813       pr "=head2 %s" name;
7814       if name <> alias then
7815         pr " | %s" alias;
7816       pr "\n";
7817       pr "\n";
7818       pr " %s" name;
7819       List.iter (
7820         function
7821         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7822         | OptString n -> pr " %s" n
7823         | StringList n | DeviceList n -> pr " '%s ...'" n
7824         | Bool _ -> pr " true|false"
7825         | Int n -> pr " %s" n
7826         | Int64 n -> pr " %s" n
7827         | FileIn n | FileOut n -> pr " (%s|-)" n
7828       ) (snd style);
7829       pr "\n";
7830       pr "\n";
7831       pr "%s\n\n" longdesc;
7832
7833       if List.exists (function FileIn _ | FileOut _ -> true
7834                       | _ -> false) (snd style) then
7835         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7836
7837       if List.mem ProtocolLimitWarning flags then
7838         pr "%s\n\n" protocol_limit_warning;
7839
7840       if List.mem DangerWillRobinson flags then
7841         pr "%s\n\n" danger_will_robinson;
7842
7843       match deprecation_notice flags with
7844       | None -> ()
7845       | Some txt -> pr "%s\n\n" txt
7846   ) all_functions_sorted
7847
7848 (* Generate a C function prototype. *)
7849 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7850     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7851     ?(prefix = "")
7852     ?handle name style =
7853   if extern then pr "extern ";
7854   if static then pr "static ";
7855   (match fst style with
7856    | RErr -> pr "int "
7857    | RInt _ -> pr "int "
7858    | RInt64 _ -> pr "int64_t "
7859    | RBool _ -> pr "int "
7860    | RConstString _ | RConstOptString _ -> pr "const char *"
7861    | RString _ | RBufferOut _ -> pr "char *"
7862    | RStringList _ | RHashtable _ -> pr "char **"
7863    | RStruct (_, typ) ->
7864        if not in_daemon then pr "struct guestfs_%s *" typ
7865        else pr "guestfs_int_%s *" typ
7866    | RStructList (_, typ) ->
7867        if not in_daemon then pr "struct guestfs_%s_list *" typ
7868        else pr "guestfs_int_%s_list *" typ
7869   );
7870   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7871   pr "%s%s (" prefix name;
7872   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7873     pr "void"
7874   else (
7875     let comma = ref false in
7876     (match handle with
7877      | None -> ()
7878      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7879     );
7880     let next () =
7881       if !comma then (
7882         if single_line then pr ", " else pr ",\n\t\t"
7883       );
7884       comma := true
7885     in
7886     List.iter (
7887       function
7888       | Pathname n
7889       | Device n | Dev_or_Path n
7890       | String n
7891       | OptString n ->
7892           next ();
7893           pr "const char *%s" n
7894       | StringList n | DeviceList n ->
7895           next ();
7896           pr "char *const *%s" n
7897       | Bool n -> next (); pr "int %s" n
7898       | Int n -> next (); pr "int %s" n
7899       | Int64 n -> next (); pr "int64_t %s" n
7900       | FileIn n
7901       | FileOut n ->
7902           if not in_daemon then (next (); pr "const char *%s" n)
7903     ) (snd style);
7904     if is_RBufferOut then (next (); pr "size_t *size_r");
7905   );
7906   pr ")";
7907   if semicolon then pr ";";
7908   if newline then pr "\n"
7909
7910 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7911 and generate_c_call_args ?handle ?(decl = false) style =
7912   pr "(";
7913   let comma = ref false in
7914   let next () =
7915     if !comma then pr ", ";
7916     comma := true
7917   in
7918   (match handle with
7919    | None -> ()
7920    | Some handle -> pr "%s" handle; comma := true
7921   );
7922   List.iter (
7923     fun arg ->
7924       next ();
7925       pr "%s" (name_of_argt arg)
7926   ) (snd style);
7927   (* For RBufferOut calls, add implicit &size parameter. *)
7928   if not decl then (
7929     match fst style with
7930     | RBufferOut _ ->
7931         next ();
7932         pr "&size"
7933     | _ -> ()
7934   );
7935   pr ")"
7936
7937 (* Generate the OCaml bindings interface. *)
7938 and generate_ocaml_mli () =
7939   generate_header OCamlStyle LGPLv2plus;
7940
7941   pr "\
7942 (** For API documentation you should refer to the C API
7943     in the guestfs(3) manual page.  The OCaml API uses almost
7944     exactly the same calls. *)
7945
7946 type t
7947 (** A [guestfs_h] handle. *)
7948
7949 exception Error of string
7950 (** This exception is raised when there is an error. *)
7951
7952 exception Handle_closed of string
7953 (** This exception is raised if you use a {!Guestfs.t} handle
7954     after calling {!close} on it.  The string is the name of
7955     the function. *)
7956
7957 val create : unit -> t
7958 (** Create a {!Guestfs.t} handle. *)
7959
7960 val close : t -> unit
7961 (** Close the {!Guestfs.t} handle and free up all resources used
7962     by it immediately.
7963
7964     Handles are closed by the garbage collector when they become
7965     unreferenced, but callers can call this in order to provide
7966     predictable cleanup. *)
7967
7968 ";
7969   generate_ocaml_structure_decls ();
7970
7971   (* The actions. *)
7972   List.iter (
7973     fun (name, style, _, _, _, shortdesc, _) ->
7974       generate_ocaml_prototype name style;
7975       pr "(** %s *)\n" shortdesc;
7976       pr "\n"
7977   ) all_functions_sorted
7978
7979 (* Generate the OCaml bindings implementation. *)
7980 and generate_ocaml_ml () =
7981   generate_header OCamlStyle LGPLv2plus;
7982
7983   pr "\
7984 type t
7985
7986 exception Error of string
7987 exception Handle_closed of string
7988
7989 external create : unit -> t = \"ocaml_guestfs_create\"
7990 external close : t -> unit = \"ocaml_guestfs_close\"
7991
7992 (* Give the exceptions names, so they can be raised from the C code. *)
7993 let () =
7994   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7995   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7996
7997 ";
7998
7999   generate_ocaml_structure_decls ();
8000
8001   (* The actions. *)
8002   List.iter (
8003     fun (name, style, _, _, _, shortdesc, _) ->
8004       generate_ocaml_prototype ~is_external:true name style;
8005   ) all_functions_sorted
8006
8007 (* Generate the OCaml bindings C implementation. *)
8008 and generate_ocaml_c () =
8009   generate_header CStyle LGPLv2plus;
8010
8011   pr "\
8012 #include <stdio.h>
8013 #include <stdlib.h>
8014 #include <string.h>
8015
8016 #include <caml/config.h>
8017 #include <caml/alloc.h>
8018 #include <caml/callback.h>
8019 #include <caml/fail.h>
8020 #include <caml/memory.h>
8021 #include <caml/mlvalues.h>
8022 #include <caml/signals.h>
8023
8024 #include <guestfs.h>
8025
8026 #include \"guestfs_c.h\"
8027
8028 /* Copy a hashtable of string pairs into an assoc-list.  We return
8029  * the list in reverse order, but hashtables aren't supposed to be
8030  * ordered anyway.
8031  */
8032 static CAMLprim value
8033 copy_table (char * const * argv)
8034 {
8035   CAMLparam0 ();
8036   CAMLlocal5 (rv, pairv, kv, vv, cons);
8037   int i;
8038
8039   rv = Val_int (0);
8040   for (i = 0; argv[i] != NULL; i += 2) {
8041     kv = caml_copy_string (argv[i]);
8042     vv = caml_copy_string (argv[i+1]);
8043     pairv = caml_alloc (2, 0);
8044     Store_field (pairv, 0, kv);
8045     Store_field (pairv, 1, vv);
8046     cons = caml_alloc (2, 0);
8047     Store_field (cons, 1, rv);
8048     rv = cons;
8049     Store_field (cons, 0, pairv);
8050   }
8051
8052   CAMLreturn (rv);
8053 }
8054
8055 ";
8056
8057   (* Struct copy functions. *)
8058
8059   let emit_ocaml_copy_list_function typ =
8060     pr "static CAMLprim value\n";
8061     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8062     pr "{\n";
8063     pr "  CAMLparam0 ();\n";
8064     pr "  CAMLlocal2 (rv, v);\n";
8065     pr "  unsigned int i;\n";
8066     pr "\n";
8067     pr "  if (%ss->len == 0)\n" typ;
8068     pr "    CAMLreturn (Atom (0));\n";
8069     pr "  else {\n";
8070     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8071     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8072     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8073     pr "      caml_modify (&Field (rv, i), v);\n";
8074     pr "    }\n";
8075     pr "    CAMLreturn (rv);\n";
8076     pr "  }\n";
8077     pr "}\n";
8078     pr "\n";
8079   in
8080
8081   List.iter (
8082     fun (typ, cols) ->
8083       let has_optpercent_col =
8084         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8085
8086       pr "static CAMLprim value\n";
8087       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8088       pr "{\n";
8089       pr "  CAMLparam0 ();\n";
8090       if has_optpercent_col then
8091         pr "  CAMLlocal3 (rv, v, v2);\n"
8092       else
8093         pr "  CAMLlocal2 (rv, v);\n";
8094       pr "\n";
8095       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8096       iteri (
8097         fun i col ->
8098           (match col with
8099            | name, FString ->
8100                pr "  v = caml_copy_string (%s->%s);\n" typ name
8101            | name, FBuffer ->
8102                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8103                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8104                  typ name typ name
8105            | name, FUUID ->
8106                pr "  v = caml_alloc_string (32);\n";
8107                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8108            | name, (FBytes|FInt64|FUInt64) ->
8109                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8110            | name, (FInt32|FUInt32) ->
8111                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8112            | name, FOptPercent ->
8113                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8114                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8115                pr "    v = caml_alloc (1, 0);\n";
8116                pr "    Store_field (v, 0, v2);\n";
8117                pr "  } else /* None */\n";
8118                pr "    v = Val_int (0);\n";
8119            | name, FChar ->
8120                pr "  v = Val_int (%s->%s);\n" typ name
8121           );
8122           pr "  Store_field (rv, %d, v);\n" i
8123       ) cols;
8124       pr "  CAMLreturn (rv);\n";
8125       pr "}\n";
8126       pr "\n";
8127   ) structs;
8128
8129   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8130   List.iter (
8131     function
8132     | typ, (RStructListOnly | RStructAndList) ->
8133         (* generate the function for typ *)
8134         emit_ocaml_copy_list_function typ
8135     | typ, _ -> () (* empty *)
8136   ) (rstructs_used_by all_functions);
8137
8138   (* The wrappers. *)
8139   List.iter (
8140     fun (name, style, _, _, _, _, _) ->
8141       pr "/* Automatically generated wrapper for function\n";
8142       pr " * ";
8143       generate_ocaml_prototype name style;
8144       pr " */\n";
8145       pr "\n";
8146
8147       let params =
8148         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8149
8150       let needs_extra_vs =
8151         match fst style with RConstOptString _ -> true | _ -> false in
8152
8153       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8154       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8155       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8156       pr "\n";
8157
8158       pr "CAMLprim value\n";
8159       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8160       List.iter (pr ", value %s") (List.tl params);
8161       pr ")\n";
8162       pr "{\n";
8163
8164       (match params with
8165        | [p1; p2; p3; p4; p5] ->
8166            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8167        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8168            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8169            pr "  CAMLxparam%d (%s);\n"
8170              (List.length rest) (String.concat ", " rest)
8171        | ps ->
8172            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8173       );
8174       if not needs_extra_vs then
8175         pr "  CAMLlocal1 (rv);\n"
8176       else
8177         pr "  CAMLlocal3 (rv, v, v2);\n";
8178       pr "\n";
8179
8180       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8181       pr "  if (g == NULL)\n";
8182       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8183       pr "\n";
8184
8185       List.iter (
8186         function
8187         | Pathname n
8188         | Device n | Dev_or_Path n
8189         | String n
8190         | FileIn n
8191         | FileOut n ->
8192             pr "  const char *%s = String_val (%sv);\n" n n
8193         | OptString n ->
8194             pr "  const char *%s =\n" n;
8195             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8196               n n
8197         | StringList n | DeviceList n ->
8198             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8199         | Bool n ->
8200             pr "  int %s = Bool_val (%sv);\n" n n
8201         | Int n ->
8202             pr "  int %s = Int_val (%sv);\n" n n
8203         | Int64 n ->
8204             pr "  int64_t %s = Int64_val (%sv);\n" n n
8205       ) (snd style);
8206       let error_code =
8207         match fst style with
8208         | RErr -> pr "  int r;\n"; "-1"
8209         | RInt _ -> pr "  int r;\n"; "-1"
8210         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8211         | RBool _ -> pr "  int r;\n"; "-1"
8212         | RConstString _ | RConstOptString _ ->
8213             pr "  const char *r;\n"; "NULL"
8214         | RString _ -> pr "  char *r;\n"; "NULL"
8215         | RStringList _ ->
8216             pr "  int i;\n";
8217             pr "  char **r;\n";
8218             "NULL"
8219         | RStruct (_, typ) ->
8220             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8221         | RStructList (_, typ) ->
8222             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8223         | RHashtable _ ->
8224             pr "  int i;\n";
8225             pr "  char **r;\n";
8226             "NULL"
8227         | RBufferOut _ ->
8228             pr "  char *r;\n";
8229             pr "  size_t size;\n";
8230             "NULL" in
8231       pr "\n";
8232
8233       pr "  caml_enter_blocking_section ();\n";
8234       pr "  r = guestfs_%s " name;
8235       generate_c_call_args ~handle:"g" style;
8236       pr ";\n";
8237       pr "  caml_leave_blocking_section ();\n";
8238
8239       List.iter (
8240         function
8241         | StringList n | DeviceList n ->
8242             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8243         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8244         | Bool _ | Int _ | Int64 _
8245         | FileIn _ | FileOut _ -> ()
8246       ) (snd style);
8247
8248       pr "  if (r == %s)\n" error_code;
8249       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8250       pr "\n";
8251
8252       (match fst style with
8253        | RErr -> pr "  rv = Val_unit;\n"
8254        | RInt _ -> pr "  rv = Val_int (r);\n"
8255        | RInt64 _ ->
8256            pr "  rv = caml_copy_int64 (r);\n"
8257        | RBool _ -> pr "  rv = Val_bool (r);\n"
8258        | RConstString _ ->
8259            pr "  rv = caml_copy_string (r);\n"
8260        | RConstOptString _ ->
8261            pr "  if (r) { /* Some string */\n";
8262            pr "    v = caml_alloc (1, 0);\n";
8263            pr "    v2 = caml_copy_string (r);\n";
8264            pr "    Store_field (v, 0, v2);\n";
8265            pr "  } else /* None */\n";
8266            pr "    v = Val_int (0);\n";
8267        | RString _ ->
8268            pr "  rv = caml_copy_string (r);\n";
8269            pr "  free (r);\n"
8270        | RStringList _ ->
8271            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8272            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8273            pr "  free (r);\n"
8274        | RStruct (_, typ) ->
8275            pr "  rv = copy_%s (r);\n" typ;
8276            pr "  guestfs_free_%s (r);\n" typ;
8277        | RStructList (_, typ) ->
8278            pr "  rv = copy_%s_list (r);\n" typ;
8279            pr "  guestfs_free_%s_list (r);\n" typ;
8280        | RHashtable _ ->
8281            pr "  rv = copy_table (r);\n";
8282            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8283            pr "  free (r);\n";
8284        | RBufferOut _ ->
8285            pr "  rv = caml_alloc_string (size);\n";
8286            pr "  memcpy (String_val (rv), r, size);\n";
8287       );
8288
8289       pr "  CAMLreturn (rv);\n";
8290       pr "}\n";
8291       pr "\n";
8292
8293       if List.length params > 5 then (
8294         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8295         pr "CAMLprim value ";
8296         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8297         pr "CAMLprim value\n";
8298         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8299         pr "{\n";
8300         pr "  return ocaml_guestfs_%s (argv[0]" name;
8301         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8302         pr ");\n";
8303         pr "}\n";
8304         pr "\n"
8305       )
8306   ) all_functions_sorted
8307
8308 and generate_ocaml_structure_decls () =
8309   List.iter (
8310     fun (typ, cols) ->
8311       pr "type %s = {\n" typ;
8312       List.iter (
8313         function
8314         | name, FString -> pr "  %s : string;\n" name
8315         | name, FBuffer -> pr "  %s : string;\n" name
8316         | name, FUUID -> pr "  %s : string;\n" name
8317         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8318         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8319         | name, FChar -> pr "  %s : char;\n" name
8320         | name, FOptPercent -> pr "  %s : float option;\n" name
8321       ) cols;
8322       pr "}\n";
8323       pr "\n"
8324   ) structs
8325
8326 and generate_ocaml_prototype ?(is_external = false) name style =
8327   if is_external then pr "external " else pr "val ";
8328   pr "%s : t -> " name;
8329   List.iter (
8330     function
8331     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8332     | OptString _ -> pr "string option -> "
8333     | StringList _ | DeviceList _ -> pr "string array -> "
8334     | Bool _ -> pr "bool -> "
8335     | Int _ -> pr "int -> "
8336     | Int64 _ -> pr "int64 -> "
8337   ) (snd style);
8338   (match fst style with
8339    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8340    | RInt _ -> pr "int"
8341    | RInt64 _ -> pr "int64"
8342    | RBool _ -> pr "bool"
8343    | RConstString _ -> pr "string"
8344    | RConstOptString _ -> pr "string option"
8345    | RString _ | RBufferOut _ -> pr "string"
8346    | RStringList _ -> pr "string array"
8347    | RStruct (_, typ) -> pr "%s" typ
8348    | RStructList (_, typ) -> pr "%s array" typ
8349    | RHashtable _ -> pr "(string * string) list"
8350   );
8351   if is_external then (
8352     pr " = ";
8353     if List.length (snd style) + 1 > 5 then
8354       pr "\"ocaml_guestfs_%s_byte\" " name;
8355     pr "\"ocaml_guestfs_%s\"" name
8356   );
8357   pr "\n"
8358
8359 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8360 and generate_perl_xs () =
8361   generate_header CStyle LGPLv2plus;
8362
8363   pr "\
8364 #include \"EXTERN.h\"
8365 #include \"perl.h\"
8366 #include \"XSUB.h\"
8367
8368 #include <guestfs.h>
8369
8370 #ifndef PRId64
8371 #define PRId64 \"lld\"
8372 #endif
8373
8374 static SV *
8375 my_newSVll(long long val) {
8376 #ifdef USE_64_BIT_ALL
8377   return newSViv(val);
8378 #else
8379   char buf[100];
8380   int len;
8381   len = snprintf(buf, 100, \"%%\" PRId64, val);
8382   return newSVpv(buf, len);
8383 #endif
8384 }
8385
8386 #ifndef PRIu64
8387 #define PRIu64 \"llu\"
8388 #endif
8389
8390 static SV *
8391 my_newSVull(unsigned long long val) {
8392 #ifdef USE_64_BIT_ALL
8393   return newSVuv(val);
8394 #else
8395   char buf[100];
8396   int len;
8397   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8398   return newSVpv(buf, len);
8399 #endif
8400 }
8401
8402 /* http://www.perlmonks.org/?node_id=680842 */
8403 static char **
8404 XS_unpack_charPtrPtr (SV *arg) {
8405   char **ret;
8406   AV *av;
8407   I32 i;
8408
8409   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8410     croak (\"array reference expected\");
8411
8412   av = (AV *)SvRV (arg);
8413   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8414   if (!ret)
8415     croak (\"malloc failed\");
8416
8417   for (i = 0; i <= av_len (av); i++) {
8418     SV **elem = av_fetch (av, i, 0);
8419
8420     if (!elem || !*elem)
8421       croak (\"missing element in list\");
8422
8423     ret[i] = SvPV_nolen (*elem);
8424   }
8425
8426   ret[i] = NULL;
8427
8428   return ret;
8429 }
8430
8431 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8432
8433 PROTOTYPES: ENABLE
8434
8435 guestfs_h *
8436 _create ()
8437    CODE:
8438       RETVAL = guestfs_create ();
8439       if (!RETVAL)
8440         croak (\"could not create guestfs handle\");
8441       guestfs_set_error_handler (RETVAL, NULL, NULL);
8442  OUTPUT:
8443       RETVAL
8444
8445 void
8446 DESTROY (g)
8447       guestfs_h *g;
8448  PPCODE:
8449       guestfs_close (g);
8450
8451 ";
8452
8453   List.iter (
8454     fun (name, style, _, _, _, _, _) ->
8455       (match fst style with
8456        | RErr -> pr "void\n"
8457        | RInt _ -> pr "SV *\n"
8458        | RInt64 _ -> pr "SV *\n"
8459        | RBool _ -> pr "SV *\n"
8460        | RConstString _ -> pr "SV *\n"
8461        | RConstOptString _ -> pr "SV *\n"
8462        | RString _ -> pr "SV *\n"
8463        | RBufferOut _ -> pr "SV *\n"
8464        | RStringList _
8465        | RStruct _ | RStructList _
8466        | RHashtable _ ->
8467            pr "void\n" (* all lists returned implictly on the stack *)
8468       );
8469       (* Call and arguments. *)
8470       pr "%s " name;
8471       generate_c_call_args ~handle:"g" ~decl:true style;
8472       pr "\n";
8473       pr "      guestfs_h *g;\n";
8474       iteri (
8475         fun i ->
8476           function
8477           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8478               pr "      char *%s;\n" n
8479           | OptString n ->
8480               (* http://www.perlmonks.org/?node_id=554277
8481                * Note that the implicit handle argument means we have
8482                * to add 1 to the ST(x) operator.
8483                *)
8484               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8485           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8486           | Bool n -> pr "      int %s;\n" n
8487           | Int n -> pr "      int %s;\n" n
8488           | Int64 n -> pr "      int64_t %s;\n" n
8489       ) (snd style);
8490
8491       let do_cleanups () =
8492         List.iter (
8493           function
8494           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8495           | Bool _ | Int _ | Int64 _
8496           | FileIn _ | FileOut _ -> ()
8497           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8498         ) (snd style)
8499       in
8500
8501       (* Code. *)
8502       (match fst style with
8503        | RErr ->
8504            pr "PREINIT:\n";
8505            pr "      int r;\n";
8506            pr " PPCODE:\n";
8507            pr "      r = guestfs_%s " name;
8508            generate_c_call_args ~handle:"g" style;
8509            pr ";\n";
8510            do_cleanups ();
8511            pr "      if (r == -1)\n";
8512            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8513        | RInt n
8514        | RBool n ->
8515            pr "PREINIT:\n";
8516            pr "      int %s;\n" n;
8517            pr "   CODE:\n";
8518            pr "      %s = guestfs_%s " n name;
8519            generate_c_call_args ~handle:"g" style;
8520            pr ";\n";
8521            do_cleanups ();
8522            pr "      if (%s == -1)\n" n;
8523            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8524            pr "      RETVAL = newSViv (%s);\n" n;
8525            pr " OUTPUT:\n";
8526            pr "      RETVAL\n"
8527        | RInt64 n ->
8528            pr "PREINIT:\n";
8529            pr "      int64_t %s;\n" n;
8530            pr "   CODE:\n";
8531            pr "      %s = guestfs_%s " n name;
8532            generate_c_call_args ~handle:"g" style;
8533            pr ";\n";
8534            do_cleanups ();
8535            pr "      if (%s == -1)\n" n;
8536            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8537            pr "      RETVAL = my_newSVll (%s);\n" n;
8538            pr " OUTPUT:\n";
8539            pr "      RETVAL\n"
8540        | RConstString n ->
8541            pr "PREINIT:\n";
8542            pr "      const char *%s;\n" n;
8543            pr "   CODE:\n";
8544            pr "      %s = guestfs_%s " n name;
8545            generate_c_call_args ~handle:"g" style;
8546            pr ";\n";
8547            do_cleanups ();
8548            pr "      if (%s == NULL)\n" n;
8549            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8550            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8551            pr " OUTPUT:\n";
8552            pr "      RETVAL\n"
8553        | RConstOptString n ->
8554            pr "PREINIT:\n";
8555            pr "      const char *%s;\n" n;
8556            pr "   CODE:\n";
8557            pr "      %s = guestfs_%s " n name;
8558            generate_c_call_args ~handle:"g" style;
8559            pr ";\n";
8560            do_cleanups ();
8561            pr "      if (%s == NULL)\n" n;
8562            pr "        RETVAL = &PL_sv_undef;\n";
8563            pr "      else\n";
8564            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8565            pr " OUTPUT:\n";
8566            pr "      RETVAL\n"
8567        | RString n ->
8568            pr "PREINIT:\n";
8569            pr "      char *%s;\n" n;
8570            pr "   CODE:\n";
8571            pr "      %s = guestfs_%s " n name;
8572            generate_c_call_args ~handle:"g" style;
8573            pr ";\n";
8574            do_cleanups ();
8575            pr "      if (%s == NULL)\n" n;
8576            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8577            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8578            pr "      free (%s);\n" n;
8579            pr " OUTPUT:\n";
8580            pr "      RETVAL\n"
8581        | RStringList n | RHashtable n ->
8582            pr "PREINIT:\n";
8583            pr "      char **%s;\n" n;
8584            pr "      int i, n;\n";
8585            pr " PPCODE:\n";
8586            pr "      %s = guestfs_%s " n name;
8587            generate_c_call_args ~handle:"g" style;
8588            pr ";\n";
8589            do_cleanups ();
8590            pr "      if (%s == NULL)\n" n;
8591            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8592            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8593            pr "      EXTEND (SP, n);\n";
8594            pr "      for (i = 0; i < n; ++i) {\n";
8595            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8596            pr "        free (%s[i]);\n" n;
8597            pr "      }\n";
8598            pr "      free (%s);\n" n;
8599        | RStruct (n, typ) ->
8600            let cols = cols_of_struct typ in
8601            generate_perl_struct_code typ cols name style n do_cleanups
8602        | RStructList (n, typ) ->
8603            let cols = cols_of_struct typ in
8604            generate_perl_struct_list_code typ cols name style n do_cleanups
8605        | RBufferOut n ->
8606            pr "PREINIT:\n";
8607            pr "      char *%s;\n" n;
8608            pr "      size_t size;\n";
8609            pr "   CODE:\n";
8610            pr "      %s = guestfs_%s " n name;
8611            generate_c_call_args ~handle:"g" style;
8612            pr ";\n";
8613            do_cleanups ();
8614            pr "      if (%s == NULL)\n" n;
8615            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8616            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8617            pr "      free (%s);\n" n;
8618            pr " OUTPUT:\n";
8619            pr "      RETVAL\n"
8620       );
8621
8622       pr "\n"
8623   ) all_functions
8624
8625 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8626   pr "PREINIT:\n";
8627   pr "      struct guestfs_%s_list *%s;\n" typ n;
8628   pr "      int i;\n";
8629   pr "      HV *hv;\n";
8630   pr " PPCODE:\n";
8631   pr "      %s = guestfs_%s " n name;
8632   generate_c_call_args ~handle:"g" style;
8633   pr ";\n";
8634   do_cleanups ();
8635   pr "      if (%s == NULL)\n" n;
8636   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8637   pr "      EXTEND (SP, %s->len);\n" n;
8638   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8639   pr "        hv = newHV ();\n";
8640   List.iter (
8641     function
8642     | name, FString ->
8643         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8644           name (String.length name) n name
8645     | name, FUUID ->
8646         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8647           name (String.length name) n name
8648     | name, FBuffer ->
8649         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8650           name (String.length name) n name n name
8651     | name, (FBytes|FUInt64) ->
8652         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8653           name (String.length name) n name
8654     | name, FInt64 ->
8655         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8656           name (String.length name) n name
8657     | name, (FInt32|FUInt32) ->
8658         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8659           name (String.length name) n name
8660     | name, FChar ->
8661         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8662           name (String.length name) n name
8663     | name, FOptPercent ->
8664         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8665           name (String.length name) n name
8666   ) cols;
8667   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8668   pr "      }\n";
8669   pr "      guestfs_free_%s_list (%s);\n" typ n
8670
8671 and generate_perl_struct_code typ cols name style n do_cleanups =
8672   pr "PREINIT:\n";
8673   pr "      struct guestfs_%s *%s;\n" typ n;
8674   pr " PPCODE:\n";
8675   pr "      %s = guestfs_%s " n name;
8676   generate_c_call_args ~handle:"g" style;
8677   pr ";\n";
8678   do_cleanups ();
8679   pr "      if (%s == NULL)\n" n;
8680   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8681   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8682   List.iter (
8683     fun ((name, _) as col) ->
8684       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8685
8686       match col with
8687       | name, FString ->
8688           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8689             n name
8690       | name, FBuffer ->
8691           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8692             n name n name
8693       | name, FUUID ->
8694           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8695             n name
8696       | name, (FBytes|FUInt64) ->
8697           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8698             n name
8699       | name, FInt64 ->
8700           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8701             n name
8702       | name, (FInt32|FUInt32) ->
8703           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8704             n name
8705       | name, FChar ->
8706           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8707             n name
8708       | name, FOptPercent ->
8709           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8710             n name
8711   ) cols;
8712   pr "      free (%s);\n" n
8713
8714 (* Generate Sys/Guestfs.pm. *)
8715 and generate_perl_pm () =
8716   generate_header HashStyle LGPLv2plus;
8717
8718   pr "\
8719 =pod
8720
8721 =head1 NAME
8722
8723 Sys::Guestfs - Perl bindings for libguestfs
8724
8725 =head1 SYNOPSIS
8726
8727  use Sys::Guestfs;
8728
8729  my $h = Sys::Guestfs->new ();
8730  $h->add_drive ('guest.img');
8731  $h->launch ();
8732  $h->mount ('/dev/sda1', '/');
8733  $h->touch ('/hello');
8734  $h->sync ();
8735
8736 =head1 DESCRIPTION
8737
8738 The C<Sys::Guestfs> module provides a Perl XS binding to the
8739 libguestfs API for examining and modifying virtual machine
8740 disk images.
8741
8742 Amongst the things this is good for: making batch configuration
8743 changes to guests, getting disk used/free statistics (see also:
8744 virt-df), migrating between virtualization systems (see also:
8745 virt-p2v), performing partial backups, performing partial guest
8746 clones, cloning guests and changing registry/UUID/hostname info, and
8747 much else besides.
8748
8749 Libguestfs uses Linux kernel and qemu code, and can access any type of
8750 guest filesystem that Linux and qemu can, including but not limited
8751 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8752 schemes, qcow, qcow2, vmdk.
8753
8754 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8755 LVs, what filesystem is in each LV, etc.).  It can also run commands
8756 in the context of the guest.  Also you can access filesystems over
8757 FUSE.
8758
8759 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8760 functions for using libguestfs from Perl, including integration
8761 with libvirt.
8762
8763 =head1 ERRORS
8764
8765 All errors turn into calls to C<croak> (see L<Carp(3)>).
8766
8767 =head1 METHODS
8768
8769 =over 4
8770
8771 =cut
8772
8773 package Sys::Guestfs;
8774
8775 use strict;
8776 use warnings;
8777
8778 require XSLoader;
8779 XSLoader::load ('Sys::Guestfs');
8780
8781 =item $h = Sys::Guestfs->new ();
8782
8783 Create a new guestfs handle.
8784
8785 =cut
8786
8787 sub new {
8788   my $proto = shift;
8789   my $class = ref ($proto) || $proto;
8790
8791   my $self = Sys::Guestfs::_create ();
8792   bless $self, $class;
8793   return $self;
8794 }
8795
8796 ";
8797
8798   (* Actions.  We only need to print documentation for these as
8799    * they are pulled in from the XS code automatically.
8800    *)
8801   List.iter (
8802     fun (name, style, _, flags, _, _, longdesc) ->
8803       if not (List.mem NotInDocs flags) then (
8804         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8805         pr "=item ";
8806         generate_perl_prototype name style;
8807         pr "\n\n";
8808         pr "%s\n\n" longdesc;
8809         if List.mem ProtocolLimitWarning flags then
8810           pr "%s\n\n" protocol_limit_warning;
8811         if List.mem DangerWillRobinson flags then
8812           pr "%s\n\n" danger_will_robinson;
8813         match deprecation_notice flags with
8814         | None -> ()
8815         | Some txt -> pr "%s\n\n" txt
8816       )
8817   ) all_functions_sorted;
8818
8819   (* End of file. *)
8820   pr "\
8821 =cut
8822
8823 1;
8824
8825 =back
8826
8827 =head1 COPYRIGHT
8828
8829 Copyright (C) %s Red Hat Inc.
8830
8831 =head1 LICENSE
8832
8833 Please see the file COPYING.LIB for the full license.
8834
8835 =head1 SEE ALSO
8836
8837 L<guestfs(3)>,
8838 L<guestfish(1)>,
8839 L<http://libguestfs.org>,
8840 L<Sys::Guestfs::Lib(3)>.
8841
8842 =cut
8843 " copyright_years
8844
8845 and generate_perl_prototype name style =
8846   (match fst style with
8847    | RErr -> ()
8848    | RBool n
8849    | RInt n
8850    | RInt64 n
8851    | RConstString n
8852    | RConstOptString n
8853    | RString n
8854    | RBufferOut n -> pr "$%s = " n
8855    | RStruct (n,_)
8856    | RHashtable n -> pr "%%%s = " n
8857    | RStringList n
8858    | RStructList (n,_) -> pr "@%s = " n
8859   );
8860   pr "$h->%s (" name;
8861   let comma = ref false in
8862   List.iter (
8863     fun arg ->
8864       if !comma then pr ", ";
8865       comma := true;
8866       match arg with
8867       | Pathname n | Device n | Dev_or_Path n | String n
8868       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8869           pr "$%s" n
8870       | StringList n | DeviceList n ->
8871           pr "\\@%s" n
8872   ) (snd style);
8873   pr ");"
8874
8875 (* Generate Python C module. *)
8876 and generate_python_c () =
8877   generate_header CStyle LGPLv2plus;
8878
8879   pr "\
8880 #include <Python.h>
8881
8882 #include <stdio.h>
8883 #include <stdlib.h>
8884 #include <assert.h>
8885
8886 #include \"guestfs.h\"
8887
8888 typedef struct {
8889   PyObject_HEAD
8890   guestfs_h *g;
8891 } Pyguestfs_Object;
8892
8893 static guestfs_h *
8894 get_handle (PyObject *obj)
8895 {
8896   assert (obj);
8897   assert (obj != Py_None);
8898   return ((Pyguestfs_Object *) obj)->g;
8899 }
8900
8901 static PyObject *
8902 put_handle (guestfs_h *g)
8903 {
8904   assert (g);
8905   return
8906     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8907 }
8908
8909 /* This list should be freed (but not the strings) after use. */
8910 static char **
8911 get_string_list (PyObject *obj)
8912 {
8913   int i, len;
8914   char **r;
8915
8916   assert (obj);
8917
8918   if (!PyList_Check (obj)) {
8919     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8920     return NULL;
8921   }
8922
8923   len = PyList_Size (obj);
8924   r = malloc (sizeof (char *) * (len+1));
8925   if (r == NULL) {
8926     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8927     return NULL;
8928   }
8929
8930   for (i = 0; i < len; ++i)
8931     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8932   r[len] = NULL;
8933
8934   return r;
8935 }
8936
8937 static PyObject *
8938 put_string_list (char * const * const argv)
8939 {
8940   PyObject *list;
8941   int argc, i;
8942
8943   for (argc = 0; argv[argc] != NULL; ++argc)
8944     ;
8945
8946   list = PyList_New (argc);
8947   for (i = 0; i < argc; ++i)
8948     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8949
8950   return list;
8951 }
8952
8953 static PyObject *
8954 put_table (char * const * const argv)
8955 {
8956   PyObject *list, *item;
8957   int argc, i;
8958
8959   for (argc = 0; argv[argc] != NULL; ++argc)
8960     ;
8961
8962   list = PyList_New (argc >> 1);
8963   for (i = 0; i < argc; i += 2) {
8964     item = PyTuple_New (2);
8965     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8966     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8967     PyList_SetItem (list, i >> 1, item);
8968   }
8969
8970   return list;
8971 }
8972
8973 static void
8974 free_strings (char **argv)
8975 {
8976   int argc;
8977
8978   for (argc = 0; argv[argc] != NULL; ++argc)
8979     free (argv[argc]);
8980   free (argv);
8981 }
8982
8983 static PyObject *
8984 py_guestfs_create (PyObject *self, PyObject *args)
8985 {
8986   guestfs_h *g;
8987
8988   g = guestfs_create ();
8989   if (g == NULL) {
8990     PyErr_SetString (PyExc_RuntimeError,
8991                      \"guestfs.create: failed to allocate handle\");
8992     return NULL;
8993   }
8994   guestfs_set_error_handler (g, NULL, NULL);
8995   return put_handle (g);
8996 }
8997
8998 static PyObject *
8999 py_guestfs_close (PyObject *self, PyObject *args)
9000 {
9001   PyObject *py_g;
9002   guestfs_h *g;
9003
9004   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9005     return NULL;
9006   g = get_handle (py_g);
9007
9008   guestfs_close (g);
9009
9010   Py_INCREF (Py_None);
9011   return Py_None;
9012 }
9013
9014 ";
9015
9016   let emit_put_list_function typ =
9017     pr "static PyObject *\n";
9018     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9019     pr "{\n";
9020     pr "  PyObject *list;\n";
9021     pr "  int i;\n";
9022     pr "\n";
9023     pr "  list = PyList_New (%ss->len);\n" typ;
9024     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9025     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9026     pr "  return list;\n";
9027     pr "};\n";
9028     pr "\n"
9029   in
9030
9031   (* Structures, turned into Python dictionaries. *)
9032   List.iter (
9033     fun (typ, cols) ->
9034       pr "static PyObject *\n";
9035       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9036       pr "{\n";
9037       pr "  PyObject *dict;\n";
9038       pr "\n";
9039       pr "  dict = PyDict_New ();\n";
9040       List.iter (
9041         function
9042         | name, FString ->
9043             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9044             pr "                        PyString_FromString (%s->%s));\n"
9045               typ name
9046         | name, FBuffer ->
9047             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9048             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9049               typ name typ name
9050         | name, FUUID ->
9051             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9052             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9053               typ name
9054         | name, (FBytes|FUInt64) ->
9055             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9056             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9057               typ name
9058         | name, FInt64 ->
9059             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9060             pr "                        PyLong_FromLongLong (%s->%s));\n"
9061               typ name
9062         | name, FUInt32 ->
9063             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9064             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9065               typ name
9066         | name, FInt32 ->
9067             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9068             pr "                        PyLong_FromLong (%s->%s));\n"
9069               typ name
9070         | name, FOptPercent ->
9071             pr "  if (%s->%s >= 0)\n" typ name;
9072             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9073             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9074               typ name;
9075             pr "  else {\n";
9076             pr "    Py_INCREF (Py_None);\n";
9077             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9078             pr "  }\n"
9079         | name, FChar ->
9080             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9081             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9082       ) cols;
9083       pr "  return dict;\n";
9084       pr "};\n";
9085       pr "\n";
9086
9087   ) structs;
9088
9089   (* Emit a put_TYPE_list function definition only if that function is used. *)
9090   List.iter (
9091     function
9092     | typ, (RStructListOnly | RStructAndList) ->
9093         (* generate the function for typ *)
9094         emit_put_list_function typ
9095     | typ, _ -> () (* empty *)
9096   ) (rstructs_used_by all_functions);
9097
9098   (* Python wrapper functions. *)
9099   List.iter (
9100     fun (name, style, _, _, _, _, _) ->
9101       pr "static PyObject *\n";
9102       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9103       pr "{\n";
9104
9105       pr "  PyObject *py_g;\n";
9106       pr "  guestfs_h *g;\n";
9107       pr "  PyObject *py_r;\n";
9108
9109       let error_code =
9110         match fst style with
9111         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9112         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9113         | RConstString _ | RConstOptString _ ->
9114             pr "  const char *r;\n"; "NULL"
9115         | RString _ -> pr "  char *r;\n"; "NULL"
9116         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9117         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9118         | RStructList (_, typ) ->
9119             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9120         | RBufferOut _ ->
9121             pr "  char *r;\n";
9122             pr "  size_t size;\n";
9123             "NULL" in
9124
9125       List.iter (
9126         function
9127         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9128             pr "  const char *%s;\n" n
9129         | OptString n -> pr "  const char *%s;\n" n
9130         | StringList n | DeviceList n ->
9131             pr "  PyObject *py_%s;\n" n;
9132             pr "  char **%s;\n" n
9133         | Bool n -> pr "  int %s;\n" n
9134         | Int n -> pr "  int %s;\n" n
9135         | Int64 n -> pr "  long long %s;\n" n
9136       ) (snd style);
9137
9138       pr "\n";
9139
9140       (* Convert the parameters. *)
9141       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9142       List.iter (
9143         function
9144         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9145         | OptString _ -> pr "z"
9146         | StringList _ | DeviceList _ -> pr "O"
9147         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9148         | Int _ -> pr "i"
9149         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9150                              * emulate C's int/long/long long in Python?
9151                              *)
9152       ) (snd style);
9153       pr ":guestfs_%s\",\n" name;
9154       pr "                         &py_g";
9155       List.iter (
9156         function
9157         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9158         | OptString n -> pr ", &%s" n
9159         | StringList n | DeviceList n -> pr ", &py_%s" n
9160         | Bool n -> pr ", &%s" n
9161         | Int n -> pr ", &%s" n
9162         | Int64 n -> pr ", &%s" n
9163       ) (snd style);
9164
9165       pr "))\n";
9166       pr "    return NULL;\n";
9167
9168       pr "  g = get_handle (py_g);\n";
9169       List.iter (
9170         function
9171         | Pathname _ | Device _ | Dev_or_Path _ | String _
9172         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9173         | StringList n | DeviceList n ->
9174             pr "  %s = get_string_list (py_%s);\n" n n;
9175             pr "  if (!%s) return NULL;\n" n
9176       ) (snd style);
9177
9178       pr "\n";
9179
9180       pr "  r = guestfs_%s " name;
9181       generate_c_call_args ~handle:"g" style;
9182       pr ";\n";
9183
9184       List.iter (
9185         function
9186         | Pathname _ | Device _ | Dev_or_Path _ | String _
9187         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9188         | StringList n | DeviceList n ->
9189             pr "  free (%s);\n" n
9190       ) (snd style);
9191
9192       pr "  if (r == %s) {\n" error_code;
9193       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9194       pr "    return NULL;\n";
9195       pr "  }\n";
9196       pr "\n";
9197
9198       (match fst style with
9199        | RErr ->
9200            pr "  Py_INCREF (Py_None);\n";
9201            pr "  py_r = Py_None;\n"
9202        | RInt _
9203        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9204        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9205        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9206        | RConstOptString _ ->
9207            pr "  if (r)\n";
9208            pr "    py_r = PyString_FromString (r);\n";
9209            pr "  else {\n";
9210            pr "    Py_INCREF (Py_None);\n";
9211            pr "    py_r = Py_None;\n";
9212            pr "  }\n"
9213        | RString _ ->
9214            pr "  py_r = PyString_FromString (r);\n";
9215            pr "  free (r);\n"
9216        | RStringList _ ->
9217            pr "  py_r = put_string_list (r);\n";
9218            pr "  free_strings (r);\n"
9219        | RStruct (_, typ) ->
9220            pr "  py_r = put_%s (r);\n" typ;
9221            pr "  guestfs_free_%s (r);\n" typ
9222        | RStructList (_, typ) ->
9223            pr "  py_r = put_%s_list (r);\n" typ;
9224            pr "  guestfs_free_%s_list (r);\n" typ
9225        | RHashtable n ->
9226            pr "  py_r = put_table (r);\n";
9227            pr "  free_strings (r);\n"
9228        | RBufferOut _ ->
9229            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9230            pr "  free (r);\n"
9231       );
9232
9233       pr "  return py_r;\n";
9234       pr "}\n";
9235       pr "\n"
9236   ) all_functions;
9237
9238   (* Table of functions. *)
9239   pr "static PyMethodDef methods[] = {\n";
9240   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9241   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9242   List.iter (
9243     fun (name, _, _, _, _, _, _) ->
9244       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9245         name name
9246   ) all_functions;
9247   pr "  { NULL, NULL, 0, NULL }\n";
9248   pr "};\n";
9249   pr "\n";
9250
9251   (* Init function. *)
9252   pr "\
9253 void
9254 initlibguestfsmod (void)
9255 {
9256   static int initialized = 0;
9257
9258   if (initialized) return;
9259   Py_InitModule ((char *) \"libguestfsmod\", methods);
9260   initialized = 1;
9261 }
9262 "
9263
9264 (* Generate Python module. *)
9265 and generate_python_py () =
9266   generate_header HashStyle LGPLv2plus;
9267
9268   pr "\
9269 u\"\"\"Python bindings for libguestfs
9270
9271 import guestfs
9272 g = guestfs.GuestFS ()
9273 g.add_drive (\"guest.img\")
9274 g.launch ()
9275 parts = g.list_partitions ()
9276
9277 The guestfs module provides a Python binding to the libguestfs API
9278 for examining and modifying virtual machine disk images.
9279
9280 Amongst the things this is good for: making batch configuration
9281 changes to guests, getting disk used/free statistics (see also:
9282 virt-df), migrating between virtualization systems (see also:
9283 virt-p2v), performing partial backups, performing partial guest
9284 clones, cloning guests and changing registry/UUID/hostname info, and
9285 much else besides.
9286
9287 Libguestfs uses Linux kernel and qemu code, and can access any type of
9288 guest filesystem that Linux and qemu can, including but not limited
9289 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9290 schemes, qcow, qcow2, vmdk.
9291
9292 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9293 LVs, what filesystem is in each LV, etc.).  It can also run commands
9294 in the context of the guest.  Also you can access filesystems over
9295 FUSE.
9296
9297 Errors which happen while using the API are turned into Python
9298 RuntimeError exceptions.
9299
9300 To create a guestfs handle you usually have to perform the following
9301 sequence of calls:
9302
9303 # Create the handle, call add_drive at least once, and possibly
9304 # several times if the guest has multiple block devices:
9305 g = guestfs.GuestFS ()
9306 g.add_drive (\"guest.img\")
9307
9308 # Launch the qemu subprocess and wait for it to become ready:
9309 g.launch ()
9310
9311 # Now you can issue commands, for example:
9312 logvols = g.lvs ()
9313
9314 \"\"\"
9315
9316 import libguestfsmod
9317
9318 class GuestFS:
9319     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9320
9321     def __init__ (self):
9322         \"\"\"Create a new libguestfs handle.\"\"\"
9323         self._o = libguestfsmod.create ()
9324
9325     def __del__ (self):
9326         libguestfsmod.close (self._o)
9327
9328 ";
9329
9330   List.iter (
9331     fun (name, style, _, flags, _, _, longdesc) ->
9332       pr "    def %s " name;
9333       generate_py_call_args ~handle:"self" (snd style);
9334       pr ":\n";
9335
9336       if not (List.mem NotInDocs flags) then (
9337         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9338         let doc =
9339           match fst style with
9340           | RErr | RInt _ | RInt64 _ | RBool _
9341           | RConstOptString _ | RConstString _
9342           | RString _ | RBufferOut _ -> doc
9343           | RStringList _ ->
9344               doc ^ "\n\nThis function returns a list of strings."
9345           | RStruct (_, typ) ->
9346               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9347           | RStructList (_, typ) ->
9348               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9349           | RHashtable _ ->
9350               doc ^ "\n\nThis function returns a dictionary." in
9351         let doc =
9352           if List.mem ProtocolLimitWarning flags then
9353             doc ^ "\n\n" ^ protocol_limit_warning
9354           else doc in
9355         let doc =
9356           if List.mem DangerWillRobinson flags then
9357             doc ^ "\n\n" ^ danger_will_robinson
9358           else doc in
9359         let doc =
9360           match deprecation_notice flags with
9361           | None -> doc
9362           | Some txt -> doc ^ "\n\n" ^ txt in
9363         let doc = pod2text ~width:60 name doc in
9364         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9365         let doc = String.concat "\n        " doc in
9366         pr "        u\"\"\"%s\"\"\"\n" doc;
9367       );
9368       pr "        return libguestfsmod.%s " name;
9369       generate_py_call_args ~handle:"self._o" (snd style);
9370       pr "\n";
9371       pr "\n";
9372   ) all_functions
9373
9374 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9375 and generate_py_call_args ~handle args =
9376   pr "(%s" handle;
9377   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9378   pr ")"
9379
9380 (* Useful if you need the longdesc POD text as plain text.  Returns a
9381  * list of lines.
9382  *
9383  * Because this is very slow (the slowest part of autogeneration),
9384  * we memoize the results.
9385  *)
9386 and pod2text ~width name longdesc =
9387   let key = width, name, longdesc in
9388   try Hashtbl.find pod2text_memo key
9389   with Not_found ->
9390     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9391     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9392     close_out chan;
9393     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9394     let chan = open_process_in cmd in
9395     let lines = ref [] in
9396     let rec loop i =
9397       let line = input_line chan in
9398       if i = 1 then             (* discard the first line of output *)
9399         loop (i+1)
9400       else (
9401         let line = triml line in
9402         lines := line :: !lines;
9403         loop (i+1)
9404       ) in
9405     let lines = try loop 1 with End_of_file -> List.rev !lines in
9406     unlink filename;
9407     (match close_process_in chan with
9408      | WEXITED 0 -> ()
9409      | WEXITED i ->
9410          failwithf "pod2text: process exited with non-zero status (%d)" i
9411      | WSIGNALED i | WSTOPPED i ->
9412          failwithf "pod2text: process signalled or stopped by signal %d" i
9413     );
9414     Hashtbl.add pod2text_memo key lines;
9415     pod2text_memo_updated ();
9416     lines
9417
9418 (* Generate ruby bindings. *)
9419 and generate_ruby_c () =
9420   generate_header CStyle LGPLv2plus;
9421
9422   pr "\
9423 #include <stdio.h>
9424 #include <stdlib.h>
9425
9426 #include <ruby.h>
9427
9428 #include \"guestfs.h\"
9429
9430 #include \"extconf.h\"
9431
9432 /* For Ruby < 1.9 */
9433 #ifndef RARRAY_LEN
9434 #define RARRAY_LEN(r) (RARRAY((r))->len)
9435 #endif
9436
9437 static VALUE m_guestfs;                 /* guestfs module */
9438 static VALUE c_guestfs;                 /* guestfs_h handle */
9439 static VALUE e_Error;                   /* used for all errors */
9440
9441 static void ruby_guestfs_free (void *p)
9442 {
9443   if (!p) return;
9444   guestfs_close ((guestfs_h *) p);
9445 }
9446
9447 static VALUE ruby_guestfs_create (VALUE m)
9448 {
9449   guestfs_h *g;
9450
9451   g = guestfs_create ();
9452   if (!g)
9453     rb_raise (e_Error, \"failed to create guestfs handle\");
9454
9455   /* Don't print error messages to stderr by default. */
9456   guestfs_set_error_handler (g, NULL, NULL);
9457
9458   /* Wrap it, and make sure the close function is called when the
9459    * handle goes away.
9460    */
9461   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9462 }
9463
9464 static VALUE ruby_guestfs_close (VALUE gv)
9465 {
9466   guestfs_h *g;
9467   Data_Get_Struct (gv, guestfs_h, g);
9468
9469   ruby_guestfs_free (g);
9470   DATA_PTR (gv) = NULL;
9471
9472   return Qnil;
9473 }
9474
9475 ";
9476
9477   List.iter (
9478     fun (name, style, _, _, _, _, _) ->
9479       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9480       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9481       pr ")\n";
9482       pr "{\n";
9483       pr "  guestfs_h *g;\n";
9484       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9485       pr "  if (!g)\n";
9486       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9487         name;
9488       pr "\n";
9489
9490       List.iter (
9491         function
9492         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9493             pr "  Check_Type (%sv, T_STRING);\n" n;
9494             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9495             pr "  if (!%s)\n" n;
9496             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9497             pr "              \"%s\", \"%s\");\n" n name
9498         | OptString n ->
9499             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9500         | StringList n | DeviceList n ->
9501             pr "  char **%s;\n" n;
9502             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9503             pr "  {\n";
9504             pr "    int i, len;\n";
9505             pr "    len = RARRAY_LEN (%sv);\n" n;
9506             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9507               n;
9508             pr "    for (i = 0; i < len; ++i) {\n";
9509             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9510             pr "      %s[i] = StringValueCStr (v);\n" n;
9511             pr "    }\n";
9512             pr "    %s[len] = NULL;\n" n;
9513             pr "  }\n";
9514         | Bool n ->
9515             pr "  int %s = RTEST (%sv);\n" n n
9516         | Int n ->
9517             pr "  int %s = NUM2INT (%sv);\n" n n
9518         | Int64 n ->
9519             pr "  long long %s = NUM2LL (%sv);\n" n n
9520       ) (snd style);
9521       pr "\n";
9522
9523       let error_code =
9524         match fst style with
9525         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9526         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9527         | RConstString _ | RConstOptString _ ->
9528             pr "  const char *r;\n"; "NULL"
9529         | RString _ -> pr "  char *r;\n"; "NULL"
9530         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9531         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9532         | RStructList (_, typ) ->
9533             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9534         | RBufferOut _ ->
9535             pr "  char *r;\n";
9536             pr "  size_t size;\n";
9537             "NULL" in
9538       pr "\n";
9539
9540       pr "  r = guestfs_%s " name;
9541       generate_c_call_args ~handle:"g" style;
9542       pr ";\n";
9543
9544       List.iter (
9545         function
9546         | Pathname _ | Device _ | Dev_or_Path _ | String _
9547         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9548         | StringList n | DeviceList n ->
9549             pr "  free (%s);\n" n
9550       ) (snd style);
9551
9552       pr "  if (r == %s)\n" error_code;
9553       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9554       pr "\n";
9555
9556       (match fst style with
9557        | RErr ->
9558            pr "  return Qnil;\n"
9559        | RInt _ | RBool _ ->
9560            pr "  return INT2NUM (r);\n"
9561        | RInt64 _ ->
9562            pr "  return ULL2NUM (r);\n"
9563        | RConstString _ ->
9564            pr "  return rb_str_new2 (r);\n";
9565        | RConstOptString _ ->
9566            pr "  if (r)\n";
9567            pr "    return rb_str_new2 (r);\n";
9568            pr "  else\n";
9569            pr "    return Qnil;\n";
9570        | RString _ ->
9571            pr "  VALUE rv = rb_str_new2 (r);\n";
9572            pr "  free (r);\n";
9573            pr "  return rv;\n";
9574        | RStringList _ ->
9575            pr "  int i, len = 0;\n";
9576            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9577            pr "  VALUE rv = rb_ary_new2 (len);\n";
9578            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9579            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9580            pr "    free (r[i]);\n";
9581            pr "  }\n";
9582            pr "  free (r);\n";
9583            pr "  return rv;\n"
9584        | RStruct (_, typ) ->
9585            let cols = cols_of_struct typ in
9586            generate_ruby_struct_code typ cols
9587        | RStructList (_, typ) ->
9588            let cols = cols_of_struct typ in
9589            generate_ruby_struct_list_code typ cols
9590        | RHashtable _ ->
9591            pr "  VALUE rv = rb_hash_new ();\n";
9592            pr "  int i;\n";
9593            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9594            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9595            pr "    free (r[i]);\n";
9596            pr "    free (r[i+1]);\n";
9597            pr "  }\n";
9598            pr "  free (r);\n";
9599            pr "  return rv;\n"
9600        | RBufferOut _ ->
9601            pr "  VALUE rv = rb_str_new (r, size);\n";
9602            pr "  free (r);\n";
9603            pr "  return rv;\n";
9604       );
9605
9606       pr "}\n";
9607       pr "\n"
9608   ) all_functions;
9609
9610   pr "\
9611 /* Initialize the module. */
9612 void Init__guestfs ()
9613 {
9614   m_guestfs = rb_define_module (\"Guestfs\");
9615   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9616   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9617
9618   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9619   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9620
9621 ";
9622   (* Define the rest of the methods. *)
9623   List.iter (
9624     fun (name, style, _, _, _, _, _) ->
9625       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9626       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9627   ) all_functions;
9628
9629   pr "}\n"
9630
9631 (* Ruby code to return a struct. *)
9632 and generate_ruby_struct_code typ cols =
9633   pr "  VALUE rv = rb_hash_new ();\n";
9634   List.iter (
9635     function
9636     | name, FString ->
9637         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9638     | name, FBuffer ->
9639         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9640     | name, FUUID ->
9641         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9642     | name, (FBytes|FUInt64) ->
9643         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9644     | name, FInt64 ->
9645         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9646     | name, FUInt32 ->
9647         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9648     | name, FInt32 ->
9649         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9650     | name, FOptPercent ->
9651         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9652     | name, FChar -> (* XXX wrong? *)
9653         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9654   ) cols;
9655   pr "  guestfs_free_%s (r);\n" typ;
9656   pr "  return rv;\n"
9657
9658 (* Ruby code to return a struct list. *)
9659 and generate_ruby_struct_list_code typ cols =
9660   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9661   pr "  int i;\n";
9662   pr "  for (i = 0; i < r->len; ++i) {\n";
9663   pr "    VALUE hv = rb_hash_new ();\n";
9664   List.iter (
9665     function
9666     | name, FString ->
9667         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9668     | name, FBuffer ->
9669         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
9670     | name, FUUID ->
9671         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9672     | name, (FBytes|FUInt64) ->
9673         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9674     | name, FInt64 ->
9675         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9676     | name, FUInt32 ->
9677         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9678     | name, FInt32 ->
9679         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9680     | name, FOptPercent ->
9681         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9682     | name, FChar -> (* XXX wrong? *)
9683         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9684   ) cols;
9685   pr "    rb_ary_push (rv, hv);\n";
9686   pr "  }\n";
9687   pr "  guestfs_free_%s_list (r);\n" typ;
9688   pr "  return rv;\n"
9689
9690 (* Generate Java bindings GuestFS.java file. *)
9691 and generate_java_java () =
9692   generate_header CStyle LGPLv2plus;
9693
9694   pr "\
9695 package com.redhat.et.libguestfs;
9696
9697 import java.util.HashMap;
9698 import com.redhat.et.libguestfs.LibGuestFSException;
9699 import com.redhat.et.libguestfs.PV;
9700 import com.redhat.et.libguestfs.VG;
9701 import com.redhat.et.libguestfs.LV;
9702 import com.redhat.et.libguestfs.Stat;
9703 import com.redhat.et.libguestfs.StatVFS;
9704 import com.redhat.et.libguestfs.IntBool;
9705 import com.redhat.et.libguestfs.Dirent;
9706
9707 /**
9708  * The GuestFS object is a libguestfs handle.
9709  *
9710  * @author rjones
9711  */
9712 public class GuestFS {
9713   // Load the native code.
9714   static {
9715     System.loadLibrary (\"guestfs_jni\");
9716   }
9717
9718   /**
9719    * The native guestfs_h pointer.
9720    */
9721   long g;
9722
9723   /**
9724    * Create a libguestfs handle.
9725    *
9726    * @throws LibGuestFSException
9727    */
9728   public GuestFS () throws LibGuestFSException
9729   {
9730     g = _create ();
9731   }
9732   private native long _create () throws LibGuestFSException;
9733
9734   /**
9735    * Close a libguestfs handle.
9736    *
9737    * You can also leave handles to be collected by the garbage
9738    * collector, but this method ensures that the resources used
9739    * by the handle are freed up immediately.  If you call any
9740    * other methods after closing the handle, you will get an
9741    * exception.
9742    *
9743    * @throws LibGuestFSException
9744    */
9745   public void close () throws LibGuestFSException
9746   {
9747     if (g != 0)
9748       _close (g);
9749     g = 0;
9750   }
9751   private native void _close (long g) throws LibGuestFSException;
9752
9753   public void finalize () throws LibGuestFSException
9754   {
9755     close ();
9756   }
9757
9758 ";
9759
9760   List.iter (
9761     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9762       if not (List.mem NotInDocs flags); then (
9763         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9764         let doc =
9765           if List.mem ProtocolLimitWarning flags then
9766             doc ^ "\n\n" ^ protocol_limit_warning
9767           else doc in
9768         let doc =
9769           if List.mem DangerWillRobinson flags then
9770             doc ^ "\n\n" ^ danger_will_robinson
9771           else doc in
9772         let doc =
9773           match deprecation_notice flags with
9774           | None -> doc
9775           | Some txt -> doc ^ "\n\n" ^ txt in
9776         let doc = pod2text ~width:60 name doc in
9777         let doc = List.map (            (* RHBZ#501883 *)
9778           function
9779           | "" -> "<p>"
9780           | nonempty -> nonempty
9781         ) doc in
9782         let doc = String.concat "\n   * " doc in
9783
9784         pr "  /**\n";
9785         pr "   * %s\n" shortdesc;
9786         pr "   * <p>\n";
9787         pr "   * %s\n" doc;
9788         pr "   * @throws LibGuestFSException\n";
9789         pr "   */\n";
9790         pr "  ";
9791       );
9792       generate_java_prototype ~public:true ~semicolon:false name style;
9793       pr "\n";
9794       pr "  {\n";
9795       pr "    if (g == 0)\n";
9796       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9797         name;
9798       pr "    ";
9799       if fst style <> RErr then pr "return ";
9800       pr "_%s " name;
9801       generate_java_call_args ~handle:"g" (snd style);
9802       pr ";\n";
9803       pr "  }\n";
9804       pr "  ";
9805       generate_java_prototype ~privat:true ~native:true name style;
9806       pr "\n";
9807       pr "\n";
9808   ) all_functions;
9809
9810   pr "}\n"
9811
9812 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9813 and generate_java_call_args ~handle args =
9814   pr "(%s" handle;
9815   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9816   pr ")"
9817
9818 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9819     ?(semicolon=true) name style =
9820   if privat then pr "private ";
9821   if public then pr "public ";
9822   if native then pr "native ";
9823
9824   (* return type *)
9825   (match fst style with
9826    | RErr -> pr "void ";
9827    | RInt _ -> pr "int ";
9828    | RInt64 _ -> pr "long ";
9829    | RBool _ -> pr "boolean ";
9830    | RConstString _ | RConstOptString _ | RString _
9831    | RBufferOut _ -> pr "String ";
9832    | RStringList _ -> pr "String[] ";
9833    | RStruct (_, typ) ->
9834        let name = java_name_of_struct typ in
9835        pr "%s " name;
9836    | RStructList (_, typ) ->
9837        let name = java_name_of_struct typ in
9838        pr "%s[] " name;
9839    | RHashtable _ -> pr "HashMap<String,String> ";
9840   );
9841
9842   if native then pr "_%s " name else pr "%s " name;
9843   pr "(";
9844   let needs_comma = ref false in
9845   if native then (
9846     pr "long g";
9847     needs_comma := true
9848   );
9849
9850   (* args *)
9851   List.iter (
9852     fun arg ->
9853       if !needs_comma then pr ", ";
9854       needs_comma := true;
9855
9856       match arg with
9857       | Pathname n
9858       | Device n | Dev_or_Path n
9859       | String n
9860       | OptString n
9861       | FileIn n
9862       | FileOut n ->
9863           pr "String %s" n
9864       | StringList n | DeviceList n ->
9865           pr "String[] %s" n
9866       | Bool n ->
9867           pr "boolean %s" n
9868       | Int n ->
9869           pr "int %s" n
9870       | Int64 n ->
9871           pr "long %s" n
9872   ) (snd style);
9873
9874   pr ")\n";
9875   pr "    throws LibGuestFSException";
9876   if semicolon then pr ";"
9877
9878 and generate_java_struct jtyp cols () =
9879   generate_header CStyle LGPLv2plus;
9880
9881   pr "\
9882 package com.redhat.et.libguestfs;
9883
9884 /**
9885  * Libguestfs %s structure.
9886  *
9887  * @author rjones
9888  * @see GuestFS
9889  */
9890 public class %s {
9891 " jtyp jtyp;
9892
9893   List.iter (
9894     function
9895     | name, FString
9896     | name, FUUID
9897     | name, FBuffer -> pr "  public String %s;\n" name
9898     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9899     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9900     | name, FChar -> pr "  public char %s;\n" name
9901     | name, FOptPercent ->
9902         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9903         pr "  public float %s;\n" name
9904   ) cols;
9905
9906   pr "}\n"
9907
9908 and generate_java_c () =
9909   generate_header CStyle LGPLv2plus;
9910
9911   pr "\
9912 #include <stdio.h>
9913 #include <stdlib.h>
9914 #include <string.h>
9915
9916 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9917 #include \"guestfs.h\"
9918
9919 /* Note that this function returns.  The exception is not thrown
9920  * until after the wrapper function returns.
9921  */
9922 static void
9923 throw_exception (JNIEnv *env, const char *msg)
9924 {
9925   jclass cl;
9926   cl = (*env)->FindClass (env,
9927                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9928   (*env)->ThrowNew (env, cl, msg);
9929 }
9930
9931 JNIEXPORT jlong JNICALL
9932 Java_com_redhat_et_libguestfs_GuestFS__1create
9933   (JNIEnv *env, jobject obj)
9934 {
9935   guestfs_h *g;
9936
9937   g = guestfs_create ();
9938   if (g == NULL) {
9939     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9940     return 0;
9941   }
9942   guestfs_set_error_handler (g, NULL, NULL);
9943   return (jlong) (long) g;
9944 }
9945
9946 JNIEXPORT void JNICALL
9947 Java_com_redhat_et_libguestfs_GuestFS__1close
9948   (JNIEnv *env, jobject obj, jlong jg)
9949 {
9950   guestfs_h *g = (guestfs_h *) (long) jg;
9951   guestfs_close (g);
9952 }
9953
9954 ";
9955
9956   List.iter (
9957     fun (name, style, _, _, _, _, _) ->
9958       pr "JNIEXPORT ";
9959       (match fst style with
9960        | RErr -> pr "void ";
9961        | RInt _ -> pr "jint ";
9962        | RInt64 _ -> pr "jlong ";
9963        | RBool _ -> pr "jboolean ";
9964        | RConstString _ | RConstOptString _ | RString _
9965        | RBufferOut _ -> pr "jstring ";
9966        | RStruct _ | RHashtable _ ->
9967            pr "jobject ";
9968        | RStringList _ | RStructList _ ->
9969            pr "jobjectArray ";
9970       );
9971       pr "JNICALL\n";
9972       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9973       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9974       pr "\n";
9975       pr "  (JNIEnv *env, jobject obj, jlong jg";
9976       List.iter (
9977         function
9978         | Pathname n
9979         | Device n | Dev_or_Path n
9980         | String n
9981         | OptString n
9982         | FileIn n
9983         | FileOut n ->
9984             pr ", jstring j%s" n
9985         | StringList n | DeviceList n ->
9986             pr ", jobjectArray j%s" n
9987         | Bool n ->
9988             pr ", jboolean j%s" n
9989         | Int n ->
9990             pr ", jint j%s" n
9991         | Int64 n ->
9992             pr ", jlong j%s" n
9993       ) (snd style);
9994       pr ")\n";
9995       pr "{\n";
9996       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9997       let error_code, no_ret =
9998         match fst style with
9999         | RErr -> pr "  int r;\n"; "-1", ""
10000         | RBool _
10001         | RInt _ -> pr "  int r;\n"; "-1", "0"
10002         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10003         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10004         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10005         | RString _ ->
10006             pr "  jstring jr;\n";
10007             pr "  char *r;\n"; "NULL", "NULL"
10008         | RStringList _ ->
10009             pr "  jobjectArray jr;\n";
10010             pr "  int r_len;\n";
10011             pr "  jclass cl;\n";
10012             pr "  jstring jstr;\n";
10013             pr "  char **r;\n"; "NULL", "NULL"
10014         | RStruct (_, typ) ->
10015             pr "  jobject jr;\n";
10016             pr "  jclass cl;\n";
10017             pr "  jfieldID fl;\n";
10018             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10019         | RStructList (_, typ) ->
10020             pr "  jobjectArray jr;\n";
10021             pr "  jclass cl;\n";
10022             pr "  jfieldID fl;\n";
10023             pr "  jobject jfl;\n";
10024             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10025         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10026         | RBufferOut _ ->
10027             pr "  jstring jr;\n";
10028             pr "  char *r;\n";
10029             pr "  size_t size;\n";
10030             "NULL", "NULL" in
10031       List.iter (
10032         function
10033         | Pathname n
10034         | Device n | Dev_or_Path n
10035         | String n
10036         | OptString n
10037         | FileIn n
10038         | FileOut n ->
10039             pr "  const char *%s;\n" n
10040         | StringList n | DeviceList n ->
10041             pr "  int %s_len;\n" n;
10042             pr "  const char **%s;\n" n
10043         | Bool n
10044         | Int n ->
10045             pr "  int %s;\n" n
10046         | Int64 n ->
10047             pr "  int64_t %s;\n" n
10048       ) (snd style);
10049
10050       let needs_i =
10051         (match fst style with
10052          | RStringList _ | RStructList _ -> true
10053          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10054          | RConstOptString _
10055          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10056           List.exists (function
10057                        | StringList _ -> true
10058                        | DeviceList _ -> true
10059                        | _ -> false) (snd style) in
10060       if needs_i then
10061         pr "  int i;\n";
10062
10063       pr "\n";
10064
10065       (* Get the parameters. *)
10066       List.iter (
10067         function
10068         | Pathname n
10069         | Device n | Dev_or_Path n
10070         | String n
10071         | FileIn n
10072         | FileOut n ->
10073             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10074         | OptString n ->
10075             (* This is completely undocumented, but Java null becomes
10076              * a NULL parameter.
10077              *)
10078             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10079         | StringList n | DeviceList n ->
10080             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10081             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10082             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10083             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10084               n;
10085             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10086             pr "  }\n";
10087             pr "  %s[%s_len] = NULL;\n" n n;
10088         | Bool n
10089         | Int n
10090         | Int64 n ->
10091             pr "  %s = j%s;\n" n n
10092       ) (snd style);
10093
10094       (* Make the call. *)
10095       pr "  r = guestfs_%s " name;
10096       generate_c_call_args ~handle:"g" style;
10097       pr ";\n";
10098
10099       (* Release the parameters. *)
10100       List.iter (
10101         function
10102         | Pathname n
10103         | Device n | Dev_or_Path n
10104         | String n
10105         | FileIn n
10106         | FileOut n ->
10107             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10108         | OptString n ->
10109             pr "  if (j%s)\n" n;
10110             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10111         | StringList n | DeviceList n ->
10112             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10113             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10114               n;
10115             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10116             pr "  }\n";
10117             pr "  free (%s);\n" n
10118         | Bool n
10119         | Int n
10120         | Int64 n -> ()
10121       ) (snd style);
10122
10123       (* Check for errors. *)
10124       pr "  if (r == %s) {\n" error_code;
10125       pr "    throw_exception (env, guestfs_last_error (g));\n";
10126       pr "    return %s;\n" no_ret;
10127       pr "  }\n";
10128
10129       (* Return value. *)
10130       (match fst style with
10131        | RErr -> ()
10132        | RInt _ -> pr "  return (jint) r;\n"
10133        | RBool _ -> pr "  return (jboolean) r;\n"
10134        | RInt64 _ -> pr "  return (jlong) r;\n"
10135        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10136        | RConstOptString _ ->
10137            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10138        | RString _ ->
10139            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10140            pr "  free (r);\n";
10141            pr "  return jr;\n"
10142        | RStringList _ ->
10143            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10144            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10145            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10146            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10147            pr "  for (i = 0; i < r_len; ++i) {\n";
10148            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10149            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10150            pr "    free (r[i]);\n";
10151            pr "  }\n";
10152            pr "  free (r);\n";
10153            pr "  return jr;\n"
10154        | RStruct (_, typ) ->
10155            let jtyp = java_name_of_struct typ in
10156            let cols = cols_of_struct typ in
10157            generate_java_struct_return typ jtyp cols
10158        | RStructList (_, typ) ->
10159            let jtyp = java_name_of_struct typ in
10160            let cols = cols_of_struct typ in
10161            generate_java_struct_list_return typ jtyp cols
10162        | RHashtable _ ->
10163            (* XXX *)
10164            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10165            pr "  return NULL;\n"
10166        | RBufferOut _ ->
10167            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10168            pr "  free (r);\n";
10169            pr "  return jr;\n"
10170       );
10171
10172       pr "}\n";
10173       pr "\n"
10174   ) all_functions
10175
10176 and generate_java_struct_return typ jtyp cols =
10177   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10178   pr "  jr = (*env)->AllocObject (env, cl);\n";
10179   List.iter (
10180     function
10181     | name, FString ->
10182         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10183         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10184     | name, FUUID ->
10185         pr "  {\n";
10186         pr "    char s[33];\n";
10187         pr "    memcpy (s, r->%s, 32);\n" name;
10188         pr "    s[32] = 0;\n";
10189         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10190         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10191         pr "  }\n";
10192     | name, FBuffer ->
10193         pr "  {\n";
10194         pr "    int len = r->%s_len;\n" name;
10195         pr "    char s[len+1];\n";
10196         pr "    memcpy (s, r->%s, len);\n" name;
10197         pr "    s[len] = 0;\n";
10198         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10199         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10200         pr "  }\n";
10201     | name, (FBytes|FUInt64|FInt64) ->
10202         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10203         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10204     | name, (FUInt32|FInt32) ->
10205         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10206         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10207     | name, FOptPercent ->
10208         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10209         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10210     | name, FChar ->
10211         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10212         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10213   ) cols;
10214   pr "  free (r);\n";
10215   pr "  return jr;\n"
10216
10217 and generate_java_struct_list_return typ jtyp cols =
10218   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10219   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10220   pr "  for (i = 0; i < r->len; ++i) {\n";
10221   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10222   List.iter (
10223     function
10224     | name, FString ->
10225         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10226         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10227     | name, FUUID ->
10228         pr "    {\n";
10229         pr "      char s[33];\n";
10230         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10231         pr "      s[32] = 0;\n";
10232         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10233         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10234         pr "    }\n";
10235     | name, FBuffer ->
10236         pr "    {\n";
10237         pr "      int len = r->val[i].%s_len;\n" name;
10238         pr "      char s[len+1];\n";
10239         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10240         pr "      s[len] = 0;\n";
10241         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10242         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10243         pr "    }\n";
10244     | name, (FBytes|FUInt64|FInt64) ->
10245         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10246         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10247     | name, (FUInt32|FInt32) ->
10248         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10249         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10250     | name, FOptPercent ->
10251         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10252         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10253     | name, FChar ->
10254         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10255         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10256   ) cols;
10257   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10258   pr "  }\n";
10259   pr "  guestfs_free_%s_list (r);\n" typ;
10260   pr "  return jr;\n"
10261
10262 and generate_java_makefile_inc () =
10263   generate_header HashStyle GPLv2plus;
10264
10265   pr "java_built_sources = \\\n";
10266   List.iter (
10267     fun (typ, jtyp) ->
10268         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10269   ) java_structs;
10270   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10271
10272 and generate_haskell_hs () =
10273   generate_header HaskellStyle LGPLv2plus;
10274
10275   (* XXX We only know how to generate partial FFI for Haskell
10276    * at the moment.  Please help out!
10277    *)
10278   let can_generate style =
10279     match style with
10280     | RErr, _
10281     | RInt _, _
10282     | RInt64 _, _ -> true
10283     | RBool _, _
10284     | RConstString _, _
10285     | RConstOptString _, _
10286     | RString _, _
10287     | RStringList _, _
10288     | RStruct _, _
10289     | RStructList _, _
10290     | RHashtable _, _
10291     | RBufferOut _, _ -> false in
10292
10293   pr "\
10294 {-# INCLUDE <guestfs.h> #-}
10295 {-# LANGUAGE ForeignFunctionInterface #-}
10296
10297 module Guestfs (
10298   create";
10299
10300   (* List out the names of the actions we want to export. *)
10301   List.iter (
10302     fun (name, style, _, _, _, _, _) ->
10303       if can_generate style then pr ",\n  %s" name
10304   ) all_functions;
10305
10306   pr "
10307   ) where
10308
10309 -- Unfortunately some symbols duplicate ones already present
10310 -- in Prelude.  We don't know which, so we hard-code a list
10311 -- here.
10312 import Prelude hiding (truncate)
10313
10314 import Foreign
10315 import Foreign.C
10316 import Foreign.C.Types
10317 import IO
10318 import Control.Exception
10319 import Data.Typeable
10320
10321 data GuestfsS = GuestfsS            -- represents the opaque C struct
10322 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10323 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10324
10325 -- XXX define properly later XXX
10326 data PV = PV
10327 data VG = VG
10328 data LV = LV
10329 data IntBool = IntBool
10330 data Stat = Stat
10331 data StatVFS = StatVFS
10332 data Hashtable = Hashtable
10333
10334 foreign import ccall unsafe \"guestfs_create\" c_create
10335   :: IO GuestfsP
10336 foreign import ccall unsafe \"&guestfs_close\" c_close
10337   :: FunPtr (GuestfsP -> IO ())
10338 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10339   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10340
10341 create :: IO GuestfsH
10342 create = do
10343   p <- c_create
10344   c_set_error_handler p nullPtr nullPtr
10345   h <- newForeignPtr c_close p
10346   return h
10347
10348 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10349   :: GuestfsP -> IO CString
10350
10351 -- last_error :: GuestfsH -> IO (Maybe String)
10352 -- last_error h = do
10353 --   str <- withForeignPtr h (\\p -> c_last_error p)
10354 --   maybePeek peekCString str
10355
10356 last_error :: GuestfsH -> IO (String)
10357 last_error h = do
10358   str <- withForeignPtr h (\\p -> c_last_error p)
10359   if (str == nullPtr)
10360     then return \"no error\"
10361     else peekCString str
10362
10363 ";
10364
10365   (* Generate wrappers for each foreign function. *)
10366   List.iter (
10367     fun (name, style, _, _, _, _, _) ->
10368       if can_generate style then (
10369         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10370         pr "  :: ";
10371         generate_haskell_prototype ~handle:"GuestfsP" style;
10372         pr "\n";
10373         pr "\n";
10374         pr "%s :: " name;
10375         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10376         pr "\n";
10377         pr "%s %s = do\n" name
10378           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10379         pr "  r <- ";
10380         (* Convert pointer arguments using with* functions. *)
10381         List.iter (
10382           function
10383           | FileIn n
10384           | FileOut n
10385           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10386           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10387           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10388           | Bool _ | Int _ | Int64 _ -> ()
10389         ) (snd style);
10390         (* Convert integer arguments. *)
10391         let args =
10392           List.map (
10393             function
10394             | Bool n -> sprintf "(fromBool %s)" n
10395             | Int n -> sprintf "(fromIntegral %s)" n
10396             | Int64 n -> sprintf "(fromIntegral %s)" n
10397             | FileIn n | FileOut n
10398             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10399           ) (snd style) in
10400         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10401           (String.concat " " ("p" :: args));
10402         (match fst style with
10403          | RErr | RInt _ | RInt64 _ | RBool _ ->
10404              pr "  if (r == -1)\n";
10405              pr "    then do\n";
10406              pr "      err <- last_error h\n";
10407              pr "      fail err\n";
10408          | RConstString _ | RConstOptString _ | RString _
10409          | RStringList _ | RStruct _
10410          | RStructList _ | RHashtable _ | RBufferOut _ ->
10411              pr "  if (r == nullPtr)\n";
10412              pr "    then do\n";
10413              pr "      err <- last_error h\n";
10414              pr "      fail err\n";
10415         );
10416         (match fst style with
10417          | RErr ->
10418              pr "    else return ()\n"
10419          | RInt _ ->
10420              pr "    else return (fromIntegral r)\n"
10421          | RInt64 _ ->
10422              pr "    else return (fromIntegral r)\n"
10423          | RBool _ ->
10424              pr "    else return (toBool r)\n"
10425          | RConstString _
10426          | RConstOptString _
10427          | RString _
10428          | RStringList _
10429          | RStruct _
10430          | RStructList _
10431          | RHashtable _
10432          | RBufferOut _ ->
10433              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10434         );
10435         pr "\n";
10436       )
10437   ) all_functions
10438
10439 and generate_haskell_prototype ~handle ?(hs = false) style =
10440   pr "%s -> " handle;
10441   let string = if hs then "String" else "CString" in
10442   let int = if hs then "Int" else "CInt" in
10443   let bool = if hs then "Bool" else "CInt" in
10444   let int64 = if hs then "Integer" else "Int64" in
10445   List.iter (
10446     fun arg ->
10447       (match arg with
10448        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10449        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10450        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10451        | Bool _ -> pr "%s" bool
10452        | Int _ -> pr "%s" int
10453        | Int64 _ -> pr "%s" int
10454        | FileIn _ -> pr "%s" string
10455        | FileOut _ -> pr "%s" string
10456       );
10457       pr " -> ";
10458   ) (snd style);
10459   pr "IO (";
10460   (match fst style with
10461    | RErr -> if not hs then pr "CInt"
10462    | RInt _ -> pr "%s" int
10463    | RInt64 _ -> pr "%s" int64
10464    | RBool _ -> pr "%s" bool
10465    | RConstString _ -> pr "%s" string
10466    | RConstOptString _ -> pr "Maybe %s" string
10467    | RString _ -> pr "%s" string
10468    | RStringList _ -> pr "[%s]" string
10469    | RStruct (_, typ) ->
10470        let name = java_name_of_struct typ in
10471        pr "%s" name
10472    | RStructList (_, typ) ->
10473        let name = java_name_of_struct typ in
10474        pr "[%s]" name
10475    | RHashtable _ -> pr "Hashtable"
10476    | RBufferOut _ -> pr "%s" string
10477   );
10478   pr ")"
10479
10480 and generate_csharp () =
10481   generate_header CPlusPlusStyle LGPLv2plus;
10482
10483   (* XXX Make this configurable by the C# assembly users. *)
10484   let library = "libguestfs.so.0" in
10485
10486   pr "\
10487 // These C# bindings are highly experimental at present.
10488 //
10489 // Firstly they only work on Linux (ie. Mono).  In order to get them
10490 // to work on Windows (ie. .Net) you would need to port the library
10491 // itself to Windows first.
10492 //
10493 // The second issue is that some calls are known to be incorrect and
10494 // can cause Mono to segfault.  Particularly: calls which pass or
10495 // return string[], or return any structure value.  This is because
10496 // we haven't worked out the correct way to do this from C#.
10497 //
10498 // The third issue is that when compiling you get a lot of warnings.
10499 // We are not sure whether the warnings are important or not.
10500 //
10501 // Fourthly we do not routinely build or test these bindings as part
10502 // of the make && make check cycle, which means that regressions might
10503 // go unnoticed.
10504 //
10505 // Suggestions and patches are welcome.
10506
10507 // To compile:
10508 //
10509 // gmcs Libguestfs.cs
10510 // mono Libguestfs.exe
10511 //
10512 // (You'll probably want to add a Test class / static main function
10513 // otherwise this won't do anything useful).
10514
10515 using System;
10516 using System.IO;
10517 using System.Runtime.InteropServices;
10518 using System.Runtime.Serialization;
10519 using System.Collections;
10520
10521 namespace Guestfs
10522 {
10523   class Error : System.ApplicationException
10524   {
10525     public Error (string message) : base (message) {}
10526     protected Error (SerializationInfo info, StreamingContext context) {}
10527   }
10528
10529   class Guestfs
10530   {
10531     IntPtr _handle;
10532
10533     [DllImport (\"%s\")]
10534     static extern IntPtr guestfs_create ();
10535
10536     public Guestfs ()
10537     {
10538       _handle = guestfs_create ();
10539       if (_handle == IntPtr.Zero)
10540         throw new Error (\"could not create guestfs handle\");
10541     }
10542
10543     [DllImport (\"%s\")]
10544     static extern void guestfs_close (IntPtr h);
10545
10546     ~Guestfs ()
10547     {
10548       guestfs_close (_handle);
10549     }
10550
10551     [DllImport (\"%s\")]
10552     static extern string guestfs_last_error (IntPtr h);
10553
10554 " library library library;
10555
10556   (* Generate C# structure bindings.  We prefix struct names with
10557    * underscore because C# cannot have conflicting struct names and
10558    * method names (eg. "class stat" and "stat").
10559    *)
10560   List.iter (
10561     fun (typ, cols) ->
10562       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10563       pr "    public class _%s {\n" typ;
10564       List.iter (
10565         function
10566         | name, FChar -> pr "      char %s;\n" name
10567         | name, FString -> pr "      string %s;\n" name
10568         | name, FBuffer ->
10569             pr "      uint %s_len;\n" name;
10570             pr "      string %s;\n" name
10571         | name, FUUID ->
10572             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10573             pr "      string %s;\n" name
10574         | name, FUInt32 -> pr "      uint %s;\n" name
10575         | name, FInt32 -> pr "      int %s;\n" name
10576         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10577         | name, FInt64 -> pr "      long %s;\n" name
10578         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10579       ) cols;
10580       pr "    }\n";
10581       pr "\n"
10582   ) structs;
10583
10584   (* Generate C# function bindings. *)
10585   List.iter (
10586     fun (name, style, _, _, _, shortdesc, _) ->
10587       let rec csharp_return_type () =
10588         match fst style with
10589         | RErr -> "void"
10590         | RBool n -> "bool"
10591         | RInt n -> "int"
10592         | RInt64 n -> "long"
10593         | RConstString n
10594         | RConstOptString n
10595         | RString n
10596         | RBufferOut n -> "string"
10597         | RStruct (_,n) -> "_" ^ n
10598         | RHashtable n -> "Hashtable"
10599         | RStringList n -> "string[]"
10600         | RStructList (_,n) -> sprintf "_%s[]" n
10601
10602       and c_return_type () =
10603         match fst style with
10604         | RErr
10605         | RBool _
10606         | RInt _ -> "int"
10607         | RInt64 _ -> "long"
10608         | RConstString _
10609         | RConstOptString _
10610         | RString _
10611         | RBufferOut _ -> "string"
10612         | RStruct (_,n) -> "_" ^ n
10613         | RHashtable _
10614         | RStringList _ -> "string[]"
10615         | RStructList (_,n) -> sprintf "_%s[]" n
10616
10617       and c_error_comparison () =
10618         match fst style with
10619         | RErr
10620         | RBool _
10621         | RInt _
10622         | RInt64 _ -> "== -1"
10623         | RConstString _
10624         | RConstOptString _
10625         | RString _
10626         | RBufferOut _
10627         | RStruct (_,_)
10628         | RHashtable _
10629         | RStringList _
10630         | RStructList (_,_) -> "== null"
10631
10632       and generate_extern_prototype () =
10633         pr "    static extern %s guestfs_%s (IntPtr h"
10634           (c_return_type ()) name;
10635         List.iter (
10636           function
10637           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10638           | FileIn n | FileOut n ->
10639               pr ", [In] string %s" n
10640           | StringList n | DeviceList n ->
10641               pr ", [In] string[] %s" n
10642           | Bool n ->
10643               pr ", bool %s" n
10644           | Int n ->
10645               pr ", int %s" n
10646           | Int64 n ->
10647               pr ", long %s" n
10648         ) (snd style);
10649         pr ");\n"
10650
10651       and generate_public_prototype () =
10652         pr "    public %s %s (" (csharp_return_type ()) name;
10653         let comma = ref false in
10654         let next () =
10655           if !comma then pr ", ";
10656           comma := true
10657         in
10658         List.iter (
10659           function
10660           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10661           | FileIn n | FileOut n ->
10662               next (); pr "string %s" n
10663           | StringList n | DeviceList n ->
10664               next (); pr "string[] %s" n
10665           | Bool n ->
10666               next (); pr "bool %s" n
10667           | Int n ->
10668               next (); pr "int %s" n
10669           | Int64 n ->
10670               next (); pr "long %s" n
10671         ) (snd style);
10672         pr ")\n"
10673
10674       and generate_call () =
10675         pr "guestfs_%s (_handle" name;
10676         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10677         pr ");\n";
10678       in
10679
10680       pr "    [DllImport (\"%s\")]\n" library;
10681       generate_extern_prototype ();
10682       pr "\n";
10683       pr "    /// <summary>\n";
10684       pr "    /// %s\n" shortdesc;
10685       pr "    /// </summary>\n";
10686       generate_public_prototype ();
10687       pr "    {\n";
10688       pr "      %s r;\n" (c_return_type ());
10689       pr "      r = ";
10690       generate_call ();
10691       pr "      if (r %s)\n" (c_error_comparison ());
10692       pr "        throw new Error (guestfs_last_error (_handle));\n";
10693       (match fst style with
10694        | RErr -> ()
10695        | RBool _ ->
10696            pr "      return r != 0 ? true : false;\n"
10697        | RHashtable _ ->
10698            pr "      Hashtable rr = new Hashtable ();\n";
10699            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10700            pr "        rr.Add (r[i], r[i+1]);\n";
10701            pr "      return rr;\n"
10702        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10703        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10704        | RStructList _ ->
10705            pr "      return r;\n"
10706       );
10707       pr "    }\n";
10708       pr "\n";
10709   ) all_functions_sorted;
10710
10711   pr "  }
10712 }
10713 "
10714
10715 and generate_bindtests () =
10716   generate_header CStyle LGPLv2plus;
10717
10718   pr "\
10719 #include <stdio.h>
10720 #include <stdlib.h>
10721 #include <inttypes.h>
10722 #include <string.h>
10723
10724 #include \"guestfs.h\"
10725 #include \"guestfs-internal.h\"
10726 #include \"guestfs-internal-actions.h\"
10727 #include \"guestfs_protocol.h\"
10728
10729 #define error guestfs_error
10730 #define safe_calloc guestfs_safe_calloc
10731 #define safe_malloc guestfs_safe_malloc
10732
10733 static void
10734 print_strings (char *const *argv)
10735 {
10736   int argc;
10737
10738   printf (\"[\");
10739   for (argc = 0; argv[argc] != NULL; ++argc) {
10740     if (argc > 0) printf (\", \");
10741     printf (\"\\\"%%s\\\"\", argv[argc]);
10742   }
10743   printf (\"]\\n\");
10744 }
10745
10746 /* The test0 function prints its parameters to stdout. */
10747 ";
10748
10749   let test0, tests =
10750     match test_functions with
10751     | [] -> assert false
10752     | test0 :: tests -> test0, tests in
10753
10754   let () =
10755     let (name, style, _, _, _, _, _) = test0 in
10756     generate_prototype ~extern:false ~semicolon:false ~newline:true
10757       ~handle:"g" ~prefix:"guestfs__" name style;
10758     pr "{\n";
10759     List.iter (
10760       function
10761       | Pathname n
10762       | Device n | Dev_or_Path n
10763       | String n
10764       | FileIn n
10765       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10766       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10767       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10768       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10769       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10770       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10771     ) (snd style);
10772     pr "  /* Java changes stdout line buffering so we need this: */\n";
10773     pr "  fflush (stdout);\n";
10774     pr "  return 0;\n";
10775     pr "}\n";
10776     pr "\n" in
10777
10778   List.iter (
10779     fun (name, style, _, _, _, _, _) ->
10780       if String.sub name (String.length name - 3) 3 <> "err" then (
10781         pr "/* Test normal return. */\n";
10782         generate_prototype ~extern:false ~semicolon:false ~newline:true
10783           ~handle:"g" ~prefix:"guestfs__" name style;
10784         pr "{\n";
10785         (match fst style with
10786          | RErr ->
10787              pr "  return 0;\n"
10788          | RInt _ ->
10789              pr "  int r;\n";
10790              pr "  sscanf (val, \"%%d\", &r);\n";
10791              pr "  return r;\n"
10792          | RInt64 _ ->
10793              pr "  int64_t r;\n";
10794              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10795              pr "  return r;\n"
10796          | RBool _ ->
10797              pr "  return STREQ (val, \"true\");\n"
10798          | RConstString _
10799          | RConstOptString _ ->
10800              (* Can't return the input string here.  Return a static
10801               * string so we ensure we get a segfault if the caller
10802               * tries to free it.
10803               *)
10804              pr "  return \"static string\";\n"
10805          | RString _ ->
10806              pr "  return strdup (val);\n"
10807          | RStringList _ ->
10808              pr "  char **strs;\n";
10809              pr "  int n, i;\n";
10810              pr "  sscanf (val, \"%%d\", &n);\n";
10811              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10812              pr "  for (i = 0; i < n; ++i) {\n";
10813              pr "    strs[i] = safe_malloc (g, 16);\n";
10814              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10815              pr "  }\n";
10816              pr "  strs[n] = NULL;\n";
10817              pr "  return strs;\n"
10818          | RStruct (_, typ) ->
10819              pr "  struct guestfs_%s *r;\n" typ;
10820              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10821              pr "  return r;\n"
10822          | RStructList (_, typ) ->
10823              pr "  struct guestfs_%s_list *r;\n" typ;
10824              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10825              pr "  sscanf (val, \"%%d\", &r->len);\n";
10826              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10827              pr "  return r;\n"
10828          | RHashtable _ ->
10829              pr "  char **strs;\n";
10830              pr "  int n, i;\n";
10831              pr "  sscanf (val, \"%%d\", &n);\n";
10832              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10833              pr "  for (i = 0; i < n; ++i) {\n";
10834              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10835              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10836              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10837              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10838              pr "  }\n";
10839              pr "  strs[n*2] = NULL;\n";
10840              pr "  return strs;\n"
10841          | RBufferOut _ ->
10842              pr "  return strdup (val);\n"
10843         );
10844         pr "}\n";
10845         pr "\n"
10846       ) else (
10847         pr "/* Test error return. */\n";
10848         generate_prototype ~extern:false ~semicolon:false ~newline:true
10849           ~handle:"g" ~prefix:"guestfs__" name style;
10850         pr "{\n";
10851         pr "  error (g, \"error\");\n";
10852         (match fst style with
10853          | RErr | RInt _ | RInt64 _ | RBool _ ->
10854              pr "  return -1;\n"
10855          | RConstString _ | RConstOptString _
10856          | RString _ | RStringList _ | RStruct _
10857          | RStructList _
10858          | RHashtable _
10859          | RBufferOut _ ->
10860              pr "  return NULL;\n"
10861         );
10862         pr "}\n";
10863         pr "\n"
10864       )
10865   ) tests
10866
10867 and generate_ocaml_bindtests () =
10868   generate_header OCamlStyle GPLv2plus;
10869
10870   pr "\
10871 let () =
10872   let g = Guestfs.create () in
10873 ";
10874
10875   let mkargs args =
10876     String.concat " " (
10877       List.map (
10878         function
10879         | CallString s -> "\"" ^ s ^ "\""
10880         | CallOptString None -> "None"
10881         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10882         | CallStringList xs ->
10883             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10884         | CallInt i when i >= 0 -> string_of_int i
10885         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10886         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10887         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10888         | CallBool b -> string_of_bool b
10889       ) args
10890     )
10891   in
10892
10893   generate_lang_bindtests (
10894     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10895   );
10896
10897   pr "print_endline \"EOF\"\n"
10898
10899 and generate_perl_bindtests () =
10900   pr "#!/usr/bin/perl -w\n";
10901   generate_header HashStyle GPLv2plus;
10902
10903   pr "\
10904 use strict;
10905
10906 use Sys::Guestfs;
10907
10908 my $g = Sys::Guestfs->new ();
10909 ";
10910
10911   let mkargs args =
10912     String.concat ", " (
10913       List.map (
10914         function
10915         | CallString s -> "\"" ^ s ^ "\""
10916         | CallOptString None -> "undef"
10917         | CallOptString (Some s) -> sprintf "\"%s\"" s
10918         | CallStringList xs ->
10919             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10920         | CallInt i -> string_of_int i
10921         | CallInt64 i -> Int64.to_string i
10922         | CallBool b -> if b then "1" else "0"
10923       ) args
10924     )
10925   in
10926
10927   generate_lang_bindtests (
10928     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10929   );
10930
10931   pr "print \"EOF\\n\"\n"
10932
10933 and generate_python_bindtests () =
10934   generate_header HashStyle GPLv2plus;
10935
10936   pr "\
10937 import guestfs
10938
10939 g = guestfs.GuestFS ()
10940 ";
10941
10942   let mkargs args =
10943     String.concat ", " (
10944       List.map (
10945         function
10946         | CallString s -> "\"" ^ s ^ "\""
10947         | CallOptString None -> "None"
10948         | CallOptString (Some s) -> sprintf "\"%s\"" s
10949         | CallStringList xs ->
10950             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10951         | CallInt i -> string_of_int i
10952         | CallInt64 i -> Int64.to_string i
10953         | CallBool b -> if b then "1" else "0"
10954       ) args
10955     )
10956   in
10957
10958   generate_lang_bindtests (
10959     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10960   );
10961
10962   pr "print \"EOF\"\n"
10963
10964 and generate_ruby_bindtests () =
10965   generate_header HashStyle GPLv2plus;
10966
10967   pr "\
10968 require 'guestfs'
10969
10970 g = Guestfs::create()
10971 ";
10972
10973   let mkargs args =
10974     String.concat ", " (
10975       List.map (
10976         function
10977         | CallString s -> "\"" ^ s ^ "\""
10978         | CallOptString None -> "nil"
10979         | CallOptString (Some s) -> sprintf "\"%s\"" s
10980         | CallStringList xs ->
10981             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10982         | CallInt i -> string_of_int i
10983         | CallInt64 i -> Int64.to_string i
10984         | CallBool b -> string_of_bool b
10985       ) args
10986     )
10987   in
10988
10989   generate_lang_bindtests (
10990     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10991   );
10992
10993   pr "print \"EOF\\n\"\n"
10994
10995 and generate_java_bindtests () =
10996   generate_header CStyle GPLv2plus;
10997
10998   pr "\
10999 import com.redhat.et.libguestfs.*;
11000
11001 public class Bindtests {
11002     public static void main (String[] argv)
11003     {
11004         try {
11005             GuestFS g = new GuestFS ();
11006 ";
11007
11008   let mkargs args =
11009     String.concat ", " (
11010       List.map (
11011         function
11012         | CallString s -> "\"" ^ s ^ "\""
11013         | CallOptString None -> "null"
11014         | CallOptString (Some s) -> sprintf "\"%s\"" s
11015         | CallStringList xs ->
11016             "new String[]{" ^
11017               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11018         | CallInt i -> string_of_int i
11019         | CallInt64 i -> Int64.to_string i
11020         | CallBool b -> string_of_bool b
11021       ) args
11022     )
11023   in
11024
11025   generate_lang_bindtests (
11026     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11027   );
11028
11029   pr "
11030             System.out.println (\"EOF\");
11031         }
11032         catch (Exception exn) {
11033             System.err.println (exn);
11034             System.exit (1);
11035         }
11036     }
11037 }
11038 "
11039
11040 and generate_haskell_bindtests () =
11041   generate_header HaskellStyle GPLv2plus;
11042
11043   pr "\
11044 module Bindtests where
11045 import qualified Guestfs
11046
11047 main = do
11048   g <- Guestfs.create
11049 ";
11050
11051   let mkargs args =
11052     String.concat " " (
11053       List.map (
11054         function
11055         | CallString s -> "\"" ^ s ^ "\""
11056         | CallOptString None -> "Nothing"
11057         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11058         | CallStringList xs ->
11059             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11060         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11061         | CallInt i -> string_of_int i
11062         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11063         | CallInt64 i -> Int64.to_string i
11064         | CallBool true -> "True"
11065         | CallBool false -> "False"
11066       ) args
11067     )
11068   in
11069
11070   generate_lang_bindtests (
11071     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11072   );
11073
11074   pr "  putStrLn \"EOF\"\n"
11075
11076 (* Language-independent bindings tests - we do it this way to
11077  * ensure there is parity in testing bindings across all languages.
11078  *)
11079 and generate_lang_bindtests call =
11080   call "test0" [CallString "abc"; CallOptString (Some "def");
11081                 CallStringList []; CallBool false;
11082                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11083   call "test0" [CallString "abc"; CallOptString None;
11084                 CallStringList []; CallBool false;
11085                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11086   call "test0" [CallString ""; CallOptString (Some "def");
11087                 CallStringList []; CallBool false;
11088                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11089   call "test0" [CallString ""; CallOptString (Some "");
11090                 CallStringList []; CallBool false;
11091                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11092   call "test0" [CallString "abc"; CallOptString (Some "def");
11093                 CallStringList ["1"]; CallBool false;
11094                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11095   call "test0" [CallString "abc"; CallOptString (Some "def");
11096                 CallStringList ["1"; "2"]; CallBool false;
11097                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11098   call "test0" [CallString "abc"; CallOptString (Some "def");
11099                 CallStringList ["1"]; CallBool true;
11100                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11101   call "test0" [CallString "abc"; CallOptString (Some "def");
11102                 CallStringList ["1"]; CallBool false;
11103                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11104   call "test0" [CallString "abc"; CallOptString (Some "def");
11105                 CallStringList ["1"]; CallBool false;
11106                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11107   call "test0" [CallString "abc"; CallOptString (Some "def");
11108                 CallStringList ["1"]; CallBool false;
11109                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11110   call "test0" [CallString "abc"; CallOptString (Some "def");
11111                 CallStringList ["1"]; CallBool false;
11112                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11113   call "test0" [CallString "abc"; CallOptString (Some "def");
11114                 CallStringList ["1"]; CallBool false;
11115                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11116   call "test0" [CallString "abc"; CallOptString (Some "def");
11117                 CallStringList ["1"]; CallBool false;
11118                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11119
11120 (* XXX Add here tests of the return and error functions. *)
11121
11122 (* Code to generator bindings for virt-inspector.  Currently only
11123  * implemented for OCaml code (for virt-p2v 2.0).
11124  *)
11125 let rng_input = "inspector/virt-inspector.rng"
11126
11127 (* Read the input file and parse it into internal structures.  This is
11128  * by no means a complete RELAX NG parser, but is just enough to be
11129  * able to parse the specific input file.
11130  *)
11131 type rng =
11132   | Element of string * rng list        (* <element name=name/> *)
11133   | Attribute of string * rng list        (* <attribute name=name/> *)
11134   | Interleave of rng list                (* <interleave/> *)
11135   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11136   | OneOrMore of rng                        (* <oneOrMore/> *)
11137   | Optional of rng                        (* <optional/> *)
11138   | Choice of string list                (* <choice><value/>*</choice> *)
11139   | Value of string                        (* <value>str</value> *)
11140   | Text                                (* <text/> *)
11141
11142 let rec string_of_rng = function
11143   | Element (name, xs) ->
11144       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11145   | Attribute (name, xs) ->
11146       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11147   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11148   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11149   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11150   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11151   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11152   | Value value -> "Value \"" ^ value ^ "\""
11153   | Text -> "Text"
11154
11155 and string_of_rng_list xs =
11156   String.concat ", " (List.map string_of_rng xs)
11157
11158 let rec parse_rng ?defines context = function
11159   | [] -> []
11160   | Xml.Element ("element", ["name", name], children) :: rest ->
11161       Element (name, parse_rng ?defines context children)
11162       :: parse_rng ?defines context rest
11163   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11164       Attribute (name, parse_rng ?defines context children)
11165       :: parse_rng ?defines context rest
11166   | Xml.Element ("interleave", [], children) :: rest ->
11167       Interleave (parse_rng ?defines context children)
11168       :: parse_rng ?defines context rest
11169   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11170       let rng = parse_rng ?defines context [child] in
11171       (match rng with
11172        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11173        | _ ->
11174            failwithf "%s: <zeroOrMore> contains more than one child element"
11175              context
11176       )
11177   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11178       let rng = parse_rng ?defines context [child] in
11179       (match rng with
11180        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11181        | _ ->
11182            failwithf "%s: <oneOrMore> contains more than one child element"
11183              context
11184       )
11185   | Xml.Element ("optional", [], [child]) :: rest ->
11186       let rng = parse_rng ?defines context [child] in
11187       (match rng with
11188        | [child] -> Optional child :: parse_rng ?defines context rest
11189        | _ ->
11190            failwithf "%s: <optional> contains more than one child element"
11191              context
11192       )
11193   | Xml.Element ("choice", [], children) :: rest ->
11194       let values = List.map (
11195         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11196         | _ ->
11197             failwithf "%s: can't handle anything except <value> in <choice>"
11198               context
11199       ) children in
11200       Choice values
11201       :: parse_rng ?defines context rest
11202   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11203       Value value :: parse_rng ?defines context rest
11204   | Xml.Element ("text", [], []) :: rest ->
11205       Text :: parse_rng ?defines context rest
11206   | Xml.Element ("ref", ["name", name], []) :: rest ->
11207       (* Look up the reference.  Because of limitations in this parser,
11208        * we can't handle arbitrarily nested <ref> yet.  You can only
11209        * use <ref> from inside <start>.
11210        *)
11211       (match defines with
11212        | None ->
11213            failwithf "%s: contains <ref>, but no refs are defined yet" context
11214        | Some map ->
11215            let rng = StringMap.find name map in
11216            rng @ parse_rng ?defines context rest
11217       )
11218   | x :: _ ->
11219       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11220
11221 let grammar =
11222   let xml = Xml.parse_file rng_input in
11223   match xml with
11224   | Xml.Element ("grammar", _,
11225                  Xml.Element ("start", _, gram) :: defines) ->
11226       (* The <define/> elements are referenced in the <start> section,
11227        * so build a map of those first.
11228        *)
11229       let defines = List.fold_left (
11230         fun map ->
11231           function Xml.Element ("define", ["name", name], defn) ->
11232             StringMap.add name defn map
11233           | _ ->
11234               failwithf "%s: expected <define name=name/>" rng_input
11235       ) StringMap.empty defines in
11236       let defines = StringMap.mapi parse_rng defines in
11237
11238       (* Parse the <start> clause, passing the defines. *)
11239       parse_rng ~defines "<start>" gram
11240   | _ ->
11241       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11242         rng_input
11243
11244 let name_of_field = function
11245   | Element (name, _) | Attribute (name, _)
11246   | ZeroOrMore (Element (name, _))
11247   | OneOrMore (Element (name, _))
11248   | Optional (Element (name, _)) -> name
11249   | Optional (Attribute (name, _)) -> name
11250   | Text -> (* an unnamed field in an element *)
11251       "data"
11252   | rng ->
11253       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11254
11255 (* At the moment this function only generates OCaml types.  However we
11256  * should parameterize it later so it can generate types/structs in a
11257  * variety of languages.
11258  *)
11259 let generate_types xs =
11260   (* A simple type is one that can be printed out directly, eg.
11261    * "string option".  A complex type is one which has a name and has
11262    * to be defined via another toplevel definition, eg. a struct.
11263    *
11264    * generate_type generates code for either simple or complex types.
11265    * In the simple case, it returns the string ("string option").  In
11266    * the complex case, it returns the name ("mountpoint").  In the
11267    * complex case it has to print out the definition before returning,
11268    * so it should only be called when we are at the beginning of a
11269    * new line (BOL context).
11270    *)
11271   let rec generate_type = function
11272     | Text ->                                (* string *)
11273         "string", true
11274     | Choice values ->                        (* [`val1|`val2|...] *)
11275         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11276     | ZeroOrMore rng ->                        (* <rng> list *)
11277         let t, is_simple = generate_type rng in
11278         t ^ " list (* 0 or more *)", is_simple
11279     | OneOrMore rng ->                        (* <rng> list *)
11280         let t, is_simple = generate_type rng in
11281         t ^ " list (* 1 or more *)", is_simple
11282                                         (* virt-inspector hack: bool *)
11283     | Optional (Attribute (name, [Value "1"])) ->
11284         "bool", true
11285     | Optional rng ->                        (* <rng> list *)
11286         let t, is_simple = generate_type rng in
11287         t ^ " option", is_simple
11288                                         (* type name = { fields ... } *)
11289     | Element (name, fields) when is_attrs_interleave fields ->
11290         generate_type_struct name (get_attrs_interleave fields)
11291     | Element (name, [field])                (* type name = field *)
11292     | Attribute (name, [field]) ->
11293         let t, is_simple = generate_type field in
11294         if is_simple then (t, true)
11295         else (
11296           pr "type %s = %s\n" name t;
11297           name, false
11298         )
11299     | Element (name, fields) ->              (* type name = { fields ... } *)
11300         generate_type_struct name fields
11301     | rng ->
11302         failwithf "generate_type failed at: %s" (string_of_rng rng)
11303
11304   and is_attrs_interleave = function
11305     | [Interleave _] -> true
11306     | Attribute _ :: fields -> is_attrs_interleave fields
11307     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11308     | _ -> false
11309
11310   and get_attrs_interleave = function
11311     | [Interleave fields] -> fields
11312     | ((Attribute _) as field) :: fields
11313     | ((Optional (Attribute _)) as field) :: fields ->
11314         field :: get_attrs_interleave fields
11315     | _ -> assert false
11316
11317   and generate_types xs =
11318     List.iter (fun x -> ignore (generate_type x)) xs
11319
11320   and generate_type_struct name fields =
11321     (* Calculate the types of the fields first.  We have to do this
11322      * before printing anything so we are still in BOL context.
11323      *)
11324     let types = List.map fst (List.map generate_type fields) in
11325
11326     (* Special case of a struct containing just a string and another
11327      * field.  Turn it into an assoc list.
11328      *)
11329     match types with
11330     | ["string"; other] ->
11331         let fname1, fname2 =
11332           match fields with
11333           | [f1; f2] -> name_of_field f1, name_of_field f2
11334           | _ -> assert false in
11335         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11336         name, false
11337
11338     | types ->
11339         pr "type %s = {\n" name;
11340         List.iter (
11341           fun (field, ftype) ->
11342             let fname = name_of_field field in
11343             pr "  %s_%s : %s;\n" name fname ftype
11344         ) (List.combine fields types);
11345         pr "}\n";
11346         (* Return the name of this type, and
11347          * false because it's not a simple type.
11348          *)
11349         name, false
11350   in
11351
11352   generate_types xs
11353
11354 let generate_parsers xs =
11355   (* As for generate_type above, generate_parser makes a parser for
11356    * some type, and returns the name of the parser it has generated.
11357    * Because it (may) need to print something, it should always be
11358    * called in BOL context.
11359    *)
11360   let rec generate_parser = function
11361     | Text ->                                (* string *)
11362         "string_child_or_empty"
11363     | Choice values ->                        (* [`val1|`val2|...] *)
11364         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11365           (String.concat "|"
11366              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11367     | ZeroOrMore rng ->                        (* <rng> list *)
11368         let pa = generate_parser rng in
11369         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11370     | OneOrMore rng ->                        (* <rng> list *)
11371         let pa = generate_parser rng in
11372         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11373                                         (* virt-inspector hack: bool *)
11374     | Optional (Attribute (name, [Value "1"])) ->
11375         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11376     | Optional rng ->                        (* <rng> list *)
11377         let pa = generate_parser rng in
11378         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11379                                         (* type name = { fields ... } *)
11380     | Element (name, fields) when is_attrs_interleave fields ->
11381         generate_parser_struct name (get_attrs_interleave fields)
11382     | Element (name, [field]) ->        (* type name = field *)
11383         let pa = generate_parser field in
11384         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11385         pr "let %s =\n" parser_name;
11386         pr "  %s\n" pa;
11387         pr "let parse_%s = %s\n" name parser_name;
11388         parser_name
11389     | Attribute (name, [field]) ->
11390         let pa = generate_parser field in
11391         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11392         pr "let %s =\n" parser_name;
11393         pr "  %s\n" pa;
11394         pr "let parse_%s = %s\n" name parser_name;
11395         parser_name
11396     | Element (name, fields) ->              (* type name = { fields ... } *)
11397         generate_parser_struct name ([], fields)
11398     | rng ->
11399         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11400
11401   and is_attrs_interleave = function
11402     | [Interleave _] -> true
11403     | Attribute _ :: fields -> is_attrs_interleave fields
11404     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11405     | _ -> false
11406
11407   and get_attrs_interleave = function
11408     | [Interleave fields] -> [], fields
11409     | ((Attribute _) as field) :: fields
11410     | ((Optional (Attribute _)) as field) :: fields ->
11411         let attrs, interleaves = get_attrs_interleave fields in
11412         (field :: attrs), interleaves
11413     | _ -> assert false
11414
11415   and generate_parsers xs =
11416     List.iter (fun x -> ignore (generate_parser x)) xs
11417
11418   and generate_parser_struct name (attrs, interleaves) =
11419     (* Generate parsers for the fields first.  We have to do this
11420      * before printing anything so we are still in BOL context.
11421      *)
11422     let fields = attrs @ interleaves in
11423     let pas = List.map generate_parser fields in
11424
11425     (* Generate an intermediate tuple from all the fields first.
11426      * If the type is just a string + another field, then we will
11427      * return this directly, otherwise it is turned into a record.
11428      *
11429      * RELAX NG note: This code treats <interleave> and plain lists of
11430      * fields the same.  In other words, it doesn't bother enforcing
11431      * any ordering of fields in the XML.
11432      *)
11433     pr "let parse_%s x =\n" name;
11434     pr "  let t = (\n    ";
11435     let comma = ref false in
11436     List.iter (
11437       fun x ->
11438         if !comma then pr ",\n    ";
11439         comma := true;
11440         match x with
11441         | Optional (Attribute (fname, [field])), pa ->
11442             pr "%s x" pa
11443         | Optional (Element (fname, [field])), pa ->
11444             pr "%s (optional_child %S x)" pa fname
11445         | Attribute (fname, [Text]), _ ->
11446             pr "attribute %S x" fname
11447         | (ZeroOrMore _ | OneOrMore _), pa ->
11448             pr "%s x" pa
11449         | Text, pa ->
11450             pr "%s x" pa
11451         | (field, pa) ->
11452             let fname = name_of_field field in
11453             pr "%s (child %S x)" pa fname
11454     ) (List.combine fields pas);
11455     pr "\n  ) in\n";
11456
11457     (match fields with
11458      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11459          pr "  t\n"
11460
11461      | _ ->
11462          pr "  (Obj.magic t : %s)\n" name
11463 (*
11464          List.iter (
11465            function
11466            | (Optional (Attribute (fname, [field])), pa) ->
11467                pr "  %s_%s =\n" name fname;
11468                pr "    %s x;\n" pa
11469            | (Optional (Element (fname, [field])), pa) ->
11470                pr "  %s_%s =\n" name fname;
11471                pr "    (let x = optional_child %S x in\n" fname;
11472                pr "     %s x);\n" pa
11473            | (field, pa) ->
11474                let fname = name_of_field field in
11475                pr "  %s_%s =\n" name fname;
11476                pr "    (let x = child %S x in\n" fname;
11477                pr "     %s x);\n" pa
11478          ) (List.combine fields pas);
11479          pr "}\n"
11480 *)
11481     );
11482     sprintf "parse_%s" name
11483   in
11484
11485   generate_parsers xs
11486
11487 (* Generate ocaml/guestfs_inspector.mli. *)
11488 let generate_ocaml_inspector_mli () =
11489   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11490
11491   pr "\
11492 (** This is an OCaml language binding to the external [virt-inspector]
11493     program.
11494
11495     For more information, please read the man page [virt-inspector(1)].
11496 *)
11497
11498 ";
11499
11500   generate_types grammar;
11501   pr "(** The nested information returned from the {!inspect} function. *)\n";
11502   pr "\n";
11503
11504   pr "\
11505 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11506 (** To inspect a libvirt domain called [name], pass a singleton
11507     list: [inspect [name]].  When using libvirt only, you may
11508     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11509
11510     To inspect a disk image or images, pass a list of the filenames
11511     of the disk images: [inspect filenames]
11512
11513     This function inspects the given guest or disk images and
11514     returns a list of operating system(s) found and a large amount
11515     of information about them.  In the vast majority of cases,
11516     a virtual machine only contains a single operating system.
11517
11518     If the optional [~xml] parameter is given, then this function
11519     skips running the external virt-inspector program and just
11520     parses the given XML directly (which is expected to be XML
11521     produced from a previous run of virt-inspector).  The list of
11522     names and connect URI are ignored in this case.
11523
11524     This function can throw a wide variety of exceptions, for example
11525     if the external virt-inspector program cannot be found, or if
11526     it doesn't generate valid XML.
11527 *)
11528 "
11529
11530 (* Generate ocaml/guestfs_inspector.ml. *)
11531 let generate_ocaml_inspector_ml () =
11532   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11533
11534   pr "open Unix\n";
11535   pr "\n";
11536
11537   generate_types grammar;
11538   pr "\n";
11539
11540   pr "\
11541 (* Misc functions which are used by the parser code below. *)
11542 let first_child = function
11543   | Xml.Element (_, _, c::_) -> c
11544   | Xml.Element (name, _, []) ->
11545       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11546   | Xml.PCData str ->
11547       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11548
11549 let string_child_or_empty = function
11550   | Xml.Element (_, _, [Xml.PCData s]) -> s
11551   | Xml.Element (_, _, []) -> \"\"
11552   | Xml.Element (x, _, _) ->
11553       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11554                 x ^ \" instead\")
11555   | Xml.PCData str ->
11556       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11557
11558 let optional_child name xml =
11559   let children = Xml.children xml in
11560   try
11561     Some (List.find (function
11562                      | Xml.Element (n, _, _) when n = name -> true
11563                      | _ -> false) children)
11564   with
11565     Not_found -> None
11566
11567 let child name xml =
11568   match optional_child name xml with
11569   | Some c -> c
11570   | None ->
11571       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11572
11573 let attribute name xml =
11574   try Xml.attrib xml name
11575   with Xml.No_attribute _ ->
11576     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11577
11578 ";
11579
11580   generate_parsers grammar;
11581   pr "\n";
11582
11583   pr "\
11584 (* Run external virt-inspector, then use parser to parse the XML. *)
11585 let inspect ?connect ?xml names =
11586   let xml =
11587     match xml with
11588     | None ->
11589         if names = [] then invalid_arg \"inspect: no names given\";
11590         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11591           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11592           names in
11593         let cmd = List.map Filename.quote cmd in
11594         let cmd = String.concat \" \" cmd in
11595         let chan = open_process_in cmd in
11596         let xml = Xml.parse_in chan in
11597         (match close_process_in chan with
11598          | WEXITED 0 -> ()
11599          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11600          | WSIGNALED i | WSTOPPED i ->
11601              failwith (\"external virt-inspector command died or stopped on sig \" ^
11602                        string_of_int i)
11603         );
11604         xml
11605     | Some doc ->
11606         Xml.parse_string doc in
11607   parse_operatingsystems xml
11608 "
11609
11610 (* This is used to generate the src/MAX_PROC_NR file which
11611  * contains the maximum procedure number, a surrogate for the
11612  * ABI version number.  See src/Makefile.am for the details.
11613  *)
11614 and generate_max_proc_nr () =
11615   let proc_nrs = List.map (
11616     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11617   ) daemon_functions in
11618
11619   let max_proc_nr = List.fold_left max 0 proc_nrs in
11620
11621   pr "%d\n" max_proc_nr
11622
11623 let output_to filename k =
11624   let filename_new = filename ^ ".new" in
11625   chan := open_out filename_new;
11626   k ();
11627   close_out !chan;
11628   chan := Pervasives.stdout;
11629
11630   (* Is the new file different from the current file? *)
11631   if Sys.file_exists filename && files_equal filename filename_new then
11632     unlink filename_new                 (* same, so skip it *)
11633   else (
11634     (* different, overwrite old one *)
11635     (try chmod filename 0o644 with Unix_error _ -> ());
11636     rename filename_new filename;
11637     chmod filename 0o444;
11638     printf "written %s\n%!" filename;
11639   )
11640
11641 let perror msg = function
11642   | Unix_error (err, _, _) ->
11643       eprintf "%s: %s\n" msg (error_message err)
11644   | exn ->
11645       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11646
11647 (* Main program. *)
11648 let () =
11649   let lock_fd =
11650     try openfile "HACKING" [O_RDWR] 0
11651     with
11652     | Unix_error (ENOENT, _, _) ->
11653         eprintf "\
11654 You are probably running this from the wrong directory.
11655 Run it from the top source directory using the command
11656   src/generator.ml
11657 ";
11658         exit 1
11659     | exn ->
11660         perror "open: HACKING" exn;
11661         exit 1 in
11662
11663   (* Acquire a lock so parallel builds won't try to run the generator
11664    * twice at the same time.  Subsequent builds will wait for the first
11665    * one to finish.  Note the lock is released implicitly when the
11666    * program exits.
11667    *)
11668   (try lockf lock_fd F_LOCK 1
11669    with exn ->
11670      perror "lock: HACKING" exn;
11671      exit 1);
11672
11673   check_functions ();
11674
11675   output_to "src/guestfs_protocol.x" generate_xdr;
11676   output_to "src/guestfs-structs.h" generate_structs_h;
11677   output_to "src/guestfs-actions.h" generate_actions_h;
11678   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11679   output_to "src/guestfs-actions.c" generate_client_actions;
11680   output_to "src/guestfs-bindtests.c" generate_bindtests;
11681   output_to "src/guestfs-structs.pod" generate_structs_pod;
11682   output_to "src/guestfs-actions.pod" generate_actions_pod;
11683   output_to "src/guestfs-availability.pod" generate_availability_pod;
11684   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11685   output_to "src/libguestfs.syms" generate_linker_script;
11686   output_to "daemon/actions.h" generate_daemon_actions_h;
11687   output_to "daemon/stubs.c" generate_daemon_actions;
11688   output_to "daemon/names.c" generate_daemon_names;
11689   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11690   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11691   output_to "capitests/tests.c" generate_tests;
11692   output_to "fish/cmds.c" generate_fish_cmds;
11693   output_to "fish/completion.c" generate_fish_completion;
11694   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11695   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11696   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11697   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11698   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11699   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11700   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11701   output_to "perl/Guestfs.xs" generate_perl_xs;
11702   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11703   output_to "perl/bindtests.pl" generate_perl_bindtests;
11704   output_to "python/guestfs-py.c" generate_python_c;
11705   output_to "python/guestfs.py" generate_python_py;
11706   output_to "python/bindtests.py" generate_python_bindtests;
11707   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11708   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11709   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11710
11711   List.iter (
11712     fun (typ, jtyp) ->
11713       let cols = cols_of_struct typ in
11714       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11715       output_to filename (generate_java_struct jtyp cols);
11716   ) java_structs;
11717
11718   output_to "java/Makefile.inc" generate_java_makefile_inc;
11719   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11720   output_to "java/Bindtests.java" generate_java_bindtests;
11721   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11722   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11723   output_to "csharp/Libguestfs.cs" generate_csharp;
11724
11725   (* Always generate this file last, and unconditionally.  It's used
11726    * by the Makefile to know when we must re-run the generator.
11727    *)
11728   let chan = open_out "src/stamp-generator" in
11729   fprintf chan "1\n";
11730   close_out chan;
11731
11732   printf "generated %d lines of code\n" !lines