87855e7d1e919e0b0274fb0b50c061a292ab1263
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | FishOutput of fish_output_t (* how to display output in guestfish *)
186   | NotInFish             (* do not export via guestfish *)
187   | NotInDocs             (* do not add this function to documentation *)
188   | DeprecatedBy of string (* function is deprecated, use .. instead *)
189   | Optional of string    (* function is part of an optional group *)
190
191 and fish_output_t =
192   | FishOutputOctal       (* for int return, print in octal *)
193   | FishOutputHexadecimal (* for int return, print in hex *)
194
195 (* You can supply zero or as many tests as you want per API call.
196  *
197  * Note that the test environment has 3 block devices, of size 500MB,
198  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
199  * a fourth ISO block device with some known files on it (/dev/sdd).
200  *
201  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
202  * Number of cylinders was 63 for IDE emulated disks with precisely
203  * the same size.  How exactly this is calculated is a mystery.
204  *
205  * The ISO block device (/dev/sdd) comes from images/test.iso.
206  *
207  * To be able to run the tests in a reasonable amount of time,
208  * the virtual machine and block devices are reused between tests.
209  * So don't try testing kill_subprocess :-x
210  *
211  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
212  *
213  * Don't assume anything about the previous contents of the block
214  * devices.  Use 'Init*' to create some initial scenarios.
215  *
216  * You can add a prerequisite clause to any individual test.  This
217  * is a run-time check, which, if it fails, causes the test to be
218  * skipped.  Useful if testing a command which might not work on
219  * all variations of libguestfs builds.  A test that has prerequisite
220  * of 'Always' is run unconditionally.
221  *
222  * In addition, packagers can skip individual tests by setting the
223  * environment variables:     eg:
224  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
225  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
226  *)
227 type tests = (test_init * test_prereq * test) list
228 and test =
229     (* Run the command sequence and just expect nothing to fail. *)
230   | TestRun of seq
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the string.
234      *)
235   | TestOutput of seq * string
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of strings.
239      *)
240   | TestOutputList of seq * string list
241
242     (* Run the command sequence and expect the output of the final
243      * command to be the list of block devices (could be either
244      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
245      * character of each string).
246      *)
247   | TestOutputListOfDevices of seq * string list
248
249     (* Run the command sequence and expect the output of the final
250      * command to be the integer.
251      *)
252   | TestOutputInt of seq * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be <op> <int>, eg. ">=", "1".
256      *)
257   | TestOutputIntOp of seq * string * int
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a true value (!= 0 or != NULL).
261      *)
262   | TestOutputTrue of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a false value (== 0 or == NULL, but not an error).
266      *)
267   | TestOutputFalse of seq
268
269     (* Run the command sequence and expect the output of the final
270      * command to be a list of the given length (but don't care about
271      * content).
272      *)
273   | TestOutputLength of seq * int
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a buffer (RBufferOut), ie. string + size.
277      *)
278   | TestOutputBuffer of seq * string
279
280     (* Run the command sequence and expect the output of the final
281      * command to be a structure.
282      *)
283   | TestOutputStruct of seq * test_field_compare list
284
285     (* Run the command sequence and expect the final command (only)
286      * to fail.
287      *)
288   | TestLastFail of seq
289
290 and test_field_compare =
291   | CompareWithInt of string * int
292   | CompareWithIntOp of string * string * int
293   | CompareWithString of string * string
294   | CompareFieldsIntEq of string * string
295   | CompareFieldsStrEq of string * string
296
297 (* Test prerequisites. *)
298 and test_prereq =
299     (* Test always runs. *)
300   | Always
301
302     (* Test is currently disabled - eg. it fails, or it tests some
303      * unimplemented feature.
304      *)
305   | Disabled
306
307     (* 'string' is some C code (a function body) that should return
308      * true or false.  The test will run if the code returns true.
309      *)
310   | If of string
311
312     (* As for 'If' but the test runs _unless_ the code returns true. *)
313   | Unless of string
314
315 (* Some initial scenarios for testing. *)
316 and test_init =
317     (* Do nothing, block devices could contain random stuff including
318      * LVM PVs, and some filesystems might be mounted.  This is usually
319      * a bad idea.
320      *)
321   | InitNone
322
323     (* Block devices are empty and no filesystems are mounted. *)
324   | InitEmpty
325
326     (* /dev/sda contains a single partition /dev/sda1, with random
327      * content.  /dev/sdb and /dev/sdc may have random content.
328      * No LVM.
329      *)
330   | InitPartition
331
332     (* /dev/sda contains a single partition /dev/sda1, which is formatted
333      * as ext2, empty [except for lost+found] and mounted on /.
334      * /dev/sdb and /dev/sdc may have random content.
335      * No LVM.
336      *)
337   | InitBasicFS
338
339     (* /dev/sda:
340      *   /dev/sda1 (is a PV):
341      *     /dev/VG/LV (size 8MB):
342      *       formatted as ext2, empty [except for lost+found], mounted on /
343      * /dev/sdb and /dev/sdc may have random content.
344      *)
345   | InitBasicFSonLVM
346
347     (* /dev/sdd (the ISO, see images/ directory in source)
348      * is mounted on /
349      *)
350   | InitISOFS
351
352 (* Sequence of commands for testing. *)
353 and seq = cmd list
354 and cmd = string list
355
356 (* Note about long descriptions: When referring to another
357  * action, use the format C<guestfs_other> (ie. the full name of
358  * the C function).  This will be replaced as appropriate in other
359  * language bindings.
360  *
361  * Apart from that, long descriptions are just perldoc paragraphs.
362  *)
363
364 (* Generate a random UUID (used in tests). *)
365 let uuidgen () =
366   let chan = open_process_in "uuidgen" in
367   let uuid = input_line chan in
368   (match close_process_in chan with
369    | WEXITED 0 -> ()
370    | WEXITED _ ->
371        failwith "uuidgen: process exited with non-zero status"
372    | WSIGNALED _ | WSTOPPED _ ->
373        failwith "uuidgen: process signalled or stopped by signal"
374   );
375   uuid
376
377 (* These test functions are used in the language binding tests. *)
378
379 let test_all_args = [
380   String "str";
381   OptString "optstr";
382   StringList "strlist";
383   Bool "b";
384   Int "integer";
385   Int64 "integer64";
386   FileIn "filein";
387   FileOut "fileout";
388 ]
389
390 let test_all_rets = [
391   (* except for RErr, which is tested thoroughly elsewhere *)
392   "test0rint",         RInt "valout";
393   "test0rint64",       RInt64 "valout";
394   "test0rbool",        RBool "valout";
395   "test0rconststring", RConstString "valout";
396   "test0rconstoptstring", RConstOptString "valout";
397   "test0rstring",      RString "valout";
398   "test0rstringlist",  RStringList "valout";
399   "test0rstruct",      RStruct ("valout", "lvm_pv");
400   "test0rstructlist",  RStructList ("valout", "lvm_pv");
401   "test0rhashtable",   RHashtable "valout";
402 ]
403
404 let test_functions = [
405   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
406    [],
407    "internal test function - do not use",
408    "\
409 This is an internal test function which is used to test whether
410 the automatically generated bindings can handle every possible
411 parameter type correctly.
412
413 It echos the contents of each parameter to stdout.
414
415 You probably don't want to call this function.");
416 ] @ List.flatten (
417   List.map (
418     fun (name, ret) ->
419       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
420         [],
421         "internal test function - do not use",
422         "\
423 This is an internal test function which is used to test whether
424 the automatically generated bindings can handle every possible
425 return type correctly.
426
427 It converts string C<val> to the return type.
428
429 You probably don't want to call this function.");
430        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
431         [],
432         "internal test function - do not use",
433         "\
434 This is an internal test function which is used to test whether
435 the automatically generated bindings can handle every possible
436 return type correctly.
437
438 This function always returns an error.
439
440 You probably don't want to call this function.")]
441   ) test_all_rets
442 )
443
444 (* non_daemon_functions are any functions which don't get processed
445  * in the daemon, eg. functions for setting and getting local
446  * configuration values.
447  *)
448
449 let non_daemon_functions = test_functions @ [
450   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
451    [],
452    "launch the qemu subprocess",
453    "\
454 Internally libguestfs is implemented by running a virtual machine
455 using L<qemu(1)>.
456
457 You should call this after configuring the handle
458 (eg. adding drives) but before performing any actions.");
459
460   ("wait_ready", (RErr, []), -1, [NotInFish],
461    [],
462    "wait until the qemu subprocess launches (no op)",
463    "\
464 This function is a no op.
465
466 In versions of the API E<lt> 1.0.71 you had to call this function
467 just after calling C<guestfs_launch> to wait for the launch
468 to complete.  However this is no longer necessary because
469 C<guestfs_launch> now does the waiting.
470
471 If you see any calls to this function in code then you can just
472 remove them, unless you want to retain compatibility with older
473 versions of the API.");
474
475   ("kill_subprocess", (RErr, []), -1, [],
476    [],
477    "kill the qemu subprocess",
478    "\
479 This kills the qemu subprocess.  You should never need to call this.");
480
481   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
482    [],
483    "add an image to examine or modify",
484    "\
485 This function adds a virtual machine disk image C<filename> to the
486 guest.  The first time you call this function, the disk appears as IDE
487 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
488 so on.
489
490 You don't necessarily need to be root when using libguestfs.  However
491 you obviously do need sufficient permissions to access the filename
492 for whatever operations you want to perform (ie. read access if you
493 just want to read the image or write access if you want to modify the
494 image).
495
496 This is equivalent to the qemu parameter
497 C<-drive file=filename,cache=off,if=...>.
498
499 C<cache=off> is omitted in cases where it is not supported by
500 the underlying filesystem.
501
502 C<if=...> is set at compile time by the configuration option
503 C<./configure --with-drive-if=...>.  In the rare case where you
504 might need to change this at run time, use C<guestfs_add_drive_with_if>
505 or C<guestfs_add_drive_ro_with_if>.
506
507 Note that this call checks for the existence of C<filename>.  This
508 stops you from specifying other types of drive which are supported
509 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
510 the general C<guestfs_config> call instead.");
511
512   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
513    [],
514    "add a CD-ROM disk image to examine",
515    "\
516 This function adds a virtual CD-ROM disk image to the guest.
517
518 This is equivalent to the qemu parameter C<-cdrom filename>.
519
520 Notes:
521
522 =over 4
523
524 =item *
525
526 This call checks for the existence of C<filename>.  This
527 stops you from specifying other types of drive which are supported
528 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
529 the general C<guestfs_config> call instead.
530
531 =item *
532
533 If you just want to add an ISO file (often you use this as an
534 efficient way to transfer large files into the guest), then you
535 should probably use C<guestfs_add_drive_ro> instead.
536
537 =back");
538
539   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
540    [],
541    "add a drive in snapshot mode (read-only)",
542    "\
543 This adds a drive in snapshot mode, making it effectively
544 read-only.
545
546 Note that writes to the device are allowed, and will be seen for
547 the duration of the guestfs handle, but they are written
548 to a temporary file which is discarded as soon as the guestfs
549 handle is closed.  We don't currently have any method to enable
550 changes to be committed, although qemu can support this.
551
552 This is equivalent to the qemu parameter
553 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
554
555 C<if=...> is set at compile time by the configuration option
556 C<./configure --with-drive-if=...>.  In the rare case where you
557 might need to change this at run time, use C<guestfs_add_drive_with_if>
558 or C<guestfs_add_drive_ro_with_if>.
559
560 C<readonly=on> is only added where qemu supports this option.
561
562 Note that this call checks for the existence of C<filename>.  This
563 stops you from specifying other types of drive which are supported
564 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
565 the general C<guestfs_config> call instead.");
566
567   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
568    [],
569    "add qemu parameters",
570    "\
571 This can be used to add arbitrary qemu command line parameters
572 of the form C<-param value>.  Actually it's not quite arbitrary - we
573 prevent you from setting some parameters which would interfere with
574 parameters that we use.
575
576 The first character of C<param> string must be a C<-> (dash).
577
578 C<value> can be NULL.");
579
580   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
581    [],
582    "set the qemu binary",
583    "\
584 Set the qemu binary that we will use.
585
586 The default is chosen when the library was compiled by the
587 configure script.
588
589 You can also override this by setting the C<LIBGUESTFS_QEMU>
590 environment variable.
591
592 Setting C<qemu> to C<NULL> restores the default qemu binary.
593
594 Note that you should call this function as early as possible
595 after creating the handle.  This is because some pre-launch
596 operations depend on testing qemu features (by running C<qemu -help>).
597 If the qemu binary changes, we don't retest features, and
598 so you might see inconsistent results.  Using the environment
599 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
600 the qemu binary at the same time as the handle is created.");
601
602   ("get_qemu", (RConstString "qemu", []), -1, [],
603    [InitNone, Always, TestRun (
604       [["get_qemu"]])],
605    "get the qemu binary",
606    "\
607 Return the current qemu binary.
608
609 This is always non-NULL.  If it wasn't set already, then this will
610 return the default qemu binary name.");
611
612   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
613    [],
614    "set the search path",
615    "\
616 Set the path that libguestfs searches for kernel and initrd.img.
617
618 The default is C<$libdir/guestfs> unless overridden by setting
619 C<LIBGUESTFS_PATH> environment variable.
620
621 Setting C<path> to C<NULL> restores the default path.");
622
623   ("get_path", (RConstString "path", []), -1, [],
624    [InitNone, Always, TestRun (
625       [["get_path"]])],
626    "get the search path",
627    "\
628 Return the current search path.
629
630 This is always non-NULL.  If it wasn't set already, then this will
631 return the default path.");
632
633   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
634    [],
635    "add options to kernel command line",
636    "\
637 This function is used to add additional options to the
638 guest kernel command line.
639
640 The default is C<NULL> unless overridden by setting
641 C<LIBGUESTFS_APPEND> environment variable.
642
643 Setting C<append> to C<NULL> means I<no> additional options
644 are passed (libguestfs always adds a few of its own).");
645
646   ("get_append", (RConstOptString "append", []), -1, [],
647    (* This cannot be tested with the current framework.  The
648     * function can return NULL in normal operations, which the
649     * test framework interprets as an error.
650     *)
651    [],
652    "get the additional kernel options",
653    "\
654 Return the additional kernel options which are added to the
655 guest kernel command line.
656
657 If C<NULL> then no options are added.");
658
659   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
660    [],
661    "set autosync mode",
662    "\
663 If C<autosync> is true, this enables autosync.  Libguestfs will make a
664 best effort attempt to run C<guestfs_umount_all> followed by
665 C<guestfs_sync> when the handle is closed
666 (also if the program exits without closing handles).
667
668 This is disabled by default (except in guestfish where it is
669 enabled by default).");
670
671   ("get_autosync", (RBool "autosync", []), -1, [],
672    [InitNone, Always, TestRun (
673       [["get_autosync"]])],
674    "get autosync mode",
675    "\
676 Get the autosync flag.");
677
678   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
679    [],
680    "set verbose mode",
681    "\
682 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
683
684 Verbose messages are disabled unless the environment variable
685 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
686
687   ("get_verbose", (RBool "verbose", []), -1, [],
688    [],
689    "get verbose mode",
690    "\
691 This returns the verbose messages flag.");
692
693   ("is_ready", (RBool "ready", []), -1, [],
694    [InitNone, Always, TestOutputTrue (
695       [["is_ready"]])],
696    "is ready to accept commands",
697    "\
698 This returns true iff this handle is ready to accept commands
699 (in the C<READY> state).
700
701 For more information on states, see L<guestfs(3)>.");
702
703   ("is_config", (RBool "config", []), -1, [],
704    [InitNone, Always, TestOutputFalse (
705       [["is_config"]])],
706    "is in configuration state",
707    "\
708 This returns true iff this handle is being configured
709 (in the C<CONFIG> state).
710
711 For more information on states, see L<guestfs(3)>.");
712
713   ("is_launching", (RBool "launching", []), -1, [],
714    [InitNone, Always, TestOutputFalse (
715       [["is_launching"]])],
716    "is launching subprocess",
717    "\
718 This returns true iff this handle is launching the subprocess
719 (in the C<LAUNCHING> state).
720
721 For more information on states, see L<guestfs(3)>.");
722
723   ("is_busy", (RBool "busy", []), -1, [],
724    [InitNone, Always, TestOutputFalse (
725       [["is_busy"]])],
726    "is busy processing a command",
727    "\
728 This returns true iff this handle is busy processing a command
729 (in the C<BUSY> state).
730
731 For more information on states, see L<guestfs(3)>.");
732
733   ("get_state", (RInt "state", []), -1, [],
734    [],
735    "get the current state",
736    "\
737 This returns the current state as an opaque integer.  This is
738 only useful for printing debug and internal error messages.
739
740 For more information on states, see L<guestfs(3)>.");
741
742   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
743    [InitNone, Always, TestOutputInt (
744       [["set_memsize"; "500"];
745        ["get_memsize"]], 500)],
746    "set memory allocated to the qemu subprocess",
747    "\
748 This sets the memory size in megabytes allocated to the
749 qemu subprocess.  This only has any effect if called before
750 C<guestfs_launch>.
751
752 You can also change this by setting the environment
753 variable C<LIBGUESTFS_MEMSIZE> before the handle is
754 created.
755
756 For more information on the architecture of libguestfs,
757 see L<guestfs(3)>.");
758
759   ("get_memsize", (RInt "memsize", []), -1, [],
760    [InitNone, Always, TestOutputIntOp (
761       [["get_memsize"]], ">=", 256)],
762    "get memory allocated to the qemu subprocess",
763    "\
764 This gets the memory size in megabytes allocated to the
765 qemu subprocess.
766
767 If C<guestfs_set_memsize> was not called
768 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
769 then this returns the compiled-in default value for memsize.
770
771 For more information on the architecture of libguestfs,
772 see L<guestfs(3)>.");
773
774   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
775    [InitNone, Always, TestOutputIntOp (
776       [["get_pid"]], ">=", 1)],
777    "get PID of qemu subprocess",
778    "\
779 Return the process ID of the qemu subprocess.  If there is no
780 qemu subprocess, then this will return an error.
781
782 This is an internal call used for debugging and testing.");
783
784   ("version", (RStruct ("version", "version"), []), -1, [],
785    [InitNone, Always, TestOutputStruct (
786       [["version"]], [CompareWithInt ("major", 1)])],
787    "get the library version number",
788    "\
789 Return the libguestfs version number that the program is linked
790 against.
791
792 Note that because of dynamic linking this is not necessarily
793 the version of libguestfs that you compiled against.  You can
794 compile the program, and then at runtime dynamically link
795 against a completely different C<libguestfs.so> library.
796
797 This call was added in version C<1.0.58>.  In previous
798 versions of libguestfs there was no way to get the version
799 number.  From C code you can use ELF weak linking tricks to find out if
800 this symbol exists (if it doesn't, then it's an earlier version).
801
802 The call returns a structure with four elements.  The first
803 three (C<major>, C<minor> and C<release>) are numbers and
804 correspond to the usual version triplet.  The fourth element
805 (C<extra>) is a string and is normally empty, but may be
806 used for distro-specific information.
807
808 To construct the original version string:
809 C<$major.$minor.$release$extra>
810
811 I<Note:> Don't use this call to test for availability
812 of features.  Distro backports makes this unreliable.  Use
813 C<guestfs_available> instead.");
814
815   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
816    [InitNone, Always, TestOutputTrue (
817       [["set_selinux"; "true"];
818        ["get_selinux"]])],
819    "set SELinux enabled or disabled at appliance boot",
820    "\
821 This sets the selinux flag that is passed to the appliance
822 at boot time.  The default is C<selinux=0> (disabled).
823
824 Note that if SELinux is enabled, it is always in
825 Permissive mode (C<enforcing=0>).
826
827 For more information on the architecture of libguestfs,
828 see L<guestfs(3)>.");
829
830   ("get_selinux", (RBool "selinux", []), -1, [],
831    [],
832    "get SELinux enabled flag",
833    "\
834 This returns the current setting of the selinux flag which
835 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
836
837 For more information on the architecture of libguestfs,
838 see L<guestfs(3)>.");
839
840   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
841    [InitNone, Always, TestOutputFalse (
842       [["set_trace"; "false"];
843        ["get_trace"]])],
844    "enable or disable command traces",
845    "\
846 If the command trace flag is set to 1, then commands are
847 printed on stdout before they are executed in a format
848 which is very similar to the one used by guestfish.  In
849 other words, you can run a program with this enabled, and
850 you will get out a script which you can feed to guestfish
851 to perform the same set of actions.
852
853 If you want to trace C API calls into libguestfs (and
854 other libraries) then possibly a better way is to use
855 the external ltrace(1) command.
856
857 Command traces are disabled unless the environment variable
858 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
859
860   ("get_trace", (RBool "trace", []), -1, [],
861    [],
862    "get command trace enabled flag",
863    "\
864 Return the command trace flag.");
865
866   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
867    [InitNone, Always, TestOutputFalse (
868       [["set_direct"; "false"];
869        ["get_direct"]])],
870    "enable or disable direct appliance mode",
871    "\
872 If the direct appliance mode flag is enabled, then stdin and
873 stdout are passed directly through to the appliance once it
874 is launched.
875
876 One consequence of this is that log messages aren't caught
877 by the library and handled by C<guestfs_set_log_message_callback>,
878 but go straight to stdout.
879
880 You probably don't want to use this unless you know what you
881 are doing.
882
883 The default is disabled.");
884
885   ("get_direct", (RBool "direct", []), -1, [],
886    [],
887    "get direct appliance mode flag",
888    "\
889 Return the direct appliance mode flag.");
890
891   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
892    [InitNone, Always, TestOutputTrue (
893       [["set_recovery_proc"; "true"];
894        ["get_recovery_proc"]])],
895    "enable or disable the recovery process",
896    "\
897 If this is called with the parameter C<false> then
898 C<guestfs_launch> does not create a recovery process.  The
899 purpose of the recovery process is to stop runaway qemu
900 processes in the case where the main program aborts abruptly.
901
902 This only has any effect if called before C<guestfs_launch>,
903 and the default is true.
904
905 About the only time when you would want to disable this is
906 if the main process will fork itself into the background
907 (\"daemonize\" itself).  In this case the recovery process
908 thinks that the main program has disappeared and so kills
909 qemu, which is not very helpful.");
910
911   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
912    [],
913    "get recovery process enabled flag",
914    "\
915 Return the recovery process enabled flag.");
916
917   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
918    [],
919    "add a drive specifying the QEMU block emulation to use",
920    "\
921 This is the same as C<guestfs_add_drive> but it allows you
922 to specify the QEMU interface emulation to use at run time.");
923
924   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
925    [],
926    "add a drive read-only specifying the QEMU block emulation to use",
927    "\
928 This is the same as C<guestfs_add_drive_ro> but it allows you
929 to specify the QEMU interface emulation to use at run time.");
930
931 ]
932
933 (* daemon_functions are any functions which cause some action
934  * to take place in the daemon.
935  *)
936
937 let daemon_functions = [
938   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
939    [InitEmpty, Always, TestOutput (
940       [["part_disk"; "/dev/sda"; "mbr"];
941        ["mkfs"; "ext2"; "/dev/sda1"];
942        ["mount"; "/dev/sda1"; "/"];
943        ["write_file"; "/new"; "new file contents"; "0"];
944        ["cat"; "/new"]], "new file contents")],
945    "mount a guest disk at a position in the filesystem",
946    "\
947 Mount a guest disk at a position in the filesystem.  Block devices
948 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
949 the guest.  If those block devices contain partitions, they will have
950 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
951 names can be used.
952
953 The rules are the same as for L<mount(2)>:  A filesystem must
954 first be mounted on C</> before others can be mounted.  Other
955 filesystems can only be mounted on directories which already
956 exist.
957
958 The mounted filesystem is writable, if we have sufficient permissions
959 on the underlying device.
960
961 The filesystem options C<sync> and C<noatime> are set with this
962 call, in order to improve reliability.");
963
964   ("sync", (RErr, []), 2, [],
965    [ InitEmpty, Always, TestRun [["sync"]]],
966    "sync disks, writes are flushed through to the disk image",
967    "\
968 This syncs the disk, so that any writes are flushed through to the
969 underlying disk image.
970
971 You should always call this if you have modified a disk image, before
972 closing the handle.");
973
974   ("touch", (RErr, [Pathname "path"]), 3, [],
975    [InitBasicFS, Always, TestOutputTrue (
976       [["touch"; "/new"];
977        ["exists"; "/new"]])],
978    "update file timestamps or create a new file",
979    "\
980 Touch acts like the L<touch(1)> command.  It can be used to
981 update the timestamps on a file, or, if the file does not exist,
982 to create a new zero-length file.");
983
984   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
985    [InitISOFS, Always, TestOutput (
986       [["cat"; "/known-2"]], "abcdef\n")],
987    "list the contents of a file",
988    "\
989 Return the contents of the file named C<path>.
990
991 Note that this function cannot correctly handle binary files
992 (specifically, files containing C<\\0> character which is treated
993 as end of string).  For those you need to use the C<guestfs_read_file>
994 or C<guestfs_download> functions which have a more complex interface.");
995
996   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
997    [], (* XXX Tricky to test because it depends on the exact format
998         * of the 'ls -l' command, which changes between F10 and F11.
999         *)
1000    "list the files in a directory (long format)",
1001    "\
1002 List the files in C<directory> (relative to the root directory,
1003 there is no cwd) in the format of 'ls -la'.
1004
1005 This command is mostly useful for interactive sessions.  It
1006 is I<not> intended that you try to parse the output string.");
1007
1008   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1009    [InitBasicFS, Always, TestOutputList (
1010       [["touch"; "/new"];
1011        ["touch"; "/newer"];
1012        ["touch"; "/newest"];
1013        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1014    "list the files in a directory",
1015    "\
1016 List the files in C<directory> (relative to the root directory,
1017 there is no cwd).  The '.' and '..' entries are not returned, but
1018 hidden files are shown.
1019
1020 This command is mostly useful for interactive sessions.  Programs
1021 should probably use C<guestfs_readdir> instead.");
1022
1023   ("list_devices", (RStringList "devices", []), 7, [],
1024    [InitEmpty, Always, TestOutputListOfDevices (
1025       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1026    "list the block devices",
1027    "\
1028 List all the block devices.
1029
1030 The full block device names are returned, eg. C</dev/sda>");
1031
1032   ("list_partitions", (RStringList "partitions", []), 8, [],
1033    [InitBasicFS, Always, TestOutputListOfDevices (
1034       [["list_partitions"]], ["/dev/sda1"]);
1035     InitEmpty, Always, TestOutputListOfDevices (
1036       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1037        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1038    "list the partitions",
1039    "\
1040 List all the partitions detected on all block devices.
1041
1042 The full partition device names are returned, eg. C</dev/sda1>
1043
1044 This does not return logical volumes.  For that you will need to
1045 call C<guestfs_lvs>.");
1046
1047   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1048    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1049       [["pvs"]], ["/dev/sda1"]);
1050     InitEmpty, Always, TestOutputListOfDevices (
1051       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1052        ["pvcreate"; "/dev/sda1"];
1053        ["pvcreate"; "/dev/sda2"];
1054        ["pvcreate"; "/dev/sda3"];
1055        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1056    "list the LVM physical volumes (PVs)",
1057    "\
1058 List all the physical volumes detected.  This is the equivalent
1059 of the L<pvs(8)> command.
1060
1061 This returns a list of just the device names that contain
1062 PVs (eg. C</dev/sda2>).
1063
1064 See also C<guestfs_pvs_full>.");
1065
1066   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1067    [InitBasicFSonLVM, Always, TestOutputList (
1068       [["vgs"]], ["VG"]);
1069     InitEmpty, Always, TestOutputList (
1070       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1071        ["pvcreate"; "/dev/sda1"];
1072        ["pvcreate"; "/dev/sda2"];
1073        ["pvcreate"; "/dev/sda3"];
1074        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1075        ["vgcreate"; "VG2"; "/dev/sda3"];
1076        ["vgs"]], ["VG1"; "VG2"])],
1077    "list the LVM volume groups (VGs)",
1078    "\
1079 List all the volumes groups detected.  This is the equivalent
1080 of the L<vgs(8)> command.
1081
1082 This returns a list of just the volume group names that were
1083 detected (eg. C<VolGroup00>).
1084
1085 See also C<guestfs_vgs_full>.");
1086
1087   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1088    [InitBasicFSonLVM, Always, TestOutputList (
1089       [["lvs"]], ["/dev/VG/LV"]);
1090     InitEmpty, Always, TestOutputList (
1091       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1092        ["pvcreate"; "/dev/sda1"];
1093        ["pvcreate"; "/dev/sda2"];
1094        ["pvcreate"; "/dev/sda3"];
1095        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1096        ["vgcreate"; "VG2"; "/dev/sda3"];
1097        ["lvcreate"; "LV1"; "VG1"; "50"];
1098        ["lvcreate"; "LV2"; "VG1"; "50"];
1099        ["lvcreate"; "LV3"; "VG2"; "50"];
1100        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1101    "list the LVM logical volumes (LVs)",
1102    "\
1103 List all the logical volumes detected.  This is the equivalent
1104 of the L<lvs(8)> command.
1105
1106 This returns a list of the logical volume device names
1107 (eg. C</dev/VolGroup00/LogVol00>).
1108
1109 See also C<guestfs_lvs_full>.");
1110
1111   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1112    [], (* XXX how to test? *)
1113    "list the LVM physical volumes (PVs)",
1114    "\
1115 List all the physical volumes detected.  This is the equivalent
1116 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1117
1118   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1119    [], (* XXX how to test? *)
1120    "list the LVM volume groups (VGs)",
1121    "\
1122 List all the volumes groups detected.  This is the equivalent
1123 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1124
1125   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM logical volumes (LVs)",
1128    "\
1129 List all the logical volumes detected.  This is the equivalent
1130 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1133    [InitISOFS, Always, TestOutputList (
1134       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1135     InitISOFS, Always, TestOutputList (
1136       [["read_lines"; "/empty"]], [])],
1137    "read file as lines",
1138    "\
1139 Return the contents of the file named C<path>.
1140
1141 The file contents are returned as a list of lines.  Trailing
1142 C<LF> and C<CRLF> character sequences are I<not> returned.
1143
1144 Note that this function cannot correctly handle binary files
1145 (specifically, files containing C<\\0> character which is treated
1146 as end of line).  For those you need to use the C<guestfs_read_file>
1147 function which has a more complex interface.");
1148
1149   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1150    [], (* XXX Augeas code needs tests. *)
1151    "create a new Augeas handle",
1152    "\
1153 Create a new Augeas handle for editing configuration files.
1154 If there was any previous Augeas handle associated with this
1155 guestfs session, then it is closed.
1156
1157 You must call this before using any other C<guestfs_aug_*>
1158 commands.
1159
1160 C<root> is the filesystem root.  C<root> must not be NULL,
1161 use C</> instead.
1162
1163 The flags are the same as the flags defined in
1164 E<lt>augeas.hE<gt>, the logical I<or> of the following
1165 integers:
1166
1167 =over 4
1168
1169 =item C<AUG_SAVE_BACKUP> = 1
1170
1171 Keep the original file with a C<.augsave> extension.
1172
1173 =item C<AUG_SAVE_NEWFILE> = 2
1174
1175 Save changes into a file with extension C<.augnew>, and
1176 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1177
1178 =item C<AUG_TYPE_CHECK> = 4
1179
1180 Typecheck lenses (can be expensive).
1181
1182 =item C<AUG_NO_STDINC> = 8
1183
1184 Do not use standard load path for modules.
1185
1186 =item C<AUG_SAVE_NOOP> = 16
1187
1188 Make save a no-op, just record what would have been changed.
1189
1190 =item C<AUG_NO_LOAD> = 32
1191
1192 Do not load the tree in C<guestfs_aug_init>.
1193
1194 =back
1195
1196 To close the handle, you can call C<guestfs_aug_close>.
1197
1198 To find out more about Augeas, see L<http://augeas.net/>.");
1199
1200   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1201    [], (* XXX Augeas code needs tests. *)
1202    "close the current Augeas handle",
1203    "\
1204 Close the current Augeas handle and free up any resources
1205 used by it.  After calling this, you have to call
1206 C<guestfs_aug_init> again before you can use any other
1207 Augeas functions.");
1208
1209   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1210    [], (* XXX Augeas code needs tests. *)
1211    "define an Augeas variable",
1212    "\
1213 Defines an Augeas variable C<name> whose value is the result
1214 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1215 undefined.
1216
1217 On success this returns the number of nodes in C<expr>, or
1218 C<0> if C<expr> evaluates to something which is not a nodeset.");
1219
1220   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1221    [], (* XXX Augeas code needs tests. *)
1222    "define an Augeas node",
1223    "\
1224 Defines a variable C<name> whose value is the result of
1225 evaluating C<expr>.
1226
1227 If C<expr> evaluates to an empty nodeset, a node is created,
1228 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1229 C<name> will be the nodeset containing that single node.
1230
1231 On success this returns a pair containing the
1232 number of nodes in the nodeset, and a boolean flag
1233 if a node was created.");
1234
1235   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1236    [], (* XXX Augeas code needs tests. *)
1237    "look up the value of an Augeas path",
1238    "\
1239 Look up the value associated with C<path>.  If C<path>
1240 matches exactly one node, the C<value> is returned.");
1241
1242   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "set Augeas path to value",
1245    "\
1246 Set the value associated with C<path> to C<val>.
1247
1248 In the Augeas API, it is possible to clear a node by setting
1249 the value to NULL.  Due to an oversight in the libguestfs API
1250 you cannot do that with this call.  Instead you must use the
1251 C<guestfs_aug_clear> call.");
1252
1253   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1254    [], (* XXX Augeas code needs tests. *)
1255    "insert a sibling Augeas node",
1256    "\
1257 Create a new sibling C<label> for C<path>, inserting it into
1258 the tree before or after C<path> (depending on the boolean
1259 flag C<before>).
1260
1261 C<path> must match exactly one existing node in the tree, and
1262 C<label> must be a label, ie. not contain C</>, C<*> or end
1263 with a bracketed index C<[N]>.");
1264
1265   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1266    [], (* XXX Augeas code needs tests. *)
1267    "remove an Augeas path",
1268    "\
1269 Remove C<path> and all of its children.
1270
1271 On success this returns the number of entries which were removed.");
1272
1273   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1274    [], (* XXX Augeas code needs tests. *)
1275    "move Augeas node",
1276    "\
1277 Move the node C<src> to C<dest>.  C<src> must match exactly
1278 one node.  C<dest> is overwritten if it exists.");
1279
1280   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1281    [], (* XXX Augeas code needs tests. *)
1282    "return Augeas nodes which match augpath",
1283    "\
1284 Returns a list of paths which match the path expression C<path>.
1285 The returned paths are sufficiently qualified so that they match
1286 exactly one node in the current tree.");
1287
1288   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1289    [], (* XXX Augeas code needs tests. *)
1290    "write all pending Augeas changes to disk",
1291    "\
1292 This writes all pending changes to disk.
1293
1294 The flags which were passed to C<guestfs_aug_init> affect exactly
1295 how files are saved.");
1296
1297   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1298    [], (* XXX Augeas code needs tests. *)
1299    "load files into the tree",
1300    "\
1301 Load files into the tree.
1302
1303 See C<aug_load> in the Augeas documentation for the full gory
1304 details.");
1305
1306   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1307    [], (* XXX Augeas code needs tests. *)
1308    "list Augeas nodes under augpath",
1309    "\
1310 This is just a shortcut for listing C<guestfs_aug_match>
1311 C<path/*> and sorting the resulting nodes into alphabetical order.");
1312
1313   ("rm", (RErr, [Pathname "path"]), 29, [],
1314    [InitBasicFS, Always, TestRun
1315       [["touch"; "/new"];
1316        ["rm"; "/new"]];
1317     InitBasicFS, Always, TestLastFail
1318       [["rm"; "/new"]];
1319     InitBasicFS, Always, TestLastFail
1320       [["mkdir"; "/new"];
1321        ["rm"; "/new"]]],
1322    "remove a file",
1323    "\
1324 Remove the single file C<path>.");
1325
1326   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1327    [InitBasicFS, Always, TestRun
1328       [["mkdir"; "/new"];
1329        ["rmdir"; "/new"]];
1330     InitBasicFS, Always, TestLastFail
1331       [["rmdir"; "/new"]];
1332     InitBasicFS, Always, TestLastFail
1333       [["touch"; "/new"];
1334        ["rmdir"; "/new"]]],
1335    "remove a directory",
1336    "\
1337 Remove the single directory C<path>.");
1338
1339   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1340    [InitBasicFS, Always, TestOutputFalse
1341       [["mkdir"; "/new"];
1342        ["mkdir"; "/new/foo"];
1343        ["touch"; "/new/foo/bar"];
1344        ["rm_rf"; "/new"];
1345        ["exists"; "/new"]]],
1346    "remove a file or directory recursively",
1347    "\
1348 Remove the file or directory C<path>, recursively removing the
1349 contents if its a directory.  This is like the C<rm -rf> shell
1350 command.");
1351
1352   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir"; "/new"];
1355        ["is_dir"; "/new"]];
1356     InitBasicFS, Always, TestLastFail
1357       [["mkdir"; "/new/foo/bar"]]],
1358    "create a directory",
1359    "\
1360 Create a directory named C<path>.");
1361
1362   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1363    [InitBasicFS, Always, TestOutputTrue
1364       [["mkdir_p"; "/new/foo/bar"];
1365        ["is_dir"; "/new/foo/bar"]];
1366     InitBasicFS, Always, TestOutputTrue
1367       [["mkdir_p"; "/new/foo/bar"];
1368        ["is_dir"; "/new/foo"]];
1369     InitBasicFS, Always, TestOutputTrue
1370       [["mkdir_p"; "/new/foo/bar"];
1371        ["is_dir"; "/new"]];
1372     (* Regression tests for RHBZ#503133: *)
1373     InitBasicFS, Always, TestRun
1374       [["mkdir"; "/new"];
1375        ["mkdir_p"; "/new"]];
1376     InitBasicFS, Always, TestLastFail
1377       [["touch"; "/new"];
1378        ["mkdir_p"; "/new"]]],
1379    "create a directory and parents",
1380    "\
1381 Create a directory named C<path>, creating any parent directories
1382 as necessary.  This is like the C<mkdir -p> shell command.");
1383
1384   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1385    [], (* XXX Need stat command to test *)
1386    "change file mode",
1387    "\
1388 Change the mode (permissions) of C<path> to C<mode>.  Only
1389 numeric modes are supported.
1390
1391 I<Note>: When using this command from guestfish, C<mode>
1392 by default would be decimal, unless you prefix it with
1393 C<0> to get octal, ie. use C<0700> not C<700>.");
1394
1395   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1396    [], (* XXX Need stat command to test *)
1397    "change file owner and group",
1398    "\
1399 Change the file owner to C<owner> and group to C<group>.
1400
1401 Only numeric uid and gid are supported.  If you want to use
1402 names, you will need to locate and parse the password file
1403 yourself (Augeas support makes this relatively easy).");
1404
1405   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1406    [InitISOFS, Always, TestOutputTrue (
1407       [["exists"; "/empty"]]);
1408     InitISOFS, Always, TestOutputTrue (
1409       [["exists"; "/directory"]])],
1410    "test if file or directory exists",
1411    "\
1412 This returns C<true> if and only if there is a file, directory
1413 (or anything) with the given C<path> name.
1414
1415 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1416
1417   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1418    [InitISOFS, Always, TestOutputTrue (
1419       [["is_file"; "/known-1"]]);
1420     InitISOFS, Always, TestOutputFalse (
1421       [["is_file"; "/directory"]])],
1422    "test if file exists",
1423    "\
1424 This returns C<true> if and only if there is a file
1425 with the given C<path> name.  Note that it returns false for
1426 other objects like directories.
1427
1428 See also C<guestfs_stat>.");
1429
1430   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1431    [InitISOFS, Always, TestOutputFalse (
1432       [["is_dir"; "/known-3"]]);
1433     InitISOFS, Always, TestOutputTrue (
1434       [["is_dir"; "/directory"]])],
1435    "test if file exists",
1436    "\
1437 This returns C<true> if and only if there is a directory
1438 with the given C<path> name.  Note that it returns false for
1439 other objects like files.
1440
1441 See also C<guestfs_stat>.");
1442
1443   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1444    [InitEmpty, Always, TestOutputListOfDevices (
1445       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1446        ["pvcreate"; "/dev/sda1"];
1447        ["pvcreate"; "/dev/sda2"];
1448        ["pvcreate"; "/dev/sda3"];
1449        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1450    "create an LVM physical volume",
1451    "\
1452 This creates an LVM physical volume on the named C<device>,
1453 where C<device> should usually be a partition name such
1454 as C</dev/sda1>.");
1455
1456   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1457    [InitEmpty, Always, TestOutputList (
1458       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1459        ["pvcreate"; "/dev/sda1"];
1460        ["pvcreate"; "/dev/sda2"];
1461        ["pvcreate"; "/dev/sda3"];
1462        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1463        ["vgcreate"; "VG2"; "/dev/sda3"];
1464        ["vgs"]], ["VG1"; "VG2"])],
1465    "create an LVM volume group",
1466    "\
1467 This creates an LVM volume group called C<volgroup>
1468 from the non-empty list of physical volumes C<physvols>.");
1469
1470   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1471    [InitEmpty, Always, TestOutputList (
1472       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1473        ["pvcreate"; "/dev/sda1"];
1474        ["pvcreate"; "/dev/sda2"];
1475        ["pvcreate"; "/dev/sda3"];
1476        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1477        ["vgcreate"; "VG2"; "/dev/sda3"];
1478        ["lvcreate"; "LV1"; "VG1"; "50"];
1479        ["lvcreate"; "LV2"; "VG1"; "50"];
1480        ["lvcreate"; "LV3"; "VG2"; "50"];
1481        ["lvcreate"; "LV4"; "VG2"; "50"];
1482        ["lvcreate"; "LV5"; "VG2"; "50"];
1483        ["lvs"]],
1484       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1485        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1486    "create an LVM logical volume",
1487    "\
1488 This creates an LVM logical volume called C<logvol>
1489 on the volume group C<volgroup>, with C<size> megabytes.");
1490
1491   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1492    [InitEmpty, Always, TestOutput (
1493       [["part_disk"; "/dev/sda"; "mbr"];
1494        ["mkfs"; "ext2"; "/dev/sda1"];
1495        ["mount_options"; ""; "/dev/sda1"; "/"];
1496        ["write_file"; "/new"; "new file contents"; "0"];
1497        ["cat"; "/new"]], "new file contents")],
1498    "make a filesystem",
1499    "\
1500 This creates a filesystem on C<device> (usually a partition
1501 or LVM logical volume).  The filesystem type is C<fstype>, for
1502 example C<ext3>.");
1503
1504   ("sfdisk", (RErr, [Device "device";
1505                      Int "cyls"; Int "heads"; Int "sectors";
1506                      StringList "lines"]), 43, [DangerWillRobinson],
1507    [],
1508    "create partitions on a block device",
1509    "\
1510 This is a direct interface to the L<sfdisk(8)> program for creating
1511 partitions on block devices.
1512
1513 C<device> should be a block device, for example C</dev/sda>.
1514
1515 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1516 and sectors on the device, which are passed directly to sfdisk as
1517 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1518 of these, then the corresponding parameter is omitted.  Usually for
1519 'large' disks, you can just pass C<0> for these, but for small
1520 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1521 out the right geometry and you will need to tell it.
1522
1523 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1524 information refer to the L<sfdisk(8)> manpage.
1525
1526 To create a single partition occupying the whole disk, you would
1527 pass C<lines> as a single element list, when the single element being
1528 the string C<,> (comma).
1529
1530 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1531 C<guestfs_part_init>");
1532
1533   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1534    [InitBasicFS, Always, TestOutput (
1535       [["write_file"; "/new"; "new file contents"; "0"];
1536        ["cat"; "/new"]], "new file contents");
1537     InitBasicFS, Always, TestOutput (
1538       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1539        ["cat"; "/new"]], "\nnew file contents\n");
1540     InitBasicFS, Always, TestOutput (
1541       [["write_file"; "/new"; "\n\n"; "0"];
1542        ["cat"; "/new"]], "\n\n");
1543     InitBasicFS, Always, TestOutput (
1544       [["write_file"; "/new"; ""; "0"];
1545        ["cat"; "/new"]], "");
1546     InitBasicFS, Always, TestOutput (
1547       [["write_file"; "/new"; "\n\n\n"; "0"];
1548        ["cat"; "/new"]], "\n\n\n");
1549     InitBasicFS, Always, TestOutput (
1550       [["write_file"; "/new"; "\n"; "0"];
1551        ["cat"; "/new"]], "\n")],
1552    "create a file",
1553    "\
1554 This call creates a file called C<path>.  The contents of the
1555 file is the string C<content> (which can contain any 8 bit data),
1556 with length C<size>.
1557
1558 As a special case, if C<size> is C<0>
1559 then the length is calculated using C<strlen> (so in this case
1560 the content cannot contain embedded ASCII NULs).
1561
1562 I<NB.> Owing to a bug, writing content containing ASCII NUL
1563 characters does I<not> work, even if the length is specified.
1564 We hope to resolve this bug in a future version.  In the meantime
1565 use C<guestfs_upload>.");
1566
1567   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1568    [InitEmpty, Always, TestOutputListOfDevices (
1569       [["part_disk"; "/dev/sda"; "mbr"];
1570        ["mkfs"; "ext2"; "/dev/sda1"];
1571        ["mount_options"; ""; "/dev/sda1"; "/"];
1572        ["mounts"]], ["/dev/sda1"]);
1573     InitEmpty, Always, TestOutputList (
1574       [["part_disk"; "/dev/sda"; "mbr"];
1575        ["mkfs"; "ext2"; "/dev/sda1"];
1576        ["mount_options"; ""; "/dev/sda1"; "/"];
1577        ["umount"; "/"];
1578        ["mounts"]], [])],
1579    "unmount a filesystem",
1580    "\
1581 This unmounts the given filesystem.  The filesystem may be
1582 specified either by its mountpoint (path) or the device which
1583 contains the filesystem.");
1584
1585   ("mounts", (RStringList "devices", []), 46, [],
1586    [InitBasicFS, Always, TestOutputListOfDevices (
1587       [["mounts"]], ["/dev/sda1"])],
1588    "show mounted filesystems",
1589    "\
1590 This returns the list of currently mounted filesystems.  It returns
1591 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1592
1593 Some internal mounts are not shown.
1594
1595 See also: C<guestfs_mountpoints>");
1596
1597   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1598    [InitBasicFS, Always, TestOutputList (
1599       [["umount_all"];
1600        ["mounts"]], []);
1601     (* check that umount_all can unmount nested mounts correctly: *)
1602     InitEmpty, Always, TestOutputList (
1603       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1604        ["mkfs"; "ext2"; "/dev/sda1"];
1605        ["mkfs"; "ext2"; "/dev/sda2"];
1606        ["mkfs"; "ext2"; "/dev/sda3"];
1607        ["mount_options"; ""; "/dev/sda1"; "/"];
1608        ["mkdir"; "/mp1"];
1609        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1610        ["mkdir"; "/mp1/mp2"];
1611        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1612        ["mkdir"; "/mp1/mp2/mp3"];
1613        ["umount_all"];
1614        ["mounts"]], [])],
1615    "unmount all filesystems",
1616    "\
1617 This unmounts all mounted filesystems.
1618
1619 Some internal mounts are not unmounted by this call.");
1620
1621   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1622    [],
1623    "remove all LVM LVs, VGs and PVs",
1624    "\
1625 This command removes all LVM logical volumes, volume groups
1626 and physical volumes.");
1627
1628   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1629    [InitISOFS, Always, TestOutput (
1630       [["file"; "/empty"]], "empty");
1631     InitISOFS, Always, TestOutput (
1632       [["file"; "/known-1"]], "ASCII text");
1633     InitISOFS, Always, TestLastFail (
1634       [["file"; "/notexists"]])],
1635    "determine file type",
1636    "\
1637 This call uses the standard L<file(1)> command to determine
1638 the type or contents of the file.  This also works on devices,
1639 for example to find out whether a partition contains a filesystem.
1640
1641 This call will also transparently look inside various types
1642 of compressed file.
1643
1644 The exact command which runs is C<file -zbsL path>.  Note in
1645 particular that the filename is not prepended to the output
1646 (the C<-b> option).");
1647
1648   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1649    [InitBasicFS, Always, TestOutput (
1650       [["upload"; "test-command"; "/test-command"];
1651        ["chmod"; "0o755"; "/test-command"];
1652        ["command"; "/test-command 1"]], "Result1");
1653     InitBasicFS, Always, TestOutput (
1654       [["upload"; "test-command"; "/test-command"];
1655        ["chmod"; "0o755"; "/test-command"];
1656        ["command"; "/test-command 2"]], "Result2\n");
1657     InitBasicFS, Always, TestOutput (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command"; "/test-command 3"]], "\nResult3");
1661     InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 4"]], "\nResult4\n");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 5"]], "\nResult5\n\n");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 7"]], "");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 8"]], "\n");
1681     InitBasicFS, Always, TestOutput (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command 9"]], "\n\n");
1685     InitBasicFS, Always, TestOutput (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1689     InitBasicFS, Always, TestOutput (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1693     InitBasicFS, Always, TestLastFail (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command"; "/test-command"]])],
1697    "run a command from the guest filesystem",
1698    "\
1699 This call runs a command from the guest filesystem.  The
1700 filesystem must be mounted, and must contain a compatible
1701 operating system (ie. something Linux, with the same
1702 or compatible processor architecture).
1703
1704 The single parameter is an argv-style list of arguments.
1705 The first element is the name of the program to run.
1706 Subsequent elements are parameters.  The list must be
1707 non-empty (ie. must contain a program name).  Note that
1708 the command runs directly, and is I<not> invoked via
1709 the shell (see C<guestfs_sh>).
1710
1711 The return value is anything printed to I<stdout> by
1712 the command.
1713
1714 If the command returns a non-zero exit status, then
1715 this function returns an error message.  The error message
1716 string is the content of I<stderr> from the command.
1717
1718 The C<$PATH> environment variable will contain at least
1719 C</usr/bin> and C</bin>.  If you require a program from
1720 another location, you should provide the full path in the
1721 first parameter.
1722
1723 Shared libraries and data files required by the program
1724 must be available on filesystems which are mounted in the
1725 correct places.  It is the caller's responsibility to ensure
1726 all filesystems that are needed are mounted at the right
1727 locations.");
1728
1729   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1730    [InitBasicFS, Always, TestOutputList (
1731       [["upload"; "test-command"; "/test-command"];
1732        ["chmod"; "0o755"; "/test-command"];
1733        ["command_lines"; "/test-command 1"]], ["Result1"]);
1734     InitBasicFS, Always, TestOutputList (
1735       [["upload"; "test-command"; "/test-command"];
1736        ["chmod"; "0o755"; "/test-command"];
1737        ["command_lines"; "/test-command 2"]], ["Result2"]);
1738     InitBasicFS, Always, TestOutputList (
1739       [["upload"; "test-command"; "/test-command"];
1740        ["chmod"; "0o755"; "/test-command"];
1741        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1742     InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 7"]], []);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 8"]], [""]);
1762     InitBasicFS, Always, TestOutputList (
1763       [["upload"; "test-command"; "/test-command"];
1764        ["chmod"; "0o755"; "/test-command"];
1765        ["command_lines"; "/test-command 9"]], ["";""]);
1766     InitBasicFS, Always, TestOutputList (
1767       [["upload"; "test-command"; "/test-command"];
1768        ["chmod"; "0o755"; "/test-command"];
1769        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1770     InitBasicFS, Always, TestOutputList (
1771       [["upload"; "test-command"; "/test-command"];
1772        ["chmod"; "0o755"; "/test-command"];
1773        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1774    "run a command, returning lines",
1775    "\
1776 This is the same as C<guestfs_command>, but splits the
1777 result into a list of lines.
1778
1779 See also: C<guestfs_sh_lines>");
1780
1781   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1782    [InitISOFS, Always, TestOutputStruct (
1783       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1784    "get file information",
1785    "\
1786 Returns file information for the given C<path>.
1787
1788 This is the same as the C<stat(2)> system call.");
1789
1790   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1791    [InitISOFS, Always, TestOutputStruct (
1792       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1793    "get file information for a symbolic link",
1794    "\
1795 Returns file information for the given C<path>.
1796
1797 This is the same as C<guestfs_stat> except that if C<path>
1798 is a symbolic link, then the link is stat-ed, not the file it
1799 refers to.
1800
1801 This is the same as the C<lstat(2)> system call.");
1802
1803   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1804    [InitISOFS, Always, TestOutputStruct (
1805       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1806    "get file system statistics",
1807    "\
1808 Returns file system statistics for any mounted file system.
1809 C<path> should be a file or directory in the mounted file system
1810 (typically it is the mount point itself, but it doesn't need to be).
1811
1812 This is the same as the C<statvfs(2)> system call.");
1813
1814   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1815    [], (* XXX test *)
1816    "get ext2/ext3/ext4 superblock details",
1817    "\
1818 This returns the contents of the ext2, ext3 or ext4 filesystem
1819 superblock on C<device>.
1820
1821 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1822 manpage for more details.  The list of fields returned isn't
1823 clearly defined, and depends on both the version of C<tune2fs>
1824 that libguestfs was built against, and the filesystem itself.");
1825
1826   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1827    [InitEmpty, Always, TestOutputTrue (
1828       [["blockdev_setro"; "/dev/sda"];
1829        ["blockdev_getro"; "/dev/sda"]])],
1830    "set block device to read-only",
1831    "\
1832 Sets the block device named C<device> to read-only.
1833
1834 This uses the L<blockdev(8)> command.");
1835
1836   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1837    [InitEmpty, Always, TestOutputFalse (
1838       [["blockdev_setrw"; "/dev/sda"];
1839        ["blockdev_getro"; "/dev/sda"]])],
1840    "set block device to read-write",
1841    "\
1842 Sets the block device named C<device> to read-write.
1843
1844 This uses the L<blockdev(8)> command.");
1845
1846   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1847    [InitEmpty, Always, TestOutputTrue (
1848       [["blockdev_setro"; "/dev/sda"];
1849        ["blockdev_getro"; "/dev/sda"]])],
1850    "is block device set to read-only",
1851    "\
1852 Returns a boolean indicating if the block device is read-only
1853 (true if read-only, false if not).
1854
1855 This uses the L<blockdev(8)> command.");
1856
1857   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1858    [InitEmpty, Always, TestOutputInt (
1859       [["blockdev_getss"; "/dev/sda"]], 512)],
1860    "get sectorsize of block device",
1861    "\
1862 This returns the size of sectors on a block device.
1863 Usually 512, but can be larger for modern devices.
1864
1865 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1866 for that).
1867
1868 This uses the L<blockdev(8)> command.");
1869
1870   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1871    [InitEmpty, Always, TestOutputInt (
1872       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1873    "get blocksize of block device",
1874    "\
1875 This returns the block size of a device.
1876
1877 (Note this is different from both I<size in blocks> and
1878 I<filesystem block size>).
1879
1880 This uses the L<blockdev(8)> command.");
1881
1882   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1883    [], (* XXX test *)
1884    "set blocksize of block device",
1885    "\
1886 This sets the block size of a device.
1887
1888 (Note this is different from both I<size in blocks> and
1889 I<filesystem block size>).
1890
1891 This uses the L<blockdev(8)> command.");
1892
1893   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1894    [InitEmpty, Always, TestOutputInt (
1895       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1896    "get total size of device in 512-byte sectors",
1897    "\
1898 This returns the size of the device in units of 512-byte sectors
1899 (even if the sectorsize isn't 512 bytes ... weird).
1900
1901 See also C<guestfs_blockdev_getss> for the real sector size of
1902 the device, and C<guestfs_blockdev_getsize64> for the more
1903 useful I<size in bytes>.
1904
1905 This uses the L<blockdev(8)> command.");
1906
1907   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1908    [InitEmpty, Always, TestOutputInt (
1909       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1910    "get total size of device in bytes",
1911    "\
1912 This returns the size of the device in bytes.
1913
1914 See also C<guestfs_blockdev_getsz>.
1915
1916 This uses the L<blockdev(8)> command.");
1917
1918   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1919    [InitEmpty, Always, TestRun
1920       [["blockdev_flushbufs"; "/dev/sda"]]],
1921    "flush device buffers",
1922    "\
1923 This tells the kernel to flush internal buffers associated
1924 with C<device>.
1925
1926 This uses the L<blockdev(8)> command.");
1927
1928   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1929    [InitEmpty, Always, TestRun
1930       [["blockdev_rereadpt"; "/dev/sda"]]],
1931    "reread partition table",
1932    "\
1933 Reread the partition table on C<device>.
1934
1935 This uses the L<blockdev(8)> command.");
1936
1937   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1938    [InitBasicFS, Always, TestOutput (
1939       (* Pick a file from cwd which isn't likely to change. *)
1940       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1941        ["checksum"; "md5"; "/COPYING.LIB"]],
1942       Digest.to_hex (Digest.file "COPYING.LIB"))],
1943    "upload a file from the local machine",
1944    "\
1945 Upload local file C<filename> to C<remotefilename> on the
1946 filesystem.
1947
1948 C<filename> can also be a named pipe.
1949
1950 See also C<guestfs_download>.");
1951
1952   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1953    [InitBasicFS, Always, TestOutput (
1954       (* Pick a file from cwd which isn't likely to change. *)
1955       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1956        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1957        ["upload"; "testdownload.tmp"; "/upload"];
1958        ["checksum"; "md5"; "/upload"]],
1959       Digest.to_hex (Digest.file "COPYING.LIB"))],
1960    "download a file to the local machine",
1961    "\
1962 Download file C<remotefilename> and save it as C<filename>
1963 on the local machine.
1964
1965 C<filename> can also be a named pipe.
1966
1967 See also C<guestfs_upload>, C<guestfs_cat>.");
1968
1969   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1970    [InitISOFS, Always, TestOutput (
1971       [["checksum"; "crc"; "/known-3"]], "2891671662");
1972     InitISOFS, Always, TestLastFail (
1973       [["checksum"; "crc"; "/notexists"]]);
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1978     InitISOFS, Always, TestOutput (
1979       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1980     InitISOFS, Always, TestOutput (
1981       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1982     InitISOFS, Always, TestOutput (
1983       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1984     InitISOFS, Always, TestOutput (
1985       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1986    "compute MD5, SHAx or CRC checksum of file",
1987    "\
1988 This call computes the MD5, SHAx or CRC checksum of the
1989 file named C<path>.
1990
1991 The type of checksum to compute is given by the C<csumtype>
1992 parameter which must have one of the following values:
1993
1994 =over 4
1995
1996 =item C<crc>
1997
1998 Compute the cyclic redundancy check (CRC) specified by POSIX
1999 for the C<cksum> command.
2000
2001 =item C<md5>
2002
2003 Compute the MD5 hash (using the C<md5sum> program).
2004
2005 =item C<sha1>
2006
2007 Compute the SHA1 hash (using the C<sha1sum> program).
2008
2009 =item C<sha224>
2010
2011 Compute the SHA224 hash (using the C<sha224sum> program).
2012
2013 =item C<sha256>
2014
2015 Compute the SHA256 hash (using the C<sha256sum> program).
2016
2017 =item C<sha384>
2018
2019 Compute the SHA384 hash (using the C<sha384sum> program).
2020
2021 =item C<sha512>
2022
2023 Compute the SHA512 hash (using the C<sha512sum> program).
2024
2025 =back
2026
2027 The checksum is returned as a printable string.");
2028
2029   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2030    [InitBasicFS, Always, TestOutput (
2031       [["tar_in"; "../images/helloworld.tar"; "/"];
2032        ["cat"; "/hello"]], "hello\n")],
2033    "unpack tarfile to directory",
2034    "\
2035 This command uploads and unpacks local file C<tarfile> (an
2036 I<uncompressed> tar file) into C<directory>.
2037
2038 To upload a compressed tarball, use C<guestfs_tgz_in>
2039 or C<guestfs_txz_in>.");
2040
2041   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2042    [],
2043    "pack directory into tarfile",
2044    "\
2045 This command packs the contents of C<directory> and downloads
2046 it to local file C<tarfile>.
2047
2048 To download a compressed tarball, use C<guestfs_tgz_out>
2049 or C<guestfs_txz_out>.");
2050
2051   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2052    [InitBasicFS, Always, TestOutput (
2053       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2054        ["cat"; "/hello"]], "hello\n")],
2055    "unpack compressed tarball to directory",
2056    "\
2057 This command uploads and unpacks local file C<tarball> (a
2058 I<gzip compressed> tar file) into C<directory>.
2059
2060 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2061
2062   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2063    [],
2064    "pack directory into compressed tarball",
2065    "\
2066 This command packs the contents of C<directory> and downloads
2067 it to local file C<tarball>.
2068
2069 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2070
2071   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2072    [InitBasicFS, Always, TestLastFail (
2073       [["umount"; "/"];
2074        ["mount_ro"; "/dev/sda1"; "/"];
2075        ["touch"; "/new"]]);
2076     InitBasicFS, Always, TestOutput (
2077       [["write_file"; "/new"; "data"; "0"];
2078        ["umount"; "/"];
2079        ["mount_ro"; "/dev/sda1"; "/"];
2080        ["cat"; "/new"]], "data")],
2081    "mount a guest disk, read-only",
2082    "\
2083 This is the same as the C<guestfs_mount> command, but it
2084 mounts the filesystem with the read-only (I<-o ro>) flag.");
2085
2086   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2087    [],
2088    "mount a guest disk with mount options",
2089    "\
2090 This is the same as the C<guestfs_mount> command, but it
2091 allows you to set the mount options as for the
2092 L<mount(8)> I<-o> flag.");
2093
2094   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2095    [],
2096    "mount a guest disk with mount options and vfstype",
2097    "\
2098 This is the same as the C<guestfs_mount> command, but it
2099 allows you to set both the mount options and the vfstype
2100 as for the L<mount(8)> I<-o> and I<-t> flags.");
2101
2102   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2103    [],
2104    "debugging and internals",
2105    "\
2106 The C<guestfs_debug> command exposes some internals of
2107 C<guestfsd> (the guestfs daemon) that runs inside the
2108 qemu subprocess.
2109
2110 There is no comprehensive help for this command.  You have
2111 to look at the file C<daemon/debug.c> in the libguestfs source
2112 to find out what you can do.");
2113
2114   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2115    [InitEmpty, Always, TestOutputList (
2116       [["part_disk"; "/dev/sda"; "mbr"];
2117        ["pvcreate"; "/dev/sda1"];
2118        ["vgcreate"; "VG"; "/dev/sda1"];
2119        ["lvcreate"; "LV1"; "VG"; "50"];
2120        ["lvcreate"; "LV2"; "VG"; "50"];
2121        ["lvremove"; "/dev/VG/LV1"];
2122        ["lvs"]], ["/dev/VG/LV2"]);
2123     InitEmpty, Always, TestOutputList (
2124       [["part_disk"; "/dev/sda"; "mbr"];
2125        ["pvcreate"; "/dev/sda1"];
2126        ["vgcreate"; "VG"; "/dev/sda1"];
2127        ["lvcreate"; "LV1"; "VG"; "50"];
2128        ["lvcreate"; "LV2"; "VG"; "50"];
2129        ["lvremove"; "/dev/VG"];
2130        ["lvs"]], []);
2131     InitEmpty, Always, TestOutputList (
2132       [["part_disk"; "/dev/sda"; "mbr"];
2133        ["pvcreate"; "/dev/sda1"];
2134        ["vgcreate"; "VG"; "/dev/sda1"];
2135        ["lvcreate"; "LV1"; "VG"; "50"];
2136        ["lvcreate"; "LV2"; "VG"; "50"];
2137        ["lvremove"; "/dev/VG"];
2138        ["vgs"]], ["VG"])],
2139    "remove an LVM logical volume",
2140    "\
2141 Remove an LVM logical volume C<device>, where C<device> is
2142 the path to the LV, such as C</dev/VG/LV>.
2143
2144 You can also remove all LVs in a volume group by specifying
2145 the VG name, C</dev/VG>.");
2146
2147   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2148    [InitEmpty, Always, TestOutputList (
2149       [["part_disk"; "/dev/sda"; "mbr"];
2150        ["pvcreate"; "/dev/sda1"];
2151        ["vgcreate"; "VG"; "/dev/sda1"];
2152        ["lvcreate"; "LV1"; "VG"; "50"];
2153        ["lvcreate"; "LV2"; "VG"; "50"];
2154        ["vgremove"; "VG"];
2155        ["lvs"]], []);
2156     InitEmpty, Always, TestOutputList (
2157       [["part_disk"; "/dev/sda"; "mbr"];
2158        ["pvcreate"; "/dev/sda1"];
2159        ["vgcreate"; "VG"; "/dev/sda1"];
2160        ["lvcreate"; "LV1"; "VG"; "50"];
2161        ["lvcreate"; "LV2"; "VG"; "50"];
2162        ["vgremove"; "VG"];
2163        ["vgs"]], [])],
2164    "remove an LVM volume group",
2165    "\
2166 Remove an LVM volume group C<vgname>, (for example C<VG>).
2167
2168 This also forcibly removes all logical volumes in the volume
2169 group (if any).");
2170
2171   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2172    [InitEmpty, Always, TestOutputListOfDevices (
2173       [["part_disk"; "/dev/sda"; "mbr"];
2174        ["pvcreate"; "/dev/sda1"];
2175        ["vgcreate"; "VG"; "/dev/sda1"];
2176        ["lvcreate"; "LV1"; "VG"; "50"];
2177        ["lvcreate"; "LV2"; "VG"; "50"];
2178        ["vgremove"; "VG"];
2179        ["pvremove"; "/dev/sda1"];
2180        ["lvs"]], []);
2181     InitEmpty, Always, TestOutputListOfDevices (
2182       [["part_disk"; "/dev/sda"; "mbr"];
2183        ["pvcreate"; "/dev/sda1"];
2184        ["vgcreate"; "VG"; "/dev/sda1"];
2185        ["lvcreate"; "LV1"; "VG"; "50"];
2186        ["lvcreate"; "LV2"; "VG"; "50"];
2187        ["vgremove"; "VG"];
2188        ["pvremove"; "/dev/sda1"];
2189        ["vgs"]], []);
2190     InitEmpty, Always, TestOutputListOfDevices (
2191       [["part_disk"; "/dev/sda"; "mbr"];
2192        ["pvcreate"; "/dev/sda1"];
2193        ["vgcreate"; "VG"; "/dev/sda1"];
2194        ["lvcreate"; "LV1"; "VG"; "50"];
2195        ["lvcreate"; "LV2"; "VG"; "50"];
2196        ["vgremove"; "VG"];
2197        ["pvremove"; "/dev/sda1"];
2198        ["pvs"]], [])],
2199    "remove an LVM physical volume",
2200    "\
2201 This wipes a physical volume C<device> so that LVM will no longer
2202 recognise it.
2203
2204 The implementation uses the C<pvremove> command which refuses to
2205 wipe physical volumes that contain any volume groups, so you have
2206 to remove those first.");
2207
2208   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2209    [InitBasicFS, Always, TestOutput (
2210       [["set_e2label"; "/dev/sda1"; "testlabel"];
2211        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2212    "set the ext2/3/4 filesystem label",
2213    "\
2214 This sets the ext2/3/4 filesystem label of the filesystem on
2215 C<device> to C<label>.  Filesystem labels are limited to
2216 16 characters.
2217
2218 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2219 to return the existing label on a filesystem.");
2220
2221   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2222    [],
2223    "get the ext2/3/4 filesystem label",
2224    "\
2225 This returns the ext2/3/4 filesystem label of the filesystem on
2226 C<device>.");
2227
2228   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2229    (let uuid = uuidgen () in
2230     [InitBasicFS, Always, TestOutput (
2231        [["set_e2uuid"; "/dev/sda1"; uuid];
2232         ["get_e2uuid"; "/dev/sda1"]], uuid);
2233      InitBasicFS, Always, TestOutput (
2234        [["set_e2uuid"; "/dev/sda1"; "clear"];
2235         ["get_e2uuid"; "/dev/sda1"]], "");
2236      (* We can't predict what UUIDs will be, so just check the commands run. *)
2237      InitBasicFS, Always, TestRun (
2238        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2239      InitBasicFS, Always, TestRun (
2240        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2241    "set the ext2/3/4 filesystem UUID",
2242    "\
2243 This sets the ext2/3/4 filesystem UUID of the filesystem on
2244 C<device> to C<uuid>.  The format of the UUID and alternatives
2245 such as C<clear>, C<random> and C<time> are described in the
2246 L<tune2fs(8)> manpage.
2247
2248 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2249 to return the existing UUID of a filesystem.");
2250
2251   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2252    [],
2253    "get the ext2/3/4 filesystem UUID",
2254    "\
2255 This returns the ext2/3/4 filesystem UUID of the filesystem on
2256 C<device>.");
2257
2258   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2259    [InitBasicFS, Always, TestOutputInt (
2260       [["umount"; "/dev/sda1"];
2261        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2262     InitBasicFS, Always, TestOutputInt (
2263       [["umount"; "/dev/sda1"];
2264        ["zero"; "/dev/sda1"];
2265        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2266    "run the filesystem checker",
2267    "\
2268 This runs the filesystem checker (fsck) on C<device> which
2269 should have filesystem type C<fstype>.
2270
2271 The returned integer is the status.  See L<fsck(8)> for the
2272 list of status codes from C<fsck>.
2273
2274 Notes:
2275
2276 =over 4
2277
2278 =item *
2279
2280 Multiple status codes can be summed together.
2281
2282 =item *
2283
2284 A non-zero return code can mean \"success\", for example if
2285 errors have been corrected on the filesystem.
2286
2287 =item *
2288
2289 Checking or repairing NTFS volumes is not supported
2290 (by linux-ntfs).
2291
2292 =back
2293
2294 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2295
2296   ("zero", (RErr, [Device "device"]), 85, [],
2297    [InitBasicFS, Always, TestOutput (
2298       [["umount"; "/dev/sda1"];
2299        ["zero"; "/dev/sda1"];
2300        ["file"; "/dev/sda1"]], "data")],
2301    "write zeroes to the device",
2302    "\
2303 This command writes zeroes over the first few blocks of C<device>.
2304
2305 How many blocks are zeroed isn't specified (but it's I<not> enough
2306 to securely wipe the device).  It should be sufficient to remove
2307 any partition tables, filesystem superblocks and so on.
2308
2309 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2310
2311   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2312    (* Test disabled because grub-install incompatible with virtio-blk driver.
2313     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2314     *)
2315    [InitBasicFS, Disabled, TestOutputTrue (
2316       [["grub_install"; "/"; "/dev/sda1"];
2317        ["is_dir"; "/boot"]])],
2318    "install GRUB",
2319    "\
2320 This command installs GRUB (the Grand Unified Bootloader) on
2321 C<device>, with the root directory being C<root>.");
2322
2323   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2324    [InitBasicFS, Always, TestOutput (
2325       [["write_file"; "/old"; "file content"; "0"];
2326        ["cp"; "/old"; "/new"];
2327        ["cat"; "/new"]], "file content");
2328     InitBasicFS, Always, TestOutputTrue (
2329       [["write_file"; "/old"; "file content"; "0"];
2330        ["cp"; "/old"; "/new"];
2331        ["is_file"; "/old"]]);
2332     InitBasicFS, Always, TestOutput (
2333       [["write_file"; "/old"; "file content"; "0"];
2334        ["mkdir"; "/dir"];
2335        ["cp"; "/old"; "/dir/new"];
2336        ["cat"; "/dir/new"]], "file content")],
2337    "copy a file",
2338    "\
2339 This copies a file from C<src> to C<dest> where C<dest> is
2340 either a destination filename or destination directory.");
2341
2342   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2343    [InitBasicFS, Always, TestOutput (
2344       [["mkdir"; "/olddir"];
2345        ["mkdir"; "/newdir"];
2346        ["write_file"; "/olddir/file"; "file content"; "0"];
2347        ["cp_a"; "/olddir"; "/newdir"];
2348        ["cat"; "/newdir/olddir/file"]], "file content")],
2349    "copy a file or directory recursively",
2350    "\
2351 This copies a file or directory from C<src> to C<dest>
2352 recursively using the C<cp -a> command.");
2353
2354   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2355    [InitBasicFS, Always, TestOutput (
2356       [["write_file"; "/old"; "file content"; "0"];
2357        ["mv"; "/old"; "/new"];
2358        ["cat"; "/new"]], "file content");
2359     InitBasicFS, Always, TestOutputFalse (
2360       [["write_file"; "/old"; "file content"; "0"];
2361        ["mv"; "/old"; "/new"];
2362        ["is_file"; "/old"]])],
2363    "move a file",
2364    "\
2365 This moves a file from C<src> to C<dest> where C<dest> is
2366 either a destination filename or destination directory.");
2367
2368   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2369    [InitEmpty, Always, TestRun (
2370       [["drop_caches"; "3"]])],
2371    "drop kernel page cache, dentries and inodes",
2372    "\
2373 This instructs the guest kernel to drop its page cache,
2374 and/or dentries and inode caches.  The parameter C<whattodrop>
2375 tells the kernel what precisely to drop, see
2376 L<http://linux-mm.org/Drop_Caches>
2377
2378 Setting C<whattodrop> to 3 should drop everything.
2379
2380 This automatically calls L<sync(2)> before the operation,
2381 so that the maximum guest memory is freed.");
2382
2383   ("dmesg", (RString "kmsgs", []), 91, [],
2384    [InitEmpty, Always, TestRun (
2385       [["dmesg"]])],
2386    "return kernel messages",
2387    "\
2388 This returns the kernel messages (C<dmesg> output) from
2389 the guest kernel.  This is sometimes useful for extended
2390 debugging of problems.
2391
2392 Another way to get the same information is to enable
2393 verbose messages with C<guestfs_set_verbose> or by setting
2394 the environment variable C<LIBGUESTFS_DEBUG=1> before
2395 running the program.");
2396
2397   ("ping_daemon", (RErr, []), 92, [],
2398    [InitEmpty, Always, TestRun (
2399       [["ping_daemon"]])],
2400    "ping the guest daemon",
2401    "\
2402 This is a test probe into the guestfs daemon running inside
2403 the qemu subprocess.  Calling this function checks that the
2404 daemon responds to the ping message, without affecting the daemon
2405 or attached block device(s) in any other way.");
2406
2407   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2408    [InitBasicFS, Always, TestOutputTrue (
2409       [["write_file"; "/file1"; "contents of a file"; "0"];
2410        ["cp"; "/file1"; "/file2"];
2411        ["equal"; "/file1"; "/file2"]]);
2412     InitBasicFS, Always, TestOutputFalse (
2413       [["write_file"; "/file1"; "contents of a file"; "0"];
2414        ["write_file"; "/file2"; "contents of another file"; "0"];
2415        ["equal"; "/file1"; "/file2"]]);
2416     InitBasicFS, Always, TestLastFail (
2417       [["equal"; "/file1"; "/file2"]])],
2418    "test if two files have equal contents",
2419    "\
2420 This compares the two files C<file1> and C<file2> and returns
2421 true if their content is exactly equal, or false otherwise.
2422
2423 The external L<cmp(1)> program is used for the comparison.");
2424
2425   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2426    [InitISOFS, Always, TestOutputList (
2427       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2428     InitISOFS, Always, TestOutputList (
2429       [["strings"; "/empty"]], [])],
2430    "print the printable strings in a file",
2431    "\
2432 This runs the L<strings(1)> command on a file and returns
2433 the list of printable strings found.");
2434
2435   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2436    [InitISOFS, Always, TestOutputList (
2437       [["strings_e"; "b"; "/known-5"]], []);
2438     InitBasicFS, Disabled, TestOutputList (
2439       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2440        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2441    "print the printable strings in a file",
2442    "\
2443 This is like the C<guestfs_strings> command, but allows you to
2444 specify the encoding.
2445
2446 See the L<strings(1)> manpage for the full list of encodings.
2447
2448 Commonly useful encodings are C<l> (lower case L) which will
2449 show strings inside Windows/x86 files.
2450
2451 The returned strings are transcoded to UTF-8.");
2452
2453   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2454    [InitISOFS, Always, TestOutput (
2455       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2456     (* Test for RHBZ#501888c2 regression which caused large hexdump
2457      * commands to segfault.
2458      *)
2459     InitISOFS, Always, TestRun (
2460       [["hexdump"; "/100krandom"]])],
2461    "dump a file in hexadecimal",
2462    "\
2463 This runs C<hexdump -C> on the given C<path>.  The result is
2464 the human-readable, canonical hex dump of the file.");
2465
2466   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2467    [InitNone, Always, TestOutput (
2468       [["part_disk"; "/dev/sda"; "mbr"];
2469        ["mkfs"; "ext3"; "/dev/sda1"];
2470        ["mount_options"; ""; "/dev/sda1"; "/"];
2471        ["write_file"; "/new"; "test file"; "0"];
2472        ["umount"; "/dev/sda1"];
2473        ["zerofree"; "/dev/sda1"];
2474        ["mount_options"; ""; "/dev/sda1"; "/"];
2475        ["cat"; "/new"]], "test file")],
2476    "zero unused inodes and disk blocks on ext2/3 filesystem",
2477    "\
2478 This runs the I<zerofree> program on C<device>.  This program
2479 claims to zero unused inodes and disk blocks on an ext2/3
2480 filesystem, thus making it possible to compress the filesystem
2481 more effectively.
2482
2483 You should B<not> run this program if the filesystem is
2484 mounted.
2485
2486 It is possible that using this program can damage the filesystem
2487 or data on the filesystem.");
2488
2489   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2490    [],
2491    "resize an LVM physical volume",
2492    "\
2493 This resizes (expands or shrinks) an existing LVM physical
2494 volume to match the new size of the underlying device.");
2495
2496   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2497                        Int "cyls"; Int "heads"; Int "sectors";
2498                        String "line"]), 99, [DangerWillRobinson],
2499    [],
2500    "modify a single partition on a block device",
2501    "\
2502 This runs L<sfdisk(8)> option to modify just the single
2503 partition C<n> (note: C<n> counts from 1).
2504
2505 For other parameters, see C<guestfs_sfdisk>.  You should usually
2506 pass C<0> for the cyls/heads/sectors parameters.
2507
2508 See also: C<guestfs_part_add>");
2509
2510   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2511    [],
2512    "display the partition table",
2513    "\
2514 This displays the partition table on C<device>, in the
2515 human-readable output of the L<sfdisk(8)> command.  It is
2516 not intended to be parsed.
2517
2518 See also: C<guestfs_part_list>");
2519
2520   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2521    [],
2522    "display the kernel geometry",
2523    "\
2524 This displays the kernel's idea of the geometry of C<device>.
2525
2526 The result is in human-readable format, and not designed to
2527 be parsed.");
2528
2529   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2530    [],
2531    "display the disk geometry from the partition table",
2532    "\
2533 This displays the disk geometry of C<device> read from the
2534 partition table.  Especially in the case where the underlying
2535 block device has been resized, this can be different from the
2536 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2537
2538 The result is in human-readable format, and not designed to
2539 be parsed.");
2540
2541   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2542    [],
2543    "activate or deactivate all volume groups",
2544    "\
2545 This command activates or (if C<activate> is false) deactivates
2546 all logical volumes in all volume groups.
2547 If activated, then they are made known to the
2548 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2549 then those devices disappear.
2550
2551 This command is the same as running C<vgchange -a y|n>");
2552
2553   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2554    [],
2555    "activate or deactivate some volume groups",
2556    "\
2557 This command activates or (if C<activate> is false) deactivates
2558 all logical volumes in the listed volume groups C<volgroups>.
2559 If activated, then they are made known to the
2560 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2561 then those devices disappear.
2562
2563 This command is the same as running C<vgchange -a y|n volgroups...>
2564
2565 Note that if C<volgroups> is an empty list then B<all> volume groups
2566 are activated or deactivated.");
2567
2568   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2569    [InitNone, Always, TestOutput (
2570       [["part_disk"; "/dev/sda"; "mbr"];
2571        ["pvcreate"; "/dev/sda1"];
2572        ["vgcreate"; "VG"; "/dev/sda1"];
2573        ["lvcreate"; "LV"; "VG"; "10"];
2574        ["mkfs"; "ext2"; "/dev/VG/LV"];
2575        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2576        ["write_file"; "/new"; "test content"; "0"];
2577        ["umount"; "/"];
2578        ["lvresize"; "/dev/VG/LV"; "20"];
2579        ["e2fsck_f"; "/dev/VG/LV"];
2580        ["resize2fs"; "/dev/VG/LV"];
2581        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2582        ["cat"; "/new"]], "test content")],
2583    "resize an LVM logical volume",
2584    "\
2585 This resizes (expands or shrinks) an existing LVM logical
2586 volume to C<mbytes>.  When reducing, data in the reduced part
2587 is lost.");
2588
2589   ("resize2fs", (RErr, [Device "device"]), 106, [],
2590    [], (* lvresize tests this *)
2591    "resize an ext2/ext3 filesystem",
2592    "\
2593 This resizes an ext2 or ext3 filesystem to match the size of
2594 the underlying device.
2595
2596 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2597 on the C<device> before calling this command.  For unknown reasons
2598 C<resize2fs> sometimes gives an error about this and sometimes not.
2599 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2600 calling this function.");
2601
2602   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2603    [InitBasicFS, Always, TestOutputList (
2604       [["find"; "/"]], ["lost+found"]);
2605     InitBasicFS, Always, TestOutputList (
2606       [["touch"; "/a"];
2607        ["mkdir"; "/b"];
2608        ["touch"; "/b/c"];
2609        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2610     InitBasicFS, Always, TestOutputList (
2611       [["mkdir_p"; "/a/b/c"];
2612        ["touch"; "/a/b/c/d"];
2613        ["find"; "/a/b/"]], ["c"; "c/d"])],
2614    "find all files and directories",
2615    "\
2616 This command lists out all files and directories, recursively,
2617 starting at C<directory>.  It is essentially equivalent to
2618 running the shell command C<find directory -print> but some
2619 post-processing happens on the output, described below.
2620
2621 This returns a list of strings I<without any prefix>.  Thus
2622 if the directory structure was:
2623
2624  /tmp/a
2625  /tmp/b
2626  /tmp/c/d
2627
2628 then the returned list from C<guestfs_find> C</tmp> would be
2629 4 elements:
2630
2631  a
2632  b
2633  c
2634  c/d
2635
2636 If C<directory> is not a directory, then this command returns
2637 an error.
2638
2639 The returned list is sorted.
2640
2641 See also C<guestfs_find0>.");
2642
2643   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2644    [], (* lvresize tests this *)
2645    "check an ext2/ext3 filesystem",
2646    "\
2647 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2648 filesystem checker on C<device>, noninteractively (C<-p>),
2649 even if the filesystem appears to be clean (C<-f>).
2650
2651 This command is only needed because of C<guestfs_resize2fs>
2652 (q.v.).  Normally you should use C<guestfs_fsck>.");
2653
2654   ("sleep", (RErr, [Int "secs"]), 109, [],
2655    [InitNone, Always, TestRun (
2656       [["sleep"; "1"]])],
2657    "sleep for some seconds",
2658    "\
2659 Sleep for C<secs> seconds.");
2660
2661   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2662    [InitNone, Always, TestOutputInt (
2663       [["part_disk"; "/dev/sda"; "mbr"];
2664        ["mkfs"; "ntfs"; "/dev/sda1"];
2665        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2666     InitNone, Always, TestOutputInt (
2667       [["part_disk"; "/dev/sda"; "mbr"];
2668        ["mkfs"; "ext2"; "/dev/sda1"];
2669        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2670    "probe NTFS volume",
2671    "\
2672 This command runs the L<ntfs-3g.probe(8)> command which probes
2673 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2674 be mounted read-write, and some cannot be mounted at all).
2675
2676 C<rw> is a boolean flag.  Set it to true if you want to test
2677 if the volume can be mounted read-write.  Set it to false if
2678 you want to test if the volume can be mounted read-only.
2679
2680 The return value is an integer which C<0> if the operation
2681 would succeed, or some non-zero value documented in the
2682 L<ntfs-3g.probe(8)> manual page.");
2683
2684   ("sh", (RString "output", [String "command"]), 111, [],
2685    [], (* XXX needs tests *)
2686    "run a command via the shell",
2687    "\
2688 This call runs a command from the guest filesystem via the
2689 guest's C</bin/sh>.
2690
2691 This is like C<guestfs_command>, but passes the command to:
2692
2693  /bin/sh -c \"command\"
2694
2695 Depending on the guest's shell, this usually results in
2696 wildcards being expanded, shell expressions being interpolated
2697 and so on.
2698
2699 All the provisos about C<guestfs_command> apply to this call.");
2700
2701   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2702    [], (* XXX needs tests *)
2703    "run a command via the shell returning lines",
2704    "\
2705 This is the same as C<guestfs_sh>, but splits the result
2706 into a list of lines.
2707
2708 See also: C<guestfs_command_lines>");
2709
2710   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2711    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2712     * code in stubs.c, since all valid glob patterns must start with "/".
2713     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2714     *)
2715    [InitBasicFS, Always, TestOutputList (
2716       [["mkdir_p"; "/a/b/c"];
2717        ["touch"; "/a/b/c/d"];
2718        ["touch"; "/a/b/c/e"];
2719        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2720     InitBasicFS, Always, TestOutputList (
2721       [["mkdir_p"; "/a/b/c"];
2722        ["touch"; "/a/b/c/d"];
2723        ["touch"; "/a/b/c/e"];
2724        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2725     InitBasicFS, Always, TestOutputList (
2726       [["mkdir_p"; "/a/b/c"];
2727        ["touch"; "/a/b/c/d"];
2728        ["touch"; "/a/b/c/e"];
2729        ["glob_expand"; "/a/*/x/*"]], [])],
2730    "expand a wildcard path",
2731    "\
2732 This command searches for all the pathnames matching
2733 C<pattern> according to the wildcard expansion rules
2734 used by the shell.
2735
2736 If no paths match, then this returns an empty list
2737 (note: not an error).
2738
2739 It is just a wrapper around the C L<glob(3)> function
2740 with flags C<GLOB_MARK|GLOB_BRACE>.
2741 See that manual page for more details.");
2742
2743   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2744    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2745       [["scrub_device"; "/dev/sdc"]])],
2746    "scrub (securely wipe) a device",
2747    "\
2748 This command writes patterns over C<device> to make data retrieval
2749 more difficult.
2750
2751 It is an interface to the L<scrub(1)> program.  See that
2752 manual page for more details.");
2753
2754   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2755    [InitBasicFS, Always, TestRun (
2756       [["write_file"; "/file"; "content"; "0"];
2757        ["scrub_file"; "/file"]])],
2758    "scrub (securely wipe) a file",
2759    "\
2760 This command writes patterns over a file to make data retrieval
2761 more difficult.
2762
2763 The file is I<removed> after scrubbing.
2764
2765 It is an interface to the L<scrub(1)> program.  See that
2766 manual page for more details.");
2767
2768   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2769    [], (* XXX needs testing *)
2770    "scrub (securely wipe) free space",
2771    "\
2772 This command creates the directory C<dir> and then fills it
2773 with files until the filesystem is full, and scrubs the files
2774 as for C<guestfs_scrub_file>, and deletes them.
2775 The intention is to scrub any free space on the partition
2776 containing C<dir>.
2777
2778 It is an interface to the L<scrub(1)> program.  See that
2779 manual page for more details.");
2780
2781   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2782    [InitBasicFS, Always, TestRun (
2783       [["mkdir"; "/tmp"];
2784        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2785    "create a temporary directory",
2786    "\
2787 This command creates a temporary directory.  The
2788 C<template> parameter should be a full pathname for the
2789 temporary directory name with the final six characters being
2790 \"XXXXXX\".
2791
2792 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2793 the second one being suitable for Windows filesystems.
2794
2795 The name of the temporary directory that was created
2796 is returned.
2797
2798 The temporary directory is created with mode 0700
2799 and is owned by root.
2800
2801 The caller is responsible for deleting the temporary
2802 directory and its contents after use.
2803
2804 See also: L<mkdtemp(3)>");
2805
2806   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2807    [InitISOFS, Always, TestOutputInt (
2808       [["wc_l"; "/10klines"]], 10000)],
2809    "count lines in a file",
2810    "\
2811 This command counts the lines in a file, using the
2812 C<wc -l> external command.");
2813
2814   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2815    [InitISOFS, Always, TestOutputInt (
2816       [["wc_w"; "/10klines"]], 10000)],
2817    "count words in a file",
2818    "\
2819 This command counts the words in a file, using the
2820 C<wc -w> external command.");
2821
2822   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2823    [InitISOFS, Always, TestOutputInt (
2824       [["wc_c"; "/100kallspaces"]], 102400)],
2825    "count characters in a file",
2826    "\
2827 This command counts the characters in a file, using the
2828 C<wc -c> external command.");
2829
2830   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2831    [InitISOFS, Always, TestOutputList (
2832       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2833    "return first 10 lines of a file",
2834    "\
2835 This command returns up to the first 10 lines of a file as
2836 a list of strings.");
2837
2838   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2839    [InitISOFS, Always, TestOutputList (
2840       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2841     InitISOFS, Always, TestOutputList (
2842       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2843     InitISOFS, Always, TestOutputList (
2844       [["head_n"; "0"; "/10klines"]], [])],
2845    "return first N lines of a file",
2846    "\
2847 If the parameter C<nrlines> is a positive number, this returns the first
2848 C<nrlines> lines of the file C<path>.
2849
2850 If the parameter C<nrlines> is a negative number, this returns lines
2851 from the file C<path>, excluding the last C<nrlines> lines.
2852
2853 If the parameter C<nrlines> is zero, this returns an empty list.");
2854
2855   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2856    [InitISOFS, Always, TestOutputList (
2857       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2858    "return last 10 lines of a file",
2859    "\
2860 This command returns up to the last 10 lines of a file as
2861 a list of strings.");
2862
2863   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2864    [InitISOFS, Always, TestOutputList (
2865       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2866     InitISOFS, Always, TestOutputList (
2867       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2868     InitISOFS, Always, TestOutputList (
2869       [["tail_n"; "0"; "/10klines"]], [])],
2870    "return last N lines of a file",
2871    "\
2872 If the parameter C<nrlines> is a positive number, this returns the last
2873 C<nrlines> lines of the file C<path>.
2874
2875 If the parameter C<nrlines> is a negative number, this returns lines
2876 from the file C<path>, starting with the C<-nrlines>th line.
2877
2878 If the parameter C<nrlines> is zero, this returns an empty list.");
2879
2880   ("df", (RString "output", []), 125, [],
2881    [], (* XXX Tricky to test because it depends on the exact format
2882         * of the 'df' command and other imponderables.
2883         *)
2884    "report file system disk space usage",
2885    "\
2886 This command runs the C<df> command to report disk space used.
2887
2888 This command is mostly useful for interactive sessions.  It
2889 is I<not> intended that you try to parse the output string.
2890 Use C<statvfs> from programs.");
2891
2892   ("df_h", (RString "output", []), 126, [],
2893    [], (* XXX Tricky to test because it depends on the exact format
2894         * of the 'df' command and other imponderables.
2895         *)
2896    "report file system disk space usage (human readable)",
2897    "\
2898 This command runs the C<df -h> command to report disk space used
2899 in human-readable format.
2900
2901 This command is mostly useful for interactive sessions.  It
2902 is I<not> intended that you try to parse the output string.
2903 Use C<statvfs> from programs.");
2904
2905   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2906    [InitISOFS, Always, TestOutputInt (
2907       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2908    "estimate file space usage",
2909    "\
2910 This command runs the C<du -s> command to estimate file space
2911 usage for C<path>.
2912
2913 C<path> can be a file or a directory.  If C<path> is a directory
2914 then the estimate includes the contents of the directory and all
2915 subdirectories (recursively).
2916
2917 The result is the estimated size in I<kilobytes>
2918 (ie. units of 1024 bytes).");
2919
2920   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2921    [InitISOFS, Always, TestOutputList (
2922       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2923    "list files in an initrd",
2924    "\
2925 This command lists out files contained in an initrd.
2926
2927 The files are listed without any initial C</> character.  The
2928 files are listed in the order they appear (not necessarily
2929 alphabetical).  Directory names are listed as separate items.
2930
2931 Old Linux kernels (2.4 and earlier) used a compressed ext2
2932 filesystem as initrd.  We I<only> support the newer initramfs
2933 format (compressed cpio files).");
2934
2935   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2936    [],
2937    "mount a file using the loop device",
2938    "\
2939 This command lets you mount C<file> (a filesystem image
2940 in a file) on a mount point.  It is entirely equivalent to
2941 the command C<mount -o loop file mountpoint>.");
2942
2943   ("mkswap", (RErr, [Device "device"]), 130, [],
2944    [InitEmpty, Always, TestRun (
2945       [["part_disk"; "/dev/sda"; "mbr"];
2946        ["mkswap"; "/dev/sda1"]])],
2947    "create a swap partition",
2948    "\
2949 Create a swap partition on C<device>.");
2950
2951   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2952    [InitEmpty, Always, TestRun (
2953       [["part_disk"; "/dev/sda"; "mbr"];
2954        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2955    "create a swap partition with a label",
2956    "\
2957 Create a swap partition on C<device> with label C<label>.
2958
2959 Note that you cannot attach a swap label to a block device
2960 (eg. C</dev/sda>), just to a partition.  This appears to be
2961 a limitation of the kernel or swap tools.");
2962
2963   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2964    (let uuid = uuidgen () in
2965     [InitEmpty, Always, TestRun (
2966        [["part_disk"; "/dev/sda"; "mbr"];
2967         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2968    "create a swap partition with an explicit UUID",
2969    "\
2970 Create a swap partition on C<device> with UUID C<uuid>.");
2971
2972   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2973    [InitBasicFS, Always, TestOutputStruct (
2974       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2975        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2976        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2977     InitBasicFS, Always, TestOutputStruct (
2978       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2979        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2980    "make block, character or FIFO devices",
2981    "\
2982 This call creates block or character special devices, or
2983 named pipes (FIFOs).
2984
2985 The C<mode> parameter should be the mode, using the standard
2986 constants.  C<devmajor> and C<devminor> are the
2987 device major and minor numbers, only used when creating block
2988 and character special devices.");
2989
2990   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2991    [InitBasicFS, Always, TestOutputStruct (
2992       [["mkfifo"; "0o777"; "/node"];
2993        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2994    "make FIFO (named pipe)",
2995    "\
2996 This call creates a FIFO (named pipe) called C<path> with
2997 mode C<mode>.  It is just a convenient wrapper around
2998 C<guestfs_mknod>.");
2999
3000   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3001    [InitBasicFS, Always, TestOutputStruct (
3002       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3003        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3004    "make block device node",
3005    "\
3006 This call creates a block device node called C<path> with
3007 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3008 It is just a convenient wrapper around C<guestfs_mknod>.");
3009
3010   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3011    [InitBasicFS, Always, TestOutputStruct (
3012       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3013        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3014    "make char device node",
3015    "\
3016 This call creates a char device node called C<path> with
3017 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3018 It is just a convenient wrapper around C<guestfs_mknod>.");
3019
3020   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3021    [], (* XXX umask is one of those stateful things that we should
3022         * reset between each test.
3023         *)
3024    "set file mode creation mask (umask)",
3025    "\
3026 This function sets the mask used for creating new files and
3027 device nodes to C<mask & 0777>.
3028
3029 Typical umask values would be C<022> which creates new files
3030 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3031 C<002> which creates new files with permissions like
3032 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3033
3034 The default umask is C<022>.  This is important because it
3035 means that directories and device nodes will be created with
3036 C<0644> or C<0755> mode even if you specify C<0777>.
3037
3038 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3039
3040 This call returns the previous umask.");
3041
3042   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3043    [],
3044    "read directories entries",
3045    "\
3046 This returns the list of directory entries in directory C<dir>.
3047
3048 All entries in the directory are returned, including C<.> and
3049 C<..>.  The entries are I<not> sorted, but returned in the same
3050 order as the underlying filesystem.
3051
3052 Also this call returns basic file type information about each
3053 file.  The C<ftyp> field will contain one of the following characters:
3054
3055 =over 4
3056
3057 =item 'b'
3058
3059 Block special
3060
3061 =item 'c'
3062
3063 Char special
3064
3065 =item 'd'
3066
3067 Directory
3068
3069 =item 'f'
3070
3071 FIFO (named pipe)
3072
3073 =item 'l'
3074
3075 Symbolic link
3076
3077 =item 'r'
3078
3079 Regular file
3080
3081 =item 's'
3082
3083 Socket
3084
3085 =item 'u'
3086
3087 Unknown file type
3088
3089 =item '?'
3090
3091 The L<readdir(3)> returned a C<d_type> field with an
3092 unexpected value
3093
3094 =back
3095
3096 This function is primarily intended for use by programs.  To
3097 get a simple list of names, use C<guestfs_ls>.  To get a printable
3098 directory for human consumption, use C<guestfs_ll>.");
3099
3100   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3101    [],
3102    "create partitions on a block device",
3103    "\
3104 This is a simplified interface to the C<guestfs_sfdisk>
3105 command, where partition sizes are specified in megabytes
3106 only (rounded to the nearest cylinder) and you don't need
3107 to specify the cyls, heads and sectors parameters which
3108 were rarely if ever used anyway.
3109
3110 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3111 and C<guestfs_part_disk>");
3112
3113   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3114    [],
3115    "determine file type inside a compressed file",
3116    "\
3117 This command runs C<file> after first decompressing C<path>
3118 using C<method>.
3119
3120 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3121
3122 Since 1.0.63, use C<guestfs_file> instead which can now
3123 process compressed files.");
3124
3125   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3126    [],
3127    "list extended attributes of a file or directory",
3128    "\
3129 This call lists the extended attributes of the file or directory
3130 C<path>.
3131
3132 At the system call level, this is a combination of the
3133 L<listxattr(2)> and L<getxattr(2)> calls.
3134
3135 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3136
3137   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3138    [],
3139    "list extended attributes of a file or directory",
3140    "\
3141 This is the same as C<guestfs_getxattrs>, but if C<path>
3142 is a symbolic link, then it returns the extended attributes
3143 of the link itself.");
3144
3145   ("setxattr", (RErr, [String "xattr";
3146                        String "val"; Int "vallen"; (* will be BufferIn *)
3147                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3148    [],
3149    "set extended attribute of a file or directory",
3150    "\
3151 This call sets the extended attribute named C<xattr>
3152 of the file C<path> to the value C<val> (of length C<vallen>).
3153 The value is arbitrary 8 bit data.
3154
3155 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3156
3157   ("lsetxattr", (RErr, [String "xattr";
3158                         String "val"; Int "vallen"; (* will be BufferIn *)
3159                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3160    [],
3161    "set extended attribute of a file or directory",
3162    "\
3163 This is the same as C<guestfs_setxattr>, but if C<path>
3164 is a symbolic link, then it sets an extended attribute
3165 of the link itself.");
3166
3167   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3168    [],
3169    "remove extended attribute of a file or directory",
3170    "\
3171 This call removes the extended attribute named C<xattr>
3172 of the file C<path>.
3173
3174 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3175
3176   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3177    [],
3178    "remove extended attribute of a file or directory",
3179    "\
3180 This is the same as C<guestfs_removexattr>, but if C<path>
3181 is a symbolic link, then it removes an extended attribute
3182 of the link itself.");
3183
3184   ("mountpoints", (RHashtable "mps", []), 147, [],
3185    [],
3186    "show mountpoints",
3187    "\
3188 This call is similar to C<guestfs_mounts>.  That call returns
3189 a list of devices.  This one returns a hash table (map) of
3190 device name to directory where the device is mounted.");
3191
3192   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3193    (* This is a special case: while you would expect a parameter
3194     * of type "Pathname", that doesn't work, because it implies
3195     * NEED_ROOT in the generated calling code in stubs.c, and
3196     * this function cannot use NEED_ROOT.
3197     *)
3198    [],
3199    "create a mountpoint",
3200    "\
3201 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3202 specialized calls that can be used to create extra mountpoints
3203 before mounting the first filesystem.
3204
3205 These calls are I<only> necessary in some very limited circumstances,
3206 mainly the case where you want to mount a mix of unrelated and/or
3207 read-only filesystems together.
3208
3209 For example, live CDs often contain a \"Russian doll\" nest of
3210 filesystems, an ISO outer layer, with a squashfs image inside, with
3211 an ext2/3 image inside that.  You can unpack this as follows
3212 in guestfish:
3213
3214  add-ro Fedora-11-i686-Live.iso
3215  run
3216  mkmountpoint /cd
3217  mkmountpoint /squash
3218  mkmountpoint /ext3
3219  mount /dev/sda /cd
3220  mount-loop /cd/LiveOS/squashfs.img /squash
3221  mount-loop /squash/LiveOS/ext3fs.img /ext3
3222
3223 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3224
3225   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3226    [],
3227    "remove a mountpoint",
3228    "\
3229 This calls removes a mountpoint that was previously created
3230 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3231 for full details.");
3232
3233   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3234    [InitISOFS, Always, TestOutputBuffer (
3235       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3236    "read a file",
3237    "\
3238 This calls returns the contents of the file C<path> as a
3239 buffer.
3240
3241 Unlike C<guestfs_cat>, this function can correctly
3242 handle files that contain embedded ASCII NUL characters.
3243 However unlike C<guestfs_download>, this function is limited
3244 in the total size of file that can be handled.");
3245
3246   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3247    [InitISOFS, Always, TestOutputList (
3248       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3249     InitISOFS, Always, TestOutputList (
3250       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3251    "return lines matching a pattern",
3252    "\
3253 This calls the external C<grep> program and returns the
3254 matching lines.");
3255
3256   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3257    [InitISOFS, Always, TestOutputList (
3258       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3259    "return lines matching a pattern",
3260    "\
3261 This calls the external C<egrep> program and returns the
3262 matching lines.");
3263
3264   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3265    [InitISOFS, Always, TestOutputList (
3266       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3267    "return lines matching a pattern",
3268    "\
3269 This calls the external C<fgrep> program and returns the
3270 matching lines.");
3271
3272   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3273    [InitISOFS, Always, TestOutputList (
3274       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3275    "return lines matching a pattern",
3276    "\
3277 This calls the external C<grep -i> program and returns the
3278 matching lines.");
3279
3280   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3281    [InitISOFS, Always, TestOutputList (
3282       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3283    "return lines matching a pattern",
3284    "\
3285 This calls the external C<egrep -i> program and returns the
3286 matching lines.");
3287
3288   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3289    [InitISOFS, Always, TestOutputList (
3290       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3291    "return lines matching a pattern",
3292    "\
3293 This calls the external C<fgrep -i> program and returns the
3294 matching lines.");
3295
3296   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3297    [InitISOFS, Always, TestOutputList (
3298       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3299    "return lines matching a pattern",
3300    "\
3301 This calls the external C<zgrep> program and returns the
3302 matching lines.");
3303
3304   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3305    [InitISOFS, Always, TestOutputList (
3306       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3307    "return lines matching a pattern",
3308    "\
3309 This calls the external C<zegrep> program and returns the
3310 matching lines.");
3311
3312   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3313    [InitISOFS, Always, TestOutputList (
3314       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3315    "return lines matching a pattern",
3316    "\
3317 This calls the external C<zfgrep> program and returns the
3318 matching lines.");
3319
3320   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3321    [InitISOFS, Always, TestOutputList (
3322       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3323    "return lines matching a pattern",
3324    "\
3325 This calls the external C<zgrep -i> program and returns the
3326 matching lines.");
3327
3328   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3329    [InitISOFS, Always, TestOutputList (
3330       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3331    "return lines matching a pattern",
3332    "\
3333 This calls the external C<zegrep -i> program and returns the
3334 matching lines.");
3335
3336   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3337    [InitISOFS, Always, TestOutputList (
3338       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3339    "return lines matching a pattern",
3340    "\
3341 This calls the external C<zfgrep -i> program and returns the
3342 matching lines.");
3343
3344   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3345    [InitISOFS, Always, TestOutput (
3346       [["realpath"; "/../directory"]], "/directory")],
3347    "canonicalized absolute pathname",
3348    "\
3349 Return the canonicalized absolute pathname of C<path>.  The
3350 returned path has no C<.>, C<..> or symbolic link path elements.");
3351
3352   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3353    [InitBasicFS, Always, TestOutputStruct (
3354       [["touch"; "/a"];
3355        ["ln"; "/a"; "/b"];
3356        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3357    "create a hard link",
3358    "\
3359 This command creates a hard link using the C<ln> command.");
3360
3361   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3362    [InitBasicFS, Always, TestOutputStruct (
3363       [["touch"; "/a"];
3364        ["touch"; "/b"];
3365        ["ln_f"; "/a"; "/b"];
3366        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3367    "create a hard link",
3368    "\
3369 This command creates a hard link using the C<ln -f> command.
3370 The C<-f> option removes the link (C<linkname>) if it exists already.");
3371
3372   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3373    [InitBasicFS, Always, TestOutputStruct (
3374       [["touch"; "/a"];
3375        ["ln_s"; "a"; "/b"];
3376        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3377    "create a symbolic link",
3378    "\
3379 This command creates a symbolic link using the C<ln -s> command.");
3380
3381   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3382    [InitBasicFS, Always, TestOutput (
3383       [["mkdir_p"; "/a/b"];
3384        ["touch"; "/a/b/c"];
3385        ["ln_sf"; "../d"; "/a/b/c"];
3386        ["readlink"; "/a/b/c"]], "../d")],
3387    "create a symbolic link",
3388    "\
3389 This command creates a symbolic link using the C<ln -sf> command,
3390 The C<-f> option removes the link (C<linkname>) if it exists already.");
3391
3392   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3393    [] (* XXX tested above *),
3394    "read the target of a symbolic link",
3395    "\
3396 This command reads the target of a symbolic link.");
3397
3398   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3399    [InitBasicFS, Always, TestOutputStruct (
3400       [["fallocate"; "/a"; "1000000"];
3401        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3402    "preallocate a file in the guest filesystem",
3403    "\
3404 This command preallocates a file (containing zero bytes) named
3405 C<path> of size C<len> bytes.  If the file exists already, it
3406 is overwritten.
3407
3408 Do not confuse this with the guestfish-specific
3409 C<alloc> command which allocates a file in the host and
3410 attaches it as a device.");
3411
3412   ("swapon_device", (RErr, [Device "device"]), 170, [],
3413    [InitPartition, Always, TestRun (
3414       [["mkswap"; "/dev/sda1"];
3415        ["swapon_device"; "/dev/sda1"];
3416        ["swapoff_device"; "/dev/sda1"]])],
3417    "enable swap on device",
3418    "\
3419 This command enables the libguestfs appliance to use the
3420 swap device or partition named C<device>.  The increased
3421 memory is made available for all commands, for example
3422 those run using C<guestfs_command> or C<guestfs_sh>.
3423
3424 Note that you should not swap to existing guest swap
3425 partitions unless you know what you are doing.  They may
3426 contain hibernation information, or other information that
3427 the guest doesn't want you to trash.  You also risk leaking
3428 information about the host to the guest this way.  Instead,
3429 attach a new host device to the guest and swap on that.");
3430
3431   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3432    [], (* XXX tested by swapon_device *)
3433    "disable swap on device",
3434    "\
3435 This command disables the libguestfs appliance swap
3436 device or partition named C<device>.
3437 See C<guestfs_swapon_device>.");
3438
3439   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3440    [InitBasicFS, Always, TestRun (
3441       [["fallocate"; "/swap"; "8388608"];
3442        ["mkswap_file"; "/swap"];
3443        ["swapon_file"; "/swap"];
3444        ["swapoff_file"; "/swap"]])],
3445    "enable swap on file",
3446    "\
3447 This command enables swap to a file.
3448 See C<guestfs_swapon_device> for other notes.");
3449
3450   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3451    [], (* XXX tested by swapon_file *)
3452    "disable swap on file",
3453    "\
3454 This command disables the libguestfs appliance swap on file.");
3455
3456   ("swapon_label", (RErr, [String "label"]), 174, [],
3457    [InitEmpty, Always, TestRun (
3458       [["part_disk"; "/dev/sdb"; "mbr"];
3459        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3460        ["swapon_label"; "swapit"];
3461        ["swapoff_label"; "swapit"];
3462        ["zero"; "/dev/sdb"];
3463        ["blockdev_rereadpt"; "/dev/sdb"]])],
3464    "enable swap on labeled swap partition",
3465    "\
3466 This command enables swap to a labeled swap partition.
3467 See C<guestfs_swapon_device> for other notes.");
3468
3469   ("swapoff_label", (RErr, [String "label"]), 175, [],
3470    [], (* XXX tested by swapon_label *)
3471    "disable swap on labeled swap partition",
3472    "\
3473 This command disables the libguestfs appliance swap on
3474 labeled swap partition.");
3475
3476   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3477    (let uuid = uuidgen () in
3478     [InitEmpty, Always, TestRun (
3479        [["mkswap_U"; uuid; "/dev/sdb"];
3480         ["swapon_uuid"; uuid];
3481         ["swapoff_uuid"; uuid]])]),
3482    "enable swap on swap partition by UUID",
3483    "\
3484 This command enables swap to a swap partition with the given UUID.
3485 See C<guestfs_swapon_device> for other notes.");
3486
3487   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3488    [], (* XXX tested by swapon_uuid *)
3489    "disable swap on swap partition by UUID",
3490    "\
3491 This command disables the libguestfs appliance swap partition
3492 with the given UUID.");
3493
3494   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3495    [InitBasicFS, Always, TestRun (
3496       [["fallocate"; "/swap"; "8388608"];
3497        ["mkswap_file"; "/swap"]])],
3498    "create a swap file",
3499    "\
3500 Create a swap file.
3501
3502 This command just writes a swap file signature to an existing
3503 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3504
3505   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3506    [InitISOFS, Always, TestRun (
3507       [["inotify_init"; "0"]])],
3508    "create an inotify handle",
3509    "\
3510 This command creates a new inotify handle.
3511 The inotify subsystem can be used to notify events which happen to
3512 objects in the guest filesystem.
3513
3514 C<maxevents> is the maximum number of events which will be
3515 queued up between calls to C<guestfs_inotify_read> or
3516 C<guestfs_inotify_files>.
3517 If this is passed as C<0>, then the kernel (or previously set)
3518 default is used.  For Linux 2.6.29 the default was 16384 events.
3519 Beyond this limit, the kernel throws away events, but records
3520 the fact that it threw them away by setting a flag
3521 C<IN_Q_OVERFLOW> in the returned structure list (see
3522 C<guestfs_inotify_read>).
3523
3524 Before any events are generated, you have to add some
3525 watches to the internal watch list.  See:
3526 C<guestfs_inotify_add_watch>,
3527 C<guestfs_inotify_rm_watch> and
3528 C<guestfs_inotify_watch_all>.
3529
3530 Queued up events should be read periodically by calling
3531 C<guestfs_inotify_read>
3532 (or C<guestfs_inotify_files> which is just a helpful
3533 wrapper around C<guestfs_inotify_read>).  If you don't
3534 read the events out often enough then you risk the internal
3535 queue overflowing.
3536
3537 The handle should be closed after use by calling
3538 C<guestfs_inotify_close>.  This also removes any
3539 watches automatically.
3540
3541 See also L<inotify(7)> for an overview of the inotify interface
3542 as exposed by the Linux kernel, which is roughly what we expose
3543 via libguestfs.  Note that there is one global inotify handle
3544 per libguestfs instance.");
3545
3546   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3547    [InitBasicFS, Always, TestOutputList (
3548       [["inotify_init"; "0"];
3549        ["inotify_add_watch"; "/"; "1073741823"];
3550        ["touch"; "/a"];
3551        ["touch"; "/b"];
3552        ["inotify_files"]], ["a"; "b"])],
3553    "add an inotify watch",
3554    "\
3555 Watch C<path> for the events listed in C<mask>.
3556
3557 Note that if C<path> is a directory then events within that
3558 directory are watched, but this does I<not> happen recursively
3559 (in subdirectories).
3560
3561 Note for non-C or non-Linux callers: the inotify events are
3562 defined by the Linux kernel ABI and are listed in
3563 C</usr/include/sys/inotify.h>.");
3564
3565   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3566    [],
3567    "remove an inotify watch",
3568    "\
3569 Remove a previously defined inotify watch.
3570 See C<guestfs_inotify_add_watch>.");
3571
3572   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3573    [],
3574    "return list of inotify events",
3575    "\
3576 Return the complete queue of events that have happened
3577 since the previous read call.
3578
3579 If no events have happened, this returns an empty list.
3580
3581 I<Note>: In order to make sure that all events have been
3582 read, you must call this function repeatedly until it
3583 returns an empty list.  The reason is that the call will
3584 read events up to the maximum appliance-to-host message
3585 size and leave remaining events in the queue.");
3586
3587   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3588    [],
3589    "return list of watched files that had events",
3590    "\
3591 This function is a helpful wrapper around C<guestfs_inotify_read>
3592 which just returns a list of pathnames of objects that were
3593 touched.  The returned pathnames are sorted and deduplicated.");
3594
3595   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3596    [],
3597    "close the inotify handle",
3598    "\
3599 This closes the inotify handle which was previously
3600 opened by inotify_init.  It removes all watches, throws
3601 away any pending events, and deallocates all resources.");
3602
3603   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3604    [],
3605    "set SELinux security context",
3606    "\
3607 This sets the SELinux security context of the daemon
3608 to the string C<context>.
3609
3610 See the documentation about SELINUX in L<guestfs(3)>.");
3611
3612   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3613    [],
3614    "get SELinux security context",
3615    "\
3616 This gets the SELinux security context of the daemon.
3617
3618 See the documentation about SELINUX in L<guestfs(3)>,
3619 and C<guestfs_setcon>");
3620
3621   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3622    [InitEmpty, Always, TestOutput (
3623       [["part_disk"; "/dev/sda"; "mbr"];
3624        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3625        ["mount_options"; ""; "/dev/sda1"; "/"];
3626        ["write_file"; "/new"; "new file contents"; "0"];
3627        ["cat"; "/new"]], "new file contents")],
3628    "make a filesystem with block size",
3629    "\
3630 This call is similar to C<guestfs_mkfs>, but it allows you to
3631 control the block size of the resulting filesystem.  Supported
3632 block sizes depend on the filesystem type, but typically they
3633 are C<1024>, C<2048> or C<4096> only.");
3634
3635   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3636    [InitEmpty, Always, TestOutput (
3637       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3638        ["mke2journal"; "4096"; "/dev/sda1"];
3639        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3640        ["mount_options"; ""; "/dev/sda2"; "/"];
3641        ["write_file"; "/new"; "new file contents"; "0"];
3642        ["cat"; "/new"]], "new file contents")],
3643    "make ext2/3/4 external journal",
3644    "\
3645 This creates an ext2 external journal on C<device>.  It is equivalent
3646 to the command:
3647
3648  mke2fs -O journal_dev -b blocksize device");
3649
3650   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3651    [InitEmpty, Always, TestOutput (
3652       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3653        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3654        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3655        ["mount_options"; ""; "/dev/sda2"; "/"];
3656        ["write_file"; "/new"; "new file contents"; "0"];
3657        ["cat"; "/new"]], "new file contents")],
3658    "make ext2/3/4 external journal with label",
3659    "\
3660 This creates an ext2 external journal on C<device> with label C<label>.");
3661
3662   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3663    (let uuid = uuidgen () in
3664     [InitEmpty, Always, TestOutput (
3665        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3666         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3667         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3668         ["mount_options"; ""; "/dev/sda2"; "/"];
3669         ["write_file"; "/new"; "new file contents"; "0"];
3670         ["cat"; "/new"]], "new file contents")]),
3671    "make ext2/3/4 external journal with UUID",
3672    "\
3673 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3674
3675   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3676    [],
3677    "make ext2/3/4 filesystem with external journal",
3678    "\
3679 This creates an ext2/3/4 filesystem on C<device> with
3680 an external journal on C<journal>.  It is equivalent
3681 to the command:
3682
3683  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3684
3685 See also C<guestfs_mke2journal>.");
3686
3687   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3688    [],
3689    "make ext2/3/4 filesystem with external journal",
3690    "\
3691 This creates an ext2/3/4 filesystem on C<device> with
3692 an external journal on the journal labeled C<label>.
3693
3694 See also C<guestfs_mke2journal_L>.");
3695
3696   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3697    [],
3698    "make ext2/3/4 filesystem with external journal",
3699    "\
3700 This creates an ext2/3/4 filesystem on C<device> with
3701 an external journal on the journal with UUID C<uuid>.
3702
3703 See also C<guestfs_mke2journal_U>.");
3704
3705   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3706    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3707    "load a kernel module",
3708    "\
3709 This loads a kernel module in the appliance.
3710
3711 The kernel module must have been whitelisted when libguestfs
3712 was built (see C<appliance/kmod.whitelist.in> in the source).");
3713
3714   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3715    [InitNone, Always, TestOutput (
3716       [["echo_daemon"; "This is a test"]], "This is a test"
3717     )],
3718    "echo arguments back to the client",
3719    "\
3720 This command concatenate the list of C<words> passed with single spaces between
3721 them and returns the resulting string.
3722
3723 You can use this command to test the connection through to the daemon.
3724
3725 See also C<guestfs_ping_daemon>.");
3726
3727   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3728    [], (* There is a regression test for this. *)
3729    "find all files and directories, returning NUL-separated list",
3730    "\
3731 This command lists out all files and directories, recursively,
3732 starting at C<directory>, placing the resulting list in the
3733 external file called C<files>.
3734
3735 This command works the same way as C<guestfs_find> with the
3736 following exceptions:
3737
3738 =over 4
3739
3740 =item *
3741
3742 The resulting list is written to an external file.
3743
3744 =item *
3745
3746 Items (filenames) in the result are separated
3747 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3748
3749 =item *
3750
3751 This command is not limited in the number of names that it
3752 can return.
3753
3754 =item *
3755
3756 The result list is not sorted.
3757
3758 =back");
3759
3760   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3761    [InitISOFS, Always, TestOutput (
3762       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3763     InitISOFS, Always, TestOutput (
3764       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3765     InitISOFS, Always, TestOutput (
3766       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3767     InitISOFS, Always, TestLastFail (
3768       [["case_sensitive_path"; "/Known-1/"]]);
3769     InitBasicFS, Always, TestOutput (
3770       [["mkdir"; "/a"];
3771        ["mkdir"; "/a/bbb"];
3772        ["touch"; "/a/bbb/c"];
3773        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3774     InitBasicFS, Always, TestOutput (
3775       [["mkdir"; "/a"];
3776        ["mkdir"; "/a/bbb"];
3777        ["touch"; "/a/bbb/c"];
3778        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3779     InitBasicFS, Always, TestLastFail (
3780       [["mkdir"; "/a"];
3781        ["mkdir"; "/a/bbb"];
3782        ["touch"; "/a/bbb/c"];
3783        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3784    "return true path on case-insensitive filesystem",
3785    "\
3786 This can be used to resolve case insensitive paths on
3787 a filesystem which is case sensitive.  The use case is
3788 to resolve paths which you have read from Windows configuration
3789 files or the Windows Registry, to the true path.
3790
3791 The command handles a peculiarity of the Linux ntfs-3g
3792 filesystem driver (and probably others), which is that although
3793 the underlying filesystem is case-insensitive, the driver
3794 exports the filesystem to Linux as case-sensitive.
3795
3796 One consequence of this is that special directories such
3797 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3798 (or other things) depending on the precise details of how
3799 they were created.  In Windows itself this would not be
3800 a problem.
3801
3802 Bug or feature?  You decide:
3803 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3804
3805 This function resolves the true case of each element in the
3806 path and returns the case-sensitive path.
3807
3808 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3809 might return C<\"/WINDOWS/system32\"> (the exact return value
3810 would depend on details of how the directories were originally
3811 created under Windows).
3812
3813 I<Note>:
3814 This function does not handle drive names, backslashes etc.
3815
3816 See also C<guestfs_realpath>.");
3817
3818   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3819    [InitBasicFS, Always, TestOutput (
3820       [["vfs_type"; "/dev/sda1"]], "ext2")],
3821    "get the Linux VFS type corresponding to a mounted device",
3822    "\
3823 This command gets the block device type corresponding to
3824 a mounted device called C<device>.
3825
3826 Usually the result is the name of the Linux VFS module that
3827 is used to mount this device (probably determined automatically
3828 if you used the C<guestfs_mount> call).");
3829
3830   ("truncate", (RErr, [Pathname "path"]), 199, [],
3831    [InitBasicFS, Always, TestOutputStruct (
3832       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3833        ["truncate"; "/test"];
3834        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3835    "truncate a file to zero size",
3836    "\
3837 This command truncates C<path> to a zero-length file.  The
3838 file must exist already.");
3839
3840   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3841    [InitBasicFS, Always, TestOutputStruct (
3842       [["touch"; "/test"];
3843        ["truncate_size"; "/test"; "1000"];
3844        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3845    "truncate a file to a particular size",
3846    "\
3847 This command truncates C<path> to size C<size> bytes.  The file
3848 must exist already.  If the file is smaller than C<size> then
3849 the file is extended to the required size with null bytes.");
3850
3851   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3852    [InitBasicFS, Always, TestOutputStruct (
3853       [["touch"; "/test"];
3854        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3855        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3856    "set timestamp of a file with nanosecond precision",
3857    "\
3858 This command sets the timestamps of a file with nanosecond
3859 precision.
3860
3861 C<atsecs, atnsecs> are the last access time (atime) in secs and
3862 nanoseconds from the epoch.
3863
3864 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3865 secs and nanoseconds from the epoch.
3866
3867 If the C<*nsecs> field contains the special value C<-1> then
3868 the corresponding timestamp is set to the current time.  (The
3869 C<*secs> field is ignored in this case).
3870
3871 If the C<*nsecs> field contains the special value C<-2> then
3872 the corresponding timestamp is left unchanged.  (The
3873 C<*secs> field is ignored in this case).");
3874
3875   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3876    [InitBasicFS, Always, TestOutputStruct (
3877       [["mkdir_mode"; "/test"; "0o111"];
3878        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3879    "create a directory with a particular mode",
3880    "\
3881 This command creates a directory, setting the initial permissions
3882 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3883
3884   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3885    [], (* XXX *)
3886    "change file owner and group",
3887    "\
3888 Change the file owner to C<owner> and group to C<group>.
3889 This is like C<guestfs_chown> but if C<path> is a symlink then
3890 the link itself is changed, not the target.
3891
3892 Only numeric uid and gid are supported.  If you want to use
3893 names, you will need to locate and parse the password file
3894 yourself (Augeas support makes this relatively easy).");
3895
3896   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3897    [], (* XXX *)
3898    "lstat on multiple files",
3899    "\
3900 This call allows you to perform the C<guestfs_lstat> operation
3901 on multiple files, where all files are in the directory C<path>.
3902 C<names> is the list of files from this directory.
3903
3904 On return you get a list of stat structs, with a one-to-one
3905 correspondence to the C<names> list.  If any name did not exist
3906 or could not be lstat'd, then the C<ino> field of that structure
3907 is set to C<-1>.
3908
3909 This call is intended for programs that want to efficiently
3910 list a directory contents without making many round-trips.
3911 See also C<guestfs_lxattrlist> for a similarly efficient call
3912 for getting extended attributes.  Very long directory listings
3913 might cause the protocol message size to be exceeded, causing
3914 this call to fail.  The caller must split up such requests
3915 into smaller groups of names.");
3916
3917   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3918    [], (* XXX *)
3919    "lgetxattr on multiple files",
3920    "\
3921 This call allows you to get the extended attributes
3922 of multiple files, where all files are in the directory C<path>.
3923 C<names> is the list of files from this directory.
3924
3925 On return you get a flat list of xattr structs which must be
3926 interpreted sequentially.  The first xattr struct always has a zero-length
3927 C<attrname>.  C<attrval> in this struct is zero-length
3928 to indicate there was an error doing C<lgetxattr> for this
3929 file, I<or> is a C string which is a decimal number
3930 (the number of following attributes for this file, which could
3931 be C<\"0\">).  Then after the first xattr struct are the
3932 zero or more attributes for the first named file.
3933 This repeats for the second and subsequent files.
3934
3935 This call is intended for programs that want to efficiently
3936 list a directory contents without making many round-trips.
3937 See also C<guestfs_lstatlist> for a similarly efficient call
3938 for getting standard stats.  Very long directory listings
3939 might cause the protocol message size to be exceeded, causing
3940 this call to fail.  The caller must split up such requests
3941 into smaller groups of names.");
3942
3943   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3944    [], (* XXX *)
3945    "readlink on multiple files",
3946    "\
3947 This call allows you to do a C<readlink> operation
3948 on multiple files, where all files are in the directory C<path>.
3949 C<names> is the list of files from this directory.
3950
3951 On return you get a list of strings, with a one-to-one
3952 correspondence to the C<names> list.  Each string is the
3953 value of the symbol link.
3954
3955 If the C<readlink(2)> operation fails on any name, then
3956 the corresponding result string is the empty string C<\"\">.
3957 However the whole operation is completed even if there
3958 were C<readlink(2)> errors, and so you can call this
3959 function with names where you don't know if they are
3960 symbolic links already (albeit slightly less efficient).
3961
3962 This call is intended for programs that want to efficiently
3963 list a directory contents without making many round-trips.
3964 Very long directory listings might cause the protocol
3965 message size to be exceeded, causing
3966 this call to fail.  The caller must split up such requests
3967 into smaller groups of names.");
3968
3969   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3970    [InitISOFS, Always, TestOutputBuffer (
3971       [["pread"; "/known-4"; "1"; "3"]], "\n");
3972     InitISOFS, Always, TestOutputBuffer (
3973       [["pread"; "/empty"; "0"; "100"]], "")],
3974    "read part of a file",
3975    "\
3976 This command lets you read part of a file.  It reads C<count>
3977 bytes of the file, starting at C<offset>, from file C<path>.
3978
3979 This may read fewer bytes than requested.  For further details
3980 see the L<pread(2)> system call.");
3981
3982   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3983    [InitEmpty, Always, TestRun (
3984       [["part_init"; "/dev/sda"; "gpt"]])],
3985    "create an empty partition table",
3986    "\
3987 This creates an empty partition table on C<device> of one of the
3988 partition types listed below.  Usually C<parttype> should be
3989 either C<msdos> or C<gpt> (for large disks).
3990
3991 Initially there are no partitions.  Following this, you should
3992 call C<guestfs_part_add> for each partition required.
3993
3994 Possible values for C<parttype> are:
3995
3996 =over 4
3997
3998 =item B<efi> | B<gpt>
3999
4000 Intel EFI / GPT partition table.
4001
4002 This is recommended for >= 2 TB partitions that will be accessed
4003 from Linux and Intel-based Mac OS X.  It also has limited backwards
4004 compatibility with the C<mbr> format.
4005
4006 =item B<mbr> | B<msdos>
4007
4008 The standard PC \"Master Boot Record\" (MBR) format used
4009 by MS-DOS and Windows.  This partition type will B<only> work
4010 for device sizes up to 2 TB.  For large disks we recommend
4011 using C<gpt>.
4012
4013 =back
4014
4015 Other partition table types that may work but are not
4016 supported include:
4017
4018 =over 4
4019
4020 =item B<aix>
4021
4022 AIX disk labels.
4023
4024 =item B<amiga> | B<rdb>
4025
4026 Amiga \"Rigid Disk Block\" format.
4027
4028 =item B<bsd>
4029
4030 BSD disk labels.
4031
4032 =item B<dasd>
4033
4034 DASD, used on IBM mainframes.
4035
4036 =item B<dvh>
4037
4038 MIPS/SGI volumes.
4039
4040 =item B<mac>
4041
4042 Old Mac partition format.  Modern Macs use C<gpt>.
4043
4044 =item B<pc98>
4045
4046 NEC PC-98 format, common in Japan apparently.
4047
4048 =item B<sun>
4049
4050 Sun disk labels.
4051
4052 =back");
4053
4054   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4055    [InitEmpty, Always, TestRun (
4056       [["part_init"; "/dev/sda"; "mbr"];
4057        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4058     InitEmpty, Always, TestRun (
4059       [["part_init"; "/dev/sda"; "gpt"];
4060        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4061        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4062     InitEmpty, Always, TestRun (
4063       [["part_init"; "/dev/sda"; "mbr"];
4064        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4065        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4066        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4067        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4068    "add a partition to the device",
4069    "\
4070 This command adds a partition to C<device>.  If there is no partition
4071 table on the device, call C<guestfs_part_init> first.
4072
4073 The C<prlogex> parameter is the type of partition.  Normally you
4074 should pass C<p> or C<primary> here, but MBR partition tables also
4075 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4076 types.
4077
4078 C<startsect> and C<endsect> are the start and end of the partition
4079 in I<sectors>.  C<endsect> may be negative, which means it counts
4080 backwards from the end of the disk (C<-1> is the last sector).
4081
4082 Creating a partition which covers the whole disk is not so easy.
4083 Use C<guestfs_part_disk> to do that.");
4084
4085   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4086    [InitEmpty, Always, TestRun (
4087       [["part_disk"; "/dev/sda"; "mbr"]]);
4088     InitEmpty, Always, TestRun (
4089       [["part_disk"; "/dev/sda"; "gpt"]])],
4090    "partition whole disk with a single primary partition",
4091    "\
4092 This command is simply a combination of C<guestfs_part_init>
4093 followed by C<guestfs_part_add> to create a single primary partition
4094 covering the whole disk.
4095
4096 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4097 but other possible values are described in C<guestfs_part_init>.");
4098
4099   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4100    [InitEmpty, Always, TestRun (
4101       [["part_disk"; "/dev/sda"; "mbr"];
4102        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4103    "make a partition bootable",
4104    "\
4105 This sets the bootable flag on partition numbered C<partnum> on
4106 device C<device>.  Note that partitions are numbered from 1.
4107
4108 The bootable flag is used by some operating systems (notably
4109 Windows) to determine which partition to boot from.  It is by
4110 no means universally recognized.");
4111
4112   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4113    [InitEmpty, Always, TestRun (
4114       [["part_disk"; "/dev/sda"; "gpt"];
4115        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4116    "set partition name",
4117    "\
4118 This sets the partition name on partition numbered C<partnum> on
4119 device C<device>.  Note that partitions are numbered from 1.
4120
4121 The partition name can only be set on certain types of partition
4122 table.  This works on C<gpt> but not on C<mbr> partitions.");
4123
4124   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4125    [], (* XXX Add a regression test for this. *)
4126    "list partitions on a device",
4127    "\
4128 This command parses the partition table on C<device> and
4129 returns the list of partitions found.
4130
4131 The fields in the returned structure are:
4132
4133 =over 4
4134
4135 =item B<part_num>
4136
4137 Partition number, counting from 1.
4138
4139 =item B<part_start>
4140
4141 Start of the partition I<in bytes>.  To get sectors you have to
4142 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4143
4144 =item B<part_end>
4145
4146 End of the partition in bytes.
4147
4148 =item B<part_size>
4149
4150 Size of the partition in bytes.
4151
4152 =back");
4153
4154   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4155    [InitEmpty, Always, TestOutput (
4156       [["part_disk"; "/dev/sda"; "gpt"];
4157        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4158    "get the partition table type",
4159    "\
4160 This command examines the partition table on C<device> and
4161 returns the partition table type (format) being used.
4162
4163 Common return values include: C<msdos> (a DOS/Windows style MBR
4164 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4165 values are possible, although unusual.  See C<guestfs_part_init>
4166 for a full list.");
4167
4168   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4169    [InitBasicFS, Always, TestOutputBuffer (
4170       [["fill"; "0x63"; "10"; "/test"];
4171        ["read_file"; "/test"]], "cccccccccc")],
4172    "fill a file with octets",
4173    "\
4174 This command creates a new file called C<path>.  The initial
4175 content of the file is C<len> octets of C<c>, where C<c>
4176 must be a number in the range C<[0..255]>.
4177
4178 To fill a file with zero bytes (sparsely), it is
4179 much more efficient to use C<guestfs_truncate_size>.");
4180
4181   ("available", (RErr, [StringList "groups"]), 216, [],
4182    [InitNone, Always, TestRun [["available"; ""]]],
4183    "test availability of some parts of the API",
4184    "\
4185 This command is used to check the availability of some
4186 groups of functionality in the appliance, which not all builds of
4187 the libguestfs appliance will be able to provide.
4188
4189 The libguestfs groups, and the functions that those
4190 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4191
4192 The argument C<groups> is a list of group names, eg:
4193 C<[\"inotify\", \"augeas\"]> would check for the availability of
4194 the Linux inotify functions and Augeas (configuration file
4195 editing) functions.
4196
4197 The command returns no error if I<all> requested groups are available.
4198
4199 It fails with an error if one or more of the requested
4200 groups is unavailable in the appliance.
4201
4202 If an unknown group name is included in the
4203 list of groups then an error is always returned.
4204
4205 I<Notes:>
4206
4207 =over 4
4208
4209 =item *
4210
4211 You must call C<guestfs_launch> before calling this function.
4212
4213 The reason is because we don't know what groups are
4214 supported by the appliance/daemon until it is running and can
4215 be queried.
4216
4217 =item *
4218
4219 If a group of functions is available, this does not necessarily
4220 mean that they will work.  You still have to check for errors
4221 when calling individual API functions even if they are
4222 available.
4223
4224 =item *
4225
4226 It is usually the job of distro packagers to build
4227 complete functionality into the libguestfs appliance.
4228 Upstream libguestfs, if built from source with all
4229 requirements satisfied, will support everything.
4230
4231 =item *
4232
4233 This call was added in version C<1.0.80>.  In previous
4234 versions of libguestfs all you could do would be to speculatively
4235 execute a command to find out if the daemon implemented it.
4236 See also C<guestfs_version>.
4237
4238 =back");
4239
4240   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4241    [InitBasicFS, Always, TestOutputBuffer (
4242       [["write_file"; "/src"; "hello, world"; "0"];
4243        ["dd"; "/src"; "/dest"];
4244        ["read_file"; "/dest"]], "hello, world")],
4245    "copy from source to destination using dd",
4246    "\
4247 This command copies from one source device or file C<src>
4248 to another destination device or file C<dest>.  Normally you
4249 would use this to copy to or from a device or partition, for
4250 example to duplicate a filesystem.
4251
4252 If the destination is a device, it must be as large or larger
4253 than the source file or device, otherwise the copy will fail.
4254 This command cannot do partial copies (see C<guestfs_copy_size>).");
4255
4256   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4257    [InitBasicFS, Always, TestOutputInt (
4258       [["write_file"; "/file"; "hello, world"; "0"];
4259        ["filesize"; "/file"]], 12)],
4260    "return the size of the file in bytes",
4261    "\
4262 This command returns the size of C<file> in bytes.
4263
4264 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4265 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4266 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4267
4268   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4269    [InitBasicFSonLVM, Always, TestOutputList (
4270       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4271        ["lvs"]], ["/dev/VG/LV2"])],
4272    "rename an LVM logical volume",
4273    "\
4274 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4275
4276   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4277    [InitBasicFSonLVM, Always, TestOutputList (
4278       [["umount"; "/"];
4279        ["vg_activate"; "false"; "VG"];
4280        ["vgrename"; "VG"; "VG2"];
4281        ["vg_activate"; "true"; "VG2"];
4282        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4283        ["vgs"]], ["VG2"])],
4284    "rename an LVM volume group",
4285    "\
4286 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4287
4288   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4289    [InitISOFS, Always, TestOutputBuffer (
4290       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4291    "list the contents of a single file in an initrd",
4292    "\
4293 This command unpacks the file C<filename> from the initrd file
4294 called C<initrdpath>.  The filename must be given I<without> the
4295 initial C</> character.
4296
4297 For example, in guestfish you could use the following command
4298 to examine the boot script (usually called C</init>)
4299 contained in a Linux initrd or initramfs image:
4300
4301  initrd-cat /boot/initrd-<version>.img init
4302
4303 See also C<guestfs_initrd_list>.");
4304
4305   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4306    [],
4307    "get the UUID of a physical volume",
4308    "\
4309 This command returns the UUID of the LVM PV C<device>.");
4310
4311   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4312    [],
4313    "get the UUID of a volume group",
4314    "\
4315 This command returns the UUID of the LVM VG named C<vgname>.");
4316
4317   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4318    [],
4319    "get the UUID of a logical volume",
4320    "\
4321 This command returns the UUID of the LVM LV C<device>.");
4322
4323   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4324    [],
4325    "get the PV UUIDs containing the volume group",
4326    "\
4327 Given a VG called C<vgname>, this returns the UUIDs of all
4328 the physical volumes that this volume group resides on.
4329
4330 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4331 calls to associate physical volumes and volume groups.
4332
4333 See also C<guestfs_vglvuuids>.");
4334
4335   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4336    [],
4337    "get the LV UUIDs of all LVs in the volume group",
4338    "\
4339 Given a VG called C<vgname>, this returns the UUIDs of all
4340 the logical volumes created in this volume group.
4341
4342 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4343 calls to associate logical volumes and volume groups.
4344
4345 See also C<guestfs_vgpvuuids>.");
4346
4347   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4348    [InitBasicFS, Always, TestOutputBuffer (
4349       [["write_file"; "/src"; "hello, world"; "0"];
4350        ["copy_size"; "/src"; "/dest"; "5"];
4351        ["read_file"; "/dest"]], "hello")],
4352    "copy size bytes from source to destination using dd",
4353    "\
4354 This command copies exactly C<size> bytes from one source device
4355 or file C<src> to another destination device or file C<dest>.
4356
4357 Note this will fail if the source is too short or if the destination
4358 is not large enough.");
4359
4360   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4361    [InitBasicFSonLVM, Always, TestRun (
4362       [["zero_device"; "/dev/VG/LV"]])],
4363    "write zeroes to an entire device",
4364    "\
4365 This command writes zeroes over the entire C<device>.  Compare
4366 with C<guestfs_zero> which just zeroes the first few blocks of
4367 a device.");
4368
4369   ("txz_in", (RErr, [FileIn "tarball"; String "directory"]), 229, [],
4370    [InitBasicFS, Always, TestOutput (
4371       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4372        ["cat"; "/hello"]], "hello\n")],
4373    "unpack compressed tarball to directory",
4374    "\
4375 This command uploads and unpacks local file C<tarball> (an
4376 I<xz compressed> tar file) into C<directory>.");
4377
4378   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4379    [],
4380    "pack directory into compressed tarball",
4381    "\
4382 This command packs the contents of C<directory> and downloads
4383 it to local file C<tarball> (as an xz compressed tar archive).");
4384
4385   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4386    [],
4387    "resize an NTFS filesystem",
4388    "\
4389 This command resizes an NTFS filesystem, expanding or
4390 shrinking it to the size of the underlying device.
4391 See also L<ntfsresize(8)>.");
4392
4393   ("vgscan", (RErr, []), 232, [],
4394    [InitEmpty, Always, TestRun (
4395       [["vgscan"]])],
4396    "rescan for LVM physical volumes, volume groups and logical volumes",
4397    "\
4398 This rescans all block devices and rebuilds the list of LVM
4399 physical volumes, volume groups and logical volumes.");
4400
4401   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4402    [InitEmpty, Always, TestRun (
4403       [["part_init"; "/dev/sda"; "mbr"];
4404        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4405        ["part_del"; "/dev/sda"; "1"]])],
4406    "delete a partition",
4407    "\
4408 This command deletes the partition numbered C<partnum> on C<device>.
4409
4410 Note that in the case of MBR partitioning, deleting an
4411 extended partition also deletes any logical partitions
4412 it contains.");
4413
4414   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4415    [InitEmpty, Always, TestOutputTrue (
4416       [["part_init"; "/dev/sda"; "mbr"];
4417        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4418        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4419        ["part_get_bootable"; "/dev/sda"; "1"]])],
4420    "return true if a partition is bootable",
4421    "\
4422 This command returns true if the partition C<partnum> on
4423 C<device> has the bootable flag set.
4424
4425 See also C<guestfs_part_set_bootable>.");
4426
4427   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4428    [InitEmpty, Always, TestOutputInt (
4429       [["part_init"; "/dev/sda"; "mbr"];
4430        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4431        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4432        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4433    "get the MBR type byte (ID byte) from a partition",
4434    "\
4435 Returns the MBR type byte (also known as the ID byte) from
4436 the numbered partition C<partnum>.
4437
4438 Note that only MBR (old DOS-style) partitions have type bytes.
4439 You will get undefined results for other partition table
4440 types (see C<guestfs_part_get_parttype>).");
4441
4442   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4443    [], (* tested by part_get_mbr_id *)
4444    "set the MBR type byte (ID byte) of a partition",
4445    "\
4446 Sets the MBR type byte (also known as the ID byte) of
4447 the numbered partition C<partnum> to C<idbyte>.  Note
4448 that the type bytes quoted in most documentation are
4449 in fact hexadecimal numbers, but usually documented
4450 without any leading \"0x\" which might be confusing.
4451
4452 Note that only MBR (old DOS-style) partitions have type bytes.
4453 You will get undefined results for other partition table
4454 types (see C<guestfs_part_get_parttype>).");
4455
4456   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4457    [InitISOFS, Always, TestOutput (
4458       [["checksum_device"; "md5"; "/dev/sdd"]],
4459       (Digest.to_hex (Digest.file "images/test.iso")))],
4460    "compute MD5, SHAx or CRC checksum of the contents of a device",
4461    "\
4462 This call computes the MD5, SHAx or CRC checksum of the
4463 contents of the device named C<device>.  For the types of
4464 checksums supported see the C<guestfs_checksum> command.");
4465
4466   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4467    [InitNone, Always, TestRun (
4468       [["part_disk"; "/dev/sda"; "mbr"];
4469        ["pvcreate"; "/dev/sda1"];
4470        ["vgcreate"; "VG"; "/dev/sda1"];
4471        ["lvcreate"; "LV"; "VG"; "10"];
4472        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4473    "expand an LV to fill free space",
4474    "\
4475 This expands an existing logical volume C<lv> so that it fills
4476 C<pc>% of the remaining free space in the volume group.  Commonly
4477 you would call this with pc = 100 which expands the logical volume
4478 as much as possible, using all remaining free space in the volume
4479 group.");
4480
4481   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4482    [], (* XXX Augeas code needs tests. *)
4483    "clear Augeas path",
4484    "\
4485 Set the value associated with C<path> to C<NULL>.  This
4486 is the same as the L<augtool(1)> C<clear> command.");
4487
4488 ]
4489
4490 let all_functions = non_daemon_functions @ daemon_functions
4491
4492 (* In some places we want the functions to be displayed sorted
4493  * alphabetically, so this is useful:
4494  *)
4495 let all_functions_sorted =
4496   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4497                compare n1 n2) all_functions
4498
4499 (* Field types for structures. *)
4500 type field =
4501   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4502   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4503   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4504   | FUInt32
4505   | FInt32
4506   | FUInt64
4507   | FInt64
4508   | FBytes                      (* Any int measure that counts bytes. *)
4509   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4510   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4511
4512 (* Because we generate extra parsing code for LVM command line tools,
4513  * we have to pull out the LVM columns separately here.
4514  *)
4515 let lvm_pv_cols = [
4516   "pv_name", FString;
4517   "pv_uuid", FUUID;
4518   "pv_fmt", FString;
4519   "pv_size", FBytes;
4520   "dev_size", FBytes;
4521   "pv_free", FBytes;
4522   "pv_used", FBytes;
4523   "pv_attr", FString (* XXX *);
4524   "pv_pe_count", FInt64;
4525   "pv_pe_alloc_count", FInt64;
4526   "pv_tags", FString;
4527   "pe_start", FBytes;
4528   "pv_mda_count", FInt64;
4529   "pv_mda_free", FBytes;
4530   (* Not in Fedora 10:
4531      "pv_mda_size", FBytes;
4532   *)
4533 ]
4534 let lvm_vg_cols = [
4535   "vg_name", FString;
4536   "vg_uuid", FUUID;
4537   "vg_fmt", FString;
4538   "vg_attr", FString (* XXX *);
4539   "vg_size", FBytes;
4540   "vg_free", FBytes;
4541   "vg_sysid", FString;
4542   "vg_extent_size", FBytes;
4543   "vg_extent_count", FInt64;
4544   "vg_free_count", FInt64;
4545   "max_lv", FInt64;
4546   "max_pv", FInt64;
4547   "pv_count", FInt64;
4548   "lv_count", FInt64;
4549   "snap_count", FInt64;
4550   "vg_seqno", FInt64;
4551   "vg_tags", FString;
4552   "vg_mda_count", FInt64;
4553   "vg_mda_free", FBytes;
4554   (* Not in Fedora 10:
4555      "vg_mda_size", FBytes;
4556   *)
4557 ]
4558 let lvm_lv_cols = [
4559   "lv_name", FString;
4560   "lv_uuid", FUUID;
4561   "lv_attr", FString (* XXX *);
4562   "lv_major", FInt64;
4563   "lv_minor", FInt64;
4564   "lv_kernel_major", FInt64;
4565   "lv_kernel_minor", FInt64;
4566   "lv_size", FBytes;
4567   "seg_count", FInt64;
4568   "origin", FString;
4569   "snap_percent", FOptPercent;
4570   "copy_percent", FOptPercent;
4571   "move_pv", FString;
4572   "lv_tags", FString;
4573   "mirror_log", FString;
4574   "modules", FString;
4575 ]
4576
4577 (* Names and fields in all structures (in RStruct and RStructList)
4578  * that we support.
4579  *)
4580 let structs = [
4581   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4582    * not use this struct in any new code.
4583    *)
4584   "int_bool", [
4585     "i", FInt32;                (* for historical compatibility *)
4586     "b", FInt32;                (* for historical compatibility *)
4587   ];
4588
4589   (* LVM PVs, VGs, LVs. *)
4590   "lvm_pv", lvm_pv_cols;
4591   "lvm_vg", lvm_vg_cols;
4592   "lvm_lv", lvm_lv_cols;
4593
4594   (* Column names and types from stat structures.
4595    * NB. Can't use things like 'st_atime' because glibc header files
4596    * define some of these as macros.  Ugh.
4597    *)
4598   "stat", [
4599     "dev", FInt64;
4600     "ino", FInt64;
4601     "mode", FInt64;
4602     "nlink", FInt64;
4603     "uid", FInt64;
4604     "gid", FInt64;
4605     "rdev", FInt64;
4606     "size", FInt64;
4607     "blksize", FInt64;
4608     "blocks", FInt64;
4609     "atime", FInt64;
4610     "mtime", FInt64;
4611     "ctime", FInt64;
4612   ];
4613   "statvfs", [
4614     "bsize", FInt64;
4615     "frsize", FInt64;
4616     "blocks", FInt64;
4617     "bfree", FInt64;
4618     "bavail", FInt64;
4619     "files", FInt64;
4620     "ffree", FInt64;
4621     "favail", FInt64;
4622     "fsid", FInt64;
4623     "flag", FInt64;
4624     "namemax", FInt64;
4625   ];
4626
4627   (* Column names in dirent structure. *)
4628   "dirent", [
4629     "ino", FInt64;
4630     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4631     "ftyp", FChar;
4632     "name", FString;
4633   ];
4634
4635   (* Version numbers. *)
4636   "version", [
4637     "major", FInt64;
4638     "minor", FInt64;
4639     "release", FInt64;
4640     "extra", FString;
4641   ];
4642
4643   (* Extended attribute. *)
4644   "xattr", [
4645     "attrname", FString;
4646     "attrval", FBuffer;
4647   ];
4648
4649   (* Inotify events. *)
4650   "inotify_event", [
4651     "in_wd", FInt64;
4652     "in_mask", FUInt32;
4653     "in_cookie", FUInt32;
4654     "in_name", FString;
4655   ];
4656
4657   (* Partition table entry. *)
4658   "partition", [
4659     "part_num", FInt32;
4660     "part_start", FBytes;
4661     "part_end", FBytes;
4662     "part_size", FBytes;
4663   ];
4664 ] (* end of structs *)
4665
4666 (* Ugh, Java has to be different ..
4667  * These names are also used by the Haskell bindings.
4668  *)
4669 let java_structs = [
4670   "int_bool", "IntBool";
4671   "lvm_pv", "PV";
4672   "lvm_vg", "VG";
4673   "lvm_lv", "LV";
4674   "stat", "Stat";
4675   "statvfs", "StatVFS";
4676   "dirent", "Dirent";
4677   "version", "Version";
4678   "xattr", "XAttr";
4679   "inotify_event", "INotifyEvent";
4680   "partition", "Partition";
4681 ]
4682
4683 (* What structs are actually returned. *)
4684 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4685
4686 (* Returns a list of RStruct/RStructList structs that are returned
4687  * by any function.  Each element of returned list is a pair:
4688  *
4689  * (structname, RStructOnly)
4690  *    == there exists function which returns RStruct (_, structname)
4691  * (structname, RStructListOnly)
4692  *    == there exists function which returns RStructList (_, structname)
4693  * (structname, RStructAndList)
4694  *    == there are functions returning both RStruct (_, structname)
4695  *                                      and RStructList (_, structname)
4696  *)
4697 let rstructs_used_by functions =
4698   (* ||| is a "logical OR" for rstructs_used_t *)
4699   let (|||) a b =
4700     match a, b with
4701     | RStructAndList, _
4702     | _, RStructAndList -> RStructAndList
4703     | RStructOnly, RStructListOnly
4704     | RStructListOnly, RStructOnly -> RStructAndList
4705     | RStructOnly, RStructOnly -> RStructOnly
4706     | RStructListOnly, RStructListOnly -> RStructListOnly
4707   in
4708
4709   let h = Hashtbl.create 13 in
4710
4711   (* if elem->oldv exists, update entry using ||| operator,
4712    * else just add elem->newv to the hash
4713    *)
4714   let update elem newv =
4715     try  let oldv = Hashtbl.find h elem in
4716          Hashtbl.replace h elem (newv ||| oldv)
4717     with Not_found -> Hashtbl.add h elem newv
4718   in
4719
4720   List.iter (
4721     fun (_, style, _, _, _, _, _) ->
4722       match fst style with
4723       | RStruct (_, structname) -> update structname RStructOnly
4724       | RStructList (_, structname) -> update structname RStructListOnly
4725       | _ -> ()
4726   ) functions;
4727
4728   (* return key->values as a list of (key,value) *)
4729   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4730
4731 (* Used for testing language bindings. *)
4732 type callt =
4733   | CallString of string
4734   | CallOptString of string option
4735   | CallStringList of string list
4736   | CallInt of int
4737   | CallInt64 of int64
4738   | CallBool of bool
4739
4740 (* Used to memoize the result of pod2text. *)
4741 let pod2text_memo_filename = "src/.pod2text.data"
4742 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4743   try
4744     let chan = open_in pod2text_memo_filename in
4745     let v = input_value chan in
4746     close_in chan;
4747     v
4748   with
4749     _ -> Hashtbl.create 13
4750 let pod2text_memo_updated () =
4751   let chan = open_out pod2text_memo_filename in
4752   output_value chan pod2text_memo;
4753   close_out chan
4754
4755 (* Useful functions.
4756  * Note we don't want to use any external OCaml libraries which
4757  * makes this a bit harder than it should be.
4758  *)
4759 module StringMap = Map.Make (String)
4760
4761 let failwithf fs = ksprintf failwith fs
4762
4763 let unique = let i = ref 0 in fun () -> incr i; !i
4764
4765 let replace_char s c1 c2 =
4766   let s2 = String.copy s in
4767   let r = ref false in
4768   for i = 0 to String.length s2 - 1 do
4769     if String.unsafe_get s2 i = c1 then (
4770       String.unsafe_set s2 i c2;
4771       r := true
4772     )
4773   done;
4774   if not !r then s else s2
4775
4776 let isspace c =
4777   c = ' '
4778   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4779
4780 let triml ?(test = isspace) str =
4781   let i = ref 0 in
4782   let n = ref (String.length str) in
4783   while !n > 0 && test str.[!i]; do
4784     decr n;
4785     incr i
4786   done;
4787   if !i = 0 then str
4788   else String.sub str !i !n
4789
4790 let trimr ?(test = isspace) str =
4791   let n = ref (String.length str) in
4792   while !n > 0 && test str.[!n-1]; do
4793     decr n
4794   done;
4795   if !n = String.length str then str
4796   else String.sub str 0 !n
4797
4798 let trim ?(test = isspace) str =
4799   trimr ~test (triml ~test str)
4800
4801 let rec find s sub =
4802   let len = String.length s in
4803   let sublen = String.length sub in
4804   let rec loop i =
4805     if i <= len-sublen then (
4806       let rec loop2 j =
4807         if j < sublen then (
4808           if s.[i+j] = sub.[j] then loop2 (j+1)
4809           else -1
4810         ) else
4811           i (* found *)
4812       in
4813       let r = loop2 0 in
4814       if r = -1 then loop (i+1) else r
4815     ) else
4816       -1 (* not found *)
4817   in
4818   loop 0
4819
4820 let rec replace_str s s1 s2 =
4821   let len = String.length s in
4822   let sublen = String.length s1 in
4823   let i = find s s1 in
4824   if i = -1 then s
4825   else (
4826     let s' = String.sub s 0 i in
4827     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4828     s' ^ s2 ^ replace_str s'' s1 s2
4829   )
4830
4831 let rec string_split sep str =
4832   let len = String.length str in
4833   let seplen = String.length sep in
4834   let i = find str sep in
4835   if i = -1 then [str]
4836   else (
4837     let s' = String.sub str 0 i in
4838     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4839     s' :: string_split sep s''
4840   )
4841
4842 let files_equal n1 n2 =
4843   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4844   match Sys.command cmd with
4845   | 0 -> true
4846   | 1 -> false
4847   | i -> failwithf "%s: failed with error code %d" cmd i
4848
4849 let rec filter_map f = function
4850   | [] -> []
4851   | x :: xs ->
4852       match f x with
4853       | Some y -> y :: filter_map f xs
4854       | None -> filter_map f xs
4855
4856 let rec find_map f = function
4857   | [] -> raise Not_found
4858   | x :: xs ->
4859       match f x with
4860       | Some y -> y
4861       | None -> find_map f xs
4862
4863 let iteri f xs =
4864   let rec loop i = function
4865     | [] -> ()
4866     | x :: xs -> f i x; loop (i+1) xs
4867   in
4868   loop 0 xs
4869
4870 let mapi f xs =
4871   let rec loop i = function
4872     | [] -> []
4873     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4874   in
4875   loop 0 xs
4876
4877 let count_chars c str =
4878   let count = ref 0 in
4879   for i = 0 to String.length str - 1 do
4880     if c = String.unsafe_get str i then incr count
4881   done;
4882   !count
4883
4884 let name_of_argt = function
4885   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4886   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4887   | FileIn n | FileOut n -> n
4888
4889 let java_name_of_struct typ =
4890   try List.assoc typ java_structs
4891   with Not_found ->
4892     failwithf
4893       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4894
4895 let cols_of_struct typ =
4896   try List.assoc typ structs
4897   with Not_found ->
4898     failwithf "cols_of_struct: unknown struct %s" typ
4899
4900 let seq_of_test = function
4901   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4902   | TestOutputListOfDevices (s, _)
4903   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4904   | TestOutputTrue s | TestOutputFalse s
4905   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4906   | TestOutputStruct (s, _)
4907   | TestLastFail s -> s
4908
4909 (* Handling for function flags. *)
4910 let protocol_limit_warning =
4911   "Because of the message protocol, there is a transfer limit
4912 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4913
4914 let danger_will_robinson =
4915   "B<This command is dangerous.  Without careful use you
4916 can easily destroy all your data>."
4917
4918 let deprecation_notice flags =
4919   try
4920     let alt =
4921       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4922     let txt =
4923       sprintf "This function is deprecated.
4924 In new code, use the C<%s> call instead.
4925
4926 Deprecated functions will not be removed from the API, but the
4927 fact that they are deprecated indicates that there are problems
4928 with correct use of these functions." alt in
4929     Some txt
4930   with
4931     Not_found -> None
4932
4933 (* Create list of optional groups. *)
4934 let optgroups =
4935   let h = Hashtbl.create 13 in
4936   List.iter (
4937     fun (name, _, _, flags, _, _, _) ->
4938       List.iter (
4939         function
4940         | Optional group ->
4941             let names = try Hashtbl.find h group with Not_found -> [] in
4942             Hashtbl.replace h group (name :: names)
4943         | _ -> ()
4944       ) flags
4945   ) daemon_functions;
4946   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4947   let groups =
4948     List.map (
4949       fun group -> group, List.sort compare (Hashtbl.find h group)
4950     ) groups in
4951   List.sort (fun x y -> compare (fst x) (fst y)) groups
4952
4953 (* Check function names etc. for consistency. *)
4954 let check_functions () =
4955   let contains_uppercase str =
4956     let len = String.length str in
4957     let rec loop i =
4958       if i >= len then false
4959       else (
4960         let c = str.[i] in
4961         if c >= 'A' && c <= 'Z' then true
4962         else loop (i+1)
4963       )
4964     in
4965     loop 0
4966   in
4967
4968   (* Check function names. *)
4969   List.iter (
4970     fun (name, _, _, _, _, _, _) ->
4971       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4972         failwithf "function name %s does not need 'guestfs' prefix" name;
4973       if name = "" then
4974         failwithf "function name is empty";
4975       if name.[0] < 'a' || name.[0] > 'z' then
4976         failwithf "function name %s must start with lowercase a-z" name;
4977       if String.contains name '-' then
4978         failwithf "function name %s should not contain '-', use '_' instead."
4979           name
4980   ) all_functions;
4981
4982   (* Check function parameter/return names. *)
4983   List.iter (
4984     fun (name, style, _, _, _, _, _) ->
4985       let check_arg_ret_name n =
4986         if contains_uppercase n then
4987           failwithf "%s param/ret %s should not contain uppercase chars"
4988             name n;
4989         if String.contains n '-' || String.contains n '_' then
4990           failwithf "%s param/ret %s should not contain '-' or '_'"
4991             name n;
4992         if n = "value" then
4993           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;
4994         if n = "int" || n = "char" || n = "short" || n = "long" then
4995           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4996         if n = "i" || n = "n" then
4997           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4998         if n = "argv" || n = "args" then
4999           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5000
5001         (* List Haskell, OCaml and C keywords here.
5002          * http://www.haskell.org/haskellwiki/Keywords
5003          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5004          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5005          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5006          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5007          * Omitting _-containing words, since they're handled above.
5008          * Omitting the OCaml reserved word, "val", is ok,
5009          * and saves us from renaming several parameters.
5010          *)
5011         let reserved = [
5012           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5013           "char"; "class"; "const"; "constraint"; "continue"; "data";
5014           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5015           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5016           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5017           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5018           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5019           "interface";
5020           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5021           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5022           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5023           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5024           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5025           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5026           "volatile"; "when"; "where"; "while";
5027           ] in
5028         if List.mem n reserved then
5029           failwithf "%s has param/ret using reserved word %s" name n;
5030       in
5031
5032       (match fst style with
5033        | RErr -> ()
5034        | RInt n | RInt64 n | RBool n
5035        | RConstString n | RConstOptString n | RString n
5036        | RStringList n | RStruct (n, _) | RStructList (n, _)
5037        | RHashtable n | RBufferOut n ->
5038            check_arg_ret_name n
5039       );
5040       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5041   ) all_functions;
5042
5043   (* Check short descriptions. *)
5044   List.iter (
5045     fun (name, _, _, _, _, shortdesc, _) ->
5046       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5047         failwithf "short description of %s should begin with lowercase." name;
5048       let c = shortdesc.[String.length shortdesc-1] in
5049       if c = '\n' || c = '.' then
5050         failwithf "short description of %s should not end with . or \\n." name
5051   ) all_functions;
5052
5053   (* Check long dscriptions. *)
5054   List.iter (
5055     fun (name, _, _, _, _, _, longdesc) ->
5056       if longdesc.[String.length longdesc-1] = '\n' then
5057         failwithf "long description of %s should not end with \\n." name
5058   ) all_functions;
5059
5060   (* Check proc_nrs. *)
5061   List.iter (
5062     fun (name, _, proc_nr, _, _, _, _) ->
5063       if proc_nr <= 0 then
5064         failwithf "daemon function %s should have proc_nr > 0" name
5065   ) daemon_functions;
5066
5067   List.iter (
5068     fun (name, _, proc_nr, _, _, _, _) ->
5069       if proc_nr <> -1 then
5070         failwithf "non-daemon function %s should have proc_nr -1" name
5071   ) non_daemon_functions;
5072
5073   let proc_nrs =
5074     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5075       daemon_functions in
5076   let proc_nrs =
5077     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5078   let rec loop = function
5079     | [] -> ()
5080     | [_] -> ()
5081     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5082         loop rest
5083     | (name1,nr1) :: (name2,nr2) :: _ ->
5084         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5085           name1 name2 nr1 nr2
5086   in
5087   loop proc_nrs;
5088
5089   (* Check tests. *)
5090   List.iter (
5091     function
5092       (* Ignore functions that have no tests.  We generate a
5093        * warning when the user does 'make check' instead.
5094        *)
5095     | name, _, _, _, [], _, _ -> ()
5096     | name, _, _, _, tests, _, _ ->
5097         let funcs =
5098           List.map (
5099             fun (_, _, test) ->
5100               match seq_of_test test with
5101               | [] ->
5102                   failwithf "%s has a test containing an empty sequence" name
5103               | cmds -> List.map List.hd cmds
5104           ) tests in
5105         let funcs = List.flatten funcs in
5106
5107         let tested = List.mem name funcs in
5108
5109         if not tested then
5110           failwithf "function %s has tests but does not test itself" name
5111   ) all_functions
5112
5113 (* 'pr' prints to the current output file. *)
5114 let chan = ref Pervasives.stdout
5115 let lines = ref 0
5116 let pr fs =
5117   ksprintf
5118     (fun str ->
5119        let i = count_chars '\n' str in
5120        lines := !lines + i;
5121        output_string !chan str
5122     ) fs
5123
5124 let copyright_years =
5125   let this_year = 1900 + (localtime (time ())).tm_year in
5126   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5127
5128 (* Generate a header block in a number of standard styles. *)
5129 type comment_style =
5130     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5131 type license = GPLv2plus | LGPLv2plus
5132
5133 let generate_header ?(extra_inputs = []) comment license =
5134   let inputs = "src/generator.ml" :: extra_inputs in
5135   let c = match comment with
5136     | CStyle ->         pr "/* "; " *"
5137     | CPlusPlusStyle -> pr "// "; "//"
5138     | HashStyle ->      pr "# ";  "#"
5139     | OCamlStyle ->     pr "(* "; " *"
5140     | HaskellStyle ->   pr "{- "; "  " in
5141   pr "libguestfs generated file\n";
5142   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5143   List.iter (pr "%s   %s\n" c) inputs;
5144   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5145   pr "%s\n" c;
5146   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5147   pr "%s\n" c;
5148   (match license with
5149    | GPLv2plus ->
5150        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5151        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5152        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5153        pr "%s (at your option) any later version.\n" c;
5154        pr "%s\n" c;
5155        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5156        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5157        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5158        pr "%s GNU General Public License for more details.\n" c;
5159        pr "%s\n" c;
5160        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5161        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5162        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5163
5164    | LGPLv2plus ->
5165        pr "%s This library is free software; you can redistribute it and/or\n" c;
5166        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5167        pr "%s License as published by the Free Software Foundation; either\n" c;
5168        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5169        pr "%s\n" c;
5170        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5171        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5172        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5173        pr "%s Lesser General Public License for more details.\n" c;
5174        pr "%s\n" c;
5175        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5176        pr "%s License along with this library; if not, write to the Free Software\n" c;
5177        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5178   );
5179   (match comment with
5180    | CStyle -> pr " */\n"
5181    | CPlusPlusStyle
5182    | HashStyle -> ()
5183    | OCamlStyle -> pr " *)\n"
5184    | HaskellStyle -> pr "-}\n"
5185   );
5186   pr "\n"
5187
5188 (* Start of main code generation functions below this line. *)
5189
5190 (* Generate the pod documentation for the C API. *)
5191 let rec generate_actions_pod () =
5192   List.iter (
5193     fun (shortname, style, _, flags, _, _, longdesc) ->
5194       if not (List.mem NotInDocs flags) then (
5195         let name = "guestfs_" ^ shortname in
5196         pr "=head2 %s\n\n" name;
5197         pr " ";
5198         generate_prototype ~extern:false ~handle:"handle" name style;
5199         pr "\n\n";
5200         pr "%s\n\n" longdesc;
5201         (match fst style with
5202          | RErr ->
5203              pr "This function returns 0 on success or -1 on error.\n\n"
5204          | RInt _ ->
5205              pr "On error this function returns -1.\n\n"
5206          | RInt64 _ ->
5207              pr "On error this function returns -1.\n\n"
5208          | RBool _ ->
5209              pr "This function returns a C truth value on success or -1 on error.\n\n"
5210          | RConstString _ ->
5211              pr "This function returns a string, or NULL on error.
5212 The string is owned by the guest handle and must I<not> be freed.\n\n"
5213          | RConstOptString _ ->
5214              pr "This function returns a string which may be NULL.
5215 There is way to return an error from this function.
5216 The string is owned by the guest handle and must I<not> be freed.\n\n"
5217          | RString _ ->
5218              pr "This function returns a string, or NULL on error.
5219 I<The caller must free the returned string after use>.\n\n"
5220          | RStringList _ ->
5221              pr "This function returns a NULL-terminated array of strings
5222 (like L<environ(3)>), or NULL if there was an error.
5223 I<The caller must free the strings and the array after use>.\n\n"
5224          | RStruct (_, typ) ->
5225              pr "This function returns a C<struct guestfs_%s *>,
5226 or NULL if there was an error.
5227 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5228          | RStructList (_, typ) ->
5229              pr "This function returns a C<struct guestfs_%s_list *>
5230 (see E<lt>guestfs-structs.hE<gt>),
5231 or NULL if there was an error.
5232 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5233          | RHashtable _ ->
5234              pr "This function returns a NULL-terminated array of
5235 strings, or NULL if there was an error.
5236 The array of strings will always have length C<2n+1>, where
5237 C<n> keys and values alternate, followed by the trailing NULL entry.
5238 I<The caller must free the strings and the array after use>.\n\n"
5239          | RBufferOut _ ->
5240              pr "This function returns a buffer, or NULL on error.
5241 The size of the returned buffer is written to C<*size_r>.
5242 I<The caller must free the returned buffer after use>.\n\n"
5243         );
5244         if List.mem ProtocolLimitWarning flags then
5245           pr "%s\n\n" protocol_limit_warning;
5246         if List.mem DangerWillRobinson flags then
5247           pr "%s\n\n" danger_will_robinson;
5248         match deprecation_notice flags with
5249         | None -> ()
5250         | Some txt -> pr "%s\n\n" txt
5251       )
5252   ) all_functions_sorted
5253
5254 and generate_structs_pod () =
5255   (* Structs documentation. *)
5256   List.iter (
5257     fun (typ, cols) ->
5258       pr "=head2 guestfs_%s\n" typ;
5259       pr "\n";
5260       pr " struct guestfs_%s {\n" typ;
5261       List.iter (
5262         function
5263         | name, FChar -> pr "   char %s;\n" name
5264         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5265         | name, FInt32 -> pr "   int32_t %s;\n" name
5266         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5267         | name, FInt64 -> pr "   int64_t %s;\n" name
5268         | name, FString -> pr "   char *%s;\n" name
5269         | name, FBuffer ->
5270             pr "   /* The next two fields describe a byte array. */\n";
5271             pr "   uint32_t %s_len;\n" name;
5272             pr "   char *%s;\n" name
5273         | name, FUUID ->
5274             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5275             pr "   char %s[32];\n" name
5276         | name, FOptPercent ->
5277             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5278             pr "   float %s;\n" name
5279       ) cols;
5280       pr " };\n";
5281       pr " \n";
5282       pr " struct guestfs_%s_list {\n" typ;
5283       pr "   uint32_t len; /* Number of elements in list. */\n";
5284       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5285       pr " };\n";
5286       pr " \n";
5287       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5288       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5289         typ typ;
5290       pr "\n"
5291   ) structs
5292
5293 and generate_availability_pod () =
5294   (* Availability documentation. *)
5295   pr "=over 4\n";
5296   pr "\n";
5297   List.iter (
5298     fun (group, functions) ->
5299       pr "=item B<%s>\n" group;
5300       pr "\n";
5301       pr "The following functions:\n";
5302       List.iter (pr "L</guestfs_%s>\n") functions;
5303       pr "\n"
5304   ) optgroups;
5305   pr "=back\n";
5306   pr "\n"
5307
5308 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5309  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5310  *
5311  * We have to use an underscore instead of a dash because otherwise
5312  * rpcgen generates incorrect code.
5313  *
5314  * This header is NOT exported to clients, but see also generate_structs_h.
5315  *)
5316 and generate_xdr () =
5317   generate_header CStyle LGPLv2plus;
5318
5319   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5320   pr "typedef string str<>;\n";
5321   pr "\n";
5322
5323   (* Internal structures. *)
5324   List.iter (
5325     function
5326     | typ, cols ->
5327         pr "struct guestfs_int_%s {\n" typ;
5328         List.iter (function
5329                    | name, FChar -> pr "  char %s;\n" name
5330                    | name, FString -> pr "  string %s<>;\n" name
5331                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5332                    | name, FUUID -> pr "  opaque %s[32];\n" name
5333                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5334                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5335                    | name, FOptPercent -> pr "  float %s;\n" name
5336                   ) cols;
5337         pr "};\n";
5338         pr "\n";
5339         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5340         pr "\n";
5341   ) structs;
5342
5343   List.iter (
5344     fun (shortname, style, _, _, _, _, _) ->
5345       let name = "guestfs_" ^ shortname in
5346
5347       (match snd style with
5348        | [] -> ()
5349        | args ->
5350            pr "struct %s_args {\n" name;
5351            List.iter (
5352              function
5353              | Pathname n | Device n | Dev_or_Path n | String n ->
5354                  pr "  string %s<>;\n" n
5355              | OptString n -> pr "  str *%s;\n" n
5356              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5357              | Bool n -> pr "  bool %s;\n" n
5358              | Int n -> pr "  int %s;\n" n
5359              | Int64 n -> pr "  hyper %s;\n" n
5360              | FileIn _ | FileOut _ -> ()
5361            ) args;
5362            pr "};\n\n"
5363       );
5364       (match fst style with
5365        | RErr -> ()
5366        | RInt n ->
5367            pr "struct %s_ret {\n" name;
5368            pr "  int %s;\n" n;
5369            pr "};\n\n"
5370        | RInt64 n ->
5371            pr "struct %s_ret {\n" name;
5372            pr "  hyper %s;\n" n;
5373            pr "};\n\n"
5374        | RBool n ->
5375            pr "struct %s_ret {\n" name;
5376            pr "  bool %s;\n" n;
5377            pr "};\n\n"
5378        | RConstString _ | RConstOptString _ ->
5379            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5380        | RString n ->
5381            pr "struct %s_ret {\n" name;
5382            pr "  string %s<>;\n" n;
5383            pr "};\n\n"
5384        | RStringList n ->
5385            pr "struct %s_ret {\n" name;
5386            pr "  str %s<>;\n" n;
5387            pr "};\n\n"
5388        | RStruct (n, typ) ->
5389            pr "struct %s_ret {\n" name;
5390            pr "  guestfs_int_%s %s;\n" typ n;
5391            pr "};\n\n"
5392        | RStructList (n, typ) ->
5393            pr "struct %s_ret {\n" name;
5394            pr "  guestfs_int_%s_list %s;\n" typ n;
5395            pr "};\n\n"
5396        | RHashtable n ->
5397            pr "struct %s_ret {\n" name;
5398            pr "  str %s<>;\n" n;
5399            pr "};\n\n"
5400        | RBufferOut n ->
5401            pr "struct %s_ret {\n" name;
5402            pr "  opaque %s<>;\n" n;
5403            pr "};\n\n"
5404       );
5405   ) daemon_functions;
5406
5407   (* Table of procedure numbers. *)
5408   pr "enum guestfs_procedure {\n";
5409   List.iter (
5410     fun (shortname, _, proc_nr, _, _, _, _) ->
5411       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5412   ) daemon_functions;
5413   pr "  GUESTFS_PROC_NR_PROCS\n";
5414   pr "};\n";
5415   pr "\n";
5416
5417   (* Having to choose a maximum message size is annoying for several
5418    * reasons (it limits what we can do in the API), but it (a) makes
5419    * the protocol a lot simpler, and (b) provides a bound on the size
5420    * of the daemon which operates in limited memory space.
5421    *)
5422   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5423   pr "\n";
5424
5425   (* Message header, etc. *)
5426   pr "\
5427 /* The communication protocol is now documented in the guestfs(3)
5428  * manpage.
5429  */
5430
5431 const GUESTFS_PROGRAM = 0x2000F5F5;
5432 const GUESTFS_PROTOCOL_VERSION = 1;
5433
5434 /* These constants must be larger than any possible message length. */
5435 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5436 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5437
5438 enum guestfs_message_direction {
5439   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5440   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5441 };
5442
5443 enum guestfs_message_status {
5444   GUESTFS_STATUS_OK = 0,
5445   GUESTFS_STATUS_ERROR = 1
5446 };
5447
5448 const GUESTFS_ERROR_LEN = 256;
5449
5450 struct guestfs_message_error {
5451   string error_message<GUESTFS_ERROR_LEN>;
5452 };
5453
5454 struct guestfs_message_header {
5455   unsigned prog;                     /* GUESTFS_PROGRAM */
5456   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5457   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5458   guestfs_message_direction direction;
5459   unsigned serial;                   /* message serial number */
5460   guestfs_message_status status;
5461 };
5462
5463 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5464
5465 struct guestfs_chunk {
5466   int cancel;                        /* if non-zero, transfer is cancelled */
5467   /* data size is 0 bytes if the transfer has finished successfully */
5468   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5469 };
5470 "
5471
5472 (* Generate the guestfs-structs.h file. *)
5473 and generate_structs_h () =
5474   generate_header CStyle LGPLv2plus;
5475
5476   (* This is a public exported header file containing various
5477    * structures.  The structures are carefully written to have
5478    * exactly the same in-memory format as the XDR structures that
5479    * we use on the wire to the daemon.  The reason for creating
5480    * copies of these structures here is just so we don't have to
5481    * export the whole of guestfs_protocol.h (which includes much
5482    * unrelated and XDR-dependent stuff that we don't want to be
5483    * public, or required by clients).
5484    *
5485    * To reiterate, we will pass these structures to and from the
5486    * client with a simple assignment or memcpy, so the format
5487    * must be identical to what rpcgen / the RFC defines.
5488    *)
5489
5490   (* Public structures. *)
5491   List.iter (
5492     fun (typ, cols) ->
5493       pr "struct guestfs_%s {\n" typ;
5494       List.iter (
5495         function
5496         | name, FChar -> pr "  char %s;\n" name
5497         | name, FString -> pr "  char *%s;\n" name
5498         | name, FBuffer ->
5499             pr "  uint32_t %s_len;\n" name;
5500             pr "  char *%s;\n" name
5501         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5502         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5503         | name, FInt32 -> pr "  int32_t %s;\n" name
5504         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5505         | name, FInt64 -> pr "  int64_t %s;\n" name
5506         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5507       ) cols;
5508       pr "};\n";
5509       pr "\n";
5510       pr "struct guestfs_%s_list {\n" typ;
5511       pr "  uint32_t len;\n";
5512       pr "  struct guestfs_%s *val;\n" typ;
5513       pr "};\n";
5514       pr "\n";
5515       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5516       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5517       pr "\n"
5518   ) structs
5519
5520 (* Generate the guestfs-actions.h file. *)
5521 and generate_actions_h () =
5522   generate_header CStyle LGPLv2plus;
5523   List.iter (
5524     fun (shortname, style, _, _, _, _, _) ->
5525       let name = "guestfs_" ^ shortname in
5526       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5527         name style
5528   ) all_functions
5529
5530 (* Generate the guestfs-internal-actions.h file. *)
5531 and generate_internal_actions_h () =
5532   generate_header CStyle LGPLv2plus;
5533   List.iter (
5534     fun (shortname, style, _, _, _, _, _) ->
5535       let name = "guestfs__" ^ shortname in
5536       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5537         name style
5538   ) non_daemon_functions
5539
5540 (* Generate the client-side dispatch stubs. *)
5541 and generate_client_actions () =
5542   generate_header CStyle LGPLv2plus;
5543
5544   pr "\
5545 #include <stdio.h>
5546 #include <stdlib.h>
5547 #include <stdint.h>
5548 #include <string.h>
5549 #include <inttypes.h>
5550
5551 #include \"guestfs.h\"
5552 #include \"guestfs-internal.h\"
5553 #include \"guestfs-internal-actions.h\"
5554 #include \"guestfs_protocol.h\"
5555
5556 #define error guestfs_error
5557 //#define perrorf guestfs_perrorf
5558 #define safe_malloc guestfs_safe_malloc
5559 #define safe_realloc guestfs_safe_realloc
5560 //#define safe_strdup guestfs_safe_strdup
5561 #define safe_memdup guestfs_safe_memdup
5562
5563 /* Check the return message from a call for validity. */
5564 static int
5565 check_reply_header (guestfs_h *g,
5566                     const struct guestfs_message_header *hdr,
5567                     unsigned int proc_nr, unsigned int serial)
5568 {
5569   if (hdr->prog != GUESTFS_PROGRAM) {
5570     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5571     return -1;
5572   }
5573   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5574     error (g, \"wrong protocol version (%%d/%%d)\",
5575            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5576     return -1;
5577   }
5578   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5579     error (g, \"unexpected message direction (%%d/%%d)\",
5580            hdr->direction, GUESTFS_DIRECTION_REPLY);
5581     return -1;
5582   }
5583   if (hdr->proc != proc_nr) {
5584     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5585     return -1;
5586   }
5587   if (hdr->serial != serial) {
5588     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5589     return -1;
5590   }
5591
5592   return 0;
5593 }
5594
5595 /* Check we are in the right state to run a high-level action. */
5596 static int
5597 check_state (guestfs_h *g, const char *caller)
5598 {
5599   if (!guestfs__is_ready (g)) {
5600     if (guestfs__is_config (g) || guestfs__is_launching (g))
5601       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5602         caller);
5603     else
5604       error (g, \"%%s called from the wrong state, %%d != READY\",
5605         caller, guestfs__get_state (g));
5606     return -1;
5607   }
5608   return 0;
5609 }
5610
5611 ";
5612
5613   (* Generate code to generate guestfish call traces. *)
5614   let trace_call shortname style =
5615     pr "  if (guestfs__get_trace (g)) {\n";
5616
5617     let needs_i =
5618       List.exists (function
5619                    | StringList _ | DeviceList _ -> true
5620                    | _ -> false) (snd style) in
5621     if needs_i then (
5622       pr "    int i;\n";
5623       pr "\n"
5624     );
5625
5626     pr "    printf (\"%s\");\n" shortname;
5627     List.iter (
5628       function
5629       | String n                        (* strings *)
5630       | Device n
5631       | Pathname n
5632       | Dev_or_Path n
5633       | FileIn n
5634       | FileOut n ->
5635           (* guestfish doesn't support string escaping, so neither do we *)
5636           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5637       | OptString n ->                  (* string option *)
5638           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5639           pr "    else printf (\" null\");\n"
5640       | StringList n
5641       | DeviceList n ->                 (* string list *)
5642           pr "    putchar (' ');\n";
5643           pr "    putchar ('\"');\n";
5644           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5645           pr "      if (i > 0) putchar (' ');\n";
5646           pr "      fputs (%s[i], stdout);\n" n;
5647           pr "    }\n";
5648           pr "    putchar ('\"');\n";
5649       | Bool n ->                       (* boolean *)
5650           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5651       | Int n ->                        (* int *)
5652           pr "    printf (\" %%d\", %s);\n" n
5653       | Int64 n ->
5654           pr "    printf (\" %%\" PRIi64, %s);\n" n
5655     ) (snd style);
5656     pr "    putchar ('\\n');\n";
5657     pr "  }\n";
5658     pr "\n";
5659   in
5660
5661   (* For non-daemon functions, generate a wrapper around each function. *)
5662   List.iter (
5663     fun (shortname, style, _, _, _, _, _) ->
5664       let name = "guestfs_" ^ shortname in
5665
5666       generate_prototype ~extern:false ~semicolon:false ~newline:true
5667         ~handle:"g" name style;
5668       pr "{\n";
5669       trace_call shortname style;
5670       pr "  return guestfs__%s " shortname;
5671       generate_c_call_args ~handle:"g" style;
5672       pr ";\n";
5673       pr "}\n";
5674       pr "\n"
5675   ) non_daemon_functions;
5676
5677   (* Client-side stubs for each function. *)
5678   List.iter (
5679     fun (shortname, style, _, _, _, _, _) ->
5680       let name = "guestfs_" ^ shortname in
5681
5682       (* Generate the action stub. *)
5683       generate_prototype ~extern:false ~semicolon:false ~newline:true
5684         ~handle:"g" name style;
5685
5686       let error_code =
5687         match fst style with
5688         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5689         | RConstString _ | RConstOptString _ ->
5690             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5691         | RString _ | RStringList _
5692         | RStruct _ | RStructList _
5693         | RHashtable _ | RBufferOut _ ->
5694             "NULL" in
5695
5696       pr "{\n";
5697
5698       (match snd style with
5699        | [] -> ()
5700        | _ -> pr "  struct %s_args args;\n" name
5701       );
5702
5703       pr "  guestfs_message_header hdr;\n";
5704       pr "  guestfs_message_error err;\n";
5705       let has_ret =
5706         match fst style with
5707         | RErr -> false
5708         | RConstString _ | RConstOptString _ ->
5709             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5710         | RInt _ | RInt64 _
5711         | RBool _ | RString _ | RStringList _
5712         | RStruct _ | RStructList _
5713         | RHashtable _ | RBufferOut _ ->
5714             pr "  struct %s_ret ret;\n" name;
5715             true in
5716
5717       pr "  int serial;\n";
5718       pr "  int r;\n";
5719       pr "\n";
5720       trace_call shortname style;
5721       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5722       pr "  guestfs___set_busy (g);\n";
5723       pr "\n";
5724
5725       (* Send the main header and arguments. *)
5726       (match snd style with
5727        | [] ->
5728            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5729              (String.uppercase shortname)
5730        | args ->
5731            List.iter (
5732              function
5733              | Pathname n | Device n | Dev_or_Path n | String n ->
5734                  pr "  args.%s = (char *) %s;\n" n n
5735              | OptString n ->
5736                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5737              | StringList n | DeviceList n ->
5738                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5739                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5740              | Bool n ->
5741                  pr "  args.%s = %s;\n" n n
5742              | Int n ->
5743                  pr "  args.%s = %s;\n" n n
5744              | Int64 n ->
5745                  pr "  args.%s = %s;\n" n n
5746              | FileIn _ | FileOut _ -> ()
5747            ) args;
5748            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5749              (String.uppercase shortname);
5750            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5751              name;
5752       );
5753       pr "  if (serial == -1) {\n";
5754       pr "    guestfs___end_busy (g);\n";
5755       pr "    return %s;\n" error_code;
5756       pr "  }\n";
5757       pr "\n";
5758
5759       (* Send any additional files (FileIn) requested. *)
5760       let need_read_reply_label = ref false in
5761       List.iter (
5762         function
5763         | FileIn n ->
5764             pr "  r = guestfs___send_file (g, %s);\n" n;
5765             pr "  if (r == -1) {\n";
5766             pr "    guestfs___end_busy (g);\n";
5767             pr "    return %s;\n" error_code;
5768             pr "  }\n";
5769             pr "  if (r == -2) /* daemon cancelled */\n";
5770             pr "    goto read_reply;\n";
5771             need_read_reply_label := true;
5772             pr "\n";
5773         | _ -> ()
5774       ) (snd style);
5775
5776       (* Wait for the reply from the remote end. *)
5777       if !need_read_reply_label then pr " read_reply:\n";
5778       pr "  memset (&hdr, 0, sizeof hdr);\n";
5779       pr "  memset (&err, 0, sizeof err);\n";
5780       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5781       pr "\n";
5782       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5783       if not has_ret then
5784         pr "NULL, NULL"
5785       else
5786         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5787       pr ");\n";
5788
5789       pr "  if (r == -1) {\n";
5790       pr "    guestfs___end_busy (g);\n";
5791       pr "    return %s;\n" error_code;
5792       pr "  }\n";
5793       pr "\n";
5794
5795       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5796         (String.uppercase shortname);
5797       pr "    guestfs___end_busy (g);\n";
5798       pr "    return %s;\n" error_code;
5799       pr "  }\n";
5800       pr "\n";
5801
5802       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5803       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5804       pr "    free (err.error_message);\n";
5805       pr "    guestfs___end_busy (g);\n";
5806       pr "    return %s;\n" error_code;
5807       pr "  }\n";
5808       pr "\n";
5809
5810       (* Expecting to receive further files (FileOut)? *)
5811       List.iter (
5812         function
5813         | FileOut n ->
5814             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5815             pr "    guestfs___end_busy (g);\n";
5816             pr "    return %s;\n" error_code;
5817             pr "  }\n";
5818             pr "\n";
5819         | _ -> ()
5820       ) (snd style);
5821
5822       pr "  guestfs___end_busy (g);\n";
5823
5824       (match fst style with
5825        | RErr -> pr "  return 0;\n"
5826        | RInt n | RInt64 n | RBool n ->
5827            pr "  return ret.%s;\n" n
5828        | RConstString _ | RConstOptString _ ->
5829            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5830        | RString n ->
5831            pr "  return ret.%s; /* caller will free */\n" n
5832        | RStringList n | RHashtable n ->
5833            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5834            pr "  ret.%s.%s_val =\n" n n;
5835            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5836            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5837              n n;
5838            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5839            pr "  return ret.%s.%s_val;\n" n n
5840        | RStruct (n, _) ->
5841            pr "  /* caller will free this */\n";
5842            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5843        | RStructList (n, _) ->
5844            pr "  /* caller will free this */\n";
5845            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5846        | RBufferOut n ->
5847            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5848            pr "   * _val might be NULL here.  To make the API saner for\n";
5849            pr "   * callers, we turn this case into a unique pointer (using\n";
5850            pr "   * malloc(1)).\n";
5851            pr "   */\n";
5852            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5853            pr "    *size_r = ret.%s.%s_len;\n" n n;
5854            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5855            pr "  } else {\n";
5856            pr "    free (ret.%s.%s_val);\n" n n;
5857            pr "    char *p = safe_malloc (g, 1);\n";
5858            pr "    *size_r = ret.%s.%s_len;\n" n n;
5859            pr "    return p;\n";
5860            pr "  }\n";
5861       );
5862
5863       pr "}\n\n"
5864   ) daemon_functions;
5865
5866   (* Functions to free structures. *)
5867   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5868   pr " * structure format is identical to the XDR format.  See note in\n";
5869   pr " * generator.ml.\n";
5870   pr " */\n";
5871   pr "\n";
5872
5873   List.iter (
5874     fun (typ, _) ->
5875       pr "void\n";
5876       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5877       pr "{\n";
5878       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5879       pr "  free (x);\n";
5880       pr "}\n";
5881       pr "\n";
5882
5883       pr "void\n";
5884       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5885       pr "{\n";
5886       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5887       pr "  free (x);\n";
5888       pr "}\n";
5889       pr "\n";
5890
5891   ) structs;
5892
5893 (* Generate daemon/actions.h. *)
5894 and generate_daemon_actions_h () =
5895   generate_header CStyle GPLv2plus;
5896
5897   pr "#include \"../src/guestfs_protocol.h\"\n";
5898   pr "\n";
5899
5900   List.iter (
5901     fun (name, style, _, _, _, _, _) ->
5902       generate_prototype
5903         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5904         name style;
5905   ) daemon_functions
5906
5907 (* Generate the linker script which controls the visibility of
5908  * symbols in the public ABI and ensures no other symbols get
5909  * exported accidentally.
5910  *)
5911 and generate_linker_script () =
5912   generate_header HashStyle GPLv2plus;
5913
5914   let globals = [
5915     "guestfs_create";
5916     "guestfs_close";
5917     "guestfs_get_error_handler";
5918     "guestfs_get_out_of_memory_handler";
5919     "guestfs_last_error";
5920     "guestfs_set_error_handler";
5921     "guestfs_set_launch_done_callback";
5922     "guestfs_set_log_message_callback";
5923     "guestfs_set_out_of_memory_handler";
5924     "guestfs_set_subprocess_quit_callback";
5925
5926     (* Unofficial parts of the API: the bindings code use these
5927      * functions, so it is useful to export them.
5928      *)
5929     "guestfs_safe_calloc";
5930     "guestfs_safe_malloc";
5931   ] in
5932   let functions =
5933     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5934       all_functions in
5935   let structs =
5936     List.concat (
5937       List.map (fun (typ, _) ->
5938                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5939         structs
5940     ) in
5941   let globals = List.sort compare (globals @ functions @ structs) in
5942
5943   pr "{\n";
5944   pr "    global:\n";
5945   List.iter (pr "        %s;\n") globals;
5946   pr "\n";
5947
5948   pr "    local:\n";
5949   pr "        *;\n";
5950   pr "};\n"
5951
5952 (* Generate the server-side stubs. *)
5953 and generate_daemon_actions () =
5954   generate_header CStyle GPLv2plus;
5955
5956   pr "#include <config.h>\n";
5957   pr "\n";
5958   pr "#include <stdio.h>\n";
5959   pr "#include <stdlib.h>\n";
5960   pr "#include <string.h>\n";
5961   pr "#include <inttypes.h>\n";
5962   pr "#include <rpc/types.h>\n";
5963   pr "#include <rpc/xdr.h>\n";
5964   pr "\n";
5965   pr "#include \"daemon.h\"\n";
5966   pr "#include \"c-ctype.h\"\n";
5967   pr "#include \"../src/guestfs_protocol.h\"\n";
5968   pr "#include \"actions.h\"\n";
5969   pr "\n";
5970
5971   List.iter (
5972     fun (name, style, _, _, _, _, _) ->
5973       (* Generate server-side stubs. *)
5974       pr "static void %s_stub (XDR *xdr_in)\n" name;
5975       pr "{\n";
5976       let error_code =
5977         match fst style with
5978         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5979         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5980         | RBool _ -> pr "  int r;\n"; "-1"
5981         | RConstString _ | RConstOptString _ ->
5982             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5983         | RString _ -> pr "  char *r;\n"; "NULL"
5984         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5985         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5986         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5987         | RBufferOut _ ->
5988             pr "  size_t size = 1;\n";
5989             pr "  char *r;\n";
5990             "NULL" in
5991
5992       (match snd style with
5993        | [] -> ()
5994        | args ->
5995            pr "  struct guestfs_%s_args args;\n" name;
5996            List.iter (
5997              function
5998              | Device n | Dev_or_Path n
5999              | Pathname n
6000              | String n -> ()
6001              | OptString n -> pr "  char *%s;\n" n
6002              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6003              | Bool n -> pr "  int %s;\n" n
6004              | Int n -> pr "  int %s;\n" n
6005              | Int64 n -> pr "  int64_t %s;\n" n
6006              | FileIn _ | FileOut _ -> ()
6007            ) args
6008       );
6009       pr "\n";
6010
6011       (match snd style with
6012        | [] -> ()
6013        | args ->
6014            pr "  memset (&args, 0, sizeof args);\n";
6015            pr "\n";
6016            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6017            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6018            pr "    return;\n";
6019            pr "  }\n";
6020            let pr_args n =
6021              pr "  char *%s = args.%s;\n" n n
6022            in
6023            let pr_list_handling_code n =
6024              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6025              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6026              pr "  if (%s == NULL) {\n" n;
6027              pr "    reply_with_perror (\"realloc\");\n";
6028              pr "    goto done;\n";
6029              pr "  }\n";
6030              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6031              pr "  args.%s.%s_val = %s;\n" n n n;
6032            in
6033            List.iter (
6034              function
6035              | Pathname n ->
6036                  pr_args n;
6037                  pr "  ABS_PATH (%s, goto done);\n" n;
6038              | Device n ->
6039                  pr_args n;
6040                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
6041              | Dev_or_Path n ->
6042                  pr_args n;
6043                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6044              | String n -> pr_args n
6045              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6046              | StringList n ->
6047                  pr_list_handling_code n;
6048              | DeviceList n ->
6049                  pr_list_handling_code n;
6050                  pr "  /* Ensure that each is a device,\n";
6051                  pr "   * and perform device name translation. */\n";
6052                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6053                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6054                  pr "  }\n";
6055              | Bool n -> pr "  %s = args.%s;\n" n n
6056              | Int n -> pr "  %s = args.%s;\n" n n
6057              | Int64 n -> pr "  %s = args.%s;\n" n n
6058              | FileIn _ | FileOut _ -> ()
6059            ) args;
6060            pr "\n"
6061       );
6062
6063
6064       (* this is used at least for do_equal *)
6065       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6066         (* Emit NEED_ROOT just once, even when there are two or
6067            more Pathname args *)
6068         pr "  NEED_ROOT (goto done);\n";
6069       );
6070
6071       (* Don't want to call the impl with any FileIn or FileOut
6072        * parameters, since these go "outside" the RPC protocol.
6073        *)
6074       let args' =
6075         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6076           (snd style) in
6077       pr "  r = do_%s " name;
6078       generate_c_call_args (fst style, args');
6079       pr ";\n";
6080
6081       (match fst style with
6082        | RErr | RInt _ | RInt64 _ | RBool _
6083        | RConstString _ | RConstOptString _
6084        | RString _ | RStringList _ | RHashtable _
6085        | RStruct (_, _) | RStructList (_, _) ->
6086            pr "  if (r == %s)\n" error_code;
6087            pr "    /* do_%s has already called reply_with_error */\n" name;
6088            pr "    goto done;\n";
6089            pr "\n"
6090        | RBufferOut _ ->
6091            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6092            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6093            pr "   */\n";
6094            pr "  if (size == 1 && r == %s)\n" error_code;
6095            pr "    /* do_%s has already called reply_with_error */\n" name;
6096            pr "    goto done;\n";
6097            pr "\n"
6098       );
6099
6100       (* If there are any FileOut parameters, then the impl must
6101        * send its own reply.
6102        *)
6103       let no_reply =
6104         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6105       if no_reply then
6106         pr "  /* do_%s has already sent a reply */\n" name
6107       else (
6108         match fst style with
6109         | RErr -> pr "  reply (NULL, NULL);\n"
6110         | RInt n | RInt64 n | RBool n ->
6111             pr "  struct guestfs_%s_ret ret;\n" name;
6112             pr "  ret.%s = r;\n" n;
6113             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6114               name
6115         | RConstString _ | RConstOptString _ ->
6116             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6117         | RString n ->
6118             pr "  struct guestfs_%s_ret ret;\n" name;
6119             pr "  ret.%s = r;\n" n;
6120             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6121               name;
6122             pr "  free (r);\n"
6123         | RStringList n | RHashtable n ->
6124             pr "  struct guestfs_%s_ret ret;\n" name;
6125             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6126             pr "  ret.%s.%s_val = r;\n" n n;
6127             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6128               name;
6129             pr "  free_strings (r);\n"
6130         | RStruct (n, _) ->
6131             pr "  struct guestfs_%s_ret ret;\n" name;
6132             pr "  ret.%s = *r;\n" n;
6133             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6134               name;
6135             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6136               name
6137         | RStructList (n, _) ->
6138             pr "  struct guestfs_%s_ret ret;\n" name;
6139             pr "  ret.%s = *r;\n" n;
6140             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6141               name;
6142             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6143               name
6144         | RBufferOut n ->
6145             pr "  struct guestfs_%s_ret ret;\n" name;
6146             pr "  ret.%s.%s_val = r;\n" n n;
6147             pr "  ret.%s.%s_len = size;\n" n n;
6148             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6149               name;
6150             pr "  free (r);\n"
6151       );
6152
6153       (* Free the args. *)
6154       (match snd style with
6155        | [] ->
6156            pr "done: ;\n";
6157        | _ ->
6158            pr "done:\n";
6159            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6160              name
6161       );
6162
6163       pr "}\n\n";
6164   ) daemon_functions;
6165
6166   (* Dispatch function. *)
6167   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6168   pr "{\n";
6169   pr "  switch (proc_nr) {\n";
6170
6171   List.iter (
6172     fun (name, style, _, _, _, _, _) ->
6173       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6174       pr "      %s_stub (xdr_in);\n" name;
6175       pr "      break;\n"
6176   ) daemon_functions;
6177
6178   pr "    default:\n";
6179   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";
6180   pr "  }\n";
6181   pr "}\n";
6182   pr "\n";
6183
6184   (* LVM columns and tokenization functions. *)
6185   (* XXX This generates crap code.  We should rethink how we
6186    * do this parsing.
6187    *)
6188   List.iter (
6189     function
6190     | typ, cols ->
6191         pr "static const char *lvm_%s_cols = \"%s\";\n"
6192           typ (String.concat "," (List.map fst cols));
6193         pr "\n";
6194
6195         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6196         pr "{\n";
6197         pr "  char *tok, *p, *next;\n";
6198         pr "  int i, j;\n";
6199         pr "\n";
6200         (*
6201           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6202           pr "\n";
6203         *)
6204         pr "  if (!str) {\n";
6205         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6206         pr "    return -1;\n";
6207         pr "  }\n";
6208         pr "  if (!*str || c_isspace (*str)) {\n";
6209         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6210         pr "    return -1;\n";
6211         pr "  }\n";
6212         pr "  tok = str;\n";
6213         List.iter (
6214           fun (name, coltype) ->
6215             pr "  if (!tok) {\n";
6216             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6217             pr "    return -1;\n";
6218             pr "  }\n";
6219             pr "  p = strchrnul (tok, ',');\n";
6220             pr "  if (*p) next = p+1; else next = NULL;\n";
6221             pr "  *p = '\\0';\n";
6222             (match coltype with
6223              | FString ->
6224                  pr "  r->%s = strdup (tok);\n" name;
6225                  pr "  if (r->%s == NULL) {\n" name;
6226                  pr "    perror (\"strdup\");\n";
6227                  pr "    return -1;\n";
6228                  pr "  }\n"
6229              | FUUID ->
6230                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6231                  pr "    if (tok[j] == '\\0') {\n";
6232                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6233                  pr "      return -1;\n";
6234                  pr "    } else if (tok[j] != '-')\n";
6235                  pr "      r->%s[i++] = tok[j];\n" name;
6236                  pr "  }\n";
6237              | FBytes ->
6238                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6239                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6240                  pr "    return -1;\n";
6241                  pr "  }\n";
6242              | FInt64 ->
6243                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6244                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6245                  pr "    return -1;\n";
6246                  pr "  }\n";
6247              | FOptPercent ->
6248                  pr "  if (tok[0] == '\\0')\n";
6249                  pr "    r->%s = -1;\n" name;
6250                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6251                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6252                  pr "    return -1;\n";
6253                  pr "  }\n";
6254              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6255                  assert false (* can never be an LVM column *)
6256             );
6257             pr "  tok = next;\n";
6258         ) cols;
6259
6260         pr "  if (tok != NULL) {\n";
6261         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6262         pr "    return -1;\n";
6263         pr "  }\n";
6264         pr "  return 0;\n";
6265         pr "}\n";
6266         pr "\n";
6267
6268         pr "guestfs_int_lvm_%s_list *\n" typ;
6269         pr "parse_command_line_%ss (void)\n" typ;
6270         pr "{\n";
6271         pr "  char *out, *err;\n";
6272         pr "  char *p, *pend;\n";
6273         pr "  int r, i;\n";
6274         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6275         pr "  void *newp;\n";
6276         pr "\n";
6277         pr "  ret = malloc (sizeof *ret);\n";
6278         pr "  if (!ret) {\n";
6279         pr "    reply_with_perror (\"malloc\");\n";
6280         pr "    return NULL;\n";
6281         pr "  }\n";
6282         pr "\n";
6283         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6284         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6285         pr "\n";
6286         pr "  r = command (&out, &err,\n";
6287         pr "           \"lvm\", \"%ss\",\n" typ;
6288         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6289         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6290         pr "  if (r == -1) {\n";
6291         pr "    reply_with_error (\"%%s\", err);\n";
6292         pr "    free (out);\n";
6293         pr "    free (err);\n";
6294         pr "    free (ret);\n";
6295         pr "    return NULL;\n";
6296         pr "  }\n";
6297         pr "\n";
6298         pr "  free (err);\n";
6299         pr "\n";
6300         pr "  /* Tokenize each line of the output. */\n";
6301         pr "  p = out;\n";
6302         pr "  i = 0;\n";
6303         pr "  while (p) {\n";
6304         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6305         pr "    if (pend) {\n";
6306         pr "      *pend = '\\0';\n";
6307         pr "      pend++;\n";
6308         pr "    }\n";
6309         pr "\n";
6310         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6311         pr "      p++;\n";
6312         pr "\n";
6313         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6314         pr "      p = pend;\n";
6315         pr "      continue;\n";
6316         pr "    }\n";
6317         pr "\n";
6318         pr "    /* Allocate some space to store this next entry. */\n";
6319         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6320         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6321         pr "    if (newp == NULL) {\n";
6322         pr "      reply_with_perror (\"realloc\");\n";
6323         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6324         pr "      free (ret);\n";
6325         pr "      free (out);\n";
6326         pr "      return NULL;\n";
6327         pr "    }\n";
6328         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6329         pr "\n";
6330         pr "    /* Tokenize the next entry. */\n";
6331         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6332         pr "    if (r == -1) {\n";
6333         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6334         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6335         pr "      free (ret);\n";
6336         pr "      free (out);\n";
6337         pr "      return NULL;\n";
6338         pr "    }\n";
6339         pr "\n";
6340         pr "    ++i;\n";
6341         pr "    p = pend;\n";
6342         pr "  }\n";
6343         pr "\n";
6344         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6345         pr "\n";
6346         pr "  free (out);\n";
6347         pr "  return ret;\n";
6348         pr "}\n"
6349
6350   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6351
6352 (* Generate a list of function names, for debugging in the daemon.. *)
6353 and generate_daemon_names () =
6354   generate_header CStyle GPLv2plus;
6355
6356   pr "#include <config.h>\n";
6357   pr "\n";
6358   pr "#include \"daemon.h\"\n";
6359   pr "\n";
6360
6361   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6362   pr "const char *function_names[] = {\n";
6363   List.iter (
6364     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6365   ) daemon_functions;
6366   pr "};\n";
6367
6368 (* Generate the optional groups for the daemon to implement
6369  * guestfs_available.
6370  *)
6371 and generate_daemon_optgroups_c () =
6372   generate_header CStyle GPLv2plus;
6373
6374   pr "#include <config.h>\n";
6375   pr "\n";
6376   pr "#include \"daemon.h\"\n";
6377   pr "#include \"optgroups.h\"\n";
6378   pr "\n";
6379
6380   pr "struct optgroup optgroups[] = {\n";
6381   List.iter (
6382     fun (group, _) ->
6383       pr "  { \"%s\", optgroup_%s_available },\n" group group
6384   ) optgroups;
6385   pr "  { NULL, NULL }\n";
6386   pr "};\n"
6387
6388 and generate_daemon_optgroups_h () =
6389   generate_header CStyle GPLv2plus;
6390
6391   List.iter (
6392     fun (group, _) ->
6393       pr "extern int optgroup_%s_available (void);\n" group
6394   ) optgroups
6395
6396 (* Generate the tests. *)
6397 and generate_tests () =
6398   generate_header CStyle GPLv2plus;
6399
6400   pr "\
6401 #include <stdio.h>
6402 #include <stdlib.h>
6403 #include <string.h>
6404 #include <unistd.h>
6405 #include <sys/types.h>
6406 #include <fcntl.h>
6407
6408 #include \"guestfs.h\"
6409 #include \"guestfs-internal.h\"
6410
6411 static guestfs_h *g;
6412 static int suppress_error = 0;
6413
6414 static void print_error (guestfs_h *g, void *data, const char *msg)
6415 {
6416   if (!suppress_error)
6417     fprintf (stderr, \"%%s\\n\", msg);
6418 }
6419
6420 /* FIXME: nearly identical code appears in fish.c */
6421 static void print_strings (char *const *argv)
6422 {
6423   int argc;
6424
6425   for (argc = 0; argv[argc] != NULL; ++argc)
6426     printf (\"\\t%%s\\n\", argv[argc]);
6427 }
6428
6429 /*
6430 static void print_table (char const *const *argv)
6431 {
6432   int i;
6433
6434   for (i = 0; argv[i] != NULL; i += 2)
6435     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6436 }
6437 */
6438
6439 ";
6440
6441   (* Generate a list of commands which are not tested anywhere. *)
6442   pr "static void no_test_warnings (void)\n";
6443   pr "{\n";
6444
6445   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6446   List.iter (
6447     fun (_, _, _, _, tests, _, _) ->
6448       let tests = filter_map (
6449         function
6450         | (_, (Always|If _|Unless _), test) -> Some test
6451         | (_, Disabled, _) -> None
6452       ) tests in
6453       let seq = List.concat (List.map seq_of_test tests) in
6454       let cmds_tested = List.map List.hd seq in
6455       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6456   ) all_functions;
6457
6458   List.iter (
6459     fun (name, _, _, _, _, _, _) ->
6460       if not (Hashtbl.mem hash name) then
6461         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6462   ) all_functions;
6463
6464   pr "}\n";
6465   pr "\n";
6466
6467   (* Generate the actual tests.  Note that we generate the tests
6468    * in reverse order, deliberately, so that (in general) the
6469    * newest tests run first.  This makes it quicker and easier to
6470    * debug them.
6471    *)
6472   let test_names =
6473     List.map (
6474       fun (name, _, _, flags, tests, _, _) ->
6475         mapi (generate_one_test name flags) tests
6476     ) (List.rev all_functions) in
6477   let test_names = List.concat test_names in
6478   let nr_tests = List.length test_names in
6479
6480   pr "\
6481 int main (int argc, char *argv[])
6482 {
6483   char c = 0;
6484   unsigned long int n_failed = 0;
6485   const char *filename;
6486   int fd;
6487   int nr_tests, test_num = 0;
6488
6489   setbuf (stdout, NULL);
6490
6491   no_test_warnings ();
6492
6493   g = guestfs_create ();
6494   if (g == NULL) {
6495     printf (\"guestfs_create FAILED\\n\");
6496     exit (EXIT_FAILURE);
6497   }
6498
6499   guestfs_set_error_handler (g, print_error, NULL);
6500
6501   guestfs_set_path (g, \"../appliance\");
6502
6503   filename = \"test1.img\";
6504   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6505   if (fd == -1) {
6506     perror (filename);
6507     exit (EXIT_FAILURE);
6508   }
6509   if (lseek (fd, %d, SEEK_SET) == -1) {
6510     perror (\"lseek\");
6511     close (fd);
6512     unlink (filename);
6513     exit (EXIT_FAILURE);
6514   }
6515   if (write (fd, &c, 1) == -1) {
6516     perror (\"write\");
6517     close (fd);
6518     unlink (filename);
6519     exit (EXIT_FAILURE);
6520   }
6521   if (close (fd) == -1) {
6522     perror (filename);
6523     unlink (filename);
6524     exit (EXIT_FAILURE);
6525   }
6526   if (guestfs_add_drive (g, filename) == -1) {
6527     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6528     exit (EXIT_FAILURE);
6529   }
6530
6531   filename = \"test2.img\";
6532   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6533   if (fd == -1) {
6534     perror (filename);
6535     exit (EXIT_FAILURE);
6536   }
6537   if (lseek (fd, %d, SEEK_SET) == -1) {
6538     perror (\"lseek\");
6539     close (fd);
6540     unlink (filename);
6541     exit (EXIT_FAILURE);
6542   }
6543   if (write (fd, &c, 1) == -1) {
6544     perror (\"write\");
6545     close (fd);
6546     unlink (filename);
6547     exit (EXIT_FAILURE);
6548   }
6549   if (close (fd) == -1) {
6550     perror (filename);
6551     unlink (filename);
6552     exit (EXIT_FAILURE);
6553   }
6554   if (guestfs_add_drive (g, filename) == -1) {
6555     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6556     exit (EXIT_FAILURE);
6557   }
6558
6559   filename = \"test3.img\";
6560   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6561   if (fd == -1) {
6562     perror (filename);
6563     exit (EXIT_FAILURE);
6564   }
6565   if (lseek (fd, %d, SEEK_SET) == -1) {
6566     perror (\"lseek\");
6567     close (fd);
6568     unlink (filename);
6569     exit (EXIT_FAILURE);
6570   }
6571   if (write (fd, &c, 1) == -1) {
6572     perror (\"write\");
6573     close (fd);
6574     unlink (filename);
6575     exit (EXIT_FAILURE);
6576   }
6577   if (close (fd) == -1) {
6578     perror (filename);
6579     unlink (filename);
6580     exit (EXIT_FAILURE);
6581   }
6582   if (guestfs_add_drive (g, filename) == -1) {
6583     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6584     exit (EXIT_FAILURE);
6585   }
6586
6587   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6588     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6589     exit (EXIT_FAILURE);
6590   }
6591
6592   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6593   alarm (600);
6594
6595   if (guestfs_launch (g) == -1) {
6596     printf (\"guestfs_launch FAILED\\n\");
6597     exit (EXIT_FAILURE);
6598   }
6599
6600   /* Cancel previous alarm. */
6601   alarm (0);
6602
6603   nr_tests = %d;
6604
6605 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6606
6607   iteri (
6608     fun i test_name ->
6609       pr "  test_num++;\n";
6610       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6611       pr "  if (%s () == -1) {\n" test_name;
6612       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6613       pr "    n_failed++;\n";
6614       pr "  }\n";
6615   ) test_names;
6616   pr "\n";
6617
6618   pr "  guestfs_close (g);\n";
6619   pr "  unlink (\"test1.img\");\n";
6620   pr "  unlink (\"test2.img\");\n";
6621   pr "  unlink (\"test3.img\");\n";
6622   pr "\n";
6623
6624   pr "  if (n_failed > 0) {\n";
6625   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6626   pr "    exit (EXIT_FAILURE);\n";
6627   pr "  }\n";
6628   pr "\n";
6629
6630   pr "  exit (EXIT_SUCCESS);\n";
6631   pr "}\n"
6632
6633 and generate_one_test name flags i (init, prereq, test) =
6634   let test_name = sprintf "test_%s_%d" name i in
6635
6636   pr "\
6637 static int %s_skip (void)
6638 {
6639   const char *str;
6640
6641   str = getenv (\"TEST_ONLY\");
6642   if (str)
6643     return strstr (str, \"%s\") == NULL;
6644   str = getenv (\"SKIP_%s\");
6645   if (str && STREQ (str, \"1\")) return 1;
6646   str = getenv (\"SKIP_TEST_%s\");
6647   if (str && STREQ (str, \"1\")) return 1;
6648   return 0;
6649 }
6650
6651 " test_name name (String.uppercase test_name) (String.uppercase name);
6652
6653   (match prereq with
6654    | Disabled | Always -> ()
6655    | If code | Unless code ->
6656        pr "static int %s_prereq (void)\n" test_name;
6657        pr "{\n";
6658        pr "  %s\n" code;
6659        pr "}\n";
6660        pr "\n";
6661   );
6662
6663   pr "\
6664 static int %s (void)
6665 {
6666   if (%s_skip ()) {
6667     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6668     return 0;
6669   }
6670
6671 " test_name test_name test_name;
6672
6673   (* Optional functions should only be tested if the relevant
6674    * support is available in the daemon.
6675    *)
6676   List.iter (
6677     function
6678     | Optional group ->
6679         pr "  {\n";
6680         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6681         pr "    int r;\n";
6682         pr "    suppress_error = 1;\n";
6683         pr "    r = guestfs_available (g, (char **) groups);\n";
6684         pr "    suppress_error = 0;\n";
6685         pr "    if (r == -1) {\n";
6686         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6687         pr "      return 0;\n";
6688         pr "    }\n";
6689         pr "  }\n";
6690     | _ -> ()
6691   ) flags;
6692
6693   (match prereq with
6694    | Disabled ->
6695        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6696    | If _ ->
6697        pr "  if (! %s_prereq ()) {\n" test_name;
6698        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6699        pr "    return 0;\n";
6700        pr "  }\n";
6701        pr "\n";
6702        generate_one_test_body name i test_name init test;
6703    | Unless _ ->
6704        pr "  if (%s_prereq ()) {\n" test_name;
6705        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6706        pr "    return 0;\n";
6707        pr "  }\n";
6708        pr "\n";
6709        generate_one_test_body name i test_name init test;
6710    | Always ->
6711        generate_one_test_body name i test_name init test
6712   );
6713
6714   pr "  return 0;\n";
6715   pr "}\n";
6716   pr "\n";
6717   test_name
6718
6719 and generate_one_test_body name i test_name init test =
6720   (match init with
6721    | InitNone (* XXX at some point, InitNone and InitEmpty became
6722                * folded together as the same thing.  Really we should
6723                * make InitNone do nothing at all, but the tests may
6724                * need to be checked to make sure this is OK.
6725                *)
6726    | InitEmpty ->
6727        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6728        List.iter (generate_test_command_call test_name)
6729          [["blockdev_setrw"; "/dev/sda"];
6730           ["umount_all"];
6731           ["lvm_remove_all"]]
6732    | InitPartition ->
6733        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6734        List.iter (generate_test_command_call test_name)
6735          [["blockdev_setrw"; "/dev/sda"];
6736           ["umount_all"];
6737           ["lvm_remove_all"];
6738           ["part_disk"; "/dev/sda"; "mbr"]]
6739    | InitBasicFS ->
6740        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6741        List.iter (generate_test_command_call test_name)
6742          [["blockdev_setrw"; "/dev/sda"];
6743           ["umount_all"];
6744           ["lvm_remove_all"];
6745           ["part_disk"; "/dev/sda"; "mbr"];
6746           ["mkfs"; "ext2"; "/dev/sda1"];
6747           ["mount_options"; ""; "/dev/sda1"; "/"]]
6748    | InitBasicFSonLVM ->
6749        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6750          test_name;
6751        List.iter (generate_test_command_call test_name)
6752          [["blockdev_setrw"; "/dev/sda"];
6753           ["umount_all"];
6754           ["lvm_remove_all"];
6755           ["part_disk"; "/dev/sda"; "mbr"];
6756           ["pvcreate"; "/dev/sda1"];
6757           ["vgcreate"; "VG"; "/dev/sda1"];
6758           ["lvcreate"; "LV"; "VG"; "8"];
6759           ["mkfs"; "ext2"; "/dev/VG/LV"];
6760           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6761    | InitISOFS ->
6762        pr "  /* InitISOFS for %s */\n" test_name;
6763        List.iter (generate_test_command_call test_name)
6764          [["blockdev_setrw"; "/dev/sda"];
6765           ["umount_all"];
6766           ["lvm_remove_all"];
6767           ["mount_ro"; "/dev/sdd"; "/"]]
6768   );
6769
6770   let get_seq_last = function
6771     | [] ->
6772         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6773           test_name
6774     | seq ->
6775         let seq = List.rev seq in
6776         List.rev (List.tl seq), List.hd seq
6777   in
6778
6779   match test with
6780   | TestRun seq ->
6781       pr "  /* TestRun for %s (%d) */\n" name i;
6782       List.iter (generate_test_command_call test_name) seq
6783   | TestOutput (seq, expected) ->
6784       pr "  /* TestOutput for %s (%d) */\n" name i;
6785       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6786       let seq, last = get_seq_last seq in
6787       let test () =
6788         pr "    if (STRNEQ (r, expected)) {\n";
6789         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6790         pr "      return -1;\n";
6791         pr "    }\n"
6792       in
6793       List.iter (generate_test_command_call test_name) seq;
6794       generate_test_command_call ~test test_name last
6795   | TestOutputList (seq, expected) ->
6796       pr "  /* TestOutputList for %s (%d) */\n" name i;
6797       let seq, last = get_seq_last seq in
6798       let test () =
6799         iteri (
6800           fun i str ->
6801             pr "    if (!r[%d]) {\n" i;
6802             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6803             pr "      print_strings (r);\n";
6804             pr "      return -1;\n";
6805             pr "    }\n";
6806             pr "    {\n";
6807             pr "      const char *expected = \"%s\";\n" (c_quote str);
6808             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6809             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6810             pr "        return -1;\n";
6811             pr "      }\n";
6812             pr "    }\n"
6813         ) expected;
6814         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6815         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6816           test_name;
6817         pr "      print_strings (r);\n";
6818         pr "      return -1;\n";
6819         pr "    }\n"
6820       in
6821       List.iter (generate_test_command_call test_name) seq;
6822       generate_test_command_call ~test test_name last
6823   | TestOutputListOfDevices (seq, expected) ->
6824       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6825       let seq, last = get_seq_last seq in
6826       let test () =
6827         iteri (
6828           fun i str ->
6829             pr "    if (!r[%d]) {\n" i;
6830             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6831             pr "      print_strings (r);\n";
6832             pr "      return -1;\n";
6833             pr "    }\n";
6834             pr "    {\n";
6835             pr "      const char *expected = \"%s\";\n" (c_quote str);
6836             pr "      r[%d][5] = 's';\n" i;
6837             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6838             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6839             pr "        return -1;\n";
6840             pr "      }\n";
6841             pr "    }\n"
6842         ) expected;
6843         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6844         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6845           test_name;
6846         pr "      print_strings (r);\n";
6847         pr "      return -1;\n";
6848         pr "    }\n"
6849       in
6850       List.iter (generate_test_command_call test_name) seq;
6851       generate_test_command_call ~test test_name last
6852   | TestOutputInt (seq, expected) ->
6853       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6854       let seq, last = get_seq_last seq in
6855       let test () =
6856         pr "    if (r != %d) {\n" expected;
6857         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6858           test_name expected;
6859         pr "               (int) r);\n";
6860         pr "      return -1;\n";
6861         pr "    }\n"
6862       in
6863       List.iter (generate_test_command_call test_name) seq;
6864       generate_test_command_call ~test test_name last
6865   | TestOutputIntOp (seq, op, expected) ->
6866       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6867       let seq, last = get_seq_last seq in
6868       let test () =
6869         pr "    if (! (r %s %d)) {\n" op expected;
6870         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6871           test_name op expected;
6872         pr "               (int) r);\n";
6873         pr "      return -1;\n";
6874         pr "    }\n"
6875       in
6876       List.iter (generate_test_command_call test_name) seq;
6877       generate_test_command_call ~test test_name last
6878   | TestOutputTrue seq ->
6879       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6880       let seq, last = get_seq_last seq in
6881       let test () =
6882         pr "    if (!r) {\n";
6883         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6884           test_name;
6885         pr "      return -1;\n";
6886         pr "    }\n"
6887       in
6888       List.iter (generate_test_command_call test_name) seq;
6889       generate_test_command_call ~test test_name last
6890   | TestOutputFalse seq ->
6891       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6892       let seq, last = get_seq_last seq in
6893       let test () =
6894         pr "    if (r) {\n";
6895         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6896           test_name;
6897         pr "      return -1;\n";
6898         pr "    }\n"
6899       in
6900       List.iter (generate_test_command_call test_name) seq;
6901       generate_test_command_call ~test test_name last
6902   | TestOutputLength (seq, expected) ->
6903       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6904       let seq, last = get_seq_last seq in
6905       let test () =
6906         pr "    int j;\n";
6907         pr "    for (j = 0; j < %d; ++j)\n" expected;
6908         pr "      if (r[j] == NULL) {\n";
6909         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6910           test_name;
6911         pr "        print_strings (r);\n";
6912         pr "        return -1;\n";
6913         pr "      }\n";
6914         pr "    if (r[j] != NULL) {\n";
6915         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6916           test_name;
6917         pr "      print_strings (r);\n";
6918         pr "      return -1;\n";
6919         pr "    }\n"
6920       in
6921       List.iter (generate_test_command_call test_name) seq;
6922       generate_test_command_call ~test test_name last
6923   | TestOutputBuffer (seq, expected) ->
6924       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6925       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6926       let seq, last = get_seq_last seq in
6927       let len = String.length expected in
6928       let test () =
6929         pr "    if (size != %d) {\n" len;
6930         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6931         pr "      return -1;\n";
6932         pr "    }\n";
6933         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6934         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6935         pr "      return -1;\n";
6936         pr "    }\n"
6937       in
6938       List.iter (generate_test_command_call test_name) seq;
6939       generate_test_command_call ~test test_name last
6940   | TestOutputStruct (seq, checks) ->
6941       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6942       let seq, last = get_seq_last seq in
6943       let test () =
6944         List.iter (
6945           function
6946           | CompareWithInt (field, expected) ->
6947               pr "    if (r->%s != %d) {\n" field expected;
6948               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6949                 test_name field expected;
6950               pr "               (int) r->%s);\n" field;
6951               pr "      return -1;\n";
6952               pr "    }\n"
6953           | CompareWithIntOp (field, op, expected) ->
6954               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6955               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6956                 test_name field op expected;
6957               pr "               (int) r->%s);\n" field;
6958               pr "      return -1;\n";
6959               pr "    }\n"
6960           | CompareWithString (field, expected) ->
6961               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6962               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6963                 test_name field expected;
6964               pr "               r->%s);\n" field;
6965               pr "      return -1;\n";
6966               pr "    }\n"
6967           | CompareFieldsIntEq (field1, field2) ->
6968               pr "    if (r->%s != r->%s) {\n" field1 field2;
6969               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6970                 test_name field1 field2;
6971               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6972               pr "      return -1;\n";
6973               pr "    }\n"
6974           | CompareFieldsStrEq (field1, field2) ->
6975               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6976               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6977                 test_name field1 field2;
6978               pr "               r->%s, r->%s);\n" field1 field2;
6979               pr "      return -1;\n";
6980               pr "    }\n"
6981         ) checks
6982       in
6983       List.iter (generate_test_command_call test_name) seq;
6984       generate_test_command_call ~test test_name last
6985   | TestLastFail seq ->
6986       pr "  /* TestLastFail for %s (%d) */\n" name i;
6987       let seq, last = get_seq_last seq in
6988       List.iter (generate_test_command_call test_name) seq;
6989       generate_test_command_call test_name ~expect_error:true last
6990
6991 (* Generate the code to run a command, leaving the result in 'r'.
6992  * If you expect to get an error then you should set expect_error:true.
6993  *)
6994 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6995   match cmd with
6996   | [] -> assert false
6997   | name :: args ->
6998       (* Look up the command to find out what args/ret it has. *)
6999       let style =
7000         try
7001           let _, style, _, _, _, _, _ =
7002             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7003           style
7004         with Not_found ->
7005           failwithf "%s: in test, command %s was not found" test_name name in
7006
7007       if List.length (snd style) <> List.length args then
7008         failwithf "%s: in test, wrong number of args given to %s"
7009           test_name name;
7010
7011       pr "  {\n";
7012
7013       List.iter (
7014         function
7015         | OptString n, "NULL" -> ()
7016         | Pathname n, arg
7017         | Device n, arg
7018         | Dev_or_Path n, arg
7019         | String n, arg
7020         | OptString n, arg ->
7021             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7022         | Int _, _
7023         | Int64 _, _
7024         | Bool _, _
7025         | FileIn _, _ | FileOut _, _ -> ()
7026         | StringList n, "" | DeviceList n, "" ->
7027             pr "    const char *const %s[1] = { NULL };\n" n
7028         | StringList n, arg | DeviceList n, arg ->
7029             let strs = string_split " " arg in
7030             iteri (
7031               fun i str ->
7032                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7033             ) strs;
7034             pr "    const char *const %s[] = {\n" n;
7035             iteri (
7036               fun i _ -> pr "      %s_%d,\n" n i
7037             ) strs;
7038             pr "      NULL\n";
7039             pr "    };\n";
7040       ) (List.combine (snd style) args);
7041
7042       let error_code =
7043         match fst style with
7044         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7045         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7046         | RConstString _ | RConstOptString _ ->
7047             pr "    const char *r;\n"; "NULL"
7048         | RString _ -> pr "    char *r;\n"; "NULL"
7049         | RStringList _ | RHashtable _ ->
7050             pr "    char **r;\n";
7051             pr "    int i;\n";
7052             "NULL"
7053         | RStruct (_, typ) ->
7054             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7055         | RStructList (_, typ) ->
7056             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7057         | RBufferOut _ ->
7058             pr "    char *r;\n";
7059             pr "    size_t size;\n";
7060             "NULL" in
7061
7062       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7063       pr "    r = guestfs_%s (g" name;
7064
7065       (* Generate the parameters. *)
7066       List.iter (
7067         function
7068         | OptString _, "NULL" -> pr ", NULL"
7069         | Pathname n, _
7070         | Device n, _ | Dev_or_Path n, _
7071         | String n, _
7072         | OptString n, _ ->
7073             pr ", %s" n
7074         | FileIn _, arg | FileOut _, arg ->
7075             pr ", \"%s\"" (c_quote arg)
7076         | StringList n, _ | DeviceList n, _ ->
7077             pr ", (char **) %s" n
7078         | Int _, arg ->
7079             let i =
7080               try int_of_string arg
7081               with Failure "int_of_string" ->
7082                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7083             pr ", %d" i
7084         | Int64 _, arg ->
7085             let i =
7086               try Int64.of_string arg
7087               with Failure "int_of_string" ->
7088                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7089             pr ", %Ld" i
7090         | Bool _, arg ->
7091             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7092       ) (List.combine (snd style) args);
7093
7094       (match fst style with
7095        | RBufferOut _ -> pr ", &size"
7096        | _ -> ()
7097       );
7098
7099       pr ");\n";
7100
7101       if not expect_error then
7102         pr "    if (r == %s)\n" error_code
7103       else
7104         pr "    if (r != %s)\n" error_code;
7105       pr "      return -1;\n";
7106
7107       (* Insert the test code. *)
7108       (match test with
7109        | None -> ()
7110        | Some f -> f ()
7111       );
7112
7113       (match fst style with
7114        | RErr | RInt _ | RInt64 _ | RBool _
7115        | RConstString _ | RConstOptString _ -> ()
7116        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7117        | RStringList _ | RHashtable _ ->
7118            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7119            pr "      free (r[i]);\n";
7120            pr "    free (r);\n"
7121        | RStruct (_, typ) ->
7122            pr "    guestfs_free_%s (r);\n" typ
7123        | RStructList (_, typ) ->
7124            pr "    guestfs_free_%s_list (r);\n" typ
7125       );
7126
7127       pr "  }\n"
7128
7129 and c_quote str =
7130   let str = replace_str str "\r" "\\r" in
7131   let str = replace_str str "\n" "\\n" in
7132   let str = replace_str str "\t" "\\t" in
7133   let str = replace_str str "\000" "\\0" in
7134   str
7135
7136 (* Generate a lot of different functions for guestfish. *)
7137 and generate_fish_cmds () =
7138   generate_header CStyle GPLv2plus;
7139
7140   let all_functions =
7141     List.filter (
7142       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7143     ) all_functions in
7144   let all_functions_sorted =
7145     List.filter (
7146       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7147     ) all_functions_sorted in
7148
7149   pr "#include <config.h>\n";
7150   pr "\n";
7151   pr "#include <stdio.h>\n";
7152   pr "#include <stdlib.h>\n";
7153   pr "#include <string.h>\n";
7154   pr "#include <inttypes.h>\n";
7155   pr "\n";
7156   pr "#include <guestfs.h>\n";
7157   pr "#include \"c-ctype.h\"\n";
7158   pr "#include \"full-write.h\"\n";
7159   pr "#include \"xstrtol.h\"\n";
7160   pr "#include \"fish.h\"\n";
7161   pr "\n";
7162
7163   (* list_commands function, which implements guestfish -h *)
7164   pr "void list_commands (void)\n";
7165   pr "{\n";
7166   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7167   pr "  list_builtin_commands ();\n";
7168   List.iter (
7169     fun (name, _, _, flags, _, shortdesc, _) ->
7170       let name = replace_char name '_' '-' in
7171       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7172         name shortdesc
7173   ) all_functions_sorted;
7174   pr "  printf (\"    %%s\\n\",";
7175   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7176   pr "}\n";
7177   pr "\n";
7178
7179   (* display_command function, which implements guestfish -h cmd *)
7180   pr "void display_command (const char *cmd)\n";
7181   pr "{\n";
7182   List.iter (
7183     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7184       let name2 = replace_char name '_' '-' in
7185       let alias =
7186         try find_map (function FishAlias n -> Some n | _ -> None) flags
7187         with Not_found -> name in
7188       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7189       let synopsis =
7190         match snd style with
7191         | [] -> name2
7192         | args ->
7193             sprintf "%s %s"
7194               name2 (String.concat " " (List.map name_of_argt args)) in
7195
7196       let warnings =
7197         if List.mem ProtocolLimitWarning flags then
7198           ("\n\n" ^ protocol_limit_warning)
7199         else "" in
7200
7201       (* For DangerWillRobinson commands, we should probably have
7202        * guestfish prompt before allowing you to use them (especially
7203        * in interactive mode). XXX
7204        *)
7205       let warnings =
7206         warnings ^
7207           if List.mem DangerWillRobinson flags then
7208             ("\n\n" ^ danger_will_robinson)
7209           else "" in
7210
7211       let warnings =
7212         warnings ^
7213           match deprecation_notice flags with
7214           | None -> ""
7215           | Some txt -> "\n\n" ^ txt in
7216
7217       let describe_alias =
7218         if name <> alias then
7219           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7220         else "" in
7221
7222       pr "  if (";
7223       pr "STRCASEEQ (cmd, \"%s\")" name;
7224       if name <> name2 then
7225         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7226       if name <> alias then
7227         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7228       pr ")\n";
7229       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7230         name2 shortdesc
7231         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7232          "=head1 DESCRIPTION\n\n" ^
7233          longdesc ^ warnings ^ describe_alias);
7234       pr "  else\n"
7235   ) all_functions;
7236   pr "    display_builtin_command (cmd);\n";
7237   pr "}\n";
7238   pr "\n";
7239
7240   let emit_print_list_function typ =
7241     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7242       typ typ typ;
7243     pr "{\n";
7244     pr "  unsigned int i;\n";
7245     pr "\n";
7246     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7247     pr "    printf (\"[%%d] = {\\n\", i);\n";
7248     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7249     pr "    printf (\"}\\n\");\n";
7250     pr "  }\n";
7251     pr "}\n";
7252     pr "\n";
7253   in
7254
7255   (* print_* functions *)
7256   List.iter (
7257     fun (typ, cols) ->
7258       let needs_i =
7259         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7260
7261       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7262       pr "{\n";
7263       if needs_i then (
7264         pr "  unsigned int i;\n";
7265         pr "\n"
7266       );
7267       List.iter (
7268         function
7269         | name, FString ->
7270             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7271         | name, FUUID ->
7272             pr "  printf (\"%%s%s: \", indent);\n" name;
7273             pr "  for (i = 0; i < 32; ++i)\n";
7274             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7275             pr "  printf (\"\\n\");\n"
7276         | name, FBuffer ->
7277             pr "  printf (\"%%s%s: \", indent);\n" name;
7278             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7279             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7280             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7281             pr "    else\n";
7282             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7283             pr "  printf (\"\\n\");\n"
7284         | name, (FUInt64|FBytes) ->
7285             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7286               name typ name
7287         | name, FInt64 ->
7288             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7289               name typ name
7290         | name, FUInt32 ->
7291             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7292               name typ name
7293         | name, FInt32 ->
7294             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7295               name typ name
7296         | name, FChar ->
7297             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7298               name typ name
7299         | name, FOptPercent ->
7300             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7301               typ name name typ name;
7302             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7303       ) cols;
7304       pr "}\n";
7305       pr "\n";
7306   ) structs;
7307
7308   (* Emit a print_TYPE_list function definition only if that function is used. *)
7309   List.iter (
7310     function
7311     | typ, (RStructListOnly | RStructAndList) ->
7312         (* generate the function for typ *)
7313         emit_print_list_function typ
7314     | typ, _ -> () (* empty *)
7315   ) (rstructs_used_by all_functions);
7316
7317   (* Emit a print_TYPE function definition only if that function is used. *)
7318   List.iter (
7319     function
7320     | typ, (RStructOnly | RStructAndList) ->
7321         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7322         pr "{\n";
7323         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7324         pr "}\n";
7325         pr "\n";
7326     | typ, _ -> () (* empty *)
7327   ) (rstructs_used_by all_functions);
7328
7329   (* run_<action> actions *)
7330   List.iter (
7331     fun (name, style, _, flags, _, _, _) ->
7332       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7333       pr "{\n";
7334       (match fst style with
7335        | RErr
7336        | RInt _
7337        | RBool _ -> pr "  int r;\n"
7338        | RInt64 _ -> pr "  int64_t r;\n"
7339        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7340        | RString _ -> pr "  char *r;\n"
7341        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7342        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7343        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7344        | RBufferOut _ ->
7345            pr "  char *r;\n";
7346            pr "  size_t size;\n";
7347       );
7348       List.iter (
7349         function
7350         | Device n
7351         | String n
7352         | OptString n
7353         | FileIn n
7354         | FileOut n -> pr "  const char *%s;\n" n
7355         | Pathname n
7356         | Dev_or_Path n -> pr "  char *%s;\n" n
7357         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7358         | Bool n -> pr "  int %s;\n" n
7359         | Int n -> pr "  int %s;\n" n
7360         | Int64 n -> pr "  int64_t %s;\n" n
7361       ) (snd style);
7362
7363       (* Check and convert parameters. *)
7364       let argc_expected = List.length (snd style) in
7365       pr "  if (argc != %d) {\n" argc_expected;
7366       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7367         argc_expected;
7368       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7369       pr "    return -1;\n";
7370       pr "  }\n";
7371
7372       let parse_integer fn fntyp rtyp range name i =
7373         pr "  {\n";
7374         pr "    strtol_error xerr;\n";
7375         pr "    %s r;\n" fntyp;
7376         pr "\n";
7377         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7378         pr "    if (xerr != LONGINT_OK) {\n";
7379         pr "      fprintf (stderr,\n";
7380         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7381         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7382         pr "      return -1;\n";
7383         pr "    }\n";
7384         (match range with
7385          | None -> ()
7386          | Some (min, max, comment) ->
7387              pr "    /* %s */\n" comment;
7388              pr "    if (r < %s || r > %s) {\n" min max;
7389              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7390                name;
7391              pr "      return -1;\n";
7392              pr "    }\n";
7393              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7394         );
7395         pr "    %s = r;\n" name;
7396         pr "  }\n";
7397       in
7398
7399       iteri (
7400         fun i ->
7401           function
7402           | Device name
7403           | String name ->
7404               pr "  %s = argv[%d];\n" name i
7405           | Pathname name
7406           | Dev_or_Path name ->
7407               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7408               pr "  if (%s == NULL) return -1;\n" name
7409           | OptString name ->
7410               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7411                 name i i
7412           | FileIn name ->
7413               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7414                 name i i
7415           | FileOut name ->
7416               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7417                 name i i
7418           | StringList name | DeviceList name ->
7419               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7420               pr "  if (%s == NULL) return -1;\n" name;
7421           | Bool name ->
7422               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7423           | Int name ->
7424               let range =
7425                 let min = "(-(2LL<<30))"
7426                 and max = "((2LL<<30)-1)"
7427                 and comment =
7428                   "The Int type in the generator is a signed 31 bit int." in
7429                 Some (min, max, comment) in
7430               parse_integer "xstrtoll" "long long" "int" range name i
7431           | Int64 name ->
7432               parse_integer "xstrtoll" "long long" "int64_t" None name i
7433       ) (snd style);
7434
7435       (* Call C API function. *)
7436       let fn =
7437         try find_map (function FishAction n -> Some n | _ -> None) flags
7438         with Not_found -> sprintf "guestfs_%s" name in
7439       pr "  r = %s " fn;
7440       generate_c_call_args ~handle:"g" style;
7441       pr ";\n";
7442
7443       List.iter (
7444         function
7445         | Device name | String name
7446         | OptString name | FileIn name | FileOut name | Bool name
7447         | Int name | Int64 name -> ()
7448         | Pathname name | Dev_or_Path name ->
7449             pr "  free (%s);\n" name
7450         | StringList name | DeviceList name ->
7451             pr "  free_strings (%s);\n" name
7452       ) (snd style);
7453
7454       (* Any output flags? *)
7455       let fish_output =
7456         let flags = filter_map (
7457           function FishOutput flag -> Some flag | _ -> None
7458         ) flags in
7459         match flags with
7460         | [] -> None
7461         | [f] -> Some f
7462         | _ ->
7463             failwithf "%s: more than one FishOutput flag is not allowed" name in
7464
7465       (* Check return value for errors and display command results. *)
7466       (match fst style with
7467        | RErr -> pr "  return r;\n"
7468        | RInt _ ->
7469            pr "  if (r == -1) return -1;\n";
7470            (match fish_output with
7471             | None ->
7472                 pr "  printf (\"%%d\\n\", r);\n";
7473             | Some FishOutputOctal ->
7474                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7475             | Some FishOutputHexadecimal ->
7476                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7477            pr "  return 0;\n"
7478        | RInt64 _ ->
7479            pr "  if (r == -1) return -1;\n";
7480            (match fish_output with
7481             | None ->
7482                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7483             | Some FishOutputOctal ->
7484                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7485             | Some FishOutputHexadecimal ->
7486                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7487            pr "  return 0;\n"
7488        | RBool _ ->
7489            pr "  if (r == -1) return -1;\n";
7490            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7491            pr "  return 0;\n"
7492        | RConstString _ ->
7493            pr "  if (r == NULL) return -1;\n";
7494            pr "  printf (\"%%s\\n\", r);\n";
7495            pr "  return 0;\n"
7496        | RConstOptString _ ->
7497            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7498            pr "  return 0;\n"
7499        | RString _ ->
7500            pr "  if (r == NULL) return -1;\n";
7501            pr "  printf (\"%%s\\n\", r);\n";
7502            pr "  free (r);\n";
7503            pr "  return 0;\n"
7504        | RStringList _ ->
7505            pr "  if (r == NULL) return -1;\n";
7506            pr "  print_strings (r);\n";
7507            pr "  free_strings (r);\n";
7508            pr "  return 0;\n"
7509        | RStruct (_, typ) ->
7510            pr "  if (r == NULL) return -1;\n";
7511            pr "  print_%s (r);\n" typ;
7512            pr "  guestfs_free_%s (r);\n" typ;
7513            pr "  return 0;\n"
7514        | RStructList (_, typ) ->
7515            pr "  if (r == NULL) return -1;\n";
7516            pr "  print_%s_list (r);\n" typ;
7517            pr "  guestfs_free_%s_list (r);\n" typ;
7518            pr "  return 0;\n"
7519        | RHashtable _ ->
7520            pr "  if (r == NULL) return -1;\n";
7521            pr "  print_table (r);\n";
7522            pr "  free_strings (r);\n";
7523            pr "  return 0;\n"
7524        | RBufferOut _ ->
7525            pr "  if (r == NULL) return -1;\n";
7526            pr "  if (full_write (1, r, size) != size) {\n";
7527            pr "    perror (\"write\");\n";
7528            pr "    free (r);\n";
7529            pr "    return -1;\n";
7530            pr "  }\n";
7531            pr "  free (r);\n";
7532            pr "  return 0;\n"
7533       );
7534       pr "}\n";
7535       pr "\n"
7536   ) all_functions;
7537
7538   (* run_action function *)
7539   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7540   pr "{\n";
7541   List.iter (
7542     fun (name, _, _, flags, _, _, _) ->
7543       let name2 = replace_char name '_' '-' in
7544       let alias =
7545         try find_map (function FishAlias n -> Some n | _ -> None) flags
7546         with Not_found -> name in
7547       pr "  if (";
7548       pr "STRCASEEQ (cmd, \"%s\")" name;
7549       if name <> name2 then
7550         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7551       if name <> alias then
7552         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7553       pr ")\n";
7554       pr "    return run_%s (cmd, argc, argv);\n" name;
7555       pr "  else\n";
7556   ) all_functions;
7557   pr "    {\n";
7558   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7559   pr "      if (command_num == 1)\n";
7560   pr "        extended_help_message ();\n";
7561   pr "      return -1;\n";
7562   pr "    }\n";
7563   pr "  return 0;\n";
7564   pr "}\n";
7565   pr "\n"
7566
7567 (* Readline completion for guestfish. *)
7568 and generate_fish_completion () =
7569   generate_header CStyle GPLv2plus;
7570
7571   let all_functions =
7572     List.filter (
7573       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7574     ) all_functions in
7575
7576   pr "\
7577 #include <config.h>
7578
7579 #include <stdio.h>
7580 #include <stdlib.h>
7581 #include <string.h>
7582
7583 #ifdef HAVE_LIBREADLINE
7584 #include <readline/readline.h>
7585 #endif
7586
7587 #include \"fish.h\"
7588
7589 #ifdef HAVE_LIBREADLINE
7590
7591 static const char *const commands[] = {
7592   BUILTIN_COMMANDS_FOR_COMPLETION,
7593 ";
7594
7595   (* Get the commands, including the aliases.  They don't need to be
7596    * sorted - the generator() function just does a dumb linear search.
7597    *)
7598   let commands =
7599     List.map (
7600       fun (name, _, _, flags, _, _, _) ->
7601         let name2 = replace_char name '_' '-' in
7602         let alias =
7603           try find_map (function FishAlias n -> Some n | _ -> None) flags
7604           with Not_found -> name in
7605
7606         if name <> alias then [name2; alias] else [name2]
7607     ) all_functions in
7608   let commands = List.flatten commands in
7609
7610   List.iter (pr "  \"%s\",\n") commands;
7611
7612   pr "  NULL
7613 };
7614
7615 static char *
7616 generator (const char *text, int state)
7617 {
7618   static int index, len;
7619   const char *name;
7620
7621   if (!state) {
7622     index = 0;
7623     len = strlen (text);
7624   }
7625
7626   rl_attempted_completion_over = 1;
7627
7628   while ((name = commands[index]) != NULL) {
7629     index++;
7630     if (STRCASEEQLEN (name, text, len))
7631       return strdup (name);
7632   }
7633
7634   return NULL;
7635 }
7636
7637 #endif /* HAVE_LIBREADLINE */
7638
7639 #ifdef HAVE_RL_COMPLETION_MATCHES
7640 #define RL_COMPLETION_MATCHES rl_completion_matches
7641 #else
7642 #ifdef HAVE_COMPLETION_MATCHES
7643 #define RL_COMPLETION_MATCHES completion_matches
7644 #endif
7645 #endif /* else just fail if we don't have either symbol */
7646
7647 char **
7648 do_completion (const char *text, int start, int end)
7649 {
7650   char **matches = NULL;
7651
7652 #ifdef HAVE_LIBREADLINE
7653   rl_completion_append_character = ' ';
7654
7655   if (start == 0)
7656     matches = RL_COMPLETION_MATCHES (text, generator);
7657   else if (complete_dest_paths)
7658     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7659 #endif
7660
7661   return matches;
7662 }
7663 ";
7664
7665 (* Generate the POD documentation for guestfish. *)
7666 and generate_fish_actions_pod () =
7667   let all_functions_sorted =
7668     List.filter (
7669       fun (_, _, _, flags, _, _, _) ->
7670         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7671     ) all_functions_sorted in
7672
7673   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7674
7675   List.iter (
7676     fun (name, style, _, flags, _, _, longdesc) ->
7677       let longdesc =
7678         Str.global_substitute rex (
7679           fun s ->
7680             let sub =
7681               try Str.matched_group 1 s
7682               with Not_found ->
7683                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7684             "C<" ^ replace_char sub '_' '-' ^ ">"
7685         ) longdesc in
7686       let name = replace_char name '_' '-' in
7687       let alias =
7688         try find_map (function FishAlias n -> Some n | _ -> None) flags
7689         with Not_found -> name in
7690
7691       pr "=head2 %s" name;
7692       if name <> alias then
7693         pr " | %s" alias;
7694       pr "\n";
7695       pr "\n";
7696       pr " %s" name;
7697       List.iter (
7698         function
7699         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7700         | OptString n -> pr " %s" n
7701         | StringList n | DeviceList n -> pr " '%s ...'" n
7702         | Bool _ -> pr " true|false"
7703         | Int n -> pr " %s" n
7704         | Int64 n -> pr " %s" n
7705         | FileIn n | FileOut n -> pr " (%s|-)" n
7706       ) (snd style);
7707       pr "\n";
7708       pr "\n";
7709       pr "%s\n\n" longdesc;
7710
7711       if List.exists (function FileIn _ | FileOut _ -> true
7712                       | _ -> false) (snd style) then
7713         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7714
7715       if List.mem ProtocolLimitWarning flags then
7716         pr "%s\n\n" protocol_limit_warning;
7717
7718       if List.mem DangerWillRobinson flags then
7719         pr "%s\n\n" danger_will_robinson;
7720
7721       match deprecation_notice flags with
7722       | None -> ()
7723       | Some txt -> pr "%s\n\n" txt
7724   ) all_functions_sorted
7725
7726 (* Generate a C function prototype. *)
7727 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7728     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7729     ?(prefix = "")
7730     ?handle name style =
7731   if extern then pr "extern ";
7732   if static then pr "static ";
7733   (match fst style with
7734    | RErr -> pr "int "
7735    | RInt _ -> pr "int "
7736    | RInt64 _ -> pr "int64_t "
7737    | RBool _ -> pr "int "
7738    | RConstString _ | RConstOptString _ -> pr "const char *"
7739    | RString _ | RBufferOut _ -> pr "char *"
7740    | RStringList _ | RHashtable _ -> pr "char **"
7741    | RStruct (_, typ) ->
7742        if not in_daemon then pr "struct guestfs_%s *" typ
7743        else pr "guestfs_int_%s *" typ
7744    | RStructList (_, typ) ->
7745        if not in_daemon then pr "struct guestfs_%s_list *" typ
7746        else pr "guestfs_int_%s_list *" typ
7747   );
7748   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7749   pr "%s%s (" prefix name;
7750   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7751     pr "void"
7752   else (
7753     let comma = ref false in
7754     (match handle with
7755      | None -> ()
7756      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7757     );
7758     let next () =
7759       if !comma then (
7760         if single_line then pr ", " else pr ",\n\t\t"
7761       );
7762       comma := true
7763     in
7764     List.iter (
7765       function
7766       | Pathname n
7767       | Device n | Dev_or_Path n
7768       | String n
7769       | OptString n ->
7770           next ();
7771           pr "const char *%s" n
7772       | StringList n | DeviceList n ->
7773           next ();
7774           pr "char *const *%s" n
7775       | Bool n -> next (); pr "int %s" n
7776       | Int n -> next (); pr "int %s" n
7777       | Int64 n -> next (); pr "int64_t %s" n
7778       | FileIn n
7779       | FileOut n ->
7780           if not in_daemon then (next (); pr "const char *%s" n)
7781     ) (snd style);
7782     if is_RBufferOut then (next (); pr "size_t *size_r");
7783   );
7784   pr ")";
7785   if semicolon then pr ";";
7786   if newline then pr "\n"
7787
7788 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7789 and generate_c_call_args ?handle ?(decl = false) style =
7790   pr "(";
7791   let comma = ref false in
7792   let next () =
7793     if !comma then pr ", ";
7794     comma := true
7795   in
7796   (match handle with
7797    | None -> ()
7798    | Some handle -> pr "%s" handle; comma := true
7799   );
7800   List.iter (
7801     fun arg ->
7802       next ();
7803       pr "%s" (name_of_argt arg)
7804   ) (snd style);
7805   (* For RBufferOut calls, add implicit &size parameter. *)
7806   if not decl then (
7807     match fst style with
7808     | RBufferOut _ ->
7809         next ();
7810         pr "&size"
7811     | _ -> ()
7812   );
7813   pr ")"
7814
7815 (* Generate the OCaml bindings interface. *)
7816 and generate_ocaml_mli () =
7817   generate_header OCamlStyle LGPLv2plus;
7818
7819   pr "\
7820 (** For API documentation you should refer to the C API
7821     in the guestfs(3) manual page.  The OCaml API uses almost
7822     exactly the same calls. *)
7823
7824 type t
7825 (** A [guestfs_h] handle. *)
7826
7827 exception Error of string
7828 (** This exception is raised when there is an error. *)
7829
7830 exception Handle_closed of string
7831 (** This exception is raised if you use a {!Guestfs.t} handle
7832     after calling {!close} on it.  The string is the name of
7833     the function. *)
7834
7835 val create : unit -> t
7836 (** Create a {!Guestfs.t} handle. *)
7837
7838 val close : t -> unit
7839 (** Close the {!Guestfs.t} handle and free up all resources used
7840     by it immediately.
7841
7842     Handles are closed by the garbage collector when they become
7843     unreferenced, but callers can call this in order to provide
7844     predictable cleanup. *)
7845
7846 ";
7847   generate_ocaml_structure_decls ();
7848
7849   (* The actions. *)
7850   List.iter (
7851     fun (name, style, _, _, _, shortdesc, _) ->
7852       generate_ocaml_prototype name style;
7853       pr "(** %s *)\n" shortdesc;
7854       pr "\n"
7855   ) all_functions_sorted
7856
7857 (* Generate the OCaml bindings implementation. *)
7858 and generate_ocaml_ml () =
7859   generate_header OCamlStyle LGPLv2plus;
7860
7861   pr "\
7862 type t
7863
7864 exception Error of string
7865 exception Handle_closed of string
7866
7867 external create : unit -> t = \"ocaml_guestfs_create\"
7868 external close : t -> unit = \"ocaml_guestfs_close\"
7869
7870 (* Give the exceptions names, so they can be raised from the C code. *)
7871 let () =
7872   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7873   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7874
7875 ";
7876
7877   generate_ocaml_structure_decls ();
7878
7879   (* The actions. *)
7880   List.iter (
7881     fun (name, style, _, _, _, shortdesc, _) ->
7882       generate_ocaml_prototype ~is_external:true name style;
7883   ) all_functions_sorted
7884
7885 (* Generate the OCaml bindings C implementation. *)
7886 and generate_ocaml_c () =
7887   generate_header CStyle LGPLv2plus;
7888
7889   pr "\
7890 #include <stdio.h>
7891 #include <stdlib.h>
7892 #include <string.h>
7893
7894 #include <caml/config.h>
7895 #include <caml/alloc.h>
7896 #include <caml/callback.h>
7897 #include <caml/fail.h>
7898 #include <caml/memory.h>
7899 #include <caml/mlvalues.h>
7900 #include <caml/signals.h>
7901
7902 #include <guestfs.h>
7903
7904 #include \"guestfs_c.h\"
7905
7906 /* Copy a hashtable of string pairs into an assoc-list.  We return
7907  * the list in reverse order, but hashtables aren't supposed to be
7908  * ordered anyway.
7909  */
7910 static CAMLprim value
7911 copy_table (char * const * argv)
7912 {
7913   CAMLparam0 ();
7914   CAMLlocal5 (rv, pairv, kv, vv, cons);
7915   int i;
7916
7917   rv = Val_int (0);
7918   for (i = 0; argv[i] != NULL; i += 2) {
7919     kv = caml_copy_string (argv[i]);
7920     vv = caml_copy_string (argv[i+1]);
7921     pairv = caml_alloc (2, 0);
7922     Store_field (pairv, 0, kv);
7923     Store_field (pairv, 1, vv);
7924     cons = caml_alloc (2, 0);
7925     Store_field (cons, 1, rv);
7926     rv = cons;
7927     Store_field (cons, 0, pairv);
7928   }
7929
7930   CAMLreturn (rv);
7931 }
7932
7933 ";
7934
7935   (* Struct copy functions. *)
7936
7937   let emit_ocaml_copy_list_function typ =
7938     pr "static CAMLprim value\n";
7939     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7940     pr "{\n";
7941     pr "  CAMLparam0 ();\n";
7942     pr "  CAMLlocal2 (rv, v);\n";
7943     pr "  unsigned int i;\n";
7944     pr "\n";
7945     pr "  if (%ss->len == 0)\n" typ;
7946     pr "    CAMLreturn (Atom (0));\n";
7947     pr "  else {\n";
7948     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7949     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7950     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7951     pr "      caml_modify (&Field (rv, i), v);\n";
7952     pr "    }\n";
7953     pr "    CAMLreturn (rv);\n";
7954     pr "  }\n";
7955     pr "}\n";
7956     pr "\n";
7957   in
7958
7959   List.iter (
7960     fun (typ, cols) ->
7961       let has_optpercent_col =
7962         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7963
7964       pr "static CAMLprim value\n";
7965       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7966       pr "{\n";
7967       pr "  CAMLparam0 ();\n";
7968       if has_optpercent_col then
7969         pr "  CAMLlocal3 (rv, v, v2);\n"
7970       else
7971         pr "  CAMLlocal2 (rv, v);\n";
7972       pr "\n";
7973       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7974       iteri (
7975         fun i col ->
7976           (match col with
7977            | name, FString ->
7978                pr "  v = caml_copy_string (%s->%s);\n" typ name
7979            | name, FBuffer ->
7980                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7981                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7982                  typ name typ name
7983            | name, FUUID ->
7984                pr "  v = caml_alloc_string (32);\n";
7985                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7986            | name, (FBytes|FInt64|FUInt64) ->
7987                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7988            | name, (FInt32|FUInt32) ->
7989                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7990            | name, FOptPercent ->
7991                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7992                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7993                pr "    v = caml_alloc (1, 0);\n";
7994                pr "    Store_field (v, 0, v2);\n";
7995                pr "  } else /* None */\n";
7996                pr "    v = Val_int (0);\n";
7997            | name, FChar ->
7998                pr "  v = Val_int (%s->%s);\n" typ name
7999           );
8000           pr "  Store_field (rv, %d, v);\n" i
8001       ) cols;
8002       pr "  CAMLreturn (rv);\n";
8003       pr "}\n";
8004       pr "\n";
8005   ) structs;
8006
8007   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8008   List.iter (
8009     function
8010     | typ, (RStructListOnly | RStructAndList) ->
8011         (* generate the function for typ *)
8012         emit_ocaml_copy_list_function typ
8013     | typ, _ -> () (* empty *)
8014   ) (rstructs_used_by all_functions);
8015
8016   (* The wrappers. *)
8017   List.iter (
8018     fun (name, style, _, _, _, _, _) ->
8019       pr "/* Automatically generated wrapper for function\n";
8020       pr " * ";
8021       generate_ocaml_prototype name style;
8022       pr " */\n";
8023       pr "\n";
8024
8025       let params =
8026         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8027
8028       let needs_extra_vs =
8029         match fst style with RConstOptString _ -> true | _ -> false in
8030
8031       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8032       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8033       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8034       pr "\n";
8035
8036       pr "CAMLprim value\n";
8037       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8038       List.iter (pr ", value %s") (List.tl params);
8039       pr ")\n";
8040       pr "{\n";
8041
8042       (match params with
8043        | [p1; p2; p3; p4; p5] ->
8044            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8045        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8046            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8047            pr "  CAMLxparam%d (%s);\n"
8048              (List.length rest) (String.concat ", " rest)
8049        | ps ->
8050            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8051       );
8052       if not needs_extra_vs then
8053         pr "  CAMLlocal1 (rv);\n"
8054       else
8055         pr "  CAMLlocal3 (rv, v, v2);\n";
8056       pr "\n";
8057
8058       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8059       pr "  if (g == NULL)\n";
8060       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8061       pr "\n";
8062
8063       List.iter (
8064         function
8065         | Pathname n
8066         | Device n | Dev_or_Path n
8067         | String n
8068         | FileIn n
8069         | FileOut n ->
8070             pr "  const char *%s = String_val (%sv);\n" n n
8071         | OptString n ->
8072             pr "  const char *%s =\n" n;
8073             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8074               n n
8075         | StringList n | DeviceList n ->
8076             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8077         | Bool n ->
8078             pr "  int %s = Bool_val (%sv);\n" n n
8079         | Int n ->
8080             pr "  int %s = Int_val (%sv);\n" n n
8081         | Int64 n ->
8082             pr "  int64_t %s = Int64_val (%sv);\n" n n
8083       ) (snd style);
8084       let error_code =
8085         match fst style with
8086         | RErr -> pr "  int r;\n"; "-1"
8087         | RInt _ -> pr "  int r;\n"; "-1"
8088         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8089         | RBool _ -> pr "  int r;\n"; "-1"
8090         | RConstString _ | RConstOptString _ ->
8091             pr "  const char *r;\n"; "NULL"
8092         | RString _ -> pr "  char *r;\n"; "NULL"
8093         | RStringList _ ->
8094             pr "  int i;\n";
8095             pr "  char **r;\n";
8096             "NULL"
8097         | RStruct (_, typ) ->
8098             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8099         | RStructList (_, typ) ->
8100             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8101         | RHashtable _ ->
8102             pr "  int i;\n";
8103             pr "  char **r;\n";
8104             "NULL"
8105         | RBufferOut _ ->
8106             pr "  char *r;\n";
8107             pr "  size_t size;\n";
8108             "NULL" in
8109       pr "\n";
8110
8111       pr "  caml_enter_blocking_section ();\n";
8112       pr "  r = guestfs_%s " name;
8113       generate_c_call_args ~handle:"g" style;
8114       pr ";\n";
8115       pr "  caml_leave_blocking_section ();\n";
8116
8117       List.iter (
8118         function
8119         | StringList n | DeviceList n ->
8120             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8121         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8122         | Bool _ | Int _ | Int64 _
8123         | FileIn _ | FileOut _ -> ()
8124       ) (snd style);
8125
8126       pr "  if (r == %s)\n" error_code;
8127       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8128       pr "\n";
8129
8130       (match fst style with
8131        | RErr -> pr "  rv = Val_unit;\n"
8132        | RInt _ -> pr "  rv = Val_int (r);\n"
8133        | RInt64 _ ->
8134            pr "  rv = caml_copy_int64 (r);\n"
8135        | RBool _ -> pr "  rv = Val_bool (r);\n"
8136        | RConstString _ ->
8137            pr "  rv = caml_copy_string (r);\n"
8138        | RConstOptString _ ->
8139            pr "  if (r) { /* Some string */\n";
8140            pr "    v = caml_alloc (1, 0);\n";
8141            pr "    v2 = caml_copy_string (r);\n";
8142            pr "    Store_field (v, 0, v2);\n";
8143            pr "  } else /* None */\n";
8144            pr "    v = Val_int (0);\n";
8145        | RString _ ->
8146            pr "  rv = caml_copy_string (r);\n";
8147            pr "  free (r);\n"
8148        | RStringList _ ->
8149            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8150            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8151            pr "  free (r);\n"
8152        | RStruct (_, typ) ->
8153            pr "  rv = copy_%s (r);\n" typ;
8154            pr "  guestfs_free_%s (r);\n" typ;
8155        | RStructList (_, typ) ->
8156            pr "  rv = copy_%s_list (r);\n" typ;
8157            pr "  guestfs_free_%s_list (r);\n" typ;
8158        | RHashtable _ ->
8159            pr "  rv = copy_table (r);\n";
8160            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8161            pr "  free (r);\n";
8162        | RBufferOut _ ->
8163            pr "  rv = caml_alloc_string (size);\n";
8164            pr "  memcpy (String_val (rv), r, size);\n";
8165       );
8166
8167       pr "  CAMLreturn (rv);\n";
8168       pr "}\n";
8169       pr "\n";
8170
8171       if List.length params > 5 then (
8172         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8173         pr "CAMLprim value ";
8174         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8175         pr "CAMLprim value\n";
8176         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8177         pr "{\n";
8178         pr "  return ocaml_guestfs_%s (argv[0]" name;
8179         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8180         pr ");\n";
8181         pr "}\n";
8182         pr "\n"
8183       )
8184   ) all_functions_sorted
8185
8186 and generate_ocaml_structure_decls () =
8187   List.iter (
8188     fun (typ, cols) ->
8189       pr "type %s = {\n" typ;
8190       List.iter (
8191         function
8192         | name, FString -> pr "  %s : string;\n" name
8193         | name, FBuffer -> pr "  %s : string;\n" name
8194         | name, FUUID -> pr "  %s : string;\n" name
8195         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8196         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8197         | name, FChar -> pr "  %s : char;\n" name
8198         | name, FOptPercent -> pr "  %s : float option;\n" name
8199       ) cols;
8200       pr "}\n";
8201       pr "\n"
8202   ) structs
8203
8204 and generate_ocaml_prototype ?(is_external = false) name style =
8205   if is_external then pr "external " else pr "val ";
8206   pr "%s : t -> " name;
8207   List.iter (
8208     function
8209     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8210     | OptString _ -> pr "string option -> "
8211     | StringList _ | DeviceList _ -> pr "string array -> "
8212     | Bool _ -> pr "bool -> "
8213     | Int _ -> pr "int -> "
8214     | Int64 _ -> pr "int64 -> "
8215   ) (snd style);
8216   (match fst style with
8217    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8218    | RInt _ -> pr "int"
8219    | RInt64 _ -> pr "int64"
8220    | RBool _ -> pr "bool"
8221    | RConstString _ -> pr "string"
8222    | RConstOptString _ -> pr "string option"
8223    | RString _ | RBufferOut _ -> pr "string"
8224    | RStringList _ -> pr "string array"
8225    | RStruct (_, typ) -> pr "%s" typ
8226    | RStructList (_, typ) -> pr "%s array" typ
8227    | RHashtable _ -> pr "(string * string) list"
8228   );
8229   if is_external then (
8230     pr " = ";
8231     if List.length (snd style) + 1 > 5 then
8232       pr "\"ocaml_guestfs_%s_byte\" " name;
8233     pr "\"ocaml_guestfs_%s\"" name
8234   );
8235   pr "\n"
8236
8237 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8238 and generate_perl_xs () =
8239   generate_header CStyle LGPLv2plus;
8240
8241   pr "\
8242 #include \"EXTERN.h\"
8243 #include \"perl.h\"
8244 #include \"XSUB.h\"
8245
8246 #include <guestfs.h>
8247
8248 #ifndef PRId64
8249 #define PRId64 \"lld\"
8250 #endif
8251
8252 static SV *
8253 my_newSVll(long long val) {
8254 #ifdef USE_64_BIT_ALL
8255   return newSViv(val);
8256 #else
8257   char buf[100];
8258   int len;
8259   len = snprintf(buf, 100, \"%%\" PRId64, val);
8260   return newSVpv(buf, len);
8261 #endif
8262 }
8263
8264 #ifndef PRIu64
8265 #define PRIu64 \"llu\"
8266 #endif
8267
8268 static SV *
8269 my_newSVull(unsigned long long val) {
8270 #ifdef USE_64_BIT_ALL
8271   return newSVuv(val);
8272 #else
8273   char buf[100];
8274   int len;
8275   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8276   return newSVpv(buf, len);
8277 #endif
8278 }
8279
8280 /* http://www.perlmonks.org/?node_id=680842 */
8281 static char **
8282 XS_unpack_charPtrPtr (SV *arg) {
8283   char **ret;
8284   AV *av;
8285   I32 i;
8286
8287   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8288     croak (\"array reference expected\");
8289
8290   av = (AV *)SvRV (arg);
8291   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8292   if (!ret)
8293     croak (\"malloc failed\");
8294
8295   for (i = 0; i <= av_len (av); i++) {
8296     SV **elem = av_fetch (av, i, 0);
8297
8298     if (!elem || !*elem)
8299       croak (\"missing element in list\");
8300
8301     ret[i] = SvPV_nolen (*elem);
8302   }
8303
8304   ret[i] = NULL;
8305
8306   return ret;
8307 }
8308
8309 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8310
8311 PROTOTYPES: ENABLE
8312
8313 guestfs_h *
8314 _create ()
8315    CODE:
8316       RETVAL = guestfs_create ();
8317       if (!RETVAL)
8318         croak (\"could not create guestfs handle\");
8319       guestfs_set_error_handler (RETVAL, NULL, NULL);
8320  OUTPUT:
8321       RETVAL
8322
8323 void
8324 DESTROY (g)
8325       guestfs_h *g;
8326  PPCODE:
8327       guestfs_close (g);
8328
8329 ";
8330
8331   List.iter (
8332     fun (name, style, _, _, _, _, _) ->
8333       (match fst style with
8334        | RErr -> pr "void\n"
8335        | RInt _ -> pr "SV *\n"
8336        | RInt64 _ -> pr "SV *\n"
8337        | RBool _ -> pr "SV *\n"
8338        | RConstString _ -> pr "SV *\n"
8339        | RConstOptString _ -> pr "SV *\n"
8340        | RString _ -> pr "SV *\n"
8341        | RBufferOut _ -> pr "SV *\n"
8342        | RStringList _
8343        | RStruct _ | RStructList _
8344        | RHashtable _ ->
8345            pr "void\n" (* all lists returned implictly on the stack *)
8346       );
8347       (* Call and arguments. *)
8348       pr "%s " name;
8349       generate_c_call_args ~handle:"g" ~decl:true style;
8350       pr "\n";
8351       pr "      guestfs_h *g;\n";
8352       iteri (
8353         fun i ->
8354           function
8355           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8356               pr "      char *%s;\n" n
8357           | OptString n ->
8358               (* http://www.perlmonks.org/?node_id=554277
8359                * Note that the implicit handle argument means we have
8360                * to add 1 to the ST(x) operator.
8361                *)
8362               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8363           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8364           | Bool n -> pr "      int %s;\n" n
8365           | Int n -> pr "      int %s;\n" n
8366           | Int64 n -> pr "      int64_t %s;\n" n
8367       ) (snd style);
8368
8369       let do_cleanups () =
8370         List.iter (
8371           function
8372           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8373           | Bool _ | Int _ | Int64 _
8374           | FileIn _ | FileOut _ -> ()
8375           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8376         ) (snd style)
8377       in
8378
8379       (* Code. *)
8380       (match fst style with
8381        | RErr ->
8382            pr "PREINIT:\n";
8383            pr "      int r;\n";
8384            pr " PPCODE:\n";
8385            pr "      r = guestfs_%s " name;
8386            generate_c_call_args ~handle:"g" style;
8387            pr ";\n";
8388            do_cleanups ();
8389            pr "      if (r == -1)\n";
8390            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8391        | RInt n
8392        | RBool n ->
8393            pr "PREINIT:\n";
8394            pr "      int %s;\n" n;
8395            pr "   CODE:\n";
8396            pr "      %s = guestfs_%s " n name;
8397            generate_c_call_args ~handle:"g" style;
8398            pr ";\n";
8399            do_cleanups ();
8400            pr "      if (%s == -1)\n" n;
8401            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8402            pr "      RETVAL = newSViv (%s);\n" n;
8403            pr " OUTPUT:\n";
8404            pr "      RETVAL\n"
8405        | RInt64 n ->
8406            pr "PREINIT:\n";
8407            pr "      int64_t %s;\n" n;
8408            pr "   CODE:\n";
8409            pr "      %s = guestfs_%s " n name;
8410            generate_c_call_args ~handle:"g" style;
8411            pr ";\n";
8412            do_cleanups ();
8413            pr "      if (%s == -1)\n" n;
8414            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8415            pr "      RETVAL = my_newSVll (%s);\n" n;
8416            pr " OUTPUT:\n";
8417            pr "      RETVAL\n"
8418        | RConstString n ->
8419            pr "PREINIT:\n";
8420            pr "      const char *%s;\n" n;
8421            pr "   CODE:\n";
8422            pr "      %s = guestfs_%s " n name;
8423            generate_c_call_args ~handle:"g" style;
8424            pr ";\n";
8425            do_cleanups ();
8426            pr "      if (%s == NULL)\n" n;
8427            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8428            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8429            pr " OUTPUT:\n";
8430            pr "      RETVAL\n"
8431        | RConstOptString n ->
8432            pr "PREINIT:\n";
8433            pr "      const char *%s;\n" n;
8434            pr "   CODE:\n";
8435            pr "      %s = guestfs_%s " n name;
8436            generate_c_call_args ~handle:"g" style;
8437            pr ";\n";
8438            do_cleanups ();
8439            pr "      if (%s == NULL)\n" n;
8440            pr "        RETVAL = &PL_sv_undef;\n";
8441            pr "      else\n";
8442            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8443            pr " OUTPUT:\n";
8444            pr "      RETVAL\n"
8445        | RString n ->
8446            pr "PREINIT:\n";
8447            pr "      char *%s;\n" n;
8448            pr "   CODE:\n";
8449            pr "      %s = guestfs_%s " n name;
8450            generate_c_call_args ~handle:"g" style;
8451            pr ";\n";
8452            do_cleanups ();
8453            pr "      if (%s == NULL)\n" n;
8454            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8455            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8456            pr "      free (%s);\n" n;
8457            pr " OUTPUT:\n";
8458            pr "      RETVAL\n"
8459        | RStringList n | RHashtable n ->
8460            pr "PREINIT:\n";
8461            pr "      char **%s;\n" n;
8462            pr "      int i, n;\n";
8463            pr " PPCODE:\n";
8464            pr "      %s = guestfs_%s " n name;
8465            generate_c_call_args ~handle:"g" style;
8466            pr ";\n";
8467            do_cleanups ();
8468            pr "      if (%s == NULL)\n" n;
8469            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8470            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8471            pr "      EXTEND (SP, n);\n";
8472            pr "      for (i = 0; i < n; ++i) {\n";
8473            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8474            pr "        free (%s[i]);\n" n;
8475            pr "      }\n";
8476            pr "      free (%s);\n" n;
8477        | RStruct (n, typ) ->
8478            let cols = cols_of_struct typ in
8479            generate_perl_struct_code typ cols name style n do_cleanups
8480        | RStructList (n, typ) ->
8481            let cols = cols_of_struct typ in
8482            generate_perl_struct_list_code typ cols name style n do_cleanups
8483        | RBufferOut n ->
8484            pr "PREINIT:\n";
8485            pr "      char *%s;\n" n;
8486            pr "      size_t size;\n";
8487            pr "   CODE:\n";
8488            pr "      %s = guestfs_%s " n name;
8489            generate_c_call_args ~handle:"g" style;
8490            pr ";\n";
8491            do_cleanups ();
8492            pr "      if (%s == NULL)\n" n;
8493            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8494            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8495            pr "      free (%s);\n" n;
8496            pr " OUTPUT:\n";
8497            pr "      RETVAL\n"
8498       );
8499
8500       pr "\n"
8501   ) all_functions
8502
8503 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8504   pr "PREINIT:\n";
8505   pr "      struct guestfs_%s_list *%s;\n" typ n;
8506   pr "      int i;\n";
8507   pr "      HV *hv;\n";
8508   pr " PPCODE:\n";
8509   pr "      %s = guestfs_%s " n name;
8510   generate_c_call_args ~handle:"g" style;
8511   pr ";\n";
8512   do_cleanups ();
8513   pr "      if (%s == NULL)\n" n;
8514   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8515   pr "      EXTEND (SP, %s->len);\n" n;
8516   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8517   pr "        hv = newHV ();\n";
8518   List.iter (
8519     function
8520     | name, FString ->
8521         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8522           name (String.length name) n name
8523     | name, FUUID ->
8524         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8525           name (String.length name) n name
8526     | name, FBuffer ->
8527         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8528           name (String.length name) n name n name
8529     | name, (FBytes|FUInt64) ->
8530         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8531           name (String.length name) n name
8532     | name, FInt64 ->
8533         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8534           name (String.length name) n name
8535     | name, (FInt32|FUInt32) ->
8536         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8537           name (String.length name) n name
8538     | name, FChar ->
8539         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8540           name (String.length name) n name
8541     | name, FOptPercent ->
8542         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8543           name (String.length name) n name
8544   ) cols;
8545   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8546   pr "      }\n";
8547   pr "      guestfs_free_%s_list (%s);\n" typ n
8548
8549 and generate_perl_struct_code typ cols name style n do_cleanups =
8550   pr "PREINIT:\n";
8551   pr "      struct guestfs_%s *%s;\n" typ n;
8552   pr " PPCODE:\n";
8553   pr "      %s = guestfs_%s " n name;
8554   generate_c_call_args ~handle:"g" style;
8555   pr ";\n";
8556   do_cleanups ();
8557   pr "      if (%s == NULL)\n" n;
8558   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8559   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8560   List.iter (
8561     fun ((name, _) as col) ->
8562       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8563
8564       match col with
8565       | name, FString ->
8566           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8567             n name
8568       | name, FBuffer ->
8569           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8570             n name n name
8571       | name, FUUID ->
8572           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8573             n name
8574       | name, (FBytes|FUInt64) ->
8575           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8576             n name
8577       | name, FInt64 ->
8578           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8579             n name
8580       | name, (FInt32|FUInt32) ->
8581           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8582             n name
8583       | name, FChar ->
8584           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8585             n name
8586       | name, FOptPercent ->
8587           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8588             n name
8589   ) cols;
8590   pr "      free (%s);\n" n
8591
8592 (* Generate Sys/Guestfs.pm. *)
8593 and generate_perl_pm () =
8594   generate_header HashStyle LGPLv2plus;
8595
8596   pr "\
8597 =pod
8598
8599 =head1 NAME
8600
8601 Sys::Guestfs - Perl bindings for libguestfs
8602
8603 =head1 SYNOPSIS
8604
8605  use Sys::Guestfs;
8606
8607  my $h = Sys::Guestfs->new ();
8608  $h->add_drive ('guest.img');
8609  $h->launch ();
8610  $h->mount ('/dev/sda1', '/');
8611  $h->touch ('/hello');
8612  $h->sync ();
8613
8614 =head1 DESCRIPTION
8615
8616 The C<Sys::Guestfs> module provides a Perl XS binding to the
8617 libguestfs API for examining and modifying virtual machine
8618 disk images.
8619
8620 Amongst the things this is good for: making batch configuration
8621 changes to guests, getting disk used/free statistics (see also:
8622 virt-df), migrating between virtualization systems (see also:
8623 virt-p2v), performing partial backups, performing partial guest
8624 clones, cloning guests and changing registry/UUID/hostname info, and
8625 much else besides.
8626
8627 Libguestfs uses Linux kernel and qemu code, and can access any type of
8628 guest filesystem that Linux and qemu can, including but not limited
8629 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8630 schemes, qcow, qcow2, vmdk.
8631
8632 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8633 LVs, what filesystem is in each LV, etc.).  It can also run commands
8634 in the context of the guest.  Also you can access filesystems over
8635 FUSE.
8636
8637 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8638 functions for using libguestfs from Perl, including integration
8639 with libvirt.
8640
8641 =head1 ERRORS
8642
8643 All errors turn into calls to C<croak> (see L<Carp(3)>).
8644
8645 =head1 METHODS
8646
8647 =over 4
8648
8649 =cut
8650
8651 package Sys::Guestfs;
8652
8653 use strict;
8654 use warnings;
8655
8656 require XSLoader;
8657 XSLoader::load ('Sys::Guestfs');
8658
8659 =item $h = Sys::Guestfs->new ();
8660
8661 Create a new guestfs handle.
8662
8663 =cut
8664
8665 sub new {
8666   my $proto = shift;
8667   my $class = ref ($proto) || $proto;
8668
8669   my $self = Sys::Guestfs::_create ();
8670   bless $self, $class;
8671   return $self;
8672 }
8673
8674 ";
8675
8676   (* Actions.  We only need to print documentation for these as
8677    * they are pulled in from the XS code automatically.
8678    *)
8679   List.iter (
8680     fun (name, style, _, flags, _, _, longdesc) ->
8681       if not (List.mem NotInDocs flags) then (
8682         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8683         pr "=item ";
8684         generate_perl_prototype name style;
8685         pr "\n\n";
8686         pr "%s\n\n" longdesc;
8687         if List.mem ProtocolLimitWarning flags then
8688           pr "%s\n\n" protocol_limit_warning;
8689         if List.mem DangerWillRobinson flags then
8690           pr "%s\n\n" danger_will_robinson;
8691         match deprecation_notice flags with
8692         | None -> ()
8693         | Some txt -> pr "%s\n\n" txt
8694       )
8695   ) all_functions_sorted;
8696
8697   (* End of file. *)
8698   pr "\
8699 =cut
8700
8701 1;
8702
8703 =back
8704
8705 =head1 COPYRIGHT
8706
8707 Copyright (C) %s Red Hat Inc.
8708
8709 =head1 LICENSE
8710
8711 Please see the file COPYING.LIB for the full license.
8712
8713 =head1 SEE ALSO
8714
8715 L<guestfs(3)>,
8716 L<guestfish(1)>,
8717 L<http://libguestfs.org>,
8718 L<Sys::Guestfs::Lib(3)>.
8719
8720 =cut
8721 " copyright_years
8722
8723 and generate_perl_prototype name style =
8724   (match fst style with
8725    | RErr -> ()
8726    | RBool n
8727    | RInt n
8728    | RInt64 n
8729    | RConstString n
8730    | RConstOptString n
8731    | RString n
8732    | RBufferOut n -> pr "$%s = " n
8733    | RStruct (n,_)
8734    | RHashtable n -> pr "%%%s = " n
8735    | RStringList n
8736    | RStructList (n,_) -> pr "@%s = " n
8737   );
8738   pr "$h->%s (" name;
8739   let comma = ref false in
8740   List.iter (
8741     fun arg ->
8742       if !comma then pr ", ";
8743       comma := true;
8744       match arg with
8745       | Pathname n | Device n | Dev_or_Path n | String n
8746       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8747           pr "$%s" n
8748       | StringList n | DeviceList n ->
8749           pr "\\@%s" n
8750   ) (snd style);
8751   pr ");"
8752
8753 (* Generate Python C module. *)
8754 and generate_python_c () =
8755   generate_header CStyle LGPLv2plus;
8756
8757   pr "\
8758 #include <Python.h>
8759
8760 #include <stdio.h>
8761 #include <stdlib.h>
8762 #include <assert.h>
8763
8764 #include \"guestfs.h\"
8765
8766 typedef struct {
8767   PyObject_HEAD
8768   guestfs_h *g;
8769 } Pyguestfs_Object;
8770
8771 static guestfs_h *
8772 get_handle (PyObject *obj)
8773 {
8774   assert (obj);
8775   assert (obj != Py_None);
8776   return ((Pyguestfs_Object *) obj)->g;
8777 }
8778
8779 static PyObject *
8780 put_handle (guestfs_h *g)
8781 {
8782   assert (g);
8783   return
8784     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8785 }
8786
8787 /* This list should be freed (but not the strings) after use. */
8788 static char **
8789 get_string_list (PyObject *obj)
8790 {
8791   int i, len;
8792   char **r;
8793
8794   assert (obj);
8795
8796   if (!PyList_Check (obj)) {
8797     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8798     return NULL;
8799   }
8800
8801   len = PyList_Size (obj);
8802   r = malloc (sizeof (char *) * (len+1));
8803   if (r == NULL) {
8804     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8805     return NULL;
8806   }
8807
8808   for (i = 0; i < len; ++i)
8809     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8810   r[len] = NULL;
8811
8812   return r;
8813 }
8814
8815 static PyObject *
8816 put_string_list (char * const * const argv)
8817 {
8818   PyObject *list;
8819   int argc, i;
8820
8821   for (argc = 0; argv[argc] != NULL; ++argc)
8822     ;
8823
8824   list = PyList_New (argc);
8825   for (i = 0; i < argc; ++i)
8826     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8827
8828   return list;
8829 }
8830
8831 static PyObject *
8832 put_table (char * const * const argv)
8833 {
8834   PyObject *list, *item;
8835   int argc, i;
8836
8837   for (argc = 0; argv[argc] != NULL; ++argc)
8838     ;
8839
8840   list = PyList_New (argc >> 1);
8841   for (i = 0; i < argc; i += 2) {
8842     item = PyTuple_New (2);
8843     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8844     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8845     PyList_SetItem (list, i >> 1, item);
8846   }
8847
8848   return list;
8849 }
8850
8851 static void
8852 free_strings (char **argv)
8853 {
8854   int argc;
8855
8856   for (argc = 0; argv[argc] != NULL; ++argc)
8857     free (argv[argc]);
8858   free (argv);
8859 }
8860
8861 static PyObject *
8862 py_guestfs_create (PyObject *self, PyObject *args)
8863 {
8864   guestfs_h *g;
8865
8866   g = guestfs_create ();
8867   if (g == NULL) {
8868     PyErr_SetString (PyExc_RuntimeError,
8869                      \"guestfs.create: failed to allocate handle\");
8870     return NULL;
8871   }
8872   guestfs_set_error_handler (g, NULL, NULL);
8873   return put_handle (g);
8874 }
8875
8876 static PyObject *
8877 py_guestfs_close (PyObject *self, PyObject *args)
8878 {
8879   PyObject *py_g;
8880   guestfs_h *g;
8881
8882   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8883     return NULL;
8884   g = get_handle (py_g);
8885
8886   guestfs_close (g);
8887
8888   Py_INCREF (Py_None);
8889   return Py_None;
8890 }
8891
8892 ";
8893
8894   let emit_put_list_function typ =
8895     pr "static PyObject *\n";
8896     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8897     pr "{\n";
8898     pr "  PyObject *list;\n";
8899     pr "  int i;\n";
8900     pr "\n";
8901     pr "  list = PyList_New (%ss->len);\n" typ;
8902     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8903     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8904     pr "  return list;\n";
8905     pr "};\n";
8906     pr "\n"
8907   in
8908
8909   (* Structures, turned into Python dictionaries. *)
8910   List.iter (
8911     fun (typ, cols) ->
8912       pr "static PyObject *\n";
8913       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8914       pr "{\n";
8915       pr "  PyObject *dict;\n";
8916       pr "\n";
8917       pr "  dict = PyDict_New ();\n";
8918       List.iter (
8919         function
8920         | name, FString ->
8921             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8922             pr "                        PyString_FromString (%s->%s));\n"
8923               typ name
8924         | name, FBuffer ->
8925             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8926             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8927               typ name typ name
8928         | name, FUUID ->
8929             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8930             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8931               typ name
8932         | name, (FBytes|FUInt64) ->
8933             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8934             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8935               typ name
8936         | name, FInt64 ->
8937             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8938             pr "                        PyLong_FromLongLong (%s->%s));\n"
8939               typ name
8940         | name, FUInt32 ->
8941             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8942             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8943               typ name
8944         | name, FInt32 ->
8945             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8946             pr "                        PyLong_FromLong (%s->%s));\n"
8947               typ name
8948         | name, FOptPercent ->
8949             pr "  if (%s->%s >= 0)\n" typ name;
8950             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8951             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8952               typ name;
8953             pr "  else {\n";
8954             pr "    Py_INCREF (Py_None);\n";
8955             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8956             pr "  }\n"
8957         | name, FChar ->
8958             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8959             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8960       ) cols;
8961       pr "  return dict;\n";
8962       pr "};\n";
8963       pr "\n";
8964
8965   ) structs;
8966
8967   (* Emit a put_TYPE_list function definition only if that function is used. *)
8968   List.iter (
8969     function
8970     | typ, (RStructListOnly | RStructAndList) ->
8971         (* generate the function for typ *)
8972         emit_put_list_function typ
8973     | typ, _ -> () (* empty *)
8974   ) (rstructs_used_by all_functions);
8975
8976   (* Python wrapper functions. *)
8977   List.iter (
8978     fun (name, style, _, _, _, _, _) ->
8979       pr "static PyObject *\n";
8980       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8981       pr "{\n";
8982
8983       pr "  PyObject *py_g;\n";
8984       pr "  guestfs_h *g;\n";
8985       pr "  PyObject *py_r;\n";
8986
8987       let error_code =
8988         match fst style with
8989         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8990         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8991         | RConstString _ | RConstOptString _ ->
8992             pr "  const char *r;\n"; "NULL"
8993         | RString _ -> pr "  char *r;\n"; "NULL"
8994         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8995         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8996         | RStructList (_, typ) ->
8997             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8998         | RBufferOut _ ->
8999             pr "  char *r;\n";
9000             pr "  size_t size;\n";
9001             "NULL" in
9002
9003       List.iter (
9004         function
9005         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9006             pr "  const char *%s;\n" n
9007         | OptString n -> pr "  const char *%s;\n" n
9008         | StringList n | DeviceList n ->
9009             pr "  PyObject *py_%s;\n" n;
9010             pr "  char **%s;\n" n
9011         | Bool n -> pr "  int %s;\n" n
9012         | Int n -> pr "  int %s;\n" n
9013         | Int64 n -> pr "  long long %s;\n" n
9014       ) (snd style);
9015
9016       pr "\n";
9017
9018       (* Convert the parameters. *)
9019       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9020       List.iter (
9021         function
9022         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9023         | OptString _ -> pr "z"
9024         | StringList _ | DeviceList _ -> pr "O"
9025         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9026         | Int _ -> pr "i"
9027         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9028                              * emulate C's int/long/long long in Python?
9029                              *)
9030       ) (snd style);
9031       pr ":guestfs_%s\",\n" name;
9032       pr "                         &py_g";
9033       List.iter (
9034         function
9035         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9036         | OptString n -> pr ", &%s" n
9037         | StringList n | DeviceList n -> pr ", &py_%s" n
9038         | Bool n -> pr ", &%s" n
9039         | Int n -> pr ", &%s" n
9040         | Int64 n -> pr ", &%s" n
9041       ) (snd style);
9042
9043       pr "))\n";
9044       pr "    return NULL;\n";
9045
9046       pr "  g = get_handle (py_g);\n";
9047       List.iter (
9048         function
9049         | Pathname _ | Device _ | Dev_or_Path _ | String _
9050         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9051         | StringList n | DeviceList n ->
9052             pr "  %s = get_string_list (py_%s);\n" n n;
9053             pr "  if (!%s) return NULL;\n" n
9054       ) (snd style);
9055
9056       pr "\n";
9057
9058       pr "  r = guestfs_%s " name;
9059       generate_c_call_args ~handle:"g" style;
9060       pr ";\n";
9061
9062       List.iter (
9063         function
9064         | Pathname _ | Device _ | Dev_or_Path _ | String _
9065         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9066         | StringList n | DeviceList n ->
9067             pr "  free (%s);\n" n
9068       ) (snd style);
9069
9070       pr "  if (r == %s) {\n" error_code;
9071       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9072       pr "    return NULL;\n";
9073       pr "  }\n";
9074       pr "\n";
9075
9076       (match fst style with
9077        | RErr ->
9078            pr "  Py_INCREF (Py_None);\n";
9079            pr "  py_r = Py_None;\n"
9080        | RInt _
9081        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9082        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9083        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9084        | RConstOptString _ ->
9085            pr "  if (r)\n";
9086            pr "    py_r = PyString_FromString (r);\n";
9087            pr "  else {\n";
9088            pr "    Py_INCREF (Py_None);\n";
9089            pr "    py_r = Py_None;\n";
9090            pr "  }\n"
9091        | RString _ ->
9092            pr "  py_r = PyString_FromString (r);\n";
9093            pr "  free (r);\n"
9094        | RStringList _ ->
9095            pr "  py_r = put_string_list (r);\n";
9096            pr "  free_strings (r);\n"
9097        | RStruct (_, typ) ->
9098            pr "  py_r = put_%s (r);\n" typ;
9099            pr "  guestfs_free_%s (r);\n" typ
9100        | RStructList (_, typ) ->
9101            pr "  py_r = put_%s_list (r);\n" typ;
9102            pr "  guestfs_free_%s_list (r);\n" typ
9103        | RHashtable n ->
9104            pr "  py_r = put_table (r);\n";
9105            pr "  free_strings (r);\n"
9106        | RBufferOut _ ->
9107            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9108            pr "  free (r);\n"
9109       );
9110
9111       pr "  return py_r;\n";
9112       pr "}\n";
9113       pr "\n"
9114   ) all_functions;
9115
9116   (* Table of functions. *)
9117   pr "static PyMethodDef methods[] = {\n";
9118   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9119   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9120   List.iter (
9121     fun (name, _, _, _, _, _, _) ->
9122       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9123         name name
9124   ) all_functions;
9125   pr "  { NULL, NULL, 0, NULL }\n";
9126   pr "};\n";
9127   pr "\n";
9128
9129   (* Init function. *)
9130   pr "\
9131 void
9132 initlibguestfsmod (void)
9133 {
9134   static int initialized = 0;
9135
9136   if (initialized) return;
9137   Py_InitModule ((char *) \"libguestfsmod\", methods);
9138   initialized = 1;
9139 }
9140 "
9141
9142 (* Generate Python module. *)
9143 and generate_python_py () =
9144   generate_header HashStyle LGPLv2plus;
9145
9146   pr "\
9147 u\"\"\"Python bindings for libguestfs
9148
9149 import guestfs
9150 g = guestfs.GuestFS ()
9151 g.add_drive (\"guest.img\")
9152 g.launch ()
9153 parts = g.list_partitions ()
9154
9155 The guestfs module provides a Python binding to the libguestfs API
9156 for examining and modifying virtual machine disk images.
9157
9158 Amongst the things this is good for: making batch configuration
9159 changes to guests, getting disk used/free statistics (see also:
9160 virt-df), migrating between virtualization systems (see also:
9161 virt-p2v), performing partial backups, performing partial guest
9162 clones, cloning guests and changing registry/UUID/hostname info, and
9163 much else besides.
9164
9165 Libguestfs uses Linux kernel and qemu code, and can access any type of
9166 guest filesystem that Linux and qemu can, including but not limited
9167 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9168 schemes, qcow, qcow2, vmdk.
9169
9170 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9171 LVs, what filesystem is in each LV, etc.).  It can also run commands
9172 in the context of the guest.  Also you can access filesystems over
9173 FUSE.
9174
9175 Errors which happen while using the API are turned into Python
9176 RuntimeError exceptions.
9177
9178 To create a guestfs handle you usually have to perform the following
9179 sequence of calls:
9180
9181 # Create the handle, call add_drive at least once, and possibly
9182 # several times if the guest has multiple block devices:
9183 g = guestfs.GuestFS ()
9184 g.add_drive (\"guest.img\")
9185
9186 # Launch the qemu subprocess and wait for it to become ready:
9187 g.launch ()
9188
9189 # Now you can issue commands, for example:
9190 logvols = g.lvs ()
9191
9192 \"\"\"
9193
9194 import libguestfsmod
9195
9196 class GuestFS:
9197     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9198
9199     def __init__ (self):
9200         \"\"\"Create a new libguestfs handle.\"\"\"
9201         self._o = libguestfsmod.create ()
9202
9203     def __del__ (self):
9204         libguestfsmod.close (self._o)
9205
9206 ";
9207
9208   List.iter (
9209     fun (name, style, _, flags, _, _, longdesc) ->
9210       pr "    def %s " name;
9211       generate_py_call_args ~handle:"self" (snd style);
9212       pr ":\n";
9213
9214       if not (List.mem NotInDocs flags) then (
9215         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9216         let doc =
9217           match fst style with
9218           | RErr | RInt _ | RInt64 _ | RBool _
9219           | RConstOptString _ | RConstString _
9220           | RString _ | RBufferOut _ -> doc
9221           | RStringList _ ->
9222               doc ^ "\n\nThis function returns a list of strings."
9223           | RStruct (_, typ) ->
9224               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9225           | RStructList (_, typ) ->
9226               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9227           | RHashtable _ ->
9228               doc ^ "\n\nThis function returns a dictionary." in
9229         let doc =
9230           if List.mem ProtocolLimitWarning flags then
9231             doc ^ "\n\n" ^ protocol_limit_warning
9232           else doc in
9233         let doc =
9234           if List.mem DangerWillRobinson flags then
9235             doc ^ "\n\n" ^ danger_will_robinson
9236           else doc in
9237         let doc =
9238           match deprecation_notice flags with
9239           | None -> doc
9240           | Some txt -> doc ^ "\n\n" ^ txt in
9241         let doc = pod2text ~width:60 name doc in
9242         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9243         let doc = String.concat "\n        " doc in
9244         pr "        u\"\"\"%s\"\"\"\n" doc;
9245       );
9246       pr "        return libguestfsmod.%s " name;
9247       generate_py_call_args ~handle:"self._o" (snd style);
9248       pr "\n";
9249       pr "\n";
9250   ) all_functions
9251
9252 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9253 and generate_py_call_args ~handle args =
9254   pr "(%s" handle;
9255   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9256   pr ")"
9257
9258 (* Useful if you need the longdesc POD text as plain text.  Returns a
9259  * list of lines.
9260  *
9261  * Because this is very slow (the slowest part of autogeneration),
9262  * we memoize the results.
9263  *)
9264 and pod2text ~width name longdesc =
9265   let key = width, name, longdesc in
9266   try Hashtbl.find pod2text_memo key
9267   with Not_found ->
9268     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9269     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9270     close_out chan;
9271     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9272     let chan = open_process_in cmd in
9273     let lines = ref [] in
9274     let rec loop i =
9275       let line = input_line chan in
9276       if i = 1 then             (* discard the first line of output *)
9277         loop (i+1)
9278       else (
9279         let line = triml line in
9280         lines := line :: !lines;
9281         loop (i+1)
9282       ) in
9283     let lines = try loop 1 with End_of_file -> List.rev !lines in
9284     unlink filename;
9285     (match close_process_in chan with
9286      | WEXITED 0 -> ()
9287      | WEXITED i ->
9288          failwithf "pod2text: process exited with non-zero status (%d)" i
9289      | WSIGNALED i | WSTOPPED i ->
9290          failwithf "pod2text: process signalled or stopped by signal %d" i
9291     );
9292     Hashtbl.add pod2text_memo key lines;
9293     pod2text_memo_updated ();
9294     lines
9295
9296 (* Generate ruby bindings. *)
9297 and generate_ruby_c () =
9298   generate_header CStyle LGPLv2plus;
9299
9300   pr "\
9301 #include <stdio.h>
9302 #include <stdlib.h>
9303
9304 #include <ruby.h>
9305
9306 #include \"guestfs.h\"
9307
9308 #include \"extconf.h\"
9309
9310 /* For Ruby < 1.9 */
9311 #ifndef RARRAY_LEN
9312 #define RARRAY_LEN(r) (RARRAY((r))->len)
9313 #endif
9314
9315 static VALUE m_guestfs;                 /* guestfs module */
9316 static VALUE c_guestfs;                 /* guestfs_h handle */
9317 static VALUE e_Error;                   /* used for all errors */
9318
9319 static void ruby_guestfs_free (void *p)
9320 {
9321   if (!p) return;
9322   guestfs_close ((guestfs_h *) p);
9323 }
9324
9325 static VALUE ruby_guestfs_create (VALUE m)
9326 {
9327   guestfs_h *g;
9328
9329   g = guestfs_create ();
9330   if (!g)
9331     rb_raise (e_Error, \"failed to create guestfs handle\");
9332
9333   /* Don't print error messages to stderr by default. */
9334   guestfs_set_error_handler (g, NULL, NULL);
9335
9336   /* Wrap it, and make sure the close function is called when the
9337    * handle goes away.
9338    */
9339   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9340 }
9341
9342 static VALUE ruby_guestfs_close (VALUE gv)
9343 {
9344   guestfs_h *g;
9345   Data_Get_Struct (gv, guestfs_h, g);
9346
9347   ruby_guestfs_free (g);
9348   DATA_PTR (gv) = NULL;
9349
9350   return Qnil;
9351 }
9352
9353 ";
9354
9355   List.iter (
9356     fun (name, style, _, _, _, _, _) ->
9357       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9358       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9359       pr ")\n";
9360       pr "{\n";
9361       pr "  guestfs_h *g;\n";
9362       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9363       pr "  if (!g)\n";
9364       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9365         name;
9366       pr "\n";
9367
9368       List.iter (
9369         function
9370         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9371             pr "  Check_Type (%sv, T_STRING);\n" n;
9372             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9373             pr "  if (!%s)\n" n;
9374             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9375             pr "              \"%s\", \"%s\");\n" n name
9376         | OptString n ->
9377             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9378         | StringList n | DeviceList n ->
9379             pr "  char **%s;\n" n;
9380             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9381             pr "  {\n";
9382             pr "    int i, len;\n";
9383             pr "    len = RARRAY_LEN (%sv);\n" n;
9384             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9385               n;
9386             pr "    for (i = 0; i < len; ++i) {\n";
9387             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9388             pr "      %s[i] = StringValueCStr (v);\n" n;
9389             pr "    }\n";
9390             pr "    %s[len] = NULL;\n" n;
9391             pr "  }\n";
9392         | Bool n ->
9393             pr "  int %s = RTEST (%sv);\n" n n
9394         | Int n ->
9395             pr "  int %s = NUM2INT (%sv);\n" n n
9396         | Int64 n ->
9397             pr "  long long %s = NUM2LL (%sv);\n" n n
9398       ) (snd style);
9399       pr "\n";
9400
9401       let error_code =
9402         match fst style with
9403         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9404         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9405         | RConstString _ | RConstOptString _ ->
9406             pr "  const char *r;\n"; "NULL"
9407         | RString _ -> pr "  char *r;\n"; "NULL"
9408         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9409         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9410         | RStructList (_, typ) ->
9411             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9412         | RBufferOut _ ->
9413             pr "  char *r;\n";
9414             pr "  size_t size;\n";
9415             "NULL" in
9416       pr "\n";
9417
9418       pr "  r = guestfs_%s " name;
9419       generate_c_call_args ~handle:"g" style;
9420       pr ";\n";
9421
9422       List.iter (
9423         function
9424         | Pathname _ | Device _ | Dev_or_Path _ | String _
9425         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9426         | StringList n | DeviceList n ->
9427             pr "  free (%s);\n" n
9428       ) (snd style);
9429
9430       pr "  if (r == %s)\n" error_code;
9431       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9432       pr "\n";
9433
9434       (match fst style with
9435        | RErr ->
9436            pr "  return Qnil;\n"
9437        | RInt _ | RBool _ ->
9438            pr "  return INT2NUM (r);\n"
9439        | RInt64 _ ->
9440            pr "  return ULL2NUM (r);\n"
9441        | RConstString _ ->
9442            pr "  return rb_str_new2 (r);\n";
9443        | RConstOptString _ ->
9444            pr "  if (r)\n";
9445            pr "    return rb_str_new2 (r);\n";
9446            pr "  else\n";
9447            pr "    return Qnil;\n";
9448        | RString _ ->
9449            pr "  VALUE rv = rb_str_new2 (r);\n";
9450            pr "  free (r);\n";
9451            pr "  return rv;\n";
9452        | RStringList _ ->
9453            pr "  int i, len = 0;\n";
9454            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9455            pr "  VALUE rv = rb_ary_new2 (len);\n";
9456            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9457            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9458            pr "    free (r[i]);\n";
9459            pr "  }\n";
9460            pr "  free (r);\n";
9461            pr "  return rv;\n"
9462        | RStruct (_, typ) ->
9463            let cols = cols_of_struct typ in
9464            generate_ruby_struct_code typ cols
9465        | RStructList (_, typ) ->
9466            let cols = cols_of_struct typ in
9467            generate_ruby_struct_list_code typ cols
9468        | RHashtable _ ->
9469            pr "  VALUE rv = rb_hash_new ();\n";
9470            pr "  int i;\n";
9471            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9472            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9473            pr "    free (r[i]);\n";
9474            pr "    free (r[i+1]);\n";
9475            pr "  }\n";
9476            pr "  free (r);\n";
9477            pr "  return rv;\n"
9478        | RBufferOut _ ->
9479            pr "  VALUE rv = rb_str_new (r, size);\n";
9480            pr "  free (r);\n";
9481            pr "  return rv;\n";
9482       );
9483
9484       pr "}\n";
9485       pr "\n"
9486   ) all_functions;
9487
9488   pr "\
9489 /* Initialize the module. */
9490 void Init__guestfs ()
9491 {
9492   m_guestfs = rb_define_module (\"Guestfs\");
9493   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9494   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9495
9496   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9497   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9498
9499 ";
9500   (* Define the rest of the methods. *)
9501   List.iter (
9502     fun (name, style, _, _, _, _, _) ->
9503       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9504       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9505   ) all_functions;
9506
9507   pr "}\n"
9508
9509 (* Ruby code to return a struct. *)
9510 and generate_ruby_struct_code typ cols =
9511   pr "  VALUE rv = rb_hash_new ();\n";
9512   List.iter (
9513     function
9514     | name, FString ->
9515         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9516     | name, FBuffer ->
9517         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9518     | name, FUUID ->
9519         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9520     | name, (FBytes|FUInt64) ->
9521         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9522     | name, FInt64 ->
9523         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9524     | name, FUInt32 ->
9525         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9526     | name, FInt32 ->
9527         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9528     | name, FOptPercent ->
9529         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9530     | name, FChar -> (* XXX wrong? *)
9531         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9532   ) cols;
9533   pr "  guestfs_free_%s (r);\n" typ;
9534   pr "  return rv;\n"
9535
9536 (* Ruby code to return a struct list. *)
9537 and generate_ruby_struct_list_code typ cols =
9538   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9539   pr "  int i;\n";
9540   pr "  for (i = 0; i < r->len; ++i) {\n";
9541   pr "    VALUE hv = rb_hash_new ();\n";
9542   List.iter (
9543     function
9544     | name, FString ->
9545         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9546     | name, FBuffer ->
9547         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
9548     | name, FUUID ->
9549         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9550     | name, (FBytes|FUInt64) ->
9551         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9552     | name, FInt64 ->
9553         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9554     | name, FUInt32 ->
9555         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9556     | name, FInt32 ->
9557         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9558     | name, FOptPercent ->
9559         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9560     | name, FChar -> (* XXX wrong? *)
9561         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9562   ) cols;
9563   pr "    rb_ary_push (rv, hv);\n";
9564   pr "  }\n";
9565   pr "  guestfs_free_%s_list (r);\n" typ;
9566   pr "  return rv;\n"
9567
9568 (* Generate Java bindings GuestFS.java file. *)
9569 and generate_java_java () =
9570   generate_header CStyle LGPLv2plus;
9571
9572   pr "\
9573 package com.redhat.et.libguestfs;
9574
9575 import java.util.HashMap;
9576 import com.redhat.et.libguestfs.LibGuestFSException;
9577 import com.redhat.et.libguestfs.PV;
9578 import com.redhat.et.libguestfs.VG;
9579 import com.redhat.et.libguestfs.LV;
9580 import com.redhat.et.libguestfs.Stat;
9581 import com.redhat.et.libguestfs.StatVFS;
9582 import com.redhat.et.libguestfs.IntBool;
9583 import com.redhat.et.libguestfs.Dirent;
9584
9585 /**
9586  * The GuestFS object is a libguestfs handle.
9587  *
9588  * @author rjones
9589  */
9590 public class GuestFS {
9591   // Load the native code.
9592   static {
9593     System.loadLibrary (\"guestfs_jni\");
9594   }
9595
9596   /**
9597    * The native guestfs_h pointer.
9598    */
9599   long g;
9600
9601   /**
9602    * Create a libguestfs handle.
9603    *
9604    * @throws LibGuestFSException
9605    */
9606   public GuestFS () throws LibGuestFSException
9607   {
9608     g = _create ();
9609   }
9610   private native long _create () throws LibGuestFSException;
9611
9612   /**
9613    * Close a libguestfs handle.
9614    *
9615    * You can also leave handles to be collected by the garbage
9616    * collector, but this method ensures that the resources used
9617    * by the handle are freed up immediately.  If you call any
9618    * other methods after closing the handle, you will get an
9619    * exception.
9620    *
9621    * @throws LibGuestFSException
9622    */
9623   public void close () throws LibGuestFSException
9624   {
9625     if (g != 0)
9626       _close (g);
9627     g = 0;
9628   }
9629   private native void _close (long g) throws LibGuestFSException;
9630
9631   public void finalize () throws LibGuestFSException
9632   {
9633     close ();
9634   }
9635
9636 ";
9637
9638   List.iter (
9639     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9640       if not (List.mem NotInDocs flags); then (
9641         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9642         let doc =
9643           if List.mem ProtocolLimitWarning flags then
9644             doc ^ "\n\n" ^ protocol_limit_warning
9645           else doc in
9646         let doc =
9647           if List.mem DangerWillRobinson flags then
9648             doc ^ "\n\n" ^ danger_will_robinson
9649           else doc in
9650         let doc =
9651           match deprecation_notice flags with
9652           | None -> doc
9653           | Some txt -> doc ^ "\n\n" ^ txt in
9654         let doc = pod2text ~width:60 name doc in
9655         let doc = List.map (            (* RHBZ#501883 *)
9656           function
9657           | "" -> "<p>"
9658           | nonempty -> nonempty
9659         ) doc in
9660         let doc = String.concat "\n   * " doc in
9661
9662         pr "  /**\n";
9663         pr "   * %s\n" shortdesc;
9664         pr "   * <p>\n";
9665         pr "   * %s\n" doc;
9666         pr "   * @throws LibGuestFSException\n";
9667         pr "   */\n";
9668         pr "  ";
9669       );
9670       generate_java_prototype ~public:true ~semicolon:false name style;
9671       pr "\n";
9672       pr "  {\n";
9673       pr "    if (g == 0)\n";
9674       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9675         name;
9676       pr "    ";
9677       if fst style <> RErr then pr "return ";
9678       pr "_%s " name;
9679       generate_java_call_args ~handle:"g" (snd style);
9680       pr ";\n";
9681       pr "  }\n";
9682       pr "  ";
9683       generate_java_prototype ~privat:true ~native:true name style;
9684       pr "\n";
9685       pr "\n";
9686   ) all_functions;
9687
9688   pr "}\n"
9689
9690 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9691 and generate_java_call_args ~handle args =
9692   pr "(%s" handle;
9693   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9694   pr ")"
9695
9696 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9697     ?(semicolon=true) name style =
9698   if privat then pr "private ";
9699   if public then pr "public ";
9700   if native then pr "native ";
9701
9702   (* return type *)
9703   (match fst style with
9704    | RErr -> pr "void ";
9705    | RInt _ -> pr "int ";
9706    | RInt64 _ -> pr "long ";
9707    | RBool _ -> pr "boolean ";
9708    | RConstString _ | RConstOptString _ | RString _
9709    | RBufferOut _ -> pr "String ";
9710    | RStringList _ -> pr "String[] ";
9711    | RStruct (_, typ) ->
9712        let name = java_name_of_struct typ in
9713        pr "%s " name;
9714    | RStructList (_, typ) ->
9715        let name = java_name_of_struct typ in
9716        pr "%s[] " name;
9717    | RHashtable _ -> pr "HashMap<String,String> ";
9718   );
9719
9720   if native then pr "_%s " name else pr "%s " name;
9721   pr "(";
9722   let needs_comma = ref false in
9723   if native then (
9724     pr "long g";
9725     needs_comma := true
9726   );
9727
9728   (* args *)
9729   List.iter (
9730     fun arg ->
9731       if !needs_comma then pr ", ";
9732       needs_comma := true;
9733
9734       match arg with
9735       | Pathname n
9736       | Device n | Dev_or_Path n
9737       | String n
9738       | OptString n
9739       | FileIn n
9740       | FileOut n ->
9741           pr "String %s" n
9742       | StringList n | DeviceList n ->
9743           pr "String[] %s" n
9744       | Bool n ->
9745           pr "boolean %s" n
9746       | Int n ->
9747           pr "int %s" n
9748       | Int64 n ->
9749           pr "long %s" n
9750   ) (snd style);
9751
9752   pr ")\n";
9753   pr "    throws LibGuestFSException";
9754   if semicolon then pr ";"
9755
9756 and generate_java_struct jtyp cols () =
9757   generate_header CStyle LGPLv2plus;
9758
9759   pr "\
9760 package com.redhat.et.libguestfs;
9761
9762 /**
9763  * Libguestfs %s structure.
9764  *
9765  * @author rjones
9766  * @see GuestFS
9767  */
9768 public class %s {
9769 " jtyp jtyp;
9770
9771   List.iter (
9772     function
9773     | name, FString
9774     | name, FUUID
9775     | name, FBuffer -> pr "  public String %s;\n" name
9776     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9777     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9778     | name, FChar -> pr "  public char %s;\n" name
9779     | name, FOptPercent ->
9780         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9781         pr "  public float %s;\n" name
9782   ) cols;
9783
9784   pr "}\n"
9785
9786 and generate_java_c () =
9787   generate_header CStyle LGPLv2plus;
9788
9789   pr "\
9790 #include <stdio.h>
9791 #include <stdlib.h>
9792 #include <string.h>
9793
9794 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9795 #include \"guestfs.h\"
9796
9797 /* Note that this function returns.  The exception is not thrown
9798  * until after the wrapper function returns.
9799  */
9800 static void
9801 throw_exception (JNIEnv *env, const char *msg)
9802 {
9803   jclass cl;
9804   cl = (*env)->FindClass (env,
9805                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9806   (*env)->ThrowNew (env, cl, msg);
9807 }
9808
9809 JNIEXPORT jlong JNICALL
9810 Java_com_redhat_et_libguestfs_GuestFS__1create
9811   (JNIEnv *env, jobject obj)
9812 {
9813   guestfs_h *g;
9814
9815   g = guestfs_create ();
9816   if (g == NULL) {
9817     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9818     return 0;
9819   }
9820   guestfs_set_error_handler (g, NULL, NULL);
9821   return (jlong) (long) g;
9822 }
9823
9824 JNIEXPORT void JNICALL
9825 Java_com_redhat_et_libguestfs_GuestFS__1close
9826   (JNIEnv *env, jobject obj, jlong jg)
9827 {
9828   guestfs_h *g = (guestfs_h *) (long) jg;
9829   guestfs_close (g);
9830 }
9831
9832 ";
9833
9834   List.iter (
9835     fun (name, style, _, _, _, _, _) ->
9836       pr "JNIEXPORT ";
9837       (match fst style with
9838        | RErr -> pr "void ";
9839        | RInt _ -> pr "jint ";
9840        | RInt64 _ -> pr "jlong ";
9841        | RBool _ -> pr "jboolean ";
9842        | RConstString _ | RConstOptString _ | RString _
9843        | RBufferOut _ -> pr "jstring ";
9844        | RStruct _ | RHashtable _ ->
9845            pr "jobject ";
9846        | RStringList _ | RStructList _ ->
9847            pr "jobjectArray ";
9848       );
9849       pr "JNICALL\n";
9850       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9851       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9852       pr "\n";
9853       pr "  (JNIEnv *env, jobject obj, jlong jg";
9854       List.iter (
9855         function
9856         | Pathname n
9857         | Device n | Dev_or_Path n
9858         | String n
9859         | OptString n
9860         | FileIn n
9861         | FileOut n ->
9862             pr ", jstring j%s" n
9863         | StringList n | DeviceList n ->
9864             pr ", jobjectArray j%s" n
9865         | Bool n ->
9866             pr ", jboolean j%s" n
9867         | Int n ->
9868             pr ", jint j%s" n
9869         | Int64 n ->
9870             pr ", jlong j%s" n
9871       ) (snd style);
9872       pr ")\n";
9873       pr "{\n";
9874       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9875       let error_code, no_ret =
9876         match fst style with
9877         | RErr -> pr "  int r;\n"; "-1", ""
9878         | RBool _
9879         | RInt _ -> pr "  int r;\n"; "-1", "0"
9880         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9881         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9882         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9883         | RString _ ->
9884             pr "  jstring jr;\n";
9885             pr "  char *r;\n"; "NULL", "NULL"
9886         | RStringList _ ->
9887             pr "  jobjectArray jr;\n";
9888             pr "  int r_len;\n";
9889             pr "  jclass cl;\n";
9890             pr "  jstring jstr;\n";
9891             pr "  char **r;\n"; "NULL", "NULL"
9892         | RStruct (_, typ) ->
9893             pr "  jobject jr;\n";
9894             pr "  jclass cl;\n";
9895             pr "  jfieldID fl;\n";
9896             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9897         | RStructList (_, typ) ->
9898             pr "  jobjectArray jr;\n";
9899             pr "  jclass cl;\n";
9900             pr "  jfieldID fl;\n";
9901             pr "  jobject jfl;\n";
9902             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9903         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9904         | RBufferOut _ ->
9905             pr "  jstring jr;\n";
9906             pr "  char *r;\n";
9907             pr "  size_t size;\n";
9908             "NULL", "NULL" in
9909       List.iter (
9910         function
9911         | Pathname n
9912         | Device n | Dev_or_Path n
9913         | String n
9914         | OptString n
9915         | FileIn n
9916         | FileOut n ->
9917             pr "  const char *%s;\n" n
9918         | StringList n | DeviceList n ->
9919             pr "  int %s_len;\n" n;
9920             pr "  const char **%s;\n" n
9921         | Bool n
9922         | Int n ->
9923             pr "  int %s;\n" n
9924         | Int64 n ->
9925             pr "  int64_t %s;\n" n
9926       ) (snd style);
9927
9928       let needs_i =
9929         (match fst style with
9930          | RStringList _ | RStructList _ -> true
9931          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9932          | RConstOptString _
9933          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9934           List.exists (function
9935                        | StringList _ -> true
9936                        | DeviceList _ -> true
9937                        | _ -> false) (snd style) in
9938       if needs_i then
9939         pr "  int i;\n";
9940
9941       pr "\n";
9942
9943       (* Get the parameters. *)
9944       List.iter (
9945         function
9946         | Pathname n
9947         | Device n | Dev_or_Path n
9948         | String n
9949         | FileIn n
9950         | FileOut n ->
9951             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9952         | OptString n ->
9953             (* This is completely undocumented, but Java null becomes
9954              * a NULL parameter.
9955              *)
9956             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9957         | StringList n | DeviceList n ->
9958             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9959             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9960             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9961             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9962               n;
9963             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9964             pr "  }\n";
9965             pr "  %s[%s_len] = NULL;\n" n n;
9966         | Bool n
9967         | Int n
9968         | Int64 n ->
9969             pr "  %s = j%s;\n" n n
9970       ) (snd style);
9971
9972       (* Make the call. *)
9973       pr "  r = guestfs_%s " name;
9974       generate_c_call_args ~handle:"g" style;
9975       pr ";\n";
9976
9977       (* Release the parameters. *)
9978       List.iter (
9979         function
9980         | Pathname n
9981         | Device n | Dev_or_Path n
9982         | String n
9983         | FileIn n
9984         | FileOut n ->
9985             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9986         | OptString n ->
9987             pr "  if (j%s)\n" n;
9988             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9989         | StringList n | DeviceList n ->
9990             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9991             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9992               n;
9993             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9994             pr "  }\n";
9995             pr "  free (%s);\n" n
9996         | Bool n
9997         | Int n
9998         | Int64 n -> ()
9999       ) (snd style);
10000
10001       (* Check for errors. *)
10002       pr "  if (r == %s) {\n" error_code;
10003       pr "    throw_exception (env, guestfs_last_error (g));\n";
10004       pr "    return %s;\n" no_ret;
10005       pr "  }\n";
10006
10007       (* Return value. *)
10008       (match fst style with
10009        | RErr -> ()
10010        | RInt _ -> pr "  return (jint) r;\n"
10011        | RBool _ -> pr "  return (jboolean) r;\n"
10012        | RInt64 _ -> pr "  return (jlong) r;\n"
10013        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10014        | RConstOptString _ ->
10015            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10016        | RString _ ->
10017            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10018            pr "  free (r);\n";
10019            pr "  return jr;\n"
10020        | RStringList _ ->
10021            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10022            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10023            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10024            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10025            pr "  for (i = 0; i < r_len; ++i) {\n";
10026            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10027            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10028            pr "    free (r[i]);\n";
10029            pr "  }\n";
10030            pr "  free (r);\n";
10031            pr "  return jr;\n"
10032        | RStruct (_, typ) ->
10033            let jtyp = java_name_of_struct typ in
10034            let cols = cols_of_struct typ in
10035            generate_java_struct_return typ jtyp cols
10036        | RStructList (_, typ) ->
10037            let jtyp = java_name_of_struct typ in
10038            let cols = cols_of_struct typ in
10039            generate_java_struct_list_return typ jtyp cols
10040        | RHashtable _ ->
10041            (* XXX *)
10042            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10043            pr "  return NULL;\n"
10044        | RBufferOut _ ->
10045            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10046            pr "  free (r);\n";
10047            pr "  return jr;\n"
10048       );
10049
10050       pr "}\n";
10051       pr "\n"
10052   ) all_functions
10053
10054 and generate_java_struct_return typ jtyp cols =
10055   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10056   pr "  jr = (*env)->AllocObject (env, cl);\n";
10057   List.iter (
10058     function
10059     | name, FString ->
10060         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10061         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10062     | name, FUUID ->
10063         pr "  {\n";
10064         pr "    char s[33];\n";
10065         pr "    memcpy (s, r->%s, 32);\n" name;
10066         pr "    s[32] = 0;\n";
10067         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10068         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10069         pr "  }\n";
10070     | name, FBuffer ->
10071         pr "  {\n";
10072         pr "    int len = r->%s_len;\n" name;
10073         pr "    char s[len+1];\n";
10074         pr "    memcpy (s, r->%s, len);\n" name;
10075         pr "    s[len] = 0;\n";
10076         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10077         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10078         pr "  }\n";
10079     | name, (FBytes|FUInt64|FInt64) ->
10080         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10081         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10082     | name, (FUInt32|FInt32) ->
10083         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10084         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10085     | name, FOptPercent ->
10086         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10087         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10088     | name, FChar ->
10089         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10090         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10091   ) cols;
10092   pr "  free (r);\n";
10093   pr "  return jr;\n"
10094
10095 and generate_java_struct_list_return typ jtyp cols =
10096   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10097   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10098   pr "  for (i = 0; i < r->len; ++i) {\n";
10099   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10100   List.iter (
10101     function
10102     | name, FString ->
10103         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10104         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10105     | name, FUUID ->
10106         pr "    {\n";
10107         pr "      char s[33];\n";
10108         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10109         pr "      s[32] = 0;\n";
10110         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10111         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10112         pr "    }\n";
10113     | name, FBuffer ->
10114         pr "    {\n";
10115         pr "      int len = r->val[i].%s_len;\n" name;
10116         pr "      char s[len+1];\n";
10117         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10118         pr "      s[len] = 0;\n";
10119         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10120         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10121         pr "    }\n";
10122     | name, (FBytes|FUInt64|FInt64) ->
10123         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10124         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10125     | name, (FUInt32|FInt32) ->
10126         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10127         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10128     | name, FOptPercent ->
10129         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10130         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10131     | name, FChar ->
10132         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10133         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10134   ) cols;
10135   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10136   pr "  }\n";
10137   pr "  guestfs_free_%s_list (r);\n" typ;
10138   pr "  return jr;\n"
10139
10140 and generate_java_makefile_inc () =
10141   generate_header HashStyle GPLv2plus;
10142
10143   pr "java_built_sources = \\\n";
10144   List.iter (
10145     fun (typ, jtyp) ->
10146         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10147   ) java_structs;
10148   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10149
10150 and generate_haskell_hs () =
10151   generate_header HaskellStyle LGPLv2plus;
10152
10153   (* XXX We only know how to generate partial FFI for Haskell
10154    * at the moment.  Please help out!
10155    *)
10156   let can_generate style =
10157     match style with
10158     | RErr, _
10159     | RInt _, _
10160     | RInt64 _, _ -> true
10161     | RBool _, _
10162     | RConstString _, _
10163     | RConstOptString _, _
10164     | RString _, _
10165     | RStringList _, _
10166     | RStruct _, _
10167     | RStructList _, _
10168     | RHashtable _, _
10169     | RBufferOut _, _ -> false in
10170
10171   pr "\
10172 {-# INCLUDE <guestfs.h> #-}
10173 {-# LANGUAGE ForeignFunctionInterface #-}
10174
10175 module Guestfs (
10176   create";
10177
10178   (* List out the names of the actions we want to export. *)
10179   List.iter (
10180     fun (name, style, _, _, _, _, _) ->
10181       if can_generate style then pr ",\n  %s" name
10182   ) all_functions;
10183
10184   pr "
10185   ) where
10186
10187 -- Unfortunately some symbols duplicate ones already present
10188 -- in Prelude.  We don't know which, so we hard-code a list
10189 -- here.
10190 import Prelude hiding (truncate)
10191
10192 import Foreign
10193 import Foreign.C
10194 import Foreign.C.Types
10195 import IO
10196 import Control.Exception
10197 import Data.Typeable
10198
10199 data GuestfsS = GuestfsS            -- represents the opaque C struct
10200 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10201 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10202
10203 -- XXX define properly later XXX
10204 data PV = PV
10205 data VG = VG
10206 data LV = LV
10207 data IntBool = IntBool
10208 data Stat = Stat
10209 data StatVFS = StatVFS
10210 data Hashtable = Hashtable
10211
10212 foreign import ccall unsafe \"guestfs_create\" c_create
10213   :: IO GuestfsP
10214 foreign import ccall unsafe \"&guestfs_close\" c_close
10215   :: FunPtr (GuestfsP -> IO ())
10216 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10217   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10218
10219 create :: IO GuestfsH
10220 create = do
10221   p <- c_create
10222   c_set_error_handler p nullPtr nullPtr
10223   h <- newForeignPtr c_close p
10224   return h
10225
10226 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10227   :: GuestfsP -> IO CString
10228
10229 -- last_error :: GuestfsH -> IO (Maybe String)
10230 -- last_error h = do
10231 --   str <- withForeignPtr h (\\p -> c_last_error p)
10232 --   maybePeek peekCString str
10233
10234 last_error :: GuestfsH -> IO (String)
10235 last_error h = do
10236   str <- withForeignPtr h (\\p -> c_last_error p)
10237   if (str == nullPtr)
10238     then return \"no error\"
10239     else peekCString str
10240
10241 ";
10242
10243   (* Generate wrappers for each foreign function. *)
10244   List.iter (
10245     fun (name, style, _, _, _, _, _) ->
10246       if can_generate style then (
10247         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10248         pr "  :: ";
10249         generate_haskell_prototype ~handle:"GuestfsP" style;
10250         pr "\n";
10251         pr "\n";
10252         pr "%s :: " name;
10253         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10254         pr "\n";
10255         pr "%s %s = do\n" name
10256           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10257         pr "  r <- ";
10258         (* Convert pointer arguments using with* functions. *)
10259         List.iter (
10260           function
10261           | FileIn n
10262           | FileOut n
10263           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10264           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10265           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10266           | Bool _ | Int _ | Int64 _ -> ()
10267         ) (snd style);
10268         (* Convert integer arguments. *)
10269         let args =
10270           List.map (
10271             function
10272             | Bool n -> sprintf "(fromBool %s)" n
10273             | Int n -> sprintf "(fromIntegral %s)" n
10274             | Int64 n -> sprintf "(fromIntegral %s)" n
10275             | FileIn n | FileOut n
10276             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10277           ) (snd style) in
10278         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10279           (String.concat " " ("p" :: args));
10280         (match fst style with
10281          | RErr | RInt _ | RInt64 _ | RBool _ ->
10282              pr "  if (r == -1)\n";
10283              pr "    then do\n";
10284              pr "      err <- last_error h\n";
10285              pr "      fail err\n";
10286          | RConstString _ | RConstOptString _ | RString _
10287          | RStringList _ | RStruct _
10288          | RStructList _ | RHashtable _ | RBufferOut _ ->
10289              pr "  if (r == nullPtr)\n";
10290              pr "    then do\n";
10291              pr "      err <- last_error h\n";
10292              pr "      fail err\n";
10293         );
10294         (match fst style with
10295          | RErr ->
10296              pr "    else return ()\n"
10297          | RInt _ ->
10298              pr "    else return (fromIntegral r)\n"
10299          | RInt64 _ ->
10300              pr "    else return (fromIntegral r)\n"
10301          | RBool _ ->
10302              pr "    else return (toBool r)\n"
10303          | RConstString _
10304          | RConstOptString _
10305          | RString _
10306          | RStringList _
10307          | RStruct _
10308          | RStructList _
10309          | RHashtable _
10310          | RBufferOut _ ->
10311              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10312         );
10313         pr "\n";
10314       )
10315   ) all_functions
10316
10317 and generate_haskell_prototype ~handle ?(hs = false) style =
10318   pr "%s -> " handle;
10319   let string = if hs then "String" else "CString" in
10320   let int = if hs then "Int" else "CInt" in
10321   let bool = if hs then "Bool" else "CInt" in
10322   let int64 = if hs then "Integer" else "Int64" in
10323   List.iter (
10324     fun arg ->
10325       (match arg with
10326        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10327        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10328        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10329        | Bool _ -> pr "%s" bool
10330        | Int _ -> pr "%s" int
10331        | Int64 _ -> pr "%s" int
10332        | FileIn _ -> pr "%s" string
10333        | FileOut _ -> pr "%s" string
10334       );
10335       pr " -> ";
10336   ) (snd style);
10337   pr "IO (";
10338   (match fst style with
10339    | RErr -> if not hs then pr "CInt"
10340    | RInt _ -> pr "%s" int
10341    | RInt64 _ -> pr "%s" int64
10342    | RBool _ -> pr "%s" bool
10343    | RConstString _ -> pr "%s" string
10344    | RConstOptString _ -> pr "Maybe %s" string
10345    | RString _ -> pr "%s" string
10346    | RStringList _ -> pr "[%s]" string
10347    | RStruct (_, typ) ->
10348        let name = java_name_of_struct typ in
10349        pr "%s" name
10350    | RStructList (_, typ) ->
10351        let name = java_name_of_struct typ in
10352        pr "[%s]" name
10353    | RHashtable _ -> pr "Hashtable"
10354    | RBufferOut _ -> pr "%s" string
10355   );
10356   pr ")"
10357
10358 and generate_csharp () =
10359   generate_header CPlusPlusStyle LGPLv2plus;
10360
10361   (* XXX Make this configurable by the C# assembly users. *)
10362   let library = "libguestfs.so.0" in
10363
10364   pr "\
10365 // These C# bindings are highly experimental at present.
10366 //
10367 // Firstly they only work on Linux (ie. Mono).  In order to get them
10368 // to work on Windows (ie. .Net) you would need to port the library
10369 // itself to Windows first.
10370 //
10371 // The second issue is that some calls are known to be incorrect and
10372 // can cause Mono to segfault.  Particularly: calls which pass or
10373 // return string[], or return any structure value.  This is because
10374 // we haven't worked out the correct way to do this from C#.
10375 //
10376 // The third issue is that when compiling you get a lot of warnings.
10377 // We are not sure whether the warnings are important or not.
10378 //
10379 // Fourthly we do not routinely build or test these bindings as part
10380 // of the make && make check cycle, which means that regressions might
10381 // go unnoticed.
10382 //
10383 // Suggestions and patches are welcome.
10384
10385 // To compile:
10386 //
10387 // gmcs Libguestfs.cs
10388 // mono Libguestfs.exe
10389 //
10390 // (You'll probably want to add a Test class / static main function
10391 // otherwise this won't do anything useful).
10392
10393 using System;
10394 using System.IO;
10395 using System.Runtime.InteropServices;
10396 using System.Runtime.Serialization;
10397 using System.Collections;
10398
10399 namespace Guestfs
10400 {
10401   class Error : System.ApplicationException
10402   {
10403     public Error (string message) : base (message) {}
10404     protected Error (SerializationInfo info, StreamingContext context) {}
10405   }
10406
10407   class Guestfs
10408   {
10409     IntPtr _handle;
10410
10411     [DllImport (\"%s\")]
10412     static extern IntPtr guestfs_create ();
10413
10414     public Guestfs ()
10415     {
10416       _handle = guestfs_create ();
10417       if (_handle == IntPtr.Zero)
10418         throw new Error (\"could not create guestfs handle\");
10419     }
10420
10421     [DllImport (\"%s\")]
10422     static extern void guestfs_close (IntPtr h);
10423
10424     ~Guestfs ()
10425     {
10426       guestfs_close (_handle);
10427     }
10428
10429     [DllImport (\"%s\")]
10430     static extern string guestfs_last_error (IntPtr h);
10431
10432 " library library library;
10433
10434   (* Generate C# structure bindings.  We prefix struct names with
10435    * underscore because C# cannot have conflicting struct names and
10436    * method names (eg. "class stat" and "stat").
10437    *)
10438   List.iter (
10439     fun (typ, cols) ->
10440       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10441       pr "    public class _%s {\n" typ;
10442       List.iter (
10443         function
10444         | name, FChar -> pr "      char %s;\n" name
10445         | name, FString -> pr "      string %s;\n" name
10446         | name, FBuffer ->
10447             pr "      uint %s_len;\n" name;
10448             pr "      string %s;\n" name
10449         | name, FUUID ->
10450             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10451             pr "      string %s;\n" name
10452         | name, FUInt32 -> pr "      uint %s;\n" name
10453         | name, FInt32 -> pr "      int %s;\n" name
10454         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10455         | name, FInt64 -> pr "      long %s;\n" name
10456         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10457       ) cols;
10458       pr "    }\n";
10459       pr "\n"
10460   ) structs;
10461
10462   (* Generate C# function bindings. *)
10463   List.iter (
10464     fun (name, style, _, _, _, shortdesc, _) ->
10465       let rec csharp_return_type () =
10466         match fst style with
10467         | RErr -> "void"
10468         | RBool n -> "bool"
10469         | RInt n -> "int"
10470         | RInt64 n -> "long"
10471         | RConstString n
10472         | RConstOptString n
10473         | RString n
10474         | RBufferOut n -> "string"
10475         | RStruct (_,n) -> "_" ^ n
10476         | RHashtable n -> "Hashtable"
10477         | RStringList n -> "string[]"
10478         | RStructList (_,n) -> sprintf "_%s[]" n
10479
10480       and c_return_type () =
10481         match fst style with
10482         | RErr
10483         | RBool _
10484         | RInt _ -> "int"
10485         | RInt64 _ -> "long"
10486         | RConstString _
10487         | RConstOptString _
10488         | RString _
10489         | RBufferOut _ -> "string"
10490         | RStruct (_,n) -> "_" ^ n
10491         | RHashtable _
10492         | RStringList _ -> "string[]"
10493         | RStructList (_,n) -> sprintf "_%s[]" n
10494
10495       and c_error_comparison () =
10496         match fst style with
10497         | RErr
10498         | RBool _
10499         | RInt _
10500         | RInt64 _ -> "== -1"
10501         | RConstString _
10502         | RConstOptString _
10503         | RString _
10504         | RBufferOut _
10505         | RStruct (_,_)
10506         | RHashtable _
10507         | RStringList _
10508         | RStructList (_,_) -> "== null"
10509
10510       and generate_extern_prototype () =
10511         pr "    static extern %s guestfs_%s (IntPtr h"
10512           (c_return_type ()) name;
10513         List.iter (
10514           function
10515           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10516           | FileIn n | FileOut n ->
10517               pr ", [In] string %s" n
10518           | StringList n | DeviceList n ->
10519               pr ", [In] string[] %s" n
10520           | Bool n ->
10521               pr ", bool %s" n
10522           | Int n ->
10523               pr ", int %s" n
10524           | Int64 n ->
10525               pr ", long %s" n
10526         ) (snd style);
10527         pr ");\n"
10528
10529       and generate_public_prototype () =
10530         pr "    public %s %s (" (csharp_return_type ()) name;
10531         let comma = ref false in
10532         let next () =
10533           if !comma then pr ", ";
10534           comma := true
10535         in
10536         List.iter (
10537           function
10538           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10539           | FileIn n | FileOut n ->
10540               next (); pr "string %s" n
10541           | StringList n | DeviceList n ->
10542               next (); pr "string[] %s" n
10543           | Bool n ->
10544               next (); pr "bool %s" n
10545           | Int n ->
10546               next (); pr "int %s" n
10547           | Int64 n ->
10548               next (); pr "long %s" n
10549         ) (snd style);
10550         pr ")\n"
10551
10552       and generate_call () =
10553         pr "guestfs_%s (_handle" name;
10554         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10555         pr ");\n";
10556       in
10557
10558       pr "    [DllImport (\"%s\")]\n" library;
10559       generate_extern_prototype ();
10560       pr "\n";
10561       pr "    /// <summary>\n";
10562       pr "    /// %s\n" shortdesc;
10563       pr "    /// </summary>\n";
10564       generate_public_prototype ();
10565       pr "    {\n";
10566       pr "      %s r;\n" (c_return_type ());
10567       pr "      r = ";
10568       generate_call ();
10569       pr "      if (r %s)\n" (c_error_comparison ());
10570       pr "        throw new Error (guestfs_last_error (_handle));\n";
10571       (match fst style with
10572        | RErr -> ()
10573        | RBool _ ->
10574            pr "      return r != 0 ? true : false;\n"
10575        | RHashtable _ ->
10576            pr "      Hashtable rr = new Hashtable ();\n";
10577            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10578            pr "        rr.Add (r[i], r[i+1]);\n";
10579            pr "      return rr;\n"
10580        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10581        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10582        | RStructList _ ->
10583            pr "      return r;\n"
10584       );
10585       pr "    }\n";
10586       pr "\n";
10587   ) all_functions_sorted;
10588
10589   pr "  }
10590 }
10591 "
10592
10593 and generate_bindtests () =
10594   generate_header CStyle LGPLv2plus;
10595
10596   pr "\
10597 #include <stdio.h>
10598 #include <stdlib.h>
10599 #include <inttypes.h>
10600 #include <string.h>
10601
10602 #include \"guestfs.h\"
10603 #include \"guestfs-internal.h\"
10604 #include \"guestfs-internal-actions.h\"
10605 #include \"guestfs_protocol.h\"
10606
10607 #define error guestfs_error
10608 #define safe_calloc guestfs_safe_calloc
10609 #define safe_malloc guestfs_safe_malloc
10610
10611 static void
10612 print_strings (char *const *argv)
10613 {
10614   int argc;
10615
10616   printf (\"[\");
10617   for (argc = 0; argv[argc] != NULL; ++argc) {
10618     if (argc > 0) printf (\", \");
10619     printf (\"\\\"%%s\\\"\", argv[argc]);
10620   }
10621   printf (\"]\\n\");
10622 }
10623
10624 /* The test0 function prints its parameters to stdout. */
10625 ";
10626
10627   let test0, tests =
10628     match test_functions with
10629     | [] -> assert false
10630     | test0 :: tests -> test0, tests in
10631
10632   let () =
10633     let (name, style, _, _, _, _, _) = test0 in
10634     generate_prototype ~extern:false ~semicolon:false ~newline:true
10635       ~handle:"g" ~prefix:"guestfs__" name style;
10636     pr "{\n";
10637     List.iter (
10638       function
10639       | Pathname n
10640       | Device n | Dev_or_Path n
10641       | String n
10642       | FileIn n
10643       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10644       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10645       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10646       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10647       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10648       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10649     ) (snd style);
10650     pr "  /* Java changes stdout line buffering so we need this: */\n";
10651     pr "  fflush (stdout);\n";
10652     pr "  return 0;\n";
10653     pr "}\n";
10654     pr "\n" in
10655
10656   List.iter (
10657     fun (name, style, _, _, _, _, _) ->
10658       if String.sub name (String.length name - 3) 3 <> "err" then (
10659         pr "/* Test normal return. */\n";
10660         generate_prototype ~extern:false ~semicolon:false ~newline:true
10661           ~handle:"g" ~prefix:"guestfs__" name style;
10662         pr "{\n";
10663         (match fst style with
10664          | RErr ->
10665              pr "  return 0;\n"
10666          | RInt _ ->
10667              pr "  int r;\n";
10668              pr "  sscanf (val, \"%%d\", &r);\n";
10669              pr "  return r;\n"
10670          | RInt64 _ ->
10671              pr "  int64_t r;\n";
10672              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10673              pr "  return r;\n"
10674          | RBool _ ->
10675              pr "  return STREQ (val, \"true\");\n"
10676          | RConstString _
10677          | RConstOptString _ ->
10678              (* Can't return the input string here.  Return a static
10679               * string so we ensure we get a segfault if the caller
10680               * tries to free it.
10681               *)
10682              pr "  return \"static string\";\n"
10683          | RString _ ->
10684              pr "  return strdup (val);\n"
10685          | RStringList _ ->
10686              pr "  char **strs;\n";
10687              pr "  int n, i;\n";
10688              pr "  sscanf (val, \"%%d\", &n);\n";
10689              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10690              pr "  for (i = 0; i < n; ++i) {\n";
10691              pr "    strs[i] = safe_malloc (g, 16);\n";
10692              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10693              pr "  }\n";
10694              pr "  strs[n] = NULL;\n";
10695              pr "  return strs;\n"
10696          | RStruct (_, typ) ->
10697              pr "  struct guestfs_%s *r;\n" typ;
10698              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10699              pr "  return r;\n"
10700          | RStructList (_, typ) ->
10701              pr "  struct guestfs_%s_list *r;\n" typ;
10702              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10703              pr "  sscanf (val, \"%%d\", &r->len);\n";
10704              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10705              pr "  return r;\n"
10706          | RHashtable _ ->
10707              pr "  char **strs;\n";
10708              pr "  int n, i;\n";
10709              pr "  sscanf (val, \"%%d\", &n);\n";
10710              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10711              pr "  for (i = 0; i < n; ++i) {\n";
10712              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10713              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10714              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10715              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10716              pr "  }\n";
10717              pr "  strs[n*2] = NULL;\n";
10718              pr "  return strs;\n"
10719          | RBufferOut _ ->
10720              pr "  return strdup (val);\n"
10721         );
10722         pr "}\n";
10723         pr "\n"
10724       ) else (
10725         pr "/* Test error return. */\n";
10726         generate_prototype ~extern:false ~semicolon:false ~newline:true
10727           ~handle:"g" ~prefix:"guestfs__" name style;
10728         pr "{\n";
10729         pr "  error (g, \"error\");\n";
10730         (match fst style with
10731          | RErr | RInt _ | RInt64 _ | RBool _ ->
10732              pr "  return -1;\n"
10733          | RConstString _ | RConstOptString _
10734          | RString _ | RStringList _ | RStruct _
10735          | RStructList _
10736          | RHashtable _
10737          | RBufferOut _ ->
10738              pr "  return NULL;\n"
10739         );
10740         pr "}\n";
10741         pr "\n"
10742       )
10743   ) tests
10744
10745 and generate_ocaml_bindtests () =
10746   generate_header OCamlStyle GPLv2plus;
10747
10748   pr "\
10749 let () =
10750   let g = Guestfs.create () in
10751 ";
10752
10753   let mkargs args =
10754     String.concat " " (
10755       List.map (
10756         function
10757         | CallString s -> "\"" ^ s ^ "\""
10758         | CallOptString None -> "None"
10759         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10760         | CallStringList xs ->
10761             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10762         | CallInt i when i >= 0 -> string_of_int i
10763         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10764         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10765         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10766         | CallBool b -> string_of_bool b
10767       ) args
10768     )
10769   in
10770
10771   generate_lang_bindtests (
10772     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10773   );
10774
10775   pr "print_endline \"EOF\"\n"
10776
10777 and generate_perl_bindtests () =
10778   pr "#!/usr/bin/perl -w\n";
10779   generate_header HashStyle GPLv2plus;
10780
10781   pr "\
10782 use strict;
10783
10784 use Sys::Guestfs;
10785
10786 my $g = Sys::Guestfs->new ();
10787 ";
10788
10789   let mkargs args =
10790     String.concat ", " (
10791       List.map (
10792         function
10793         | CallString s -> "\"" ^ s ^ "\""
10794         | CallOptString None -> "undef"
10795         | CallOptString (Some s) -> sprintf "\"%s\"" s
10796         | CallStringList xs ->
10797             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10798         | CallInt i -> string_of_int i
10799         | CallInt64 i -> Int64.to_string i
10800         | CallBool b -> if b then "1" else "0"
10801       ) args
10802     )
10803   in
10804
10805   generate_lang_bindtests (
10806     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10807   );
10808
10809   pr "print \"EOF\\n\"\n"
10810
10811 and generate_python_bindtests () =
10812   generate_header HashStyle GPLv2plus;
10813
10814   pr "\
10815 import guestfs
10816
10817 g = guestfs.GuestFS ()
10818 ";
10819
10820   let mkargs args =
10821     String.concat ", " (
10822       List.map (
10823         function
10824         | CallString s -> "\"" ^ s ^ "\""
10825         | CallOptString None -> "None"
10826         | CallOptString (Some s) -> sprintf "\"%s\"" s
10827         | CallStringList xs ->
10828             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10829         | CallInt i -> string_of_int i
10830         | CallInt64 i -> Int64.to_string i
10831         | CallBool b -> if b then "1" else "0"
10832       ) args
10833     )
10834   in
10835
10836   generate_lang_bindtests (
10837     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10838   );
10839
10840   pr "print \"EOF\"\n"
10841
10842 and generate_ruby_bindtests () =
10843   generate_header HashStyle GPLv2plus;
10844
10845   pr "\
10846 require 'guestfs'
10847
10848 g = Guestfs::create()
10849 ";
10850
10851   let mkargs args =
10852     String.concat ", " (
10853       List.map (
10854         function
10855         | CallString s -> "\"" ^ s ^ "\""
10856         | CallOptString None -> "nil"
10857         | CallOptString (Some s) -> sprintf "\"%s\"" s
10858         | CallStringList xs ->
10859             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10860         | CallInt i -> string_of_int i
10861         | CallInt64 i -> Int64.to_string i
10862         | CallBool b -> string_of_bool b
10863       ) args
10864     )
10865   in
10866
10867   generate_lang_bindtests (
10868     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10869   );
10870
10871   pr "print \"EOF\\n\"\n"
10872
10873 and generate_java_bindtests () =
10874   generate_header CStyle GPLv2plus;
10875
10876   pr "\
10877 import com.redhat.et.libguestfs.*;
10878
10879 public class Bindtests {
10880     public static void main (String[] argv)
10881     {
10882         try {
10883             GuestFS g = new GuestFS ();
10884 ";
10885
10886   let mkargs args =
10887     String.concat ", " (
10888       List.map (
10889         function
10890         | CallString s -> "\"" ^ s ^ "\""
10891         | CallOptString None -> "null"
10892         | CallOptString (Some s) -> sprintf "\"%s\"" s
10893         | CallStringList xs ->
10894             "new String[]{" ^
10895               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10896         | CallInt i -> string_of_int i
10897         | CallInt64 i -> Int64.to_string i
10898         | CallBool b -> string_of_bool b
10899       ) args
10900     )
10901   in
10902
10903   generate_lang_bindtests (
10904     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10905   );
10906
10907   pr "
10908             System.out.println (\"EOF\");
10909         }
10910         catch (Exception exn) {
10911             System.err.println (exn);
10912             System.exit (1);
10913         }
10914     }
10915 }
10916 "
10917
10918 and generate_haskell_bindtests () =
10919   generate_header HaskellStyle GPLv2plus;
10920
10921   pr "\
10922 module Bindtests where
10923 import qualified Guestfs
10924
10925 main = do
10926   g <- Guestfs.create
10927 ";
10928
10929   let mkargs args =
10930     String.concat " " (
10931       List.map (
10932         function
10933         | CallString s -> "\"" ^ s ^ "\""
10934         | CallOptString None -> "Nothing"
10935         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10936         | CallStringList xs ->
10937             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10938         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10939         | CallInt i -> string_of_int i
10940         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10941         | CallInt64 i -> Int64.to_string i
10942         | CallBool true -> "True"
10943         | CallBool false -> "False"
10944       ) args
10945     )
10946   in
10947
10948   generate_lang_bindtests (
10949     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10950   );
10951
10952   pr "  putStrLn \"EOF\"\n"
10953
10954 (* Language-independent bindings tests - we do it this way to
10955  * ensure there is parity in testing bindings across all languages.
10956  *)
10957 and generate_lang_bindtests call =
10958   call "test0" [CallString "abc"; CallOptString (Some "def");
10959                 CallStringList []; CallBool false;
10960                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10961   call "test0" [CallString "abc"; CallOptString None;
10962                 CallStringList []; CallBool false;
10963                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10964   call "test0" [CallString ""; CallOptString (Some "def");
10965                 CallStringList []; CallBool false;
10966                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10967   call "test0" [CallString ""; CallOptString (Some "");
10968                 CallStringList []; CallBool false;
10969                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10970   call "test0" [CallString "abc"; CallOptString (Some "def");
10971                 CallStringList ["1"]; CallBool false;
10972                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10973   call "test0" [CallString "abc"; CallOptString (Some "def");
10974                 CallStringList ["1"; "2"]; CallBool false;
10975                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10976   call "test0" [CallString "abc"; CallOptString (Some "def");
10977                 CallStringList ["1"]; CallBool true;
10978                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10979   call "test0" [CallString "abc"; CallOptString (Some "def");
10980                 CallStringList ["1"]; CallBool false;
10981                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10982   call "test0" [CallString "abc"; CallOptString (Some "def");
10983                 CallStringList ["1"]; CallBool false;
10984                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10985   call "test0" [CallString "abc"; CallOptString (Some "def");
10986                 CallStringList ["1"]; CallBool false;
10987                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10988   call "test0" [CallString "abc"; CallOptString (Some "def");
10989                 CallStringList ["1"]; CallBool false;
10990                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10991   call "test0" [CallString "abc"; CallOptString (Some "def");
10992                 CallStringList ["1"]; CallBool false;
10993                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10994   call "test0" [CallString "abc"; CallOptString (Some "def");
10995                 CallStringList ["1"]; CallBool false;
10996                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10997
10998 (* XXX Add here tests of the return and error functions. *)
10999
11000 (* Code to generator bindings for virt-inspector.  Currently only
11001  * implemented for OCaml code (for virt-p2v 2.0).
11002  *)
11003 let rng_input = "inspector/virt-inspector.rng"
11004
11005 (* Read the input file and parse it into internal structures.  This is
11006  * by no means a complete RELAX NG parser, but is just enough to be
11007  * able to parse the specific input file.
11008  *)
11009 type rng =
11010   | Element of string * rng list        (* <element name=name/> *)
11011   | Attribute of string * rng list        (* <attribute name=name/> *)
11012   | Interleave of rng list                (* <interleave/> *)
11013   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11014   | OneOrMore of rng                        (* <oneOrMore/> *)
11015   | Optional of rng                        (* <optional/> *)
11016   | Choice of string list                (* <choice><value/>*</choice> *)
11017   | Value of string                        (* <value>str</value> *)
11018   | Text                                (* <text/> *)
11019
11020 let rec string_of_rng = function
11021   | Element (name, xs) ->
11022       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11023   | Attribute (name, xs) ->
11024       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11025   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11026   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11027   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11028   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11029   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11030   | Value value -> "Value \"" ^ value ^ "\""
11031   | Text -> "Text"
11032
11033 and string_of_rng_list xs =
11034   String.concat ", " (List.map string_of_rng xs)
11035
11036 let rec parse_rng ?defines context = function
11037   | [] -> []
11038   | Xml.Element ("element", ["name", name], children) :: rest ->
11039       Element (name, parse_rng ?defines context children)
11040       :: parse_rng ?defines context rest
11041   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11042       Attribute (name, parse_rng ?defines context children)
11043       :: parse_rng ?defines context rest
11044   | Xml.Element ("interleave", [], children) :: rest ->
11045       Interleave (parse_rng ?defines context children)
11046       :: parse_rng ?defines context rest
11047   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11048       let rng = parse_rng ?defines context [child] in
11049       (match rng with
11050        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11051        | _ ->
11052            failwithf "%s: <zeroOrMore> contains more than one child element"
11053              context
11054       )
11055   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11056       let rng = parse_rng ?defines context [child] in
11057       (match rng with
11058        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11059        | _ ->
11060            failwithf "%s: <oneOrMore> contains more than one child element"
11061              context
11062       )
11063   | Xml.Element ("optional", [], [child]) :: rest ->
11064       let rng = parse_rng ?defines context [child] in
11065       (match rng with
11066        | [child] -> Optional child :: parse_rng ?defines context rest
11067        | _ ->
11068            failwithf "%s: <optional> contains more than one child element"
11069              context
11070       )
11071   | Xml.Element ("choice", [], children) :: rest ->
11072       let values = List.map (
11073         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11074         | _ ->
11075             failwithf "%s: can't handle anything except <value> in <choice>"
11076               context
11077       ) children in
11078       Choice values
11079       :: parse_rng ?defines context rest
11080   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11081       Value value :: parse_rng ?defines context rest
11082   | Xml.Element ("text", [], []) :: rest ->
11083       Text :: parse_rng ?defines context rest
11084   | Xml.Element ("ref", ["name", name], []) :: rest ->
11085       (* Look up the reference.  Because of limitations in this parser,
11086        * we can't handle arbitrarily nested <ref> yet.  You can only
11087        * use <ref> from inside <start>.
11088        *)
11089       (match defines with
11090        | None ->
11091            failwithf "%s: contains <ref>, but no refs are defined yet" context
11092        | Some map ->
11093            let rng = StringMap.find name map in
11094            rng @ parse_rng ?defines context rest
11095       )
11096   | x :: _ ->
11097       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11098
11099 let grammar =
11100   let xml = Xml.parse_file rng_input in
11101   match xml with
11102   | Xml.Element ("grammar", _,
11103                  Xml.Element ("start", _, gram) :: defines) ->
11104       (* The <define/> elements are referenced in the <start> section,
11105        * so build a map of those first.
11106        *)
11107       let defines = List.fold_left (
11108         fun map ->
11109           function Xml.Element ("define", ["name", name], defn) ->
11110             StringMap.add name defn map
11111           | _ ->
11112               failwithf "%s: expected <define name=name/>" rng_input
11113       ) StringMap.empty defines in
11114       let defines = StringMap.mapi parse_rng defines in
11115
11116       (* Parse the <start> clause, passing the defines. *)
11117       parse_rng ~defines "<start>" gram
11118   | _ ->
11119       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11120         rng_input
11121
11122 let name_of_field = function
11123   | Element (name, _) | Attribute (name, _)
11124   | ZeroOrMore (Element (name, _))
11125   | OneOrMore (Element (name, _))
11126   | Optional (Element (name, _)) -> name
11127   | Optional (Attribute (name, _)) -> name
11128   | Text -> (* an unnamed field in an element *)
11129       "data"
11130   | rng ->
11131       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11132
11133 (* At the moment this function only generates OCaml types.  However we
11134  * should parameterize it later so it can generate types/structs in a
11135  * variety of languages.
11136  *)
11137 let generate_types xs =
11138   (* A simple type is one that can be printed out directly, eg.
11139    * "string option".  A complex type is one which has a name and has
11140    * to be defined via another toplevel definition, eg. a struct.
11141    *
11142    * generate_type generates code for either simple or complex types.
11143    * In the simple case, it returns the string ("string option").  In
11144    * the complex case, it returns the name ("mountpoint").  In the
11145    * complex case it has to print out the definition before returning,
11146    * so it should only be called when we are at the beginning of a
11147    * new line (BOL context).
11148    *)
11149   let rec generate_type = function
11150     | Text ->                                (* string *)
11151         "string", true
11152     | Choice values ->                        (* [`val1|`val2|...] *)
11153         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11154     | ZeroOrMore rng ->                        (* <rng> list *)
11155         let t, is_simple = generate_type rng in
11156         t ^ " list (* 0 or more *)", is_simple
11157     | OneOrMore rng ->                        (* <rng> list *)
11158         let t, is_simple = generate_type rng in
11159         t ^ " list (* 1 or more *)", is_simple
11160                                         (* virt-inspector hack: bool *)
11161     | Optional (Attribute (name, [Value "1"])) ->
11162         "bool", true
11163     | Optional rng ->                        (* <rng> list *)
11164         let t, is_simple = generate_type rng in
11165         t ^ " option", is_simple
11166                                         (* type name = { fields ... } *)
11167     | Element (name, fields) when is_attrs_interleave fields ->
11168         generate_type_struct name (get_attrs_interleave fields)
11169     | Element (name, [field])                (* type name = field *)
11170     | Attribute (name, [field]) ->
11171         let t, is_simple = generate_type field in
11172         if is_simple then (t, true)
11173         else (
11174           pr "type %s = %s\n" name t;
11175           name, false
11176         )
11177     | Element (name, fields) ->              (* type name = { fields ... } *)
11178         generate_type_struct name fields
11179     | rng ->
11180         failwithf "generate_type failed at: %s" (string_of_rng rng)
11181
11182   and is_attrs_interleave = function
11183     | [Interleave _] -> true
11184     | Attribute _ :: fields -> is_attrs_interleave fields
11185     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11186     | _ -> false
11187
11188   and get_attrs_interleave = function
11189     | [Interleave fields] -> fields
11190     | ((Attribute _) as field) :: fields
11191     | ((Optional (Attribute _)) as field) :: fields ->
11192         field :: get_attrs_interleave fields
11193     | _ -> assert false
11194
11195   and generate_types xs =
11196     List.iter (fun x -> ignore (generate_type x)) xs
11197
11198   and generate_type_struct name fields =
11199     (* Calculate the types of the fields first.  We have to do this
11200      * before printing anything so we are still in BOL context.
11201      *)
11202     let types = List.map fst (List.map generate_type fields) in
11203
11204     (* Special case of a struct containing just a string and another
11205      * field.  Turn it into an assoc list.
11206      *)
11207     match types with
11208     | ["string"; other] ->
11209         let fname1, fname2 =
11210           match fields with
11211           | [f1; f2] -> name_of_field f1, name_of_field f2
11212           | _ -> assert false in
11213         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11214         name, false
11215
11216     | types ->
11217         pr "type %s = {\n" name;
11218         List.iter (
11219           fun (field, ftype) ->
11220             let fname = name_of_field field in
11221             pr "  %s_%s : %s;\n" name fname ftype
11222         ) (List.combine fields types);
11223         pr "}\n";
11224         (* Return the name of this type, and
11225          * false because it's not a simple type.
11226          *)
11227         name, false
11228   in
11229
11230   generate_types xs
11231
11232 let generate_parsers xs =
11233   (* As for generate_type above, generate_parser makes a parser for
11234    * some type, and returns the name of the parser it has generated.
11235    * Because it (may) need to print something, it should always be
11236    * called in BOL context.
11237    *)
11238   let rec generate_parser = function
11239     | Text ->                                (* string *)
11240         "string_child_or_empty"
11241     | Choice values ->                        (* [`val1|`val2|...] *)
11242         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11243           (String.concat "|"
11244              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11245     | ZeroOrMore rng ->                        (* <rng> list *)
11246         let pa = generate_parser rng in
11247         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11248     | OneOrMore rng ->                        (* <rng> list *)
11249         let pa = generate_parser rng in
11250         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11251                                         (* virt-inspector hack: bool *)
11252     | Optional (Attribute (name, [Value "1"])) ->
11253         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11254     | Optional rng ->                        (* <rng> list *)
11255         let pa = generate_parser rng in
11256         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11257                                         (* type name = { fields ... } *)
11258     | Element (name, fields) when is_attrs_interleave fields ->
11259         generate_parser_struct name (get_attrs_interleave fields)
11260     | Element (name, [field]) ->        (* type name = field *)
11261         let pa = generate_parser field in
11262         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11263         pr "let %s =\n" parser_name;
11264         pr "  %s\n" pa;
11265         pr "let parse_%s = %s\n" name parser_name;
11266         parser_name
11267     | Attribute (name, [field]) ->
11268         let pa = generate_parser field in
11269         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11270         pr "let %s =\n" parser_name;
11271         pr "  %s\n" pa;
11272         pr "let parse_%s = %s\n" name parser_name;
11273         parser_name
11274     | Element (name, fields) ->              (* type name = { fields ... } *)
11275         generate_parser_struct name ([], fields)
11276     | rng ->
11277         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11278
11279   and is_attrs_interleave = function
11280     | [Interleave _] -> true
11281     | Attribute _ :: fields -> is_attrs_interleave fields
11282     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11283     | _ -> false
11284
11285   and get_attrs_interleave = function
11286     | [Interleave fields] -> [], fields
11287     | ((Attribute _) as field) :: fields
11288     | ((Optional (Attribute _)) as field) :: fields ->
11289         let attrs, interleaves = get_attrs_interleave fields in
11290         (field :: attrs), interleaves
11291     | _ -> assert false
11292
11293   and generate_parsers xs =
11294     List.iter (fun x -> ignore (generate_parser x)) xs
11295
11296   and generate_parser_struct name (attrs, interleaves) =
11297     (* Generate parsers for the fields first.  We have to do this
11298      * before printing anything so we are still in BOL context.
11299      *)
11300     let fields = attrs @ interleaves in
11301     let pas = List.map generate_parser fields in
11302
11303     (* Generate an intermediate tuple from all the fields first.
11304      * If the type is just a string + another field, then we will
11305      * return this directly, otherwise it is turned into a record.
11306      *
11307      * RELAX NG note: This code treats <interleave> and plain lists of
11308      * fields the same.  In other words, it doesn't bother enforcing
11309      * any ordering of fields in the XML.
11310      *)
11311     pr "let parse_%s x =\n" name;
11312     pr "  let t = (\n    ";
11313     let comma = ref false in
11314     List.iter (
11315       fun x ->
11316         if !comma then pr ",\n    ";
11317         comma := true;
11318         match x with
11319         | Optional (Attribute (fname, [field])), pa ->
11320             pr "%s x" pa
11321         | Optional (Element (fname, [field])), pa ->
11322             pr "%s (optional_child %S x)" pa fname
11323         | Attribute (fname, [Text]), _ ->
11324             pr "attribute %S x" fname
11325         | (ZeroOrMore _ | OneOrMore _), pa ->
11326             pr "%s x" pa
11327         | Text, pa ->
11328             pr "%s x" pa
11329         | (field, pa) ->
11330             let fname = name_of_field field in
11331             pr "%s (child %S x)" pa fname
11332     ) (List.combine fields pas);
11333     pr "\n  ) in\n";
11334
11335     (match fields with
11336      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11337          pr "  t\n"
11338
11339      | _ ->
11340          pr "  (Obj.magic t : %s)\n" name
11341 (*
11342          List.iter (
11343            function
11344            | (Optional (Attribute (fname, [field])), pa) ->
11345                pr "  %s_%s =\n" name fname;
11346                pr "    %s x;\n" pa
11347            | (Optional (Element (fname, [field])), pa) ->
11348                pr "  %s_%s =\n" name fname;
11349                pr "    (let x = optional_child %S x in\n" fname;
11350                pr "     %s x);\n" pa
11351            | (field, pa) ->
11352                let fname = name_of_field field in
11353                pr "  %s_%s =\n" name fname;
11354                pr "    (let x = child %S x in\n" fname;
11355                pr "     %s x);\n" pa
11356          ) (List.combine fields pas);
11357          pr "}\n"
11358 *)
11359     );
11360     sprintf "parse_%s" name
11361   in
11362
11363   generate_parsers xs
11364
11365 (* Generate ocaml/guestfs_inspector.mli. *)
11366 let generate_ocaml_inspector_mli () =
11367   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11368
11369   pr "\
11370 (** This is an OCaml language binding to the external [virt-inspector]
11371     program.
11372
11373     For more information, please read the man page [virt-inspector(1)].
11374 *)
11375
11376 ";
11377
11378   generate_types grammar;
11379   pr "(** The nested information returned from the {!inspect} function. *)\n";
11380   pr "\n";
11381
11382   pr "\
11383 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11384 (** To inspect a libvirt domain called [name], pass a singleton
11385     list: [inspect [name]].  When using libvirt only, you may
11386     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11387
11388     To inspect a disk image or images, pass a list of the filenames
11389     of the disk images: [inspect filenames]
11390
11391     This function inspects the given guest or disk images and
11392     returns a list of operating system(s) found and a large amount
11393     of information about them.  In the vast majority of cases,
11394     a virtual machine only contains a single operating system.
11395
11396     If the optional [~xml] parameter is given, then this function
11397     skips running the external virt-inspector program and just
11398     parses the given XML directly (which is expected to be XML
11399     produced from a previous run of virt-inspector).  The list of
11400     names and connect URI are ignored in this case.
11401
11402     This function can throw a wide variety of exceptions, for example
11403     if the external virt-inspector program cannot be found, or if
11404     it doesn't generate valid XML.
11405 *)
11406 "
11407
11408 (* Generate ocaml/guestfs_inspector.ml. *)
11409 let generate_ocaml_inspector_ml () =
11410   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11411
11412   pr "open Unix\n";
11413   pr "\n";
11414
11415   generate_types grammar;
11416   pr "\n";
11417
11418   pr "\
11419 (* Misc functions which are used by the parser code below. *)
11420 let first_child = function
11421   | Xml.Element (_, _, c::_) -> c
11422   | Xml.Element (name, _, []) ->
11423       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11424   | Xml.PCData str ->
11425       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11426
11427 let string_child_or_empty = function
11428   | Xml.Element (_, _, [Xml.PCData s]) -> s
11429   | Xml.Element (_, _, []) -> \"\"
11430   | Xml.Element (x, _, _) ->
11431       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11432                 x ^ \" instead\")
11433   | Xml.PCData str ->
11434       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11435
11436 let optional_child name xml =
11437   let children = Xml.children xml in
11438   try
11439     Some (List.find (function
11440                      | Xml.Element (n, _, _) when n = name -> true
11441                      | _ -> false) children)
11442   with
11443     Not_found -> None
11444
11445 let child name xml =
11446   match optional_child name xml with
11447   | Some c -> c
11448   | None ->
11449       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11450
11451 let attribute name xml =
11452   try Xml.attrib xml name
11453   with Xml.No_attribute _ ->
11454     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11455
11456 ";
11457
11458   generate_parsers grammar;
11459   pr "\n";
11460
11461   pr "\
11462 (* Run external virt-inspector, then use parser to parse the XML. *)
11463 let inspect ?connect ?xml names =
11464   let xml =
11465     match xml with
11466     | None ->
11467         if names = [] then invalid_arg \"inspect: no names given\";
11468         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11469           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11470           names in
11471         let cmd = List.map Filename.quote cmd in
11472         let cmd = String.concat \" \" cmd in
11473         let chan = open_process_in cmd in
11474         let xml = Xml.parse_in chan in
11475         (match close_process_in chan with
11476          | WEXITED 0 -> ()
11477          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11478          | WSIGNALED i | WSTOPPED i ->
11479              failwith (\"external virt-inspector command died or stopped on sig \" ^
11480                        string_of_int i)
11481         );
11482         xml
11483     | Some doc ->
11484         Xml.parse_string doc in
11485   parse_operatingsystems xml
11486 "
11487
11488 (* This is used to generate the src/MAX_PROC_NR file which
11489  * contains the maximum procedure number, a surrogate for the
11490  * ABI version number.  See src/Makefile.am for the details.
11491  *)
11492 and generate_max_proc_nr () =
11493   let proc_nrs = List.map (
11494     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11495   ) daemon_functions in
11496
11497   let max_proc_nr = List.fold_left max 0 proc_nrs in
11498
11499   pr "%d\n" max_proc_nr
11500
11501 let output_to filename k =
11502   let filename_new = filename ^ ".new" in
11503   chan := open_out filename_new;
11504   k ();
11505   close_out !chan;
11506   chan := Pervasives.stdout;
11507
11508   (* Is the new file different from the current file? *)
11509   if Sys.file_exists filename && files_equal filename filename_new then
11510     unlink filename_new                 (* same, so skip it *)
11511   else (
11512     (* different, overwrite old one *)
11513     (try chmod filename 0o644 with Unix_error _ -> ());
11514     rename filename_new filename;
11515     chmod filename 0o444;
11516     printf "written %s\n%!" filename;
11517   )
11518
11519 let perror msg = function
11520   | Unix_error (err, _, _) ->
11521       eprintf "%s: %s\n" msg (error_message err)
11522   | exn ->
11523       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11524
11525 (* Main program. *)
11526 let () =
11527   let lock_fd =
11528     try openfile "HACKING" [O_RDWR] 0
11529     with
11530     | Unix_error (ENOENT, _, _) ->
11531         eprintf "\
11532 You are probably running this from the wrong directory.
11533 Run it from the top source directory using the command
11534   src/generator.ml
11535 ";
11536         exit 1
11537     | exn ->
11538         perror "open: HACKING" exn;
11539         exit 1 in
11540
11541   (* Acquire a lock so parallel builds won't try to run the generator
11542    * twice at the same time.  Subsequent builds will wait for the first
11543    * one to finish.  Note the lock is released implicitly when the
11544    * program exits.
11545    *)
11546   (try lockf lock_fd F_LOCK 1
11547    with exn ->
11548      perror "lock: HACKING" exn;
11549      exit 1);
11550
11551   check_functions ();
11552
11553   output_to "src/guestfs_protocol.x" generate_xdr;
11554   output_to "src/guestfs-structs.h" generate_structs_h;
11555   output_to "src/guestfs-actions.h" generate_actions_h;
11556   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11557   output_to "src/guestfs-actions.c" generate_client_actions;
11558   output_to "src/guestfs-bindtests.c" generate_bindtests;
11559   output_to "src/guestfs-structs.pod" generate_structs_pod;
11560   output_to "src/guestfs-actions.pod" generate_actions_pod;
11561   output_to "src/guestfs-availability.pod" generate_availability_pod;
11562   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11563   output_to "src/libguestfs.syms" generate_linker_script;
11564   output_to "daemon/actions.h" generate_daemon_actions_h;
11565   output_to "daemon/stubs.c" generate_daemon_actions;
11566   output_to "daemon/names.c" generate_daemon_names;
11567   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11568   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11569   output_to "capitests/tests.c" generate_tests;
11570   output_to "fish/cmds.c" generate_fish_cmds;
11571   output_to "fish/completion.c" generate_fish_completion;
11572   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11573   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11574   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11575   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11576   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11577   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11578   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11579   output_to "perl/Guestfs.xs" generate_perl_xs;
11580   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11581   output_to "perl/bindtests.pl" generate_perl_bindtests;
11582   output_to "python/guestfs-py.c" generate_python_c;
11583   output_to "python/guestfs.py" generate_python_py;
11584   output_to "python/bindtests.py" generate_python_bindtests;
11585   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11586   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11587   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11588
11589   List.iter (
11590     fun (typ, jtyp) ->
11591       let cols = cols_of_struct typ in
11592       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11593       output_to filename (generate_java_struct jtyp cols);
11594   ) java_structs;
11595
11596   output_to "java/Makefile.inc" generate_java_makefile_inc;
11597   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11598   output_to "java/Bindtests.java" generate_java_bindtests;
11599   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11600   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11601   output_to "csharp/Libguestfs.cs" generate_csharp;
11602
11603   (* Always generate this file last, and unconditionally.  It's used
11604    * by the Makefile to know when we must re-run the generator.
11605    *)
11606   let chan = open_out "src/stamp-generator" in
11607   fprintf chan "1\n";
11608   close_out chan;
11609
11610   printf "generated %d lines of code\n" !lines