30d10389ac381e26f57fb59a8ade59686e3792ca
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | FishOutput of fish_output_t (* how to display output in guestfish *)
186   | NotInFish             (* do not export via guestfish *)
187   | NotInDocs             (* do not add this function to documentation *)
188   | DeprecatedBy of string (* function is deprecated, use .. instead *)
189   | Optional of string    (* function is part of an optional group *)
190
191 and fish_output_t =
192   | FishOutputOctal       (* for int return, print in octal *)
193   | FishOutputHexadecimal (* for int return, print in hex *)
194
195 (* You can supply zero or as many tests as you want per API call.
196  *
197  * Note that the test environment has 3 block devices, of size 500MB,
198  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
199  * a fourth ISO block device with some known files on it (/dev/sdd).
200  *
201  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
202  * Number of cylinders was 63 for IDE emulated disks with precisely
203  * the same size.  How exactly this is calculated is a mystery.
204  *
205  * The ISO block device (/dev/sdd) comes from images/test.iso.
206  *
207  * To be able to run the tests in a reasonable amount of time,
208  * the virtual machine and block devices are reused between tests.
209  * So don't try testing kill_subprocess :-x
210  *
211  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
212  *
213  * Don't assume anything about the previous contents of the block
214  * devices.  Use 'Init*' to create some initial scenarios.
215  *
216  * You can add a prerequisite clause to any individual test.  This
217  * is a run-time check, which, if it fails, causes the test to be
218  * skipped.  Useful if testing a command which might not work on
219  * all variations of libguestfs builds.  A test that has prerequisite
220  * of 'Always' is run unconditionally.
221  *
222  * In addition, packagers can skip individual tests by setting the
223  * environment variables:     eg:
224  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
225  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
226  *)
227 type tests = (test_init * test_prereq * test) list
228 and test =
229     (* Run the command sequence and just expect nothing to fail. *)
230   | TestRun of seq
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the string.
234      *)
235   | TestOutput of seq * string
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of strings.
239      *)
240   | TestOutputList of seq * string list
241
242     (* Run the command sequence and expect the output of the final
243      * command to be the list of block devices (could be either
244      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
245      * character of each string).
246      *)
247   | TestOutputListOfDevices of seq * string list
248
249     (* Run the command sequence and expect the output of the final
250      * command to be the integer.
251      *)
252   | TestOutputInt of seq * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be <op> <int>, eg. ">=", "1".
256      *)
257   | TestOutputIntOp of seq * string * int
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a true value (!= 0 or != NULL).
261      *)
262   | TestOutputTrue of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a false value (== 0 or == NULL, but not an error).
266      *)
267   | TestOutputFalse of seq
268
269     (* Run the command sequence and expect the output of the final
270      * command to be a list of the given length (but don't care about
271      * content).
272      *)
273   | TestOutputLength of seq * int
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a buffer (RBufferOut), ie. string + size.
277      *)
278   | TestOutputBuffer of seq * string
279
280     (* Run the command sequence and expect the output of the final
281      * command to be a structure.
282      *)
283   | TestOutputStruct of seq * test_field_compare list
284
285     (* Run the command sequence and expect the final command (only)
286      * to fail.
287      *)
288   | TestLastFail of seq
289
290 and test_field_compare =
291   | CompareWithInt of string * int
292   | CompareWithIntOp of string * string * int
293   | CompareWithString of string * string
294   | CompareFieldsIntEq of string * string
295   | CompareFieldsStrEq of string * string
296
297 (* Test prerequisites. *)
298 and test_prereq =
299     (* Test always runs. *)
300   | Always
301
302     (* Test is currently disabled - eg. it fails, or it tests some
303      * unimplemented feature.
304      *)
305   | Disabled
306
307     (* 'string' is some C code (a function body) that should return
308      * true or false.  The test will run if the code returns true.
309      *)
310   | If of string
311
312     (* As for 'If' but the test runs _unless_ the code returns true. *)
313   | Unless of string
314
315 (* Some initial scenarios for testing. *)
316 and test_init =
317     (* Do nothing, block devices could contain random stuff including
318      * LVM PVs, and some filesystems might be mounted.  This is usually
319      * a bad idea.
320      *)
321   | InitNone
322
323     (* Block devices are empty and no filesystems are mounted. *)
324   | InitEmpty
325
326     (* /dev/sda contains a single partition /dev/sda1, with random
327      * content.  /dev/sdb and /dev/sdc may have random content.
328      * No LVM.
329      *)
330   | InitPartition
331
332     (* /dev/sda contains a single partition /dev/sda1, which is formatted
333      * as ext2, empty [except for lost+found] and mounted on /.
334      * /dev/sdb and /dev/sdc may have random content.
335      * No LVM.
336      *)
337   | InitBasicFS
338
339     (* /dev/sda:
340      *   /dev/sda1 (is a PV):
341      *     /dev/VG/LV (size 8MB):
342      *       formatted as ext2, empty [except for lost+found], mounted on /
343      * /dev/sdb and /dev/sdc may have random content.
344      *)
345   | InitBasicFSonLVM
346
347     (* /dev/sdd (the ISO, see images/ directory in source)
348      * is mounted on /
349      *)
350   | InitISOFS
351
352 (* Sequence of commands for testing. *)
353 and seq = cmd list
354 and cmd = string list
355
356 (* Note about long descriptions: When referring to another
357  * action, use the format C<guestfs_other> (ie. the full name of
358  * the C function).  This will be replaced as appropriate in other
359  * language bindings.
360  *
361  * Apart from that, long descriptions are just perldoc paragraphs.
362  *)
363
364 (* Generate a random UUID (used in tests). *)
365 let uuidgen () =
366   let chan = open_process_in "uuidgen" in
367   let uuid = input_line chan in
368   (match close_process_in chan with
369    | WEXITED 0 -> ()
370    | WEXITED _ ->
371        failwith "uuidgen: process exited with non-zero status"
372    | WSIGNALED _ | WSTOPPED _ ->
373        failwith "uuidgen: process signalled or stopped by signal"
374   );
375   uuid
376
377 (* These test functions are used in the language binding tests. *)
378
379 let test_all_args = [
380   String "str";
381   OptString "optstr";
382   StringList "strlist";
383   Bool "b";
384   Int "integer";
385   Int64 "integer64";
386   FileIn "filein";
387   FileOut "fileout";
388 ]
389
390 let test_all_rets = [
391   (* except for RErr, which is tested thoroughly elsewhere *)
392   "test0rint",         RInt "valout";
393   "test0rint64",       RInt64 "valout";
394   "test0rbool",        RBool "valout";
395   "test0rconststring", RConstString "valout";
396   "test0rconstoptstring", RConstOptString "valout";
397   "test0rstring",      RString "valout";
398   "test0rstringlist",  RStringList "valout";
399   "test0rstruct",      RStruct ("valout", "lvm_pv");
400   "test0rstructlist",  RStructList ("valout", "lvm_pv");
401   "test0rhashtable",   RHashtable "valout";
402 ]
403
404 let test_functions = [
405   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
406    [],
407    "internal test function - do not use",
408    "\
409 This is an internal test function which is used to test whether
410 the automatically generated bindings can handle every possible
411 parameter type correctly.
412
413 It echos the contents of each parameter to stdout.
414
415 You probably don't want to call this function.");
416 ] @ List.flatten (
417   List.map (
418     fun (name, ret) ->
419       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
420         [],
421         "internal test function - do not use",
422         "\
423 This is an internal test function which is used to test whether
424 the automatically generated bindings can handle every possible
425 return type correctly.
426
427 It converts string C<val> to the return type.
428
429 You probably don't want to call this function.");
430        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
431         [],
432         "internal test function - do not use",
433         "\
434 This is an internal test function which is used to test whether
435 the automatically generated bindings can handle every possible
436 return type correctly.
437
438 This function always returns an error.
439
440 You probably don't want to call this function.")]
441   ) test_all_rets
442 )
443
444 (* non_daemon_functions are any functions which don't get processed
445  * in the daemon, eg. functions for setting and getting local
446  * configuration values.
447  *)
448
449 let non_daemon_functions = test_functions @ [
450   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
451    [],
452    "launch the qemu subprocess",
453    "\
454 Internally libguestfs is implemented by running a virtual machine
455 using L<qemu(1)>.
456
457 You should call this after configuring the handle
458 (eg. adding drives) but before performing any actions.");
459
460   ("wait_ready", (RErr, []), -1, [NotInFish],
461    [],
462    "wait until the qemu subprocess launches (no op)",
463    "\
464 This function is a no op.
465
466 In versions of the API E<lt> 1.0.71 you had to call this function
467 just after calling C<guestfs_launch> to wait for the launch
468 to complete.  However this is no longer necessary because
469 C<guestfs_launch> now does the waiting.
470
471 If you see any calls to this function in code then you can just
472 remove them, unless you want to retain compatibility with older
473 versions of the API.");
474
475   ("kill_subprocess", (RErr, []), -1, [],
476    [],
477    "kill the qemu subprocess",
478    "\
479 This kills the qemu subprocess.  You should never need to call this.");
480
481   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
482    [],
483    "add an image to examine or modify",
484    "\
485 This function adds a virtual machine disk image C<filename> to the
486 guest.  The first time you call this function, the disk appears as IDE
487 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
488 so on.
489
490 You don't necessarily need to be root when using libguestfs.  However
491 you obviously do need sufficient permissions to access the filename
492 for whatever operations you want to perform (ie. read access if you
493 just want to read the image or write access if you want to modify the
494 image).
495
496 This is equivalent to the qemu parameter
497 C<-drive file=filename,cache=off,if=...>.
498
499 C<cache=off> is omitted in cases where it is not supported by
500 the underlying filesystem.
501
502 C<if=...> is set at compile time by the configuration option
503 C<./configure --with-drive-if=...>.  In the rare case where you
504 might need to change this at run time, use C<guestfs_add_drive_with_if>
505 or C<guestfs_add_drive_ro_with_if>.
506
507 Note that this call checks for the existence of C<filename>.  This
508 stops you from specifying other types of drive which are supported
509 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
510 the general C<guestfs_config> call instead.");
511
512   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
513    [],
514    "add a CD-ROM disk image to examine",
515    "\
516 This function adds a virtual CD-ROM disk image to the guest.
517
518 This is equivalent to the qemu parameter C<-cdrom filename>.
519
520 Notes:
521
522 =over 4
523
524 =item *
525
526 This call checks for the existence of C<filename>.  This
527 stops you from specifying other types of drive which are supported
528 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
529 the general C<guestfs_config> call instead.
530
531 =item *
532
533 If you just want to add an ISO file (often you use this as an
534 efficient way to transfer large files into the guest), then you
535 should probably use C<guestfs_add_drive_ro> instead.
536
537 =back");
538
539   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
540    [],
541    "add a drive in snapshot mode (read-only)",
542    "\
543 This adds a drive in snapshot mode, making it effectively
544 read-only.
545
546 Note that writes to the device are allowed, and will be seen for
547 the duration of the guestfs handle, but they are written
548 to a temporary file which is discarded as soon as the guestfs
549 handle is closed.  We don't currently have any method to enable
550 changes to be committed, although qemu can support this.
551
552 This is equivalent to the qemu parameter
553 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
554
555 C<if=...> is set at compile time by the configuration option
556 C<./configure --with-drive-if=...>.  In the rare case where you
557 might need to change this at run time, use C<guestfs_add_drive_with_if>
558 or C<guestfs_add_drive_ro_with_if>.
559
560 C<readonly=on> is only added where qemu supports this option.
561
562 Note that this call checks for the existence of C<filename>.  This
563 stops you from specifying other types of drive which are supported
564 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
565 the general C<guestfs_config> call instead.");
566
567   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
568    [],
569    "add qemu parameters",
570    "\
571 This can be used to add arbitrary qemu command line parameters
572 of the form C<-param value>.  Actually it's not quite arbitrary - we
573 prevent you from setting some parameters which would interfere with
574 parameters that we use.
575
576 The first character of C<param> string must be a C<-> (dash).
577
578 C<value> can be NULL.");
579
580   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
581    [],
582    "set the qemu binary",
583    "\
584 Set the qemu binary that we will use.
585
586 The default is chosen when the library was compiled by the
587 configure script.
588
589 You can also override this by setting the C<LIBGUESTFS_QEMU>
590 environment variable.
591
592 Setting C<qemu> to C<NULL> restores the default qemu binary.
593
594 Note that you should call this function as early as possible
595 after creating the handle.  This is because some pre-launch
596 operations depend on testing qemu features (by running C<qemu -help>).
597 If the qemu binary changes, we don't retest features, and
598 so you might see inconsistent results.  Using the environment
599 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
600 the qemu binary at the same time as the handle is created.");
601
602   ("get_qemu", (RConstString "qemu", []), -1, [],
603    [InitNone, Always, TestRun (
604       [["get_qemu"]])],
605    "get the qemu binary",
606    "\
607 Return the current qemu binary.
608
609 This is always non-NULL.  If it wasn't set already, then this will
610 return the default qemu binary name.");
611
612   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
613    [],
614    "set the search path",
615    "\
616 Set the path that libguestfs searches for kernel and initrd.img.
617
618 The default is C<$libdir/guestfs> unless overridden by setting
619 C<LIBGUESTFS_PATH> environment variable.
620
621 Setting C<path> to C<NULL> restores the default path.");
622
623   ("get_path", (RConstString "path", []), -1, [],
624    [InitNone, Always, TestRun (
625       [["get_path"]])],
626    "get the search path",
627    "\
628 Return the current search path.
629
630 This is always non-NULL.  If it wasn't set already, then this will
631 return the default path.");
632
633   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
634    [],
635    "add options to kernel command line",
636    "\
637 This function is used to add additional options to the
638 guest kernel command line.
639
640 The default is C<NULL> unless overridden by setting
641 C<LIBGUESTFS_APPEND> environment variable.
642
643 Setting C<append> to C<NULL> means I<no> additional options
644 are passed (libguestfs always adds a few of its own).");
645
646   ("get_append", (RConstOptString "append", []), -1, [],
647    (* This cannot be tested with the current framework.  The
648     * function can return NULL in normal operations, which the
649     * test framework interprets as an error.
650     *)
651    [],
652    "get the additional kernel options",
653    "\
654 Return the additional kernel options which are added to the
655 guest kernel command line.
656
657 If C<NULL> then no options are added.");
658
659   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
660    [],
661    "set autosync mode",
662    "\
663 If C<autosync> is true, this enables autosync.  Libguestfs will make a
664 best effort attempt to run C<guestfs_umount_all> followed by
665 C<guestfs_sync> when the handle is closed
666 (also if the program exits without closing handles).
667
668 This is disabled by default (except in guestfish where it is
669 enabled by default).");
670
671   ("get_autosync", (RBool "autosync", []), -1, [],
672    [InitNone, Always, TestRun (
673       [["get_autosync"]])],
674    "get autosync mode",
675    "\
676 Get the autosync flag.");
677
678   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
679    [],
680    "set verbose mode",
681    "\
682 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
683
684 Verbose messages are disabled unless the environment variable
685 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
686
687   ("get_verbose", (RBool "verbose", []), -1, [],
688    [],
689    "get verbose mode",
690    "\
691 This returns the verbose messages flag.");
692
693   ("is_ready", (RBool "ready", []), -1, [],
694    [InitNone, Always, TestOutputTrue (
695       [["is_ready"]])],
696    "is ready to accept commands",
697    "\
698 This returns true iff this handle is ready to accept commands
699 (in the C<READY> state).
700
701 For more information on states, see L<guestfs(3)>.");
702
703   ("is_config", (RBool "config", []), -1, [],
704    [InitNone, Always, TestOutputFalse (
705       [["is_config"]])],
706    "is in configuration state",
707    "\
708 This returns true iff this handle is being configured
709 (in the C<CONFIG> state).
710
711 For more information on states, see L<guestfs(3)>.");
712
713   ("is_launching", (RBool "launching", []), -1, [],
714    [InitNone, Always, TestOutputFalse (
715       [["is_launching"]])],
716    "is launching subprocess",
717    "\
718 This returns true iff this handle is launching the subprocess
719 (in the C<LAUNCHING> state).
720
721 For more information on states, see L<guestfs(3)>.");
722
723   ("is_busy", (RBool "busy", []), -1, [],
724    [InitNone, Always, TestOutputFalse (
725       [["is_busy"]])],
726    "is busy processing a command",
727    "\
728 This returns true iff this handle is busy processing a command
729 (in the C<BUSY> state).
730
731 For more information on states, see L<guestfs(3)>.");
732
733   ("get_state", (RInt "state", []), -1, [],
734    [],
735    "get the current state",
736    "\
737 This returns the current state as an opaque integer.  This is
738 only useful for printing debug and internal error messages.
739
740 For more information on states, see L<guestfs(3)>.");
741
742   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
743    [InitNone, Always, TestOutputInt (
744       [["set_memsize"; "500"];
745        ["get_memsize"]], 500)],
746    "set memory allocated to the qemu subprocess",
747    "\
748 This sets the memory size in megabytes allocated to the
749 qemu subprocess.  This only has any effect if called before
750 C<guestfs_launch>.
751
752 You can also change this by setting the environment
753 variable C<LIBGUESTFS_MEMSIZE> before the handle is
754 created.
755
756 For more information on the architecture of libguestfs,
757 see L<guestfs(3)>.");
758
759   ("get_memsize", (RInt "memsize", []), -1, [],
760    [InitNone, Always, TestOutputIntOp (
761       [["get_memsize"]], ">=", 256)],
762    "get memory allocated to the qemu subprocess",
763    "\
764 This gets the memory size in megabytes allocated to the
765 qemu subprocess.
766
767 If C<guestfs_set_memsize> was not called
768 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
769 then this returns the compiled-in default value for memsize.
770
771 For more information on the architecture of libguestfs,
772 see L<guestfs(3)>.");
773
774   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
775    [InitNone, Always, TestOutputIntOp (
776       [["get_pid"]], ">=", 1)],
777    "get PID of qemu subprocess",
778    "\
779 Return the process ID of the qemu subprocess.  If there is no
780 qemu subprocess, then this will return an error.
781
782 This is an internal call used for debugging and testing.");
783
784   ("version", (RStruct ("version", "version"), []), -1, [],
785    [InitNone, Always, TestOutputStruct (
786       [["version"]], [CompareWithInt ("major", 1)])],
787    "get the library version number",
788    "\
789 Return the libguestfs version number that the program is linked
790 against.
791
792 Note that because of dynamic linking this is not necessarily
793 the version of libguestfs that you compiled against.  You can
794 compile the program, and then at runtime dynamically link
795 against a completely different C<libguestfs.so> library.
796
797 This call was added in version C<1.0.58>.  In previous
798 versions of libguestfs there was no way to get the version
799 number.  From C code you can use ELF weak linking tricks to find out if
800 this symbol exists (if it doesn't, then it's an earlier version).
801
802 The call returns a structure with four elements.  The first
803 three (C<major>, C<minor> and C<release>) are numbers and
804 correspond to the usual version triplet.  The fourth element
805 (C<extra>) is a string and is normally empty, but may be
806 used for distro-specific information.
807
808 To construct the original version string:
809 C<$major.$minor.$release$extra>
810
811 I<Note:> Don't use this call to test for availability
812 of features.  Distro backports makes this unreliable.  Use
813 C<guestfs_available> instead.");
814
815   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
816    [InitNone, Always, TestOutputTrue (
817       [["set_selinux"; "true"];
818        ["get_selinux"]])],
819    "set SELinux enabled or disabled at appliance boot",
820    "\
821 This sets the selinux flag that is passed to the appliance
822 at boot time.  The default is C<selinux=0> (disabled).
823
824 Note that if SELinux is enabled, it is always in
825 Permissive mode (C<enforcing=0>).
826
827 For more information on the architecture of libguestfs,
828 see L<guestfs(3)>.");
829
830   ("get_selinux", (RBool "selinux", []), -1, [],
831    [],
832    "get SELinux enabled flag",
833    "\
834 This returns the current setting of the selinux flag which
835 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
836
837 For more information on the architecture of libguestfs,
838 see L<guestfs(3)>.");
839
840   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
841    [InitNone, Always, TestOutputFalse (
842       [["set_trace"; "false"];
843        ["get_trace"]])],
844    "enable or disable command traces",
845    "\
846 If the command trace flag is set to 1, then commands are
847 printed on stdout before they are executed in a format
848 which is very similar to the one used by guestfish.  In
849 other words, you can run a program with this enabled, and
850 you will get out a script which you can feed to guestfish
851 to perform the same set of actions.
852
853 If you want to trace C API calls into libguestfs (and
854 other libraries) then possibly a better way is to use
855 the external ltrace(1) command.
856
857 Command traces are disabled unless the environment variable
858 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
859
860   ("get_trace", (RBool "trace", []), -1, [],
861    [],
862    "get command trace enabled flag",
863    "\
864 Return the command trace flag.");
865
866   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
867    [InitNone, Always, TestOutputFalse (
868       [["set_direct"; "false"];
869        ["get_direct"]])],
870    "enable or disable direct appliance mode",
871    "\
872 If the direct appliance mode flag is enabled, then stdin and
873 stdout are passed directly through to the appliance once it
874 is launched.
875
876 One consequence of this is that log messages aren't caught
877 by the library and handled by C<guestfs_set_log_message_callback>,
878 but go straight to stdout.
879
880 You probably don't want to use this unless you know what you
881 are doing.
882
883 The default is disabled.");
884
885   ("get_direct", (RBool "direct", []), -1, [],
886    [],
887    "get direct appliance mode flag",
888    "\
889 Return the direct appliance mode flag.");
890
891   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
892    [InitNone, Always, TestOutputTrue (
893       [["set_recovery_proc"; "true"];
894        ["get_recovery_proc"]])],
895    "enable or disable the recovery process",
896    "\
897 If this is called with the parameter C<false> then
898 C<guestfs_launch> does not create a recovery process.  The
899 purpose of the recovery process is to stop runaway qemu
900 processes in the case where the main program aborts abruptly.
901
902 This only has any effect if called before C<guestfs_launch>,
903 and the default is true.
904
905 About the only time when you would want to disable this is
906 if the main process will fork itself into the background
907 (\"daemonize\" itself).  In this case the recovery process
908 thinks that the main program has disappeared and so kills
909 qemu, which is not very helpful.");
910
911   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
912    [],
913    "get recovery process enabled flag",
914    "\
915 Return the recovery process enabled flag.");
916
917   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
918    [],
919    "add a drive specifying the QEMU block emulation to use",
920    "\
921 This is the same as C<guestfs_add_drive> but it allows you
922 to specify the QEMU interface emulation to use at run time.");
923
924   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
925    [],
926    "add a drive read-only specifying the QEMU block emulation to use",
927    "\
928 This is the same as C<guestfs_add_drive_ro> but it allows you
929 to specify the QEMU interface emulation to use at run time.");
930
931 ]
932
933 (* daemon_functions are any functions which cause some action
934  * to take place in the daemon.
935  *)
936
937 let daemon_functions = [
938   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
939    [InitEmpty, Always, TestOutput (
940       [["part_disk"; "/dev/sda"; "mbr"];
941        ["mkfs"; "ext2"; "/dev/sda1"];
942        ["mount"; "/dev/sda1"; "/"];
943        ["write_file"; "/new"; "new file contents"; "0"];
944        ["cat"; "/new"]], "new file contents")],
945    "mount a guest disk at a position in the filesystem",
946    "\
947 Mount a guest disk at a position in the filesystem.  Block devices
948 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
949 the guest.  If those block devices contain partitions, they will have
950 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
951 names can be used.
952
953 The rules are the same as for L<mount(2)>:  A filesystem must
954 first be mounted on C</> before others can be mounted.  Other
955 filesystems can only be mounted on directories which already
956 exist.
957
958 The mounted filesystem is writable, if we have sufficient permissions
959 on the underlying device.
960
961 B<Important note:>
962 When you use this call, the filesystem options C<sync> and C<noatime>
963 are set implicitly.  This was originally done because we thought it
964 would improve reliability, but it turns out that I<-o sync> has a
965 very large negative performance impact and negligible effect on
966 reliability.  Therefore we recommend that you avoid using
967 C<guestfs_mount> in any code that needs performance, and instead
968 use C<guestfs_mount_options> (use an empty string for the first
969 parameter if you don't want any options).");
970
971   ("sync", (RErr, []), 2, [],
972    [ InitEmpty, Always, TestRun [["sync"]]],
973    "sync disks, writes are flushed through to the disk image",
974    "\
975 This syncs the disk, so that any writes are flushed through to the
976 underlying disk image.
977
978 You should always call this if you have modified a disk image, before
979 closing the handle.");
980
981   ("touch", (RErr, [Pathname "path"]), 3, [],
982    [InitBasicFS, Always, TestOutputTrue (
983       [["touch"; "/new"];
984        ["exists"; "/new"]])],
985    "update file timestamps or create a new file",
986    "\
987 Touch acts like the L<touch(1)> command.  It can be used to
988 update the timestamps on a file, or, if the file does not exist,
989 to create a new zero-length file.");
990
991   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
992    [InitISOFS, Always, TestOutput (
993       [["cat"; "/known-2"]], "abcdef\n")],
994    "list the contents of a file",
995    "\
996 Return the contents of the file named C<path>.
997
998 Note that this function cannot correctly handle binary files
999 (specifically, files containing C<\\0> character which is treated
1000 as end of string).  For those you need to use the C<guestfs_read_file>
1001 or C<guestfs_download> functions which have a more complex interface.");
1002
1003   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1004    [], (* XXX Tricky to test because it depends on the exact format
1005         * of the 'ls -l' command, which changes between F10 and F11.
1006         *)
1007    "list the files in a directory (long format)",
1008    "\
1009 List the files in C<directory> (relative to the root directory,
1010 there is no cwd) in the format of 'ls -la'.
1011
1012 This command is mostly useful for interactive sessions.  It
1013 is I<not> intended that you try to parse the output string.");
1014
1015   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1016    [InitBasicFS, Always, TestOutputList (
1017       [["touch"; "/new"];
1018        ["touch"; "/newer"];
1019        ["touch"; "/newest"];
1020        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1021    "list the files in a directory",
1022    "\
1023 List the files in C<directory> (relative to the root directory,
1024 there is no cwd).  The '.' and '..' entries are not returned, but
1025 hidden files are shown.
1026
1027 This command is mostly useful for interactive sessions.  Programs
1028 should probably use C<guestfs_readdir> instead.");
1029
1030   ("list_devices", (RStringList "devices", []), 7, [],
1031    [InitEmpty, Always, TestOutputListOfDevices (
1032       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1033    "list the block devices",
1034    "\
1035 List all the block devices.
1036
1037 The full block device names are returned, eg. C</dev/sda>");
1038
1039   ("list_partitions", (RStringList "partitions", []), 8, [],
1040    [InitBasicFS, Always, TestOutputListOfDevices (
1041       [["list_partitions"]], ["/dev/sda1"]);
1042     InitEmpty, Always, TestOutputListOfDevices (
1043       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1044        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1045    "list the partitions",
1046    "\
1047 List all the partitions detected on all block devices.
1048
1049 The full partition device names are returned, eg. C</dev/sda1>
1050
1051 This does not return logical volumes.  For that you will need to
1052 call C<guestfs_lvs>.");
1053
1054   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1055    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1056       [["pvs"]], ["/dev/sda1"]);
1057     InitEmpty, Always, TestOutputListOfDevices (
1058       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1059        ["pvcreate"; "/dev/sda1"];
1060        ["pvcreate"; "/dev/sda2"];
1061        ["pvcreate"; "/dev/sda3"];
1062        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1063    "list the LVM physical volumes (PVs)",
1064    "\
1065 List all the physical volumes detected.  This is the equivalent
1066 of the L<pvs(8)> command.
1067
1068 This returns a list of just the device names that contain
1069 PVs (eg. C</dev/sda2>).
1070
1071 See also C<guestfs_pvs_full>.");
1072
1073   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1074    [InitBasicFSonLVM, Always, TestOutputList (
1075       [["vgs"]], ["VG"]);
1076     InitEmpty, Always, TestOutputList (
1077       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1078        ["pvcreate"; "/dev/sda1"];
1079        ["pvcreate"; "/dev/sda2"];
1080        ["pvcreate"; "/dev/sda3"];
1081        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1082        ["vgcreate"; "VG2"; "/dev/sda3"];
1083        ["vgs"]], ["VG1"; "VG2"])],
1084    "list the LVM volume groups (VGs)",
1085    "\
1086 List all the volumes groups detected.  This is the equivalent
1087 of the L<vgs(8)> command.
1088
1089 This returns a list of just the volume group names that were
1090 detected (eg. C<VolGroup00>).
1091
1092 See also C<guestfs_vgs_full>.");
1093
1094   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1095    [InitBasicFSonLVM, Always, TestOutputList (
1096       [["lvs"]], ["/dev/VG/LV"]);
1097     InitEmpty, Always, TestOutputList (
1098       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1099        ["pvcreate"; "/dev/sda1"];
1100        ["pvcreate"; "/dev/sda2"];
1101        ["pvcreate"; "/dev/sda3"];
1102        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1103        ["vgcreate"; "VG2"; "/dev/sda3"];
1104        ["lvcreate"; "LV1"; "VG1"; "50"];
1105        ["lvcreate"; "LV2"; "VG1"; "50"];
1106        ["lvcreate"; "LV3"; "VG2"; "50"];
1107        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1108    "list the LVM logical volumes (LVs)",
1109    "\
1110 List all the logical volumes detected.  This is the equivalent
1111 of the L<lvs(8)> command.
1112
1113 This returns a list of the logical volume device names
1114 (eg. C</dev/VolGroup00/LogVol00>).
1115
1116 See also C<guestfs_lvs_full>.");
1117
1118   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1119    [], (* XXX how to test? *)
1120    "list the LVM physical volumes (PVs)",
1121    "\
1122 List all the physical volumes detected.  This is the equivalent
1123 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1124
1125   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM volume groups (VGs)",
1128    "\
1129 List all the volumes groups detected.  This is the equivalent
1130 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1133    [], (* XXX how to test? *)
1134    "list the LVM logical volumes (LVs)",
1135    "\
1136 List all the logical volumes detected.  This is the equivalent
1137 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1138
1139   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1140    [InitISOFS, Always, TestOutputList (
1141       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1142     InitISOFS, Always, TestOutputList (
1143       [["read_lines"; "/empty"]], [])],
1144    "read file as lines",
1145    "\
1146 Return the contents of the file named C<path>.
1147
1148 The file contents are returned as a list of lines.  Trailing
1149 C<LF> and C<CRLF> character sequences are I<not> returned.
1150
1151 Note that this function cannot correctly handle binary files
1152 (specifically, files containing C<\\0> character which is treated
1153 as end of line).  For those you need to use the C<guestfs_read_file>
1154 function which has a more complex interface.");
1155
1156   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1157    [], (* XXX Augeas code needs tests. *)
1158    "create a new Augeas handle",
1159    "\
1160 Create a new Augeas handle for editing configuration files.
1161 If there was any previous Augeas handle associated with this
1162 guestfs session, then it is closed.
1163
1164 You must call this before using any other C<guestfs_aug_*>
1165 commands.
1166
1167 C<root> is the filesystem root.  C<root> must not be NULL,
1168 use C</> instead.
1169
1170 The flags are the same as the flags defined in
1171 E<lt>augeas.hE<gt>, the logical I<or> of the following
1172 integers:
1173
1174 =over 4
1175
1176 =item C<AUG_SAVE_BACKUP> = 1
1177
1178 Keep the original file with a C<.augsave> extension.
1179
1180 =item C<AUG_SAVE_NEWFILE> = 2
1181
1182 Save changes into a file with extension C<.augnew>, and
1183 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1184
1185 =item C<AUG_TYPE_CHECK> = 4
1186
1187 Typecheck lenses (can be expensive).
1188
1189 =item C<AUG_NO_STDINC> = 8
1190
1191 Do not use standard load path for modules.
1192
1193 =item C<AUG_SAVE_NOOP> = 16
1194
1195 Make save a no-op, just record what would have been changed.
1196
1197 =item C<AUG_NO_LOAD> = 32
1198
1199 Do not load the tree in C<guestfs_aug_init>.
1200
1201 =back
1202
1203 To close the handle, you can call C<guestfs_aug_close>.
1204
1205 To find out more about Augeas, see L<http://augeas.net/>.");
1206
1207   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1208    [], (* XXX Augeas code needs tests. *)
1209    "close the current Augeas handle",
1210    "\
1211 Close the current Augeas handle and free up any resources
1212 used by it.  After calling this, you have to call
1213 C<guestfs_aug_init> again before you can use any other
1214 Augeas functions.");
1215
1216   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1217    [], (* XXX Augeas code needs tests. *)
1218    "define an Augeas variable",
1219    "\
1220 Defines an Augeas variable C<name> whose value is the result
1221 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1222 undefined.
1223
1224 On success this returns the number of nodes in C<expr>, or
1225 C<0> if C<expr> evaluates to something which is not a nodeset.");
1226
1227   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1228    [], (* XXX Augeas code needs tests. *)
1229    "define an Augeas node",
1230    "\
1231 Defines a variable C<name> whose value is the result of
1232 evaluating C<expr>.
1233
1234 If C<expr> evaluates to an empty nodeset, a node is created,
1235 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1236 C<name> will be the nodeset containing that single node.
1237
1238 On success this returns a pair containing the
1239 number of nodes in the nodeset, and a boolean flag
1240 if a node was created.");
1241
1242   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "look up the value of an Augeas path",
1245    "\
1246 Look up the value associated with C<path>.  If C<path>
1247 matches exactly one node, the C<value> is returned.");
1248
1249   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1250    [], (* XXX Augeas code needs tests. *)
1251    "set Augeas path to value",
1252    "\
1253 Set the value associated with C<path> to C<val>.
1254
1255 In the Augeas API, it is possible to clear a node by setting
1256 the value to NULL.  Due to an oversight in the libguestfs API
1257 you cannot do that with this call.  Instead you must use the
1258 C<guestfs_aug_clear> call.");
1259
1260   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1261    [], (* XXX Augeas code needs tests. *)
1262    "insert a sibling Augeas node",
1263    "\
1264 Create a new sibling C<label> for C<path>, inserting it into
1265 the tree before or after C<path> (depending on the boolean
1266 flag C<before>).
1267
1268 C<path> must match exactly one existing node in the tree, and
1269 C<label> must be a label, ie. not contain C</>, C<*> or end
1270 with a bracketed index C<[N]>.");
1271
1272   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1273    [], (* XXX Augeas code needs tests. *)
1274    "remove an Augeas path",
1275    "\
1276 Remove C<path> and all of its children.
1277
1278 On success this returns the number of entries which were removed.");
1279
1280   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1281    [], (* XXX Augeas code needs tests. *)
1282    "move Augeas node",
1283    "\
1284 Move the node C<src> to C<dest>.  C<src> must match exactly
1285 one node.  C<dest> is overwritten if it exists.");
1286
1287   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "return Augeas nodes which match augpath",
1290    "\
1291 Returns a list of paths which match the path expression C<path>.
1292 The returned paths are sufficiently qualified so that they match
1293 exactly one node in the current tree.");
1294
1295   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1296    [], (* XXX Augeas code needs tests. *)
1297    "write all pending Augeas changes to disk",
1298    "\
1299 This writes all pending changes to disk.
1300
1301 The flags which were passed to C<guestfs_aug_init> affect exactly
1302 how files are saved.");
1303
1304   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1305    [], (* XXX Augeas code needs tests. *)
1306    "load files into the tree",
1307    "\
1308 Load files into the tree.
1309
1310 See C<aug_load> in the Augeas documentation for the full gory
1311 details.");
1312
1313   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1314    [], (* XXX Augeas code needs tests. *)
1315    "list Augeas nodes under augpath",
1316    "\
1317 This is just a shortcut for listing C<guestfs_aug_match>
1318 C<path/*> and sorting the resulting nodes into alphabetical order.");
1319
1320   ("rm", (RErr, [Pathname "path"]), 29, [],
1321    [InitBasicFS, Always, TestRun
1322       [["touch"; "/new"];
1323        ["rm"; "/new"]];
1324     InitBasicFS, Always, TestLastFail
1325       [["rm"; "/new"]];
1326     InitBasicFS, Always, TestLastFail
1327       [["mkdir"; "/new"];
1328        ["rm"; "/new"]]],
1329    "remove a file",
1330    "\
1331 Remove the single file C<path>.");
1332
1333   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1334    [InitBasicFS, Always, TestRun
1335       [["mkdir"; "/new"];
1336        ["rmdir"; "/new"]];
1337     InitBasicFS, Always, TestLastFail
1338       [["rmdir"; "/new"]];
1339     InitBasicFS, Always, TestLastFail
1340       [["touch"; "/new"];
1341        ["rmdir"; "/new"]]],
1342    "remove a directory",
1343    "\
1344 Remove the single directory C<path>.");
1345
1346   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1347    [InitBasicFS, Always, TestOutputFalse
1348       [["mkdir"; "/new"];
1349        ["mkdir"; "/new/foo"];
1350        ["touch"; "/new/foo/bar"];
1351        ["rm_rf"; "/new"];
1352        ["exists"; "/new"]]],
1353    "remove a file or directory recursively",
1354    "\
1355 Remove the file or directory C<path>, recursively removing the
1356 contents if its a directory.  This is like the C<rm -rf> shell
1357 command.");
1358
1359   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1360    [InitBasicFS, Always, TestOutputTrue
1361       [["mkdir"; "/new"];
1362        ["is_dir"; "/new"]];
1363     InitBasicFS, Always, TestLastFail
1364       [["mkdir"; "/new/foo/bar"]]],
1365    "create a directory",
1366    "\
1367 Create a directory named C<path>.");
1368
1369   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1370    [InitBasicFS, Always, TestOutputTrue
1371       [["mkdir_p"; "/new/foo/bar"];
1372        ["is_dir"; "/new/foo/bar"]];
1373     InitBasicFS, Always, TestOutputTrue
1374       [["mkdir_p"; "/new/foo/bar"];
1375        ["is_dir"; "/new/foo"]];
1376     InitBasicFS, Always, TestOutputTrue
1377       [["mkdir_p"; "/new/foo/bar"];
1378        ["is_dir"; "/new"]];
1379     (* Regression tests for RHBZ#503133: *)
1380     InitBasicFS, Always, TestRun
1381       [["mkdir"; "/new"];
1382        ["mkdir_p"; "/new"]];
1383     InitBasicFS, Always, TestLastFail
1384       [["touch"; "/new"];
1385        ["mkdir_p"; "/new"]]],
1386    "create a directory and parents",
1387    "\
1388 Create a directory named C<path>, creating any parent directories
1389 as necessary.  This is like the C<mkdir -p> shell command.");
1390
1391   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1392    [], (* XXX Need stat command to test *)
1393    "change file mode",
1394    "\
1395 Change the mode (permissions) of C<path> to C<mode>.  Only
1396 numeric modes are supported.
1397
1398 I<Note>: When using this command from guestfish, C<mode>
1399 by default would be decimal, unless you prefix it with
1400 C<0> to get octal, ie. use C<0700> not C<700>.
1401
1402 The mode actually set is affected by the umask.");
1403
1404   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1405    [], (* XXX Need stat command to test *)
1406    "change file owner and group",
1407    "\
1408 Change the file owner to C<owner> and group to C<group>.
1409
1410 Only numeric uid and gid are supported.  If you want to use
1411 names, you will need to locate and parse the password file
1412 yourself (Augeas support makes this relatively easy).");
1413
1414   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1415    [InitISOFS, Always, TestOutputTrue (
1416       [["exists"; "/empty"]]);
1417     InitISOFS, Always, TestOutputTrue (
1418       [["exists"; "/directory"]])],
1419    "test if file or directory exists",
1420    "\
1421 This returns C<true> if and only if there is a file, directory
1422 (or anything) with the given C<path> name.
1423
1424 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1425
1426   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1427    [InitISOFS, Always, TestOutputTrue (
1428       [["is_file"; "/known-1"]]);
1429     InitISOFS, Always, TestOutputFalse (
1430       [["is_file"; "/directory"]])],
1431    "test if file exists",
1432    "\
1433 This returns C<true> if and only if there is a file
1434 with the given C<path> name.  Note that it returns false for
1435 other objects like directories.
1436
1437 See also C<guestfs_stat>.");
1438
1439   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1440    [InitISOFS, Always, TestOutputFalse (
1441       [["is_dir"; "/known-3"]]);
1442     InitISOFS, Always, TestOutputTrue (
1443       [["is_dir"; "/directory"]])],
1444    "test if file exists",
1445    "\
1446 This returns C<true> if and only if there is a directory
1447 with the given C<path> name.  Note that it returns false for
1448 other objects like files.
1449
1450 See also C<guestfs_stat>.");
1451
1452   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1453    [InitEmpty, Always, TestOutputListOfDevices (
1454       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1455        ["pvcreate"; "/dev/sda1"];
1456        ["pvcreate"; "/dev/sda2"];
1457        ["pvcreate"; "/dev/sda3"];
1458        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1459    "create an LVM physical volume",
1460    "\
1461 This creates an LVM physical volume on the named C<device>,
1462 where C<device> should usually be a partition name such
1463 as C</dev/sda1>.");
1464
1465   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1466    [InitEmpty, Always, TestOutputList (
1467       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1468        ["pvcreate"; "/dev/sda1"];
1469        ["pvcreate"; "/dev/sda2"];
1470        ["pvcreate"; "/dev/sda3"];
1471        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1472        ["vgcreate"; "VG2"; "/dev/sda3"];
1473        ["vgs"]], ["VG1"; "VG2"])],
1474    "create an LVM volume group",
1475    "\
1476 This creates an LVM volume group called C<volgroup>
1477 from the non-empty list of physical volumes C<physvols>.");
1478
1479   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1480    [InitEmpty, Always, TestOutputList (
1481       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1482        ["pvcreate"; "/dev/sda1"];
1483        ["pvcreate"; "/dev/sda2"];
1484        ["pvcreate"; "/dev/sda3"];
1485        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1486        ["vgcreate"; "VG2"; "/dev/sda3"];
1487        ["lvcreate"; "LV1"; "VG1"; "50"];
1488        ["lvcreate"; "LV2"; "VG1"; "50"];
1489        ["lvcreate"; "LV3"; "VG2"; "50"];
1490        ["lvcreate"; "LV4"; "VG2"; "50"];
1491        ["lvcreate"; "LV5"; "VG2"; "50"];
1492        ["lvs"]],
1493       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1494        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1495    "create an LVM logical volume",
1496    "\
1497 This creates an LVM logical volume called C<logvol>
1498 on the volume group C<volgroup>, with C<size> megabytes.");
1499
1500   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1501    [InitEmpty, Always, TestOutput (
1502       [["part_disk"; "/dev/sda"; "mbr"];
1503        ["mkfs"; "ext2"; "/dev/sda1"];
1504        ["mount_options"; ""; "/dev/sda1"; "/"];
1505        ["write_file"; "/new"; "new file contents"; "0"];
1506        ["cat"; "/new"]], "new file contents")],
1507    "make a filesystem",
1508    "\
1509 This creates a filesystem on C<device> (usually a partition
1510 or LVM logical volume).  The filesystem type is C<fstype>, for
1511 example C<ext3>.");
1512
1513   ("sfdisk", (RErr, [Device "device";
1514                      Int "cyls"; Int "heads"; Int "sectors";
1515                      StringList "lines"]), 43, [DangerWillRobinson],
1516    [],
1517    "create partitions on a block device",
1518    "\
1519 This is a direct interface to the L<sfdisk(8)> program for creating
1520 partitions on block devices.
1521
1522 C<device> should be a block device, for example C</dev/sda>.
1523
1524 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1525 and sectors on the device, which are passed directly to sfdisk as
1526 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1527 of these, then the corresponding parameter is omitted.  Usually for
1528 'large' disks, you can just pass C<0> for these, but for small
1529 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1530 out the right geometry and you will need to tell it.
1531
1532 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1533 information refer to the L<sfdisk(8)> manpage.
1534
1535 To create a single partition occupying the whole disk, you would
1536 pass C<lines> as a single element list, when the single element being
1537 the string C<,> (comma).
1538
1539 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1540 C<guestfs_part_init>");
1541
1542   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1543    [InitBasicFS, Always, TestOutput (
1544       [["write_file"; "/new"; "new file contents"; "0"];
1545        ["cat"; "/new"]], "new file contents");
1546     InitBasicFS, Always, TestOutput (
1547       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1548        ["cat"; "/new"]], "\nnew file contents\n");
1549     InitBasicFS, Always, TestOutput (
1550       [["write_file"; "/new"; "\n\n"; "0"];
1551        ["cat"; "/new"]], "\n\n");
1552     InitBasicFS, Always, TestOutput (
1553       [["write_file"; "/new"; ""; "0"];
1554        ["cat"; "/new"]], "");
1555     InitBasicFS, Always, TestOutput (
1556       [["write_file"; "/new"; "\n\n\n"; "0"];
1557        ["cat"; "/new"]], "\n\n\n");
1558     InitBasicFS, Always, TestOutput (
1559       [["write_file"; "/new"; "\n"; "0"];
1560        ["cat"; "/new"]], "\n")],
1561    "create a file",
1562    "\
1563 This call creates a file called C<path>.  The contents of the
1564 file is the string C<content> (which can contain any 8 bit data),
1565 with length C<size>.
1566
1567 As a special case, if C<size> is C<0>
1568 then the length is calculated using C<strlen> (so in this case
1569 the content cannot contain embedded ASCII NULs).
1570
1571 I<NB.> Owing to a bug, writing content containing ASCII NUL
1572 characters does I<not> work, even if the length is specified.
1573 We hope to resolve this bug in a future version.  In the meantime
1574 use C<guestfs_upload>.");
1575
1576   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1577    [InitEmpty, Always, TestOutputListOfDevices (
1578       [["part_disk"; "/dev/sda"; "mbr"];
1579        ["mkfs"; "ext2"; "/dev/sda1"];
1580        ["mount_options"; ""; "/dev/sda1"; "/"];
1581        ["mounts"]], ["/dev/sda1"]);
1582     InitEmpty, Always, TestOutputList (
1583       [["part_disk"; "/dev/sda"; "mbr"];
1584        ["mkfs"; "ext2"; "/dev/sda1"];
1585        ["mount_options"; ""; "/dev/sda1"; "/"];
1586        ["umount"; "/"];
1587        ["mounts"]], [])],
1588    "unmount a filesystem",
1589    "\
1590 This unmounts the given filesystem.  The filesystem may be
1591 specified either by its mountpoint (path) or the device which
1592 contains the filesystem.");
1593
1594   ("mounts", (RStringList "devices", []), 46, [],
1595    [InitBasicFS, Always, TestOutputListOfDevices (
1596       [["mounts"]], ["/dev/sda1"])],
1597    "show mounted filesystems",
1598    "\
1599 This returns the list of currently mounted filesystems.  It returns
1600 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1601
1602 Some internal mounts are not shown.
1603
1604 See also: C<guestfs_mountpoints>");
1605
1606   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1607    [InitBasicFS, Always, TestOutputList (
1608       [["umount_all"];
1609        ["mounts"]], []);
1610     (* check that umount_all can unmount nested mounts correctly: *)
1611     InitEmpty, Always, TestOutputList (
1612       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1613        ["mkfs"; "ext2"; "/dev/sda1"];
1614        ["mkfs"; "ext2"; "/dev/sda2"];
1615        ["mkfs"; "ext2"; "/dev/sda3"];
1616        ["mount_options"; ""; "/dev/sda1"; "/"];
1617        ["mkdir"; "/mp1"];
1618        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1619        ["mkdir"; "/mp1/mp2"];
1620        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1621        ["mkdir"; "/mp1/mp2/mp3"];
1622        ["umount_all"];
1623        ["mounts"]], [])],
1624    "unmount all filesystems",
1625    "\
1626 This unmounts all mounted filesystems.
1627
1628 Some internal mounts are not unmounted by this call.");
1629
1630   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1631    [],
1632    "remove all LVM LVs, VGs and PVs",
1633    "\
1634 This command removes all LVM logical volumes, volume groups
1635 and physical volumes.");
1636
1637   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1638    [InitISOFS, Always, TestOutput (
1639       [["file"; "/empty"]], "empty");
1640     InitISOFS, Always, TestOutput (
1641       [["file"; "/known-1"]], "ASCII text");
1642     InitISOFS, Always, TestLastFail (
1643       [["file"; "/notexists"]])],
1644    "determine file type",
1645    "\
1646 This call uses the standard L<file(1)> command to determine
1647 the type or contents of the file.  This also works on devices,
1648 for example to find out whether a partition contains a filesystem.
1649
1650 This call will also transparently look inside various types
1651 of compressed file.
1652
1653 The exact command which runs is C<file -zbsL path>.  Note in
1654 particular that the filename is not prepended to the output
1655 (the C<-b> option).");
1656
1657   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1658    [InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 1"]], "Result1");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 2"]], "Result2\n");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 3"]], "\nResult3");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 4"]], "\nResult4\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 5"]], "\nResult5\n\n");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1682     InitBasicFS, Always, TestOutput (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command 7"]], "");
1686     InitBasicFS, Always, TestOutput (
1687       [["upload"; "test-command"; "/test-command"];
1688        ["chmod"; "0o755"; "/test-command"];
1689        ["command"; "/test-command 8"]], "\n");
1690     InitBasicFS, Always, TestOutput (
1691       [["upload"; "test-command"; "/test-command"];
1692        ["chmod"; "0o755"; "/test-command"];
1693        ["command"; "/test-command 9"]], "\n\n");
1694     InitBasicFS, Always, TestOutput (
1695       [["upload"; "test-command"; "/test-command"];
1696        ["chmod"; "0o755"; "/test-command"];
1697        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1698     InitBasicFS, Always, TestOutput (
1699       [["upload"; "test-command"; "/test-command"];
1700        ["chmod"; "0o755"; "/test-command"];
1701        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1702     InitBasicFS, Always, TestLastFail (
1703       [["upload"; "test-command"; "/test-command"];
1704        ["chmod"; "0o755"; "/test-command"];
1705        ["command"; "/test-command"]])],
1706    "run a command from the guest filesystem",
1707    "\
1708 This call runs a command from the guest filesystem.  The
1709 filesystem must be mounted, and must contain a compatible
1710 operating system (ie. something Linux, with the same
1711 or compatible processor architecture).
1712
1713 The single parameter is an argv-style list of arguments.
1714 The first element is the name of the program to run.
1715 Subsequent elements are parameters.  The list must be
1716 non-empty (ie. must contain a program name).  Note that
1717 the command runs directly, and is I<not> invoked via
1718 the shell (see C<guestfs_sh>).
1719
1720 The return value is anything printed to I<stdout> by
1721 the command.
1722
1723 If the command returns a non-zero exit status, then
1724 this function returns an error message.  The error message
1725 string is the content of I<stderr> from the command.
1726
1727 The C<$PATH> environment variable will contain at least
1728 C</usr/bin> and C</bin>.  If you require a program from
1729 another location, you should provide the full path in the
1730 first parameter.
1731
1732 Shared libraries and data files required by the program
1733 must be available on filesystems which are mounted in the
1734 correct places.  It is the caller's responsibility to ensure
1735 all filesystems that are needed are mounted at the right
1736 locations.");
1737
1738   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1739    [InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 1"]], ["Result1"]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 2"]], ["Result2"]);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1763     InitBasicFS, Always, TestOutputList (
1764       [["upload"; "test-command"; "/test-command"];
1765        ["chmod"; "0o755"; "/test-command"];
1766        ["command_lines"; "/test-command 7"]], []);
1767     InitBasicFS, Always, TestOutputList (
1768       [["upload"; "test-command"; "/test-command"];
1769        ["chmod"; "0o755"; "/test-command"];
1770        ["command_lines"; "/test-command 8"]], [""]);
1771     InitBasicFS, Always, TestOutputList (
1772       [["upload"; "test-command"; "/test-command"];
1773        ["chmod"; "0o755"; "/test-command"];
1774        ["command_lines"; "/test-command 9"]], ["";""]);
1775     InitBasicFS, Always, TestOutputList (
1776       [["upload"; "test-command"; "/test-command"];
1777        ["chmod"; "0o755"; "/test-command"];
1778        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1779     InitBasicFS, Always, TestOutputList (
1780       [["upload"; "test-command"; "/test-command"];
1781        ["chmod"; "0o755"; "/test-command"];
1782        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1783    "run a command, returning lines",
1784    "\
1785 This is the same as C<guestfs_command>, but splits the
1786 result into a list of lines.
1787
1788 See also: C<guestfs_sh_lines>");
1789
1790   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1791    [InitISOFS, Always, TestOutputStruct (
1792       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1793    "get file information",
1794    "\
1795 Returns file information for the given C<path>.
1796
1797 This is the same as the C<stat(2)> system call.");
1798
1799   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1800    [InitISOFS, Always, TestOutputStruct (
1801       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1802    "get file information for a symbolic link",
1803    "\
1804 Returns file information for the given C<path>.
1805
1806 This is the same as C<guestfs_stat> except that if C<path>
1807 is a symbolic link, then the link is stat-ed, not the file it
1808 refers to.
1809
1810 This is the same as the C<lstat(2)> system call.");
1811
1812   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1813    [InitISOFS, Always, TestOutputStruct (
1814       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1815    "get file system statistics",
1816    "\
1817 Returns file system statistics for any mounted file system.
1818 C<path> should be a file or directory in the mounted file system
1819 (typically it is the mount point itself, but it doesn't need to be).
1820
1821 This is the same as the C<statvfs(2)> system call.");
1822
1823   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1824    [], (* XXX test *)
1825    "get ext2/ext3/ext4 superblock details",
1826    "\
1827 This returns the contents of the ext2, ext3 or ext4 filesystem
1828 superblock on C<device>.
1829
1830 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1831 manpage for more details.  The list of fields returned isn't
1832 clearly defined, and depends on both the version of C<tune2fs>
1833 that libguestfs was built against, and the filesystem itself.");
1834
1835   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1836    [InitEmpty, Always, TestOutputTrue (
1837       [["blockdev_setro"; "/dev/sda"];
1838        ["blockdev_getro"; "/dev/sda"]])],
1839    "set block device to read-only",
1840    "\
1841 Sets the block device named C<device> to read-only.
1842
1843 This uses the L<blockdev(8)> command.");
1844
1845   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1846    [InitEmpty, Always, TestOutputFalse (
1847       [["blockdev_setrw"; "/dev/sda"];
1848        ["blockdev_getro"; "/dev/sda"]])],
1849    "set block device to read-write",
1850    "\
1851 Sets the block device named C<device> to read-write.
1852
1853 This uses the L<blockdev(8)> command.");
1854
1855   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1856    [InitEmpty, Always, TestOutputTrue (
1857       [["blockdev_setro"; "/dev/sda"];
1858        ["blockdev_getro"; "/dev/sda"]])],
1859    "is block device set to read-only",
1860    "\
1861 Returns a boolean indicating if the block device is read-only
1862 (true if read-only, false if not).
1863
1864 This uses the L<blockdev(8)> command.");
1865
1866   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1867    [InitEmpty, Always, TestOutputInt (
1868       [["blockdev_getss"; "/dev/sda"]], 512)],
1869    "get sectorsize of block device",
1870    "\
1871 This returns the size of sectors on a block device.
1872 Usually 512, but can be larger for modern devices.
1873
1874 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1875 for that).
1876
1877 This uses the L<blockdev(8)> command.");
1878
1879   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1880    [InitEmpty, Always, TestOutputInt (
1881       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1882    "get blocksize of block device",
1883    "\
1884 This returns the block size of a device.
1885
1886 (Note this is different from both I<size in blocks> and
1887 I<filesystem block size>).
1888
1889 This uses the L<blockdev(8)> command.");
1890
1891   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1892    [], (* XXX test *)
1893    "set blocksize of block device",
1894    "\
1895 This sets the block size of a device.
1896
1897 (Note this is different from both I<size in blocks> and
1898 I<filesystem block size>).
1899
1900 This uses the L<blockdev(8)> command.");
1901
1902   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1903    [InitEmpty, Always, TestOutputInt (
1904       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1905    "get total size of device in 512-byte sectors",
1906    "\
1907 This returns the size of the device in units of 512-byte sectors
1908 (even if the sectorsize isn't 512 bytes ... weird).
1909
1910 See also C<guestfs_blockdev_getss> for the real sector size of
1911 the device, and C<guestfs_blockdev_getsize64> for the more
1912 useful I<size in bytes>.
1913
1914 This uses the L<blockdev(8)> command.");
1915
1916   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1917    [InitEmpty, Always, TestOutputInt (
1918       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1919    "get total size of device in bytes",
1920    "\
1921 This returns the size of the device in bytes.
1922
1923 See also C<guestfs_blockdev_getsz>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1928    [InitEmpty, Always, TestRun
1929       [["blockdev_flushbufs"; "/dev/sda"]]],
1930    "flush device buffers",
1931    "\
1932 This tells the kernel to flush internal buffers associated
1933 with C<device>.
1934
1935 This uses the L<blockdev(8)> command.");
1936
1937   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1938    [InitEmpty, Always, TestRun
1939       [["blockdev_rereadpt"; "/dev/sda"]]],
1940    "reread partition table",
1941    "\
1942 Reread the partition table on C<device>.
1943
1944 This uses the L<blockdev(8)> command.");
1945
1946   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1947    [InitBasicFS, Always, TestOutput (
1948       (* Pick a file from cwd which isn't likely to change. *)
1949       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1950        ["checksum"; "md5"; "/COPYING.LIB"]],
1951       Digest.to_hex (Digest.file "COPYING.LIB"))],
1952    "upload a file from the local machine",
1953    "\
1954 Upload local file C<filename> to C<remotefilename> on the
1955 filesystem.
1956
1957 C<filename> can also be a named pipe.
1958
1959 See also C<guestfs_download>.");
1960
1961   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1962    [InitBasicFS, Always, TestOutput (
1963       (* Pick a file from cwd which isn't likely to change. *)
1964       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1965        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1966        ["upload"; "testdownload.tmp"; "/upload"];
1967        ["checksum"; "md5"; "/upload"]],
1968       Digest.to_hex (Digest.file "COPYING.LIB"))],
1969    "download a file to the local machine",
1970    "\
1971 Download file C<remotefilename> and save it as C<filename>
1972 on the local machine.
1973
1974 C<filename> can also be a named pipe.
1975
1976 See also C<guestfs_upload>, C<guestfs_cat>.");
1977
1978   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1979    [InitISOFS, Always, TestOutput (
1980       [["checksum"; "crc"; "/known-3"]], "2891671662");
1981     InitISOFS, Always, TestLastFail (
1982       [["checksum"; "crc"; "/notexists"]]);
1983     InitISOFS, Always, TestOutput (
1984       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1985     InitISOFS, Always, TestOutput (
1986       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1987     InitISOFS, Always, TestOutput (
1988       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1989     InitISOFS, Always, TestOutput (
1990       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1991     InitISOFS, Always, TestOutput (
1992       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1993     InitISOFS, Always, TestOutput (
1994       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1995    "compute MD5, SHAx or CRC checksum of file",
1996    "\
1997 This call computes the MD5, SHAx or CRC checksum of the
1998 file named C<path>.
1999
2000 The type of checksum to compute is given by the C<csumtype>
2001 parameter which must have one of the following values:
2002
2003 =over 4
2004
2005 =item C<crc>
2006
2007 Compute the cyclic redundancy check (CRC) specified by POSIX
2008 for the C<cksum> command.
2009
2010 =item C<md5>
2011
2012 Compute the MD5 hash (using the C<md5sum> program).
2013
2014 =item C<sha1>
2015
2016 Compute the SHA1 hash (using the C<sha1sum> program).
2017
2018 =item C<sha224>
2019
2020 Compute the SHA224 hash (using the C<sha224sum> program).
2021
2022 =item C<sha256>
2023
2024 Compute the SHA256 hash (using the C<sha256sum> program).
2025
2026 =item C<sha384>
2027
2028 Compute the SHA384 hash (using the C<sha384sum> program).
2029
2030 =item C<sha512>
2031
2032 Compute the SHA512 hash (using the C<sha512sum> program).
2033
2034 =back
2035
2036 The checksum is returned as a printable string.
2037
2038 To get the checksum for a device, use C<guestfs_checksum_device>.
2039
2040 To get the checksums for many files, use C<guestfs_checksums_out>.");
2041
2042   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2043    [InitBasicFS, Always, TestOutput (
2044       [["tar_in"; "../images/helloworld.tar"; "/"];
2045        ["cat"; "/hello"]], "hello\n")],
2046    "unpack tarfile to directory",
2047    "\
2048 This command uploads and unpacks local file C<tarfile> (an
2049 I<uncompressed> tar file) into C<directory>.
2050
2051 To upload a compressed tarball, use C<guestfs_tgz_in>
2052 or C<guestfs_txz_in>.");
2053
2054   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2055    [],
2056    "pack directory into tarfile",
2057    "\
2058 This command packs the contents of C<directory> and downloads
2059 it to local file C<tarfile>.
2060
2061 To download a compressed tarball, use C<guestfs_tgz_out>
2062 or C<guestfs_txz_out>.");
2063
2064   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2065    [InitBasicFS, Always, TestOutput (
2066       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2067        ["cat"; "/hello"]], "hello\n")],
2068    "unpack compressed tarball to directory",
2069    "\
2070 This command uploads and unpacks local file C<tarball> (a
2071 I<gzip compressed> tar file) into C<directory>.
2072
2073 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2074
2075   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2076    [],
2077    "pack directory into compressed tarball",
2078    "\
2079 This command packs the contents of C<directory> and downloads
2080 it to local file C<tarball>.
2081
2082 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2083
2084   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2085    [InitBasicFS, Always, TestLastFail (
2086       [["umount"; "/"];
2087        ["mount_ro"; "/dev/sda1"; "/"];
2088        ["touch"; "/new"]]);
2089     InitBasicFS, Always, TestOutput (
2090       [["write_file"; "/new"; "data"; "0"];
2091        ["umount"; "/"];
2092        ["mount_ro"; "/dev/sda1"; "/"];
2093        ["cat"; "/new"]], "data")],
2094    "mount a guest disk, read-only",
2095    "\
2096 This is the same as the C<guestfs_mount> command, but it
2097 mounts the filesystem with the read-only (I<-o ro>) flag.");
2098
2099   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2100    [],
2101    "mount a guest disk with mount options",
2102    "\
2103 This is the same as the C<guestfs_mount> command, but it
2104 allows you to set the mount options as for the
2105 L<mount(8)> I<-o> flag.
2106
2107 If the C<options> parameter is an empty string, then
2108 no options are passed (all options default to whatever
2109 the filesystem uses).");
2110
2111   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2112    [],
2113    "mount a guest disk with mount options and vfstype",
2114    "\
2115 This is the same as the C<guestfs_mount> command, but it
2116 allows you to set both the mount options and the vfstype
2117 as for the L<mount(8)> I<-o> and I<-t> flags.");
2118
2119   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2120    [],
2121    "debugging and internals",
2122    "\
2123 The C<guestfs_debug> command exposes some internals of
2124 C<guestfsd> (the guestfs daemon) that runs inside the
2125 qemu subprocess.
2126
2127 There is no comprehensive help for this command.  You have
2128 to look at the file C<daemon/debug.c> in the libguestfs source
2129 to find out what you can do.");
2130
2131   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2132    [InitEmpty, Always, TestOutputList (
2133       [["part_disk"; "/dev/sda"; "mbr"];
2134        ["pvcreate"; "/dev/sda1"];
2135        ["vgcreate"; "VG"; "/dev/sda1"];
2136        ["lvcreate"; "LV1"; "VG"; "50"];
2137        ["lvcreate"; "LV2"; "VG"; "50"];
2138        ["lvremove"; "/dev/VG/LV1"];
2139        ["lvs"]], ["/dev/VG/LV2"]);
2140     InitEmpty, Always, TestOutputList (
2141       [["part_disk"; "/dev/sda"; "mbr"];
2142        ["pvcreate"; "/dev/sda1"];
2143        ["vgcreate"; "VG"; "/dev/sda1"];
2144        ["lvcreate"; "LV1"; "VG"; "50"];
2145        ["lvcreate"; "LV2"; "VG"; "50"];
2146        ["lvremove"; "/dev/VG"];
2147        ["lvs"]], []);
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        ["lvremove"; "/dev/VG"];
2155        ["vgs"]], ["VG"])],
2156    "remove an LVM logical volume",
2157    "\
2158 Remove an LVM logical volume C<device>, where C<device> is
2159 the path to the LV, such as C</dev/VG/LV>.
2160
2161 You can also remove all LVs in a volume group by specifying
2162 the VG name, C</dev/VG>.");
2163
2164   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2165    [InitEmpty, Always, TestOutputList (
2166       [["part_disk"; "/dev/sda"; "mbr"];
2167        ["pvcreate"; "/dev/sda1"];
2168        ["vgcreate"; "VG"; "/dev/sda1"];
2169        ["lvcreate"; "LV1"; "VG"; "50"];
2170        ["lvcreate"; "LV2"; "VG"; "50"];
2171        ["vgremove"; "VG"];
2172        ["lvs"]], []);
2173     InitEmpty, Always, TestOutputList (
2174       [["part_disk"; "/dev/sda"; "mbr"];
2175        ["pvcreate"; "/dev/sda1"];
2176        ["vgcreate"; "VG"; "/dev/sda1"];
2177        ["lvcreate"; "LV1"; "VG"; "50"];
2178        ["lvcreate"; "LV2"; "VG"; "50"];
2179        ["vgremove"; "VG"];
2180        ["vgs"]], [])],
2181    "remove an LVM volume group",
2182    "\
2183 Remove an LVM volume group C<vgname>, (for example C<VG>).
2184
2185 This also forcibly removes all logical volumes in the volume
2186 group (if any).");
2187
2188   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2189    [InitEmpty, Always, TestOutputListOfDevices (
2190       [["part_disk"; "/dev/sda"; "mbr"];
2191        ["pvcreate"; "/dev/sda1"];
2192        ["vgcreate"; "VG"; "/dev/sda1"];
2193        ["lvcreate"; "LV1"; "VG"; "50"];
2194        ["lvcreate"; "LV2"; "VG"; "50"];
2195        ["vgremove"; "VG"];
2196        ["pvremove"; "/dev/sda1"];
2197        ["lvs"]], []);
2198     InitEmpty, Always, TestOutputListOfDevices (
2199       [["part_disk"; "/dev/sda"; "mbr"];
2200        ["pvcreate"; "/dev/sda1"];
2201        ["vgcreate"; "VG"; "/dev/sda1"];
2202        ["lvcreate"; "LV1"; "VG"; "50"];
2203        ["lvcreate"; "LV2"; "VG"; "50"];
2204        ["vgremove"; "VG"];
2205        ["pvremove"; "/dev/sda1"];
2206        ["vgs"]], []);
2207     InitEmpty, Always, TestOutputListOfDevices (
2208       [["part_disk"; "/dev/sda"; "mbr"];
2209        ["pvcreate"; "/dev/sda1"];
2210        ["vgcreate"; "VG"; "/dev/sda1"];
2211        ["lvcreate"; "LV1"; "VG"; "50"];
2212        ["lvcreate"; "LV2"; "VG"; "50"];
2213        ["vgremove"; "VG"];
2214        ["pvremove"; "/dev/sda1"];
2215        ["pvs"]], [])],
2216    "remove an LVM physical volume",
2217    "\
2218 This wipes a physical volume C<device> so that LVM will no longer
2219 recognise it.
2220
2221 The implementation uses the C<pvremove> command which refuses to
2222 wipe physical volumes that contain any volume groups, so you have
2223 to remove those first.");
2224
2225   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2226    [InitBasicFS, Always, TestOutput (
2227       [["set_e2label"; "/dev/sda1"; "testlabel"];
2228        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2229    "set the ext2/3/4 filesystem label",
2230    "\
2231 This sets the ext2/3/4 filesystem label of the filesystem on
2232 C<device> to C<label>.  Filesystem labels are limited to
2233 16 characters.
2234
2235 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2236 to return the existing label on a filesystem.");
2237
2238   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2239    [],
2240    "get the ext2/3/4 filesystem label",
2241    "\
2242 This returns the ext2/3/4 filesystem label of the filesystem on
2243 C<device>.");
2244
2245   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2246    (let uuid = uuidgen () in
2247     [InitBasicFS, Always, TestOutput (
2248        [["set_e2uuid"; "/dev/sda1"; uuid];
2249         ["get_e2uuid"; "/dev/sda1"]], uuid);
2250      InitBasicFS, Always, TestOutput (
2251        [["set_e2uuid"; "/dev/sda1"; "clear"];
2252         ["get_e2uuid"; "/dev/sda1"]], "");
2253      (* We can't predict what UUIDs will be, so just check the commands run. *)
2254      InitBasicFS, Always, TestRun (
2255        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2256      InitBasicFS, Always, TestRun (
2257        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2258    "set the ext2/3/4 filesystem UUID",
2259    "\
2260 This sets the ext2/3/4 filesystem UUID of the filesystem on
2261 C<device> to C<uuid>.  The format of the UUID and alternatives
2262 such as C<clear>, C<random> and C<time> are described in the
2263 L<tune2fs(8)> manpage.
2264
2265 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2266 to return the existing UUID of a filesystem.");
2267
2268   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2269    [],
2270    "get the ext2/3/4 filesystem UUID",
2271    "\
2272 This returns the ext2/3/4 filesystem UUID of the filesystem on
2273 C<device>.");
2274
2275   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2276    [InitBasicFS, Always, TestOutputInt (
2277       [["umount"; "/dev/sda1"];
2278        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2279     InitBasicFS, Always, TestOutputInt (
2280       [["umount"; "/dev/sda1"];
2281        ["zero"; "/dev/sda1"];
2282        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2283    "run the filesystem checker",
2284    "\
2285 This runs the filesystem checker (fsck) on C<device> which
2286 should have filesystem type C<fstype>.
2287
2288 The returned integer is the status.  See L<fsck(8)> for the
2289 list of status codes from C<fsck>.
2290
2291 Notes:
2292
2293 =over 4
2294
2295 =item *
2296
2297 Multiple status codes can be summed together.
2298
2299 =item *
2300
2301 A non-zero return code can mean \"success\", for example if
2302 errors have been corrected on the filesystem.
2303
2304 =item *
2305
2306 Checking or repairing NTFS volumes is not supported
2307 (by linux-ntfs).
2308
2309 =back
2310
2311 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2312
2313   ("zero", (RErr, [Device "device"]), 85, [],
2314    [InitBasicFS, Always, TestOutput (
2315       [["umount"; "/dev/sda1"];
2316        ["zero"; "/dev/sda1"];
2317        ["file"; "/dev/sda1"]], "data")],
2318    "write zeroes to the device",
2319    "\
2320 This command writes zeroes over the first few blocks of C<device>.
2321
2322 How many blocks are zeroed isn't specified (but it's I<not> enough
2323 to securely wipe the device).  It should be sufficient to remove
2324 any partition tables, filesystem superblocks and so on.
2325
2326 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2327
2328   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2329    (* Test disabled because grub-install incompatible with virtio-blk driver.
2330     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2331     *)
2332    [InitBasicFS, Disabled, TestOutputTrue (
2333       [["grub_install"; "/"; "/dev/sda1"];
2334        ["is_dir"; "/boot"]])],
2335    "install GRUB",
2336    "\
2337 This command installs GRUB (the Grand Unified Bootloader) on
2338 C<device>, with the root directory being C<root>.");
2339
2340   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2341    [InitBasicFS, Always, TestOutput (
2342       [["write_file"; "/old"; "file content"; "0"];
2343        ["cp"; "/old"; "/new"];
2344        ["cat"; "/new"]], "file content");
2345     InitBasicFS, Always, TestOutputTrue (
2346       [["write_file"; "/old"; "file content"; "0"];
2347        ["cp"; "/old"; "/new"];
2348        ["is_file"; "/old"]]);
2349     InitBasicFS, Always, TestOutput (
2350       [["write_file"; "/old"; "file content"; "0"];
2351        ["mkdir"; "/dir"];
2352        ["cp"; "/old"; "/dir/new"];
2353        ["cat"; "/dir/new"]], "file content")],
2354    "copy a file",
2355    "\
2356 This copies a file from C<src> to C<dest> where C<dest> is
2357 either a destination filename or destination directory.");
2358
2359   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2360    [InitBasicFS, Always, TestOutput (
2361       [["mkdir"; "/olddir"];
2362        ["mkdir"; "/newdir"];
2363        ["write_file"; "/olddir/file"; "file content"; "0"];
2364        ["cp_a"; "/olddir"; "/newdir"];
2365        ["cat"; "/newdir/olddir/file"]], "file content")],
2366    "copy a file or directory recursively",
2367    "\
2368 This copies a file or directory from C<src> to C<dest>
2369 recursively using the C<cp -a> command.");
2370
2371   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2372    [InitBasicFS, Always, TestOutput (
2373       [["write_file"; "/old"; "file content"; "0"];
2374        ["mv"; "/old"; "/new"];
2375        ["cat"; "/new"]], "file content");
2376     InitBasicFS, Always, TestOutputFalse (
2377       [["write_file"; "/old"; "file content"; "0"];
2378        ["mv"; "/old"; "/new"];
2379        ["is_file"; "/old"]])],
2380    "move a file",
2381    "\
2382 This moves a file from C<src> to C<dest> where C<dest> is
2383 either a destination filename or destination directory.");
2384
2385   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2386    [InitEmpty, Always, TestRun (
2387       [["drop_caches"; "3"]])],
2388    "drop kernel page cache, dentries and inodes",
2389    "\
2390 This instructs the guest kernel to drop its page cache,
2391 and/or dentries and inode caches.  The parameter C<whattodrop>
2392 tells the kernel what precisely to drop, see
2393 L<http://linux-mm.org/Drop_Caches>
2394
2395 Setting C<whattodrop> to 3 should drop everything.
2396
2397 This automatically calls L<sync(2)> before the operation,
2398 so that the maximum guest memory is freed.");
2399
2400   ("dmesg", (RString "kmsgs", []), 91, [],
2401    [InitEmpty, Always, TestRun (
2402       [["dmesg"]])],
2403    "return kernel messages",
2404    "\
2405 This returns the kernel messages (C<dmesg> output) from
2406 the guest kernel.  This is sometimes useful for extended
2407 debugging of problems.
2408
2409 Another way to get the same information is to enable
2410 verbose messages with C<guestfs_set_verbose> or by setting
2411 the environment variable C<LIBGUESTFS_DEBUG=1> before
2412 running the program.");
2413
2414   ("ping_daemon", (RErr, []), 92, [],
2415    [InitEmpty, Always, TestRun (
2416       [["ping_daemon"]])],
2417    "ping the guest daemon",
2418    "\
2419 This is a test probe into the guestfs daemon running inside
2420 the qemu subprocess.  Calling this function checks that the
2421 daemon responds to the ping message, without affecting the daemon
2422 or attached block device(s) in any other way.");
2423
2424   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2425    [InitBasicFS, Always, TestOutputTrue (
2426       [["write_file"; "/file1"; "contents of a file"; "0"];
2427        ["cp"; "/file1"; "/file2"];
2428        ["equal"; "/file1"; "/file2"]]);
2429     InitBasicFS, Always, TestOutputFalse (
2430       [["write_file"; "/file1"; "contents of a file"; "0"];
2431        ["write_file"; "/file2"; "contents of another file"; "0"];
2432        ["equal"; "/file1"; "/file2"]]);
2433     InitBasicFS, Always, TestLastFail (
2434       [["equal"; "/file1"; "/file2"]])],
2435    "test if two files have equal contents",
2436    "\
2437 This compares the two files C<file1> and C<file2> and returns
2438 true if their content is exactly equal, or false otherwise.
2439
2440 The external L<cmp(1)> program is used for the comparison.");
2441
2442   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2443    [InitISOFS, Always, TestOutputList (
2444       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2445     InitISOFS, Always, TestOutputList (
2446       [["strings"; "/empty"]], [])],
2447    "print the printable strings in a file",
2448    "\
2449 This runs the L<strings(1)> command on a file and returns
2450 the list of printable strings found.");
2451
2452   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2453    [InitISOFS, Always, TestOutputList (
2454       [["strings_e"; "b"; "/known-5"]], []);
2455     InitBasicFS, Disabled, TestOutputList (
2456       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2457        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2458    "print the printable strings in a file",
2459    "\
2460 This is like the C<guestfs_strings> command, but allows you to
2461 specify the encoding.
2462
2463 See the L<strings(1)> manpage for the full list of encodings.
2464
2465 Commonly useful encodings are C<l> (lower case L) which will
2466 show strings inside Windows/x86 files.
2467
2468 The returned strings are transcoded to UTF-8.");
2469
2470   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2471    [InitISOFS, Always, TestOutput (
2472       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2473     (* Test for RHBZ#501888c2 regression which caused large hexdump
2474      * commands to segfault.
2475      *)
2476     InitISOFS, Always, TestRun (
2477       [["hexdump"; "/100krandom"]])],
2478    "dump a file in hexadecimal",
2479    "\
2480 This runs C<hexdump -C> on the given C<path>.  The result is
2481 the human-readable, canonical hex dump of the file.");
2482
2483   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2484    [InitNone, Always, TestOutput (
2485       [["part_disk"; "/dev/sda"; "mbr"];
2486        ["mkfs"; "ext3"; "/dev/sda1"];
2487        ["mount_options"; ""; "/dev/sda1"; "/"];
2488        ["write_file"; "/new"; "test file"; "0"];
2489        ["umount"; "/dev/sda1"];
2490        ["zerofree"; "/dev/sda1"];
2491        ["mount_options"; ""; "/dev/sda1"; "/"];
2492        ["cat"; "/new"]], "test file")],
2493    "zero unused inodes and disk blocks on ext2/3 filesystem",
2494    "\
2495 This runs the I<zerofree> program on C<device>.  This program
2496 claims to zero unused inodes and disk blocks on an ext2/3
2497 filesystem, thus making it possible to compress the filesystem
2498 more effectively.
2499
2500 You should B<not> run this program if the filesystem is
2501 mounted.
2502
2503 It is possible that using this program can damage the filesystem
2504 or data on the filesystem.");
2505
2506   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2507    [],
2508    "resize an LVM physical volume",
2509    "\
2510 This resizes (expands or shrinks) an existing LVM physical
2511 volume to match the new size of the underlying device.");
2512
2513   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2514                        Int "cyls"; Int "heads"; Int "sectors";
2515                        String "line"]), 99, [DangerWillRobinson],
2516    [],
2517    "modify a single partition on a block device",
2518    "\
2519 This runs L<sfdisk(8)> option to modify just the single
2520 partition C<n> (note: C<n> counts from 1).
2521
2522 For other parameters, see C<guestfs_sfdisk>.  You should usually
2523 pass C<0> for the cyls/heads/sectors parameters.
2524
2525 See also: C<guestfs_part_add>");
2526
2527   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2528    [],
2529    "display the partition table",
2530    "\
2531 This displays the partition table on C<device>, in the
2532 human-readable output of the L<sfdisk(8)> command.  It is
2533 not intended to be parsed.
2534
2535 See also: C<guestfs_part_list>");
2536
2537   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2538    [],
2539    "display the kernel geometry",
2540    "\
2541 This displays the kernel's idea of the geometry of C<device>.
2542
2543 The result is in human-readable format, and not designed to
2544 be parsed.");
2545
2546   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2547    [],
2548    "display the disk geometry from the partition table",
2549    "\
2550 This displays the disk geometry of C<device> read from the
2551 partition table.  Especially in the case where the underlying
2552 block device has been resized, this can be different from the
2553 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2554
2555 The result is in human-readable format, and not designed to
2556 be parsed.");
2557
2558   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2559    [],
2560    "activate or deactivate all volume groups",
2561    "\
2562 This command activates or (if C<activate> is false) deactivates
2563 all logical volumes in all volume groups.
2564 If activated, then they are made known to the
2565 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2566 then those devices disappear.
2567
2568 This command is the same as running C<vgchange -a y|n>");
2569
2570   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2571    [],
2572    "activate or deactivate some volume groups",
2573    "\
2574 This command activates or (if C<activate> is false) deactivates
2575 all logical volumes in the listed volume groups C<volgroups>.
2576 If activated, then they are made known to the
2577 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2578 then those devices disappear.
2579
2580 This command is the same as running C<vgchange -a y|n volgroups...>
2581
2582 Note that if C<volgroups> is an empty list then B<all> volume groups
2583 are activated or deactivated.");
2584
2585   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2586    [InitNone, Always, TestOutput (
2587       [["part_disk"; "/dev/sda"; "mbr"];
2588        ["pvcreate"; "/dev/sda1"];
2589        ["vgcreate"; "VG"; "/dev/sda1"];
2590        ["lvcreate"; "LV"; "VG"; "10"];
2591        ["mkfs"; "ext2"; "/dev/VG/LV"];
2592        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2593        ["write_file"; "/new"; "test content"; "0"];
2594        ["umount"; "/"];
2595        ["lvresize"; "/dev/VG/LV"; "20"];
2596        ["e2fsck_f"; "/dev/VG/LV"];
2597        ["resize2fs"; "/dev/VG/LV"];
2598        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2599        ["cat"; "/new"]], "test content");
2600     InitNone, Always, TestRun (
2601       (* Make an LV smaller to test RHBZ#587484. *)
2602       [["part_disk"; "/dev/sda"; "mbr"];
2603        ["pvcreate"; "/dev/sda1"];
2604        ["vgcreate"; "VG"; "/dev/sda1"];
2605        ["lvcreate"; "LV"; "VG"; "20"];
2606        ["lvresize"; "/dev/VG/LV"; "10"]])],
2607    "resize an LVM logical volume",
2608    "\
2609 This resizes (expands or shrinks) an existing LVM logical
2610 volume to C<mbytes>.  When reducing, data in the reduced part
2611 is lost.");
2612
2613   ("resize2fs", (RErr, [Device "device"]), 106, [],
2614    [], (* lvresize tests this *)
2615    "resize an ext2/ext3 filesystem",
2616    "\
2617 This resizes an ext2 or ext3 filesystem to match the size of
2618 the underlying device.
2619
2620 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2621 on the C<device> before calling this command.  For unknown reasons
2622 C<resize2fs> sometimes gives an error about this and sometimes not.
2623 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2624 calling this function.");
2625
2626   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2627    [InitBasicFS, Always, TestOutputList (
2628       [["find"; "/"]], ["lost+found"]);
2629     InitBasicFS, Always, TestOutputList (
2630       [["touch"; "/a"];
2631        ["mkdir"; "/b"];
2632        ["touch"; "/b/c"];
2633        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2634     InitBasicFS, Always, TestOutputList (
2635       [["mkdir_p"; "/a/b/c"];
2636        ["touch"; "/a/b/c/d"];
2637        ["find"; "/a/b/"]], ["c"; "c/d"])],
2638    "find all files and directories",
2639    "\
2640 This command lists out all files and directories, recursively,
2641 starting at C<directory>.  It is essentially equivalent to
2642 running the shell command C<find directory -print> but some
2643 post-processing happens on the output, described below.
2644
2645 This returns a list of strings I<without any prefix>.  Thus
2646 if the directory structure was:
2647
2648  /tmp/a
2649  /tmp/b
2650  /tmp/c/d
2651
2652 then the returned list from C<guestfs_find> C</tmp> would be
2653 4 elements:
2654
2655  a
2656  b
2657  c
2658  c/d
2659
2660 If C<directory> is not a directory, then this command returns
2661 an error.
2662
2663 The returned list is sorted.
2664
2665 See also C<guestfs_find0>.");
2666
2667   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2668    [], (* lvresize tests this *)
2669    "check an ext2/ext3 filesystem",
2670    "\
2671 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2672 filesystem checker on C<device>, noninteractively (C<-p>),
2673 even if the filesystem appears to be clean (C<-f>).
2674
2675 This command is only needed because of C<guestfs_resize2fs>
2676 (q.v.).  Normally you should use C<guestfs_fsck>.");
2677
2678   ("sleep", (RErr, [Int "secs"]), 109, [],
2679    [InitNone, Always, TestRun (
2680       [["sleep"; "1"]])],
2681    "sleep for some seconds",
2682    "\
2683 Sleep for C<secs> seconds.");
2684
2685   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2686    [InitNone, Always, TestOutputInt (
2687       [["part_disk"; "/dev/sda"; "mbr"];
2688        ["mkfs"; "ntfs"; "/dev/sda1"];
2689        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2690     InitNone, Always, TestOutputInt (
2691       [["part_disk"; "/dev/sda"; "mbr"];
2692        ["mkfs"; "ext2"; "/dev/sda1"];
2693        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2694    "probe NTFS volume",
2695    "\
2696 This command runs the L<ntfs-3g.probe(8)> command which probes
2697 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2698 be mounted read-write, and some cannot be mounted at all).
2699
2700 C<rw> is a boolean flag.  Set it to true if you want to test
2701 if the volume can be mounted read-write.  Set it to false if
2702 you want to test if the volume can be mounted read-only.
2703
2704 The return value is an integer which C<0> if the operation
2705 would succeed, or some non-zero value documented in the
2706 L<ntfs-3g.probe(8)> manual page.");
2707
2708   ("sh", (RString "output", [String "command"]), 111, [],
2709    [], (* XXX needs tests *)
2710    "run a command via the shell",
2711    "\
2712 This call runs a command from the guest filesystem via the
2713 guest's C</bin/sh>.
2714
2715 This is like C<guestfs_command>, but passes the command to:
2716
2717  /bin/sh -c \"command\"
2718
2719 Depending on the guest's shell, this usually results in
2720 wildcards being expanded, shell expressions being interpolated
2721 and so on.
2722
2723 All the provisos about C<guestfs_command> apply to this call.");
2724
2725   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2726    [], (* XXX needs tests *)
2727    "run a command via the shell returning lines",
2728    "\
2729 This is the same as C<guestfs_sh>, but splits the result
2730 into a list of lines.
2731
2732 See also: C<guestfs_command_lines>");
2733
2734   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2735    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2736     * code in stubs.c, since all valid glob patterns must start with "/".
2737     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2738     *)
2739    [InitBasicFS, Always, TestOutputList (
2740       [["mkdir_p"; "/a/b/c"];
2741        ["touch"; "/a/b/c/d"];
2742        ["touch"; "/a/b/c/e"];
2743        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2744     InitBasicFS, Always, TestOutputList (
2745       [["mkdir_p"; "/a/b/c"];
2746        ["touch"; "/a/b/c/d"];
2747        ["touch"; "/a/b/c/e"];
2748        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2749     InitBasicFS, Always, TestOutputList (
2750       [["mkdir_p"; "/a/b/c"];
2751        ["touch"; "/a/b/c/d"];
2752        ["touch"; "/a/b/c/e"];
2753        ["glob_expand"; "/a/*/x/*"]], [])],
2754    "expand a wildcard path",
2755    "\
2756 This command searches for all the pathnames matching
2757 C<pattern> according to the wildcard expansion rules
2758 used by the shell.
2759
2760 If no paths match, then this returns an empty list
2761 (note: not an error).
2762
2763 It is just a wrapper around the C L<glob(3)> function
2764 with flags C<GLOB_MARK|GLOB_BRACE>.
2765 See that manual page for more details.");
2766
2767   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2768    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2769       [["scrub_device"; "/dev/sdc"]])],
2770    "scrub (securely wipe) a device",
2771    "\
2772 This command writes patterns over C<device> to make data retrieval
2773 more difficult.
2774
2775 It is an interface to the L<scrub(1)> program.  See that
2776 manual page for more details.");
2777
2778   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2779    [InitBasicFS, Always, TestRun (
2780       [["write_file"; "/file"; "content"; "0"];
2781        ["scrub_file"; "/file"]])],
2782    "scrub (securely wipe) a file",
2783    "\
2784 This command writes patterns over a file to make data retrieval
2785 more difficult.
2786
2787 The file is I<removed> after scrubbing.
2788
2789 It is an interface to the L<scrub(1)> program.  See that
2790 manual page for more details.");
2791
2792   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2793    [], (* XXX needs testing *)
2794    "scrub (securely wipe) free space",
2795    "\
2796 This command creates the directory C<dir> and then fills it
2797 with files until the filesystem is full, and scrubs the files
2798 as for C<guestfs_scrub_file>, and deletes them.
2799 The intention is to scrub any free space on the partition
2800 containing C<dir>.
2801
2802 It is an interface to the L<scrub(1)> program.  See that
2803 manual page for more details.");
2804
2805   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2806    [InitBasicFS, Always, TestRun (
2807       [["mkdir"; "/tmp"];
2808        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2809    "create a temporary directory",
2810    "\
2811 This command creates a temporary directory.  The
2812 C<template> parameter should be a full pathname for the
2813 temporary directory name with the final six characters being
2814 \"XXXXXX\".
2815
2816 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2817 the second one being suitable for Windows filesystems.
2818
2819 The name of the temporary directory that was created
2820 is returned.
2821
2822 The temporary directory is created with mode 0700
2823 and is owned by root.
2824
2825 The caller is responsible for deleting the temporary
2826 directory and its contents after use.
2827
2828 See also: L<mkdtemp(3)>");
2829
2830   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2831    [InitISOFS, Always, TestOutputInt (
2832       [["wc_l"; "/10klines"]], 10000)],
2833    "count lines in a file",
2834    "\
2835 This command counts the lines in a file, using the
2836 C<wc -l> external command.");
2837
2838   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2839    [InitISOFS, Always, TestOutputInt (
2840       [["wc_w"; "/10klines"]], 10000)],
2841    "count words in a file",
2842    "\
2843 This command counts the words in a file, using the
2844 C<wc -w> external command.");
2845
2846   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2847    [InitISOFS, Always, TestOutputInt (
2848       [["wc_c"; "/100kallspaces"]], 102400)],
2849    "count characters in a file",
2850    "\
2851 This command counts the characters in a file, using the
2852 C<wc -c> external command.");
2853
2854   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2855    [InitISOFS, Always, TestOutputList (
2856       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2857    "return first 10 lines of a file",
2858    "\
2859 This command returns up to the first 10 lines of a file as
2860 a list of strings.");
2861
2862   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2863    [InitISOFS, Always, TestOutputList (
2864       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2865     InitISOFS, Always, TestOutputList (
2866       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2867     InitISOFS, Always, TestOutputList (
2868       [["head_n"; "0"; "/10klines"]], [])],
2869    "return first N lines of a file",
2870    "\
2871 If the parameter C<nrlines> is a positive number, this returns the first
2872 C<nrlines> lines of the file C<path>.
2873
2874 If the parameter C<nrlines> is a negative number, this returns lines
2875 from the file C<path>, excluding the last C<nrlines> lines.
2876
2877 If the parameter C<nrlines> is zero, this returns an empty list.");
2878
2879   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2880    [InitISOFS, Always, TestOutputList (
2881       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2882    "return last 10 lines of a file",
2883    "\
2884 This command returns up to the last 10 lines of a file as
2885 a list of strings.");
2886
2887   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2888    [InitISOFS, Always, TestOutputList (
2889       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2890     InitISOFS, Always, TestOutputList (
2891       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2892     InitISOFS, Always, TestOutputList (
2893       [["tail_n"; "0"; "/10klines"]], [])],
2894    "return last N lines of a file",
2895    "\
2896 If the parameter C<nrlines> is a positive number, this returns the last
2897 C<nrlines> lines of the file C<path>.
2898
2899 If the parameter C<nrlines> is a negative number, this returns lines
2900 from the file C<path>, starting with the C<-nrlines>th line.
2901
2902 If the parameter C<nrlines> is zero, this returns an empty list.");
2903
2904   ("df", (RString "output", []), 125, [],
2905    [], (* XXX Tricky to test because it depends on the exact format
2906         * of the 'df' command and other imponderables.
2907         *)
2908    "report file system disk space usage",
2909    "\
2910 This command runs the C<df> command to report disk space used.
2911
2912 This command is mostly useful for interactive sessions.  It
2913 is I<not> intended that you try to parse the output string.
2914 Use C<statvfs> from programs.");
2915
2916   ("df_h", (RString "output", []), 126, [],
2917    [], (* XXX Tricky to test because it depends on the exact format
2918         * of the 'df' command and other imponderables.
2919         *)
2920    "report file system disk space usage (human readable)",
2921    "\
2922 This command runs the C<df -h> command to report disk space used
2923 in human-readable format.
2924
2925 This command is mostly useful for interactive sessions.  It
2926 is I<not> intended that you try to parse the output string.
2927 Use C<statvfs> from programs.");
2928
2929   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2930    [InitISOFS, Always, TestOutputInt (
2931       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2932    "estimate file space usage",
2933    "\
2934 This command runs the C<du -s> command to estimate file space
2935 usage for C<path>.
2936
2937 C<path> can be a file or a directory.  If C<path> is a directory
2938 then the estimate includes the contents of the directory and all
2939 subdirectories (recursively).
2940
2941 The result is the estimated size in I<kilobytes>
2942 (ie. units of 1024 bytes).");
2943
2944   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2945    [InitISOFS, Always, TestOutputList (
2946       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2947    "list files in an initrd",
2948    "\
2949 This command lists out files contained in an initrd.
2950
2951 The files are listed without any initial C</> character.  The
2952 files are listed in the order they appear (not necessarily
2953 alphabetical).  Directory names are listed as separate items.
2954
2955 Old Linux kernels (2.4 and earlier) used a compressed ext2
2956 filesystem as initrd.  We I<only> support the newer initramfs
2957 format (compressed cpio files).");
2958
2959   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2960    [],
2961    "mount a file using the loop device",
2962    "\
2963 This command lets you mount C<file> (a filesystem image
2964 in a file) on a mount point.  It is entirely equivalent to
2965 the command C<mount -o loop file mountpoint>.");
2966
2967   ("mkswap", (RErr, [Device "device"]), 130, [],
2968    [InitEmpty, Always, TestRun (
2969       [["part_disk"; "/dev/sda"; "mbr"];
2970        ["mkswap"; "/dev/sda1"]])],
2971    "create a swap partition",
2972    "\
2973 Create a swap partition on C<device>.");
2974
2975   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2976    [InitEmpty, Always, TestRun (
2977       [["part_disk"; "/dev/sda"; "mbr"];
2978        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2979    "create a swap partition with a label",
2980    "\
2981 Create a swap partition on C<device> with label C<label>.
2982
2983 Note that you cannot attach a swap label to a block device
2984 (eg. C</dev/sda>), just to a partition.  This appears to be
2985 a limitation of the kernel or swap tools.");
2986
2987   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2988    (let uuid = uuidgen () in
2989     [InitEmpty, Always, TestRun (
2990        [["part_disk"; "/dev/sda"; "mbr"];
2991         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2992    "create a swap partition with an explicit UUID",
2993    "\
2994 Create a swap partition on C<device> with UUID C<uuid>.");
2995
2996   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2997    [InitBasicFS, Always, TestOutputStruct (
2998       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2999        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3000        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3001     InitBasicFS, Always, TestOutputStruct (
3002       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3003        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3004    "make block, character or FIFO devices",
3005    "\
3006 This call creates block or character special devices, or
3007 named pipes (FIFOs).
3008
3009 The C<mode> parameter should be the mode, using the standard
3010 constants.  C<devmajor> and C<devminor> are the
3011 device major and minor numbers, only used when creating block
3012 and character special devices.
3013
3014 Note that, just like L<mknod(2)>, the mode must be bitwise
3015 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3016 just creates a regular file).  These constants are
3017 available in the standard Linux header files, or you can use
3018 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3019 which are wrappers around this command which bitwise OR
3020 in the appropriate constant for you.
3021
3022 The mode actually set is affected by the umask.");
3023
3024   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3025    [InitBasicFS, Always, TestOutputStruct (
3026       [["mkfifo"; "0o777"; "/node"];
3027        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3028    "make FIFO (named pipe)",
3029    "\
3030 This call creates a FIFO (named pipe) called C<path> with
3031 mode C<mode>.  It is just a convenient wrapper around
3032 C<guestfs_mknod>.
3033
3034 The mode actually set is affected by the umask.");
3035
3036   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3037    [InitBasicFS, Always, TestOutputStruct (
3038       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3039        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3040    "make block device node",
3041    "\
3042 This call creates a block device node called C<path> with
3043 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3044 It is just a convenient wrapper around C<guestfs_mknod>.
3045
3046 The mode actually set is affected by the umask.");
3047
3048   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3049    [InitBasicFS, Always, TestOutputStruct (
3050       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3051        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3052    "make char device node",
3053    "\
3054 This call creates a char device node called C<path> with
3055 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3056 It is just a convenient wrapper around C<guestfs_mknod>.
3057
3058 The mode actually set is affected by the umask.");
3059
3060   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3061    [InitEmpty, Always, TestOutputInt (
3062       [["umask"; "0o22"]], 0o22)],
3063    "set file mode creation mask (umask)",
3064    "\
3065 This function sets the mask used for creating new files and
3066 device nodes to C<mask & 0777>.
3067
3068 Typical umask values would be C<022> which creates new files
3069 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3070 C<002> which creates new files with permissions like
3071 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3072
3073 The default umask is C<022>.  This is important because it
3074 means that directories and device nodes will be created with
3075 C<0644> or C<0755> mode even if you specify C<0777>.
3076
3077 See also C<guestfs_get_umask>,
3078 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3079
3080 This call returns the previous umask.");
3081
3082   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3083    [],
3084    "read directories entries",
3085    "\
3086 This returns the list of directory entries in directory C<dir>.
3087
3088 All entries in the directory are returned, including C<.> and
3089 C<..>.  The entries are I<not> sorted, but returned in the same
3090 order as the underlying filesystem.
3091
3092 Also this call returns basic file type information about each
3093 file.  The C<ftyp> field will contain one of the following characters:
3094
3095 =over 4
3096
3097 =item 'b'
3098
3099 Block special
3100
3101 =item 'c'
3102
3103 Char special
3104
3105 =item 'd'
3106
3107 Directory
3108
3109 =item 'f'
3110
3111 FIFO (named pipe)
3112
3113 =item 'l'
3114
3115 Symbolic link
3116
3117 =item 'r'
3118
3119 Regular file
3120
3121 =item 's'
3122
3123 Socket
3124
3125 =item 'u'
3126
3127 Unknown file type
3128
3129 =item '?'
3130
3131 The L<readdir(3)> returned a C<d_type> field with an
3132 unexpected value
3133
3134 =back
3135
3136 This function is primarily intended for use by programs.  To
3137 get a simple list of names, use C<guestfs_ls>.  To get a printable
3138 directory for human consumption, use C<guestfs_ll>.");
3139
3140   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3141    [],
3142    "create partitions on a block device",
3143    "\
3144 This is a simplified interface to the C<guestfs_sfdisk>
3145 command, where partition sizes are specified in megabytes
3146 only (rounded to the nearest cylinder) and you don't need
3147 to specify the cyls, heads and sectors parameters which
3148 were rarely if ever used anyway.
3149
3150 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3151 and C<guestfs_part_disk>");
3152
3153   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3154    [],
3155    "determine file type inside a compressed file",
3156    "\
3157 This command runs C<file> after first decompressing C<path>
3158 using C<method>.
3159
3160 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3161
3162 Since 1.0.63, use C<guestfs_file> instead which can now
3163 process compressed files.");
3164
3165   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3166    [],
3167    "list extended attributes of a file or directory",
3168    "\
3169 This call lists the extended attributes of the file or directory
3170 C<path>.
3171
3172 At the system call level, this is a combination of the
3173 L<listxattr(2)> and L<getxattr(2)> calls.
3174
3175 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3176
3177   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3178    [],
3179    "list extended attributes of a file or directory",
3180    "\
3181 This is the same as C<guestfs_getxattrs>, but if C<path>
3182 is a symbolic link, then it returns the extended attributes
3183 of the link itself.");
3184
3185   ("setxattr", (RErr, [String "xattr";
3186                        String "val"; Int "vallen"; (* will be BufferIn *)
3187                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3188    [],
3189    "set extended attribute of a file or directory",
3190    "\
3191 This call sets the extended attribute named C<xattr>
3192 of the file C<path> to the value C<val> (of length C<vallen>).
3193 The value is arbitrary 8 bit data.
3194
3195 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3196
3197   ("lsetxattr", (RErr, [String "xattr";
3198                         String "val"; Int "vallen"; (* will be BufferIn *)
3199                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3200    [],
3201    "set extended attribute of a file or directory",
3202    "\
3203 This is the same as C<guestfs_setxattr>, but if C<path>
3204 is a symbolic link, then it sets an extended attribute
3205 of the link itself.");
3206
3207   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3208    [],
3209    "remove extended attribute of a file or directory",
3210    "\
3211 This call removes the extended attribute named C<xattr>
3212 of the file C<path>.
3213
3214 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3215
3216   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3217    [],
3218    "remove extended attribute of a file or directory",
3219    "\
3220 This is the same as C<guestfs_removexattr>, but if C<path>
3221 is a symbolic link, then it removes an extended attribute
3222 of the link itself.");
3223
3224   ("mountpoints", (RHashtable "mps", []), 147, [],
3225    [],
3226    "show mountpoints",
3227    "\
3228 This call is similar to C<guestfs_mounts>.  That call returns
3229 a list of devices.  This one returns a hash table (map) of
3230 device name to directory where the device is mounted.");
3231
3232   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3233    (* This is a special case: while you would expect a parameter
3234     * of type "Pathname", that doesn't work, because it implies
3235     * NEED_ROOT in the generated calling code in stubs.c, and
3236     * this function cannot use NEED_ROOT.
3237     *)
3238    [],
3239    "create a mountpoint",
3240    "\
3241 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3242 specialized calls that can be used to create extra mountpoints
3243 before mounting the first filesystem.
3244
3245 These calls are I<only> necessary in some very limited circumstances,
3246 mainly the case where you want to mount a mix of unrelated and/or
3247 read-only filesystems together.
3248
3249 For example, live CDs often contain a \"Russian doll\" nest of
3250 filesystems, an ISO outer layer, with a squashfs image inside, with
3251 an ext2/3 image inside that.  You can unpack this as follows
3252 in guestfish:
3253
3254  add-ro Fedora-11-i686-Live.iso
3255  run
3256  mkmountpoint /cd
3257  mkmountpoint /squash
3258  mkmountpoint /ext3
3259  mount /dev/sda /cd
3260  mount-loop /cd/LiveOS/squashfs.img /squash
3261  mount-loop /squash/LiveOS/ext3fs.img /ext3
3262
3263 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3264
3265   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3266    [],
3267    "remove a mountpoint",
3268    "\
3269 This calls removes a mountpoint that was previously created
3270 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3271 for full details.");
3272
3273   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3274    [InitISOFS, Always, TestOutputBuffer (
3275       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3276    "read a file",
3277    "\
3278 This calls returns the contents of the file C<path> as a
3279 buffer.
3280
3281 Unlike C<guestfs_cat>, this function can correctly
3282 handle files that contain embedded ASCII NUL characters.
3283 However unlike C<guestfs_download>, this function is limited
3284 in the total size of file that can be handled.");
3285
3286   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3287    [InitISOFS, Always, TestOutputList (
3288       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3289     InitISOFS, Always, TestOutputList (
3290       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3291    "return lines matching a pattern",
3292    "\
3293 This calls the external C<grep> program and returns the
3294 matching lines.");
3295
3296   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3297    [InitISOFS, Always, TestOutputList (
3298       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3299    "return lines matching a pattern",
3300    "\
3301 This calls the external C<egrep> program and returns the
3302 matching lines.");
3303
3304   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3305    [InitISOFS, Always, TestOutputList (
3306       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3307    "return lines matching a pattern",
3308    "\
3309 This calls the external C<fgrep> program and returns the
3310 matching lines.");
3311
3312   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3313    [InitISOFS, Always, TestOutputList (
3314       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3315    "return lines matching a pattern",
3316    "\
3317 This calls the external C<grep -i> program and returns the
3318 matching lines.");
3319
3320   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3321    [InitISOFS, Always, TestOutputList (
3322       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3323    "return lines matching a pattern",
3324    "\
3325 This calls the external C<egrep -i> program and returns the
3326 matching lines.");
3327
3328   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3329    [InitISOFS, Always, TestOutputList (
3330       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3331    "return lines matching a pattern",
3332    "\
3333 This calls the external C<fgrep -i> program and returns the
3334 matching lines.");
3335
3336   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3337    [InitISOFS, Always, TestOutputList (
3338       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3339    "return lines matching a pattern",
3340    "\
3341 This calls the external C<zgrep> program and returns the
3342 matching lines.");
3343
3344   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3345    [InitISOFS, Always, TestOutputList (
3346       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3347    "return lines matching a pattern",
3348    "\
3349 This calls the external C<zegrep> program and returns the
3350 matching lines.");
3351
3352   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3353    [InitISOFS, Always, TestOutputList (
3354       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3355    "return lines matching a pattern",
3356    "\
3357 This calls the external C<zfgrep> program and returns the
3358 matching lines.");
3359
3360   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3361    [InitISOFS, Always, TestOutputList (
3362       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3363    "return lines matching a pattern",
3364    "\
3365 This calls the external C<zgrep -i> program and returns the
3366 matching lines.");
3367
3368   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3369    [InitISOFS, Always, TestOutputList (
3370       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3371    "return lines matching a pattern",
3372    "\
3373 This calls the external C<zegrep -i> program and returns the
3374 matching lines.");
3375
3376   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3377    [InitISOFS, Always, TestOutputList (
3378       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3379    "return lines matching a pattern",
3380    "\
3381 This calls the external C<zfgrep -i> program and returns the
3382 matching lines.");
3383
3384   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3385    [InitISOFS, Always, TestOutput (
3386       [["realpath"; "/../directory"]], "/directory")],
3387    "canonicalized absolute pathname",
3388    "\
3389 Return the canonicalized absolute pathname of C<path>.  The
3390 returned path has no C<.>, C<..> or symbolic link path elements.");
3391
3392   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3393    [InitBasicFS, Always, TestOutputStruct (
3394       [["touch"; "/a"];
3395        ["ln"; "/a"; "/b"];
3396        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3397    "create a hard link",
3398    "\
3399 This command creates a hard link using the C<ln> command.");
3400
3401   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3402    [InitBasicFS, Always, TestOutputStruct (
3403       [["touch"; "/a"];
3404        ["touch"; "/b"];
3405        ["ln_f"; "/a"; "/b"];
3406        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3407    "create a hard link",
3408    "\
3409 This command creates a hard link using the C<ln -f> command.
3410 The C<-f> option removes the link (C<linkname>) if it exists already.");
3411
3412   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3413    [InitBasicFS, Always, TestOutputStruct (
3414       [["touch"; "/a"];
3415        ["ln_s"; "a"; "/b"];
3416        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3417    "create a symbolic link",
3418    "\
3419 This command creates a symbolic link using the C<ln -s> command.");
3420
3421   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3422    [InitBasicFS, Always, TestOutput (
3423       [["mkdir_p"; "/a/b"];
3424        ["touch"; "/a/b/c"];
3425        ["ln_sf"; "../d"; "/a/b/c"];
3426        ["readlink"; "/a/b/c"]], "../d")],
3427    "create a symbolic link",
3428    "\
3429 This command creates a symbolic link using the C<ln -sf> command,
3430 The C<-f> option removes the link (C<linkname>) if it exists already.");
3431
3432   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3433    [] (* XXX tested above *),
3434    "read the target of a symbolic link",
3435    "\
3436 This command reads the target of a symbolic link.");
3437
3438   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3439    [InitBasicFS, Always, TestOutputStruct (
3440       [["fallocate"; "/a"; "1000000"];
3441        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3442    "preallocate a file in the guest filesystem",
3443    "\
3444 This command preallocates a file (containing zero bytes) named
3445 C<path> of size C<len> bytes.  If the file exists already, it
3446 is overwritten.
3447
3448 Do not confuse this with the guestfish-specific
3449 C<alloc> command which allocates a file in the host and
3450 attaches it as a device.");
3451
3452   ("swapon_device", (RErr, [Device "device"]), 170, [],
3453    [InitPartition, Always, TestRun (
3454       [["mkswap"; "/dev/sda1"];
3455        ["swapon_device"; "/dev/sda1"];
3456        ["swapoff_device"; "/dev/sda1"]])],
3457    "enable swap on device",
3458    "\
3459 This command enables the libguestfs appliance to use the
3460 swap device or partition named C<device>.  The increased
3461 memory is made available for all commands, for example
3462 those run using C<guestfs_command> or C<guestfs_sh>.
3463
3464 Note that you should not swap to existing guest swap
3465 partitions unless you know what you are doing.  They may
3466 contain hibernation information, or other information that
3467 the guest doesn't want you to trash.  You also risk leaking
3468 information about the host to the guest this way.  Instead,
3469 attach a new host device to the guest and swap on that.");
3470
3471   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3472    [], (* XXX tested by swapon_device *)
3473    "disable swap on device",
3474    "\
3475 This command disables the libguestfs appliance swap
3476 device or partition named C<device>.
3477 See C<guestfs_swapon_device>.");
3478
3479   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3480    [InitBasicFS, Always, TestRun (
3481       [["fallocate"; "/swap"; "8388608"];
3482        ["mkswap_file"; "/swap"];
3483        ["swapon_file"; "/swap"];
3484        ["swapoff_file"; "/swap"]])],
3485    "enable swap on file",
3486    "\
3487 This command enables swap to a file.
3488 See C<guestfs_swapon_device> for other notes.");
3489
3490   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3491    [], (* XXX tested by swapon_file *)
3492    "disable swap on file",
3493    "\
3494 This command disables the libguestfs appliance swap on file.");
3495
3496   ("swapon_label", (RErr, [String "label"]), 174, [],
3497    [InitEmpty, Always, TestRun (
3498       [["part_disk"; "/dev/sdb"; "mbr"];
3499        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3500        ["swapon_label"; "swapit"];
3501        ["swapoff_label"; "swapit"];
3502        ["zero"; "/dev/sdb"];
3503        ["blockdev_rereadpt"; "/dev/sdb"]])],
3504    "enable swap on labeled swap partition",
3505    "\
3506 This command enables swap to a labeled swap partition.
3507 See C<guestfs_swapon_device> for other notes.");
3508
3509   ("swapoff_label", (RErr, [String "label"]), 175, [],
3510    [], (* XXX tested by swapon_label *)
3511    "disable swap on labeled swap partition",
3512    "\
3513 This command disables the libguestfs appliance swap on
3514 labeled swap partition.");
3515
3516   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3517    (let uuid = uuidgen () in
3518     [InitEmpty, Always, TestRun (
3519        [["mkswap_U"; uuid; "/dev/sdb"];
3520         ["swapon_uuid"; uuid];
3521         ["swapoff_uuid"; uuid]])]),
3522    "enable swap on swap partition by UUID",
3523    "\
3524 This command enables swap to a swap partition with the given UUID.
3525 See C<guestfs_swapon_device> for other notes.");
3526
3527   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3528    [], (* XXX tested by swapon_uuid *)
3529    "disable swap on swap partition by UUID",
3530    "\
3531 This command disables the libguestfs appliance swap partition
3532 with the given UUID.");
3533
3534   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3535    [InitBasicFS, Always, TestRun (
3536       [["fallocate"; "/swap"; "8388608"];
3537        ["mkswap_file"; "/swap"]])],
3538    "create a swap file",
3539    "\
3540 Create a swap file.
3541
3542 This command just writes a swap file signature to an existing
3543 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3544
3545   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3546    [InitISOFS, Always, TestRun (
3547       [["inotify_init"; "0"]])],
3548    "create an inotify handle",
3549    "\
3550 This command creates a new inotify handle.
3551 The inotify subsystem can be used to notify events which happen to
3552 objects in the guest filesystem.
3553
3554 C<maxevents> is the maximum number of events which will be
3555 queued up between calls to C<guestfs_inotify_read> or
3556 C<guestfs_inotify_files>.
3557 If this is passed as C<0>, then the kernel (or previously set)
3558 default is used.  For Linux 2.6.29 the default was 16384 events.
3559 Beyond this limit, the kernel throws away events, but records
3560 the fact that it threw them away by setting a flag
3561 C<IN_Q_OVERFLOW> in the returned structure list (see
3562 C<guestfs_inotify_read>).
3563
3564 Before any events are generated, you have to add some
3565 watches to the internal watch list.  See:
3566 C<guestfs_inotify_add_watch>,
3567 C<guestfs_inotify_rm_watch> and
3568 C<guestfs_inotify_watch_all>.
3569
3570 Queued up events should be read periodically by calling
3571 C<guestfs_inotify_read>
3572 (or C<guestfs_inotify_files> which is just a helpful
3573 wrapper around C<guestfs_inotify_read>).  If you don't
3574 read the events out often enough then you risk the internal
3575 queue overflowing.
3576
3577 The handle should be closed after use by calling
3578 C<guestfs_inotify_close>.  This also removes any
3579 watches automatically.
3580
3581 See also L<inotify(7)> for an overview of the inotify interface
3582 as exposed by the Linux kernel, which is roughly what we expose
3583 via libguestfs.  Note that there is one global inotify handle
3584 per libguestfs instance.");
3585
3586   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3587    [InitBasicFS, Always, TestOutputList (
3588       [["inotify_init"; "0"];
3589        ["inotify_add_watch"; "/"; "1073741823"];
3590        ["touch"; "/a"];
3591        ["touch"; "/b"];
3592        ["inotify_files"]], ["a"; "b"])],
3593    "add an inotify watch",
3594    "\
3595 Watch C<path> for the events listed in C<mask>.
3596
3597 Note that if C<path> is a directory then events within that
3598 directory are watched, but this does I<not> happen recursively
3599 (in subdirectories).
3600
3601 Note for non-C or non-Linux callers: the inotify events are
3602 defined by the Linux kernel ABI and are listed in
3603 C</usr/include/sys/inotify.h>.");
3604
3605   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3606    [],
3607    "remove an inotify watch",
3608    "\
3609 Remove a previously defined inotify watch.
3610 See C<guestfs_inotify_add_watch>.");
3611
3612   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3613    [],
3614    "return list of inotify events",
3615    "\
3616 Return the complete queue of events that have happened
3617 since the previous read call.
3618
3619 If no events have happened, this returns an empty list.
3620
3621 I<Note>: In order to make sure that all events have been
3622 read, you must call this function repeatedly until it
3623 returns an empty list.  The reason is that the call will
3624 read events up to the maximum appliance-to-host message
3625 size and leave remaining events in the queue.");
3626
3627   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3628    [],
3629    "return list of watched files that had events",
3630    "\
3631 This function is a helpful wrapper around C<guestfs_inotify_read>
3632 which just returns a list of pathnames of objects that were
3633 touched.  The returned pathnames are sorted and deduplicated.");
3634
3635   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3636    [],
3637    "close the inotify handle",
3638    "\
3639 This closes the inotify handle which was previously
3640 opened by inotify_init.  It removes all watches, throws
3641 away any pending events, and deallocates all resources.");
3642
3643   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3644    [],
3645    "set SELinux security context",
3646    "\
3647 This sets the SELinux security context of the daemon
3648 to the string C<context>.
3649
3650 See the documentation about SELINUX in L<guestfs(3)>.");
3651
3652   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3653    [],
3654    "get SELinux security context",
3655    "\
3656 This gets the SELinux security context of the daemon.
3657
3658 See the documentation about SELINUX in L<guestfs(3)>,
3659 and C<guestfs_setcon>");
3660
3661   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3662    [InitEmpty, Always, TestOutput (
3663       [["part_disk"; "/dev/sda"; "mbr"];
3664        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3665        ["mount_options"; ""; "/dev/sda1"; "/"];
3666        ["write_file"; "/new"; "new file contents"; "0"];
3667        ["cat"; "/new"]], "new file contents")],
3668    "make a filesystem with block size",
3669    "\
3670 This call is similar to C<guestfs_mkfs>, but it allows you to
3671 control the block size of the resulting filesystem.  Supported
3672 block sizes depend on the filesystem type, but typically they
3673 are C<1024>, C<2048> or C<4096> only.");
3674
3675   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3676    [InitEmpty, Always, TestOutput (
3677       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3678        ["mke2journal"; "4096"; "/dev/sda1"];
3679        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3680        ["mount_options"; ""; "/dev/sda2"; "/"];
3681        ["write_file"; "/new"; "new file contents"; "0"];
3682        ["cat"; "/new"]], "new file contents")],
3683    "make ext2/3/4 external journal",
3684    "\
3685 This creates an ext2 external journal on C<device>.  It is equivalent
3686 to the command:
3687
3688  mke2fs -O journal_dev -b blocksize device");
3689
3690   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3691    [InitEmpty, Always, TestOutput (
3692       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3693        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3694        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3695        ["mount_options"; ""; "/dev/sda2"; "/"];
3696        ["write_file"; "/new"; "new file contents"; "0"];
3697        ["cat"; "/new"]], "new file contents")],
3698    "make ext2/3/4 external journal with label",
3699    "\
3700 This creates an ext2 external journal on C<device> with label C<label>.");
3701
3702   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3703    (let uuid = uuidgen () in
3704     [InitEmpty, Always, TestOutput (
3705        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3706         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3707         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3708         ["mount_options"; ""; "/dev/sda2"; "/"];
3709         ["write_file"; "/new"; "new file contents"; "0"];
3710         ["cat"; "/new"]], "new file contents")]),
3711    "make ext2/3/4 external journal with UUID",
3712    "\
3713 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3714
3715   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3716    [],
3717    "make ext2/3/4 filesystem with external journal",
3718    "\
3719 This creates an ext2/3/4 filesystem on C<device> with
3720 an external journal on C<journal>.  It is equivalent
3721 to the command:
3722
3723  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3724
3725 See also C<guestfs_mke2journal>.");
3726
3727   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3728    [],
3729    "make ext2/3/4 filesystem with external journal",
3730    "\
3731 This creates an ext2/3/4 filesystem on C<device> with
3732 an external journal on the journal labeled C<label>.
3733
3734 See also C<guestfs_mke2journal_L>.");
3735
3736   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3737    [],
3738    "make ext2/3/4 filesystem with external journal",
3739    "\
3740 This creates an ext2/3/4 filesystem on C<device> with
3741 an external journal on the journal with UUID C<uuid>.
3742
3743 See also C<guestfs_mke2journal_U>.");
3744
3745   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3746    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3747    "load a kernel module",
3748    "\
3749 This loads a kernel module in the appliance.
3750
3751 The kernel module must have been whitelisted when libguestfs
3752 was built (see C<appliance/kmod.whitelist.in> in the source).");
3753
3754   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3755    [InitNone, Always, TestOutput (
3756       [["echo_daemon"; "This is a test"]], "This is a test"
3757     )],
3758    "echo arguments back to the client",
3759    "\
3760 This command concatenate the list of C<words> passed with single spaces between
3761 them and returns the resulting string.
3762
3763 You can use this command to test the connection through to the daemon.
3764
3765 See also C<guestfs_ping_daemon>.");
3766
3767   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3768    [], (* There is a regression test for this. *)
3769    "find all files and directories, returning NUL-separated list",
3770    "\
3771 This command lists out all files and directories, recursively,
3772 starting at C<directory>, placing the resulting list in the
3773 external file called C<files>.
3774
3775 This command works the same way as C<guestfs_find> with the
3776 following exceptions:
3777
3778 =over 4
3779
3780 =item *
3781
3782 The resulting list is written to an external file.
3783
3784 =item *
3785
3786 Items (filenames) in the result are separated
3787 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3788
3789 =item *
3790
3791 This command is not limited in the number of names that it
3792 can return.
3793
3794 =item *
3795
3796 The result list is not sorted.
3797
3798 =back");
3799
3800   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3801    [InitISOFS, Always, TestOutput (
3802       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3803     InitISOFS, Always, TestOutput (
3804       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3805     InitISOFS, Always, TestOutput (
3806       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3807     InitISOFS, Always, TestLastFail (
3808       [["case_sensitive_path"; "/Known-1/"]]);
3809     InitBasicFS, Always, TestOutput (
3810       [["mkdir"; "/a"];
3811        ["mkdir"; "/a/bbb"];
3812        ["touch"; "/a/bbb/c"];
3813        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3814     InitBasicFS, Always, TestOutput (
3815       [["mkdir"; "/a"];
3816        ["mkdir"; "/a/bbb"];
3817        ["touch"; "/a/bbb/c"];
3818        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3819     InitBasicFS, Always, TestLastFail (
3820       [["mkdir"; "/a"];
3821        ["mkdir"; "/a/bbb"];
3822        ["touch"; "/a/bbb/c"];
3823        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3824    "return true path on case-insensitive filesystem",
3825    "\
3826 This can be used to resolve case insensitive paths on
3827 a filesystem which is case sensitive.  The use case is
3828 to resolve paths which you have read from Windows configuration
3829 files or the Windows Registry, to the true path.
3830
3831 The command handles a peculiarity of the Linux ntfs-3g
3832 filesystem driver (and probably others), which is that although
3833 the underlying filesystem is case-insensitive, the driver
3834 exports the filesystem to Linux as case-sensitive.
3835
3836 One consequence of this is that special directories such
3837 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3838 (or other things) depending on the precise details of how
3839 they were created.  In Windows itself this would not be
3840 a problem.
3841
3842 Bug or feature?  You decide:
3843 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3844
3845 This function resolves the true case of each element in the
3846 path and returns the case-sensitive path.
3847
3848 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3849 might return C<\"/WINDOWS/system32\"> (the exact return value
3850 would depend on details of how the directories were originally
3851 created under Windows).
3852
3853 I<Note>:
3854 This function does not handle drive names, backslashes etc.
3855
3856 See also C<guestfs_realpath>.");
3857
3858   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3859    [InitBasicFS, Always, TestOutput (
3860       [["vfs_type"; "/dev/sda1"]], "ext2")],
3861    "get the Linux VFS type corresponding to a mounted device",
3862    "\
3863 This command gets the block device type corresponding to
3864 a mounted device called C<device>.
3865
3866 Usually the result is the name of the Linux VFS module that
3867 is used to mount this device (probably determined automatically
3868 if you used the C<guestfs_mount> call).");
3869
3870   ("truncate", (RErr, [Pathname "path"]), 199, [],
3871    [InitBasicFS, Always, TestOutputStruct (
3872       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3873        ["truncate"; "/test"];
3874        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3875    "truncate a file to zero size",
3876    "\
3877 This command truncates C<path> to a zero-length file.  The
3878 file must exist already.");
3879
3880   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3881    [InitBasicFS, Always, TestOutputStruct (
3882       [["touch"; "/test"];
3883        ["truncate_size"; "/test"; "1000"];
3884        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3885    "truncate a file to a particular size",
3886    "\
3887 This command truncates C<path> to size C<size> bytes.  The file
3888 must exist already.  If the file is smaller than C<size> then
3889 the file is extended to the required size with null bytes.");
3890
3891   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3892    [InitBasicFS, Always, TestOutputStruct (
3893       [["touch"; "/test"];
3894        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3895        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3896    "set timestamp of a file with nanosecond precision",
3897    "\
3898 This command sets the timestamps of a file with nanosecond
3899 precision.
3900
3901 C<atsecs, atnsecs> are the last access time (atime) in secs and
3902 nanoseconds from the epoch.
3903
3904 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3905 secs and nanoseconds from the epoch.
3906
3907 If the C<*nsecs> field contains the special value C<-1> then
3908 the corresponding timestamp is set to the current time.  (The
3909 C<*secs> field is ignored in this case).
3910
3911 If the C<*nsecs> field contains the special value C<-2> then
3912 the corresponding timestamp is left unchanged.  (The
3913 C<*secs> field is ignored in this case).");
3914
3915   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3916    [InitBasicFS, Always, TestOutputStruct (
3917       [["mkdir_mode"; "/test"; "0o111"];
3918        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3919    "create a directory with a particular mode",
3920    "\
3921 This command creates a directory, setting the initial permissions
3922 of the directory to C<mode>.
3923
3924 For common Linux filesystems, the actual mode which is set will
3925 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3926 interpret the mode in other ways.
3927
3928 See also C<guestfs_mkdir>, C<guestfs_umask>");
3929
3930   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3931    [], (* XXX *)
3932    "change file owner and group",
3933    "\
3934 Change the file owner to C<owner> and group to C<group>.
3935 This is like C<guestfs_chown> but if C<path> is a symlink then
3936 the link itself is changed, not the target.
3937
3938 Only numeric uid and gid are supported.  If you want to use
3939 names, you will need to locate and parse the password file
3940 yourself (Augeas support makes this relatively easy).");
3941
3942   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3943    [], (* XXX *)
3944    "lstat on multiple files",
3945    "\
3946 This call allows you to perform the C<guestfs_lstat> operation
3947 on multiple files, where all files are in the directory C<path>.
3948 C<names> is the list of files from this directory.
3949
3950 On return you get a list of stat structs, with a one-to-one
3951 correspondence to the C<names> list.  If any name did not exist
3952 or could not be lstat'd, then the C<ino> field of that structure
3953 is set to C<-1>.
3954
3955 This call is intended for programs that want to efficiently
3956 list a directory contents without making many round-trips.
3957 See also C<guestfs_lxattrlist> for a similarly efficient call
3958 for getting extended attributes.  Very long directory listings
3959 might cause the protocol message size to be exceeded, causing
3960 this call to fail.  The caller must split up such requests
3961 into smaller groups of names.");
3962
3963   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3964    [], (* XXX *)
3965    "lgetxattr on multiple files",
3966    "\
3967 This call allows you to get the extended attributes
3968 of multiple files, where all files are in the directory C<path>.
3969 C<names> is the list of files from this directory.
3970
3971 On return you get a flat list of xattr structs which must be
3972 interpreted sequentially.  The first xattr struct always has a zero-length
3973 C<attrname>.  C<attrval> in this struct is zero-length
3974 to indicate there was an error doing C<lgetxattr> for this
3975 file, I<or> is a C string which is a decimal number
3976 (the number of following attributes for this file, which could
3977 be C<\"0\">).  Then after the first xattr struct are the
3978 zero or more attributes for the first named file.
3979 This repeats for the second and subsequent files.
3980
3981 This call is intended for programs that want to efficiently
3982 list a directory contents without making many round-trips.
3983 See also C<guestfs_lstatlist> for a similarly efficient call
3984 for getting standard stats.  Very long directory listings
3985 might cause the protocol message size to be exceeded, causing
3986 this call to fail.  The caller must split up such requests
3987 into smaller groups of names.");
3988
3989   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3990    [], (* XXX *)
3991    "readlink on multiple files",
3992    "\
3993 This call allows you to do a C<readlink> operation
3994 on multiple files, where all files are in the directory C<path>.
3995 C<names> is the list of files from this directory.
3996
3997 On return you get a list of strings, with a one-to-one
3998 correspondence to the C<names> list.  Each string is the
3999 value of the symbol link.
4000
4001 If the C<readlink(2)> operation fails on any name, then
4002 the corresponding result string is the empty string C<\"\">.
4003 However the whole operation is completed even if there
4004 were C<readlink(2)> errors, and so you can call this
4005 function with names where you don't know if they are
4006 symbolic links already (albeit slightly less efficient).
4007
4008 This call is intended for programs that want to efficiently
4009 list a directory contents without making many round-trips.
4010 Very long directory listings might cause the protocol
4011 message size to be exceeded, causing
4012 this call to fail.  The caller must split up such requests
4013 into smaller groups of names.");
4014
4015   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4016    [InitISOFS, Always, TestOutputBuffer (
4017       [["pread"; "/known-4"; "1"; "3"]], "\n");
4018     InitISOFS, Always, TestOutputBuffer (
4019       [["pread"; "/empty"; "0"; "100"]], "")],
4020    "read part of a file",
4021    "\
4022 This command lets you read part of a file.  It reads C<count>
4023 bytes of the file, starting at C<offset>, from file C<path>.
4024
4025 This may read fewer bytes than requested.  For further details
4026 see the L<pread(2)> system call.");
4027
4028   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4029    [InitEmpty, Always, TestRun (
4030       [["part_init"; "/dev/sda"; "gpt"]])],
4031    "create an empty partition table",
4032    "\
4033 This creates an empty partition table on C<device> of one of the
4034 partition types listed below.  Usually C<parttype> should be
4035 either C<msdos> or C<gpt> (for large disks).
4036
4037 Initially there are no partitions.  Following this, you should
4038 call C<guestfs_part_add> for each partition required.
4039
4040 Possible values for C<parttype> are:
4041
4042 =over 4
4043
4044 =item B<efi> | B<gpt>
4045
4046 Intel EFI / GPT partition table.
4047
4048 This is recommended for >= 2 TB partitions that will be accessed
4049 from Linux and Intel-based Mac OS X.  It also has limited backwards
4050 compatibility with the C<mbr> format.
4051
4052 =item B<mbr> | B<msdos>
4053
4054 The standard PC \"Master Boot Record\" (MBR) format used
4055 by MS-DOS and Windows.  This partition type will B<only> work
4056 for device sizes up to 2 TB.  For large disks we recommend
4057 using C<gpt>.
4058
4059 =back
4060
4061 Other partition table types that may work but are not
4062 supported include:
4063
4064 =over 4
4065
4066 =item B<aix>
4067
4068 AIX disk labels.
4069
4070 =item B<amiga> | B<rdb>
4071
4072 Amiga \"Rigid Disk Block\" format.
4073
4074 =item B<bsd>
4075
4076 BSD disk labels.
4077
4078 =item B<dasd>
4079
4080 DASD, used on IBM mainframes.
4081
4082 =item B<dvh>
4083
4084 MIPS/SGI volumes.
4085
4086 =item B<mac>
4087
4088 Old Mac partition format.  Modern Macs use C<gpt>.
4089
4090 =item B<pc98>
4091
4092 NEC PC-98 format, common in Japan apparently.
4093
4094 =item B<sun>
4095
4096 Sun disk labels.
4097
4098 =back");
4099
4100   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4101    [InitEmpty, Always, TestRun (
4102       [["part_init"; "/dev/sda"; "mbr"];
4103        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4104     InitEmpty, Always, TestRun (
4105       [["part_init"; "/dev/sda"; "gpt"];
4106        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4107        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4108     InitEmpty, Always, TestRun (
4109       [["part_init"; "/dev/sda"; "mbr"];
4110        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4111        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4112        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4113        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4114    "add a partition to the device",
4115    "\
4116 This command adds a partition to C<device>.  If there is no partition
4117 table on the device, call C<guestfs_part_init> first.
4118
4119 The C<prlogex> parameter is the type of partition.  Normally you
4120 should pass C<p> or C<primary> here, but MBR partition tables also
4121 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4122 types.
4123
4124 C<startsect> and C<endsect> are the start and end of the partition
4125 in I<sectors>.  C<endsect> may be negative, which means it counts
4126 backwards from the end of the disk (C<-1> is the last sector).
4127
4128 Creating a partition which covers the whole disk is not so easy.
4129 Use C<guestfs_part_disk> to do that.");
4130
4131   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4132    [InitEmpty, Always, TestRun (
4133       [["part_disk"; "/dev/sda"; "mbr"]]);
4134     InitEmpty, Always, TestRun (
4135       [["part_disk"; "/dev/sda"; "gpt"]])],
4136    "partition whole disk with a single primary partition",
4137    "\
4138 This command is simply a combination of C<guestfs_part_init>
4139 followed by C<guestfs_part_add> to create a single primary partition
4140 covering the whole disk.
4141
4142 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4143 but other possible values are described in C<guestfs_part_init>.");
4144
4145   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4146    [InitEmpty, Always, TestRun (
4147       [["part_disk"; "/dev/sda"; "mbr"];
4148        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4149    "make a partition bootable",
4150    "\
4151 This sets the bootable flag on partition numbered C<partnum> on
4152 device C<device>.  Note that partitions are numbered from 1.
4153
4154 The bootable flag is used by some operating systems (notably
4155 Windows) to determine which partition to boot from.  It is by
4156 no means universally recognized.");
4157
4158   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4159    [InitEmpty, Always, TestRun (
4160       [["part_disk"; "/dev/sda"; "gpt"];
4161        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4162    "set partition name",
4163    "\
4164 This sets the partition name on partition numbered C<partnum> on
4165 device C<device>.  Note that partitions are numbered from 1.
4166
4167 The partition name can only be set on certain types of partition
4168 table.  This works on C<gpt> but not on C<mbr> partitions.");
4169
4170   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4171    [], (* XXX Add a regression test for this. *)
4172    "list partitions on a device",
4173    "\
4174 This command parses the partition table on C<device> and
4175 returns the list of partitions found.
4176
4177 The fields in the returned structure are:
4178
4179 =over 4
4180
4181 =item B<part_num>
4182
4183 Partition number, counting from 1.
4184
4185 =item B<part_start>
4186
4187 Start of the partition I<in bytes>.  To get sectors you have to
4188 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4189
4190 =item B<part_end>
4191
4192 End of the partition in bytes.
4193
4194 =item B<part_size>
4195
4196 Size of the partition in bytes.
4197
4198 =back");
4199
4200   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4201    [InitEmpty, Always, TestOutput (
4202       [["part_disk"; "/dev/sda"; "gpt"];
4203        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4204    "get the partition table type",
4205    "\
4206 This command examines the partition table on C<device> and
4207 returns the partition table type (format) being used.
4208
4209 Common return values include: C<msdos> (a DOS/Windows style MBR
4210 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4211 values are possible, although unusual.  See C<guestfs_part_init>
4212 for a full list.");
4213
4214   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4215    [InitBasicFS, Always, TestOutputBuffer (
4216       [["fill"; "0x63"; "10"; "/test"];
4217        ["read_file"; "/test"]], "cccccccccc")],
4218    "fill a file with octets",
4219    "\
4220 This command creates a new file called C<path>.  The initial
4221 content of the file is C<len> octets of C<c>, where C<c>
4222 must be a number in the range C<[0..255]>.
4223
4224 To fill a file with zero bytes (sparsely), it is
4225 much more efficient to use C<guestfs_truncate_size>.");
4226
4227   ("available", (RErr, [StringList "groups"]), 216, [],
4228    [InitNone, Always, TestRun [["available"; ""]]],
4229    "test availability of some parts of the API",
4230    "\
4231 This command is used to check the availability of some
4232 groups of functionality in the appliance, which not all builds of
4233 the libguestfs appliance will be able to provide.
4234
4235 The libguestfs groups, and the functions that those
4236 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4237
4238 The argument C<groups> is a list of group names, eg:
4239 C<[\"inotify\", \"augeas\"]> would check for the availability of
4240 the Linux inotify functions and Augeas (configuration file
4241 editing) functions.
4242
4243 The command returns no error if I<all> requested groups are available.
4244
4245 It fails with an error if one or more of the requested
4246 groups is unavailable in the appliance.
4247
4248 If an unknown group name is included in the
4249 list of groups then an error is always returned.
4250
4251 I<Notes:>
4252
4253 =over 4
4254
4255 =item *
4256
4257 You must call C<guestfs_launch> before calling this function.
4258
4259 The reason is because we don't know what groups are
4260 supported by the appliance/daemon until it is running and can
4261 be queried.
4262
4263 =item *
4264
4265 If a group of functions is available, this does not necessarily
4266 mean that they will work.  You still have to check for errors
4267 when calling individual API functions even if they are
4268 available.
4269
4270 =item *
4271
4272 It is usually the job of distro packagers to build
4273 complete functionality into the libguestfs appliance.
4274 Upstream libguestfs, if built from source with all
4275 requirements satisfied, will support everything.
4276
4277 =item *
4278
4279 This call was added in version C<1.0.80>.  In previous
4280 versions of libguestfs all you could do would be to speculatively
4281 execute a command to find out if the daemon implemented it.
4282 See also C<guestfs_version>.
4283
4284 =back");
4285
4286   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4287    [InitBasicFS, Always, TestOutputBuffer (
4288       [["write_file"; "/src"; "hello, world"; "0"];
4289        ["dd"; "/src"; "/dest"];
4290        ["read_file"; "/dest"]], "hello, world")],
4291    "copy from source to destination using dd",
4292    "\
4293 This command copies from one source device or file C<src>
4294 to another destination device or file C<dest>.  Normally you
4295 would use this to copy to or from a device or partition, for
4296 example to duplicate a filesystem.
4297
4298 If the destination is a device, it must be as large or larger
4299 than the source file or device, otherwise the copy will fail.
4300 This command cannot do partial copies (see C<guestfs_copy_size>).");
4301
4302   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4303    [InitBasicFS, Always, TestOutputInt (
4304       [["write_file"; "/file"; "hello, world"; "0"];
4305        ["filesize"; "/file"]], 12)],
4306    "return the size of the file in bytes",
4307    "\
4308 This command returns the size of C<file> in bytes.
4309
4310 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4311 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4312 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4313
4314   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4315    [InitBasicFSonLVM, Always, TestOutputList (
4316       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4317        ["lvs"]], ["/dev/VG/LV2"])],
4318    "rename an LVM logical volume",
4319    "\
4320 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4321
4322   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4323    [InitBasicFSonLVM, Always, TestOutputList (
4324       [["umount"; "/"];
4325        ["vg_activate"; "false"; "VG"];
4326        ["vgrename"; "VG"; "VG2"];
4327        ["vg_activate"; "true"; "VG2"];
4328        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4329        ["vgs"]], ["VG2"])],
4330    "rename an LVM volume group",
4331    "\
4332 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4333
4334   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4335    [InitISOFS, Always, TestOutputBuffer (
4336       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4337    "list the contents of a single file in an initrd",
4338    "\
4339 This command unpacks the file C<filename> from the initrd file
4340 called C<initrdpath>.  The filename must be given I<without> the
4341 initial C</> character.
4342
4343 For example, in guestfish you could use the following command
4344 to examine the boot script (usually called C</init>)
4345 contained in a Linux initrd or initramfs image:
4346
4347  initrd-cat /boot/initrd-<version>.img init
4348
4349 See also C<guestfs_initrd_list>.");
4350
4351   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4352    [],
4353    "get the UUID of a physical volume",
4354    "\
4355 This command returns the UUID of the LVM PV C<device>.");
4356
4357   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4358    [],
4359    "get the UUID of a volume group",
4360    "\
4361 This command returns the UUID of the LVM VG named C<vgname>.");
4362
4363   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4364    [],
4365    "get the UUID of a logical volume",
4366    "\
4367 This command returns the UUID of the LVM LV C<device>.");
4368
4369   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4370    [],
4371    "get the PV UUIDs containing the volume group",
4372    "\
4373 Given a VG called C<vgname>, this returns the UUIDs of all
4374 the physical volumes that this volume group resides on.
4375
4376 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4377 calls to associate physical volumes and volume groups.
4378
4379 See also C<guestfs_vglvuuids>.");
4380
4381   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4382    [],
4383    "get the LV UUIDs of all LVs in the volume group",
4384    "\
4385 Given a VG called C<vgname>, this returns the UUIDs of all
4386 the logical volumes created in this volume group.
4387
4388 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4389 calls to associate logical volumes and volume groups.
4390
4391 See also C<guestfs_vgpvuuids>.");
4392
4393   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4394    [InitBasicFS, Always, TestOutputBuffer (
4395       [["write_file"; "/src"; "hello, world"; "0"];
4396        ["copy_size"; "/src"; "/dest"; "5"];
4397        ["read_file"; "/dest"]], "hello")],
4398    "copy size bytes from source to destination using dd",
4399    "\
4400 This command copies exactly C<size> bytes from one source device
4401 or file C<src> to another destination device or file C<dest>.
4402
4403 Note this will fail if the source is too short or if the destination
4404 is not large enough.");
4405
4406   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4407    [InitBasicFSonLVM, Always, TestRun (
4408       [["zero_device"; "/dev/VG/LV"]])],
4409    "write zeroes to an entire device",
4410    "\
4411 This command writes zeroes over the entire C<device>.  Compare
4412 with C<guestfs_zero> which just zeroes the first few blocks of
4413 a device.");
4414
4415   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4416    [InitBasicFS, Always, TestOutput (
4417       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4418        ["cat"; "/hello"]], "hello\n")],
4419    "unpack compressed tarball to directory",
4420    "\
4421 This command uploads and unpacks local file C<tarball> (an
4422 I<xz compressed> tar file) into C<directory>.");
4423
4424   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4425    [],
4426    "pack directory into compressed tarball",
4427    "\
4428 This command packs the contents of C<directory> and downloads
4429 it to local file C<tarball> (as an xz compressed tar archive).");
4430
4431   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4432    [],
4433    "resize an NTFS filesystem",
4434    "\
4435 This command resizes an NTFS filesystem, expanding or
4436 shrinking it to the size of the underlying device.
4437 See also L<ntfsresize(8)>.");
4438
4439   ("vgscan", (RErr, []), 232, [],
4440    [InitEmpty, Always, TestRun (
4441       [["vgscan"]])],
4442    "rescan for LVM physical volumes, volume groups and logical volumes",
4443    "\
4444 This rescans all block devices and rebuilds the list of LVM
4445 physical volumes, volume groups and logical volumes.");
4446
4447   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4448    [InitEmpty, Always, TestRun (
4449       [["part_init"; "/dev/sda"; "mbr"];
4450        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4451        ["part_del"; "/dev/sda"; "1"]])],
4452    "delete a partition",
4453    "\
4454 This command deletes the partition numbered C<partnum> on C<device>.
4455
4456 Note that in the case of MBR partitioning, deleting an
4457 extended partition also deletes any logical partitions
4458 it contains.");
4459
4460   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4461    [InitEmpty, Always, TestOutputTrue (
4462       [["part_init"; "/dev/sda"; "mbr"];
4463        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4464        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4465        ["part_get_bootable"; "/dev/sda"; "1"]])],
4466    "return true if a partition is bootable",
4467    "\
4468 This command returns true if the partition C<partnum> on
4469 C<device> has the bootable flag set.
4470
4471 See also C<guestfs_part_set_bootable>.");
4472
4473   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4474    [InitEmpty, Always, TestOutputInt (
4475       [["part_init"; "/dev/sda"; "mbr"];
4476        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4477        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4478        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4479    "get the MBR type byte (ID byte) from a partition",
4480    "\
4481 Returns the MBR type byte (also known as the ID byte) from
4482 the numbered partition C<partnum>.
4483
4484 Note that only MBR (old DOS-style) partitions have type bytes.
4485 You will get undefined results for other partition table
4486 types (see C<guestfs_part_get_parttype>).");
4487
4488   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4489    [], (* tested by part_get_mbr_id *)
4490    "set the MBR type byte (ID byte) of a partition",
4491    "\
4492 Sets the MBR type byte (also known as the ID byte) of
4493 the numbered partition C<partnum> to C<idbyte>.  Note
4494 that the type bytes quoted in most documentation are
4495 in fact hexadecimal numbers, but usually documented
4496 without any leading \"0x\" which might be confusing.
4497
4498 Note that only MBR (old DOS-style) partitions have type bytes.
4499 You will get undefined results for other partition table
4500 types (see C<guestfs_part_get_parttype>).");
4501
4502   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4503    [InitISOFS, Always, TestOutput (
4504       [["checksum_device"; "md5"; "/dev/sdd"]],
4505       (Digest.to_hex (Digest.file "images/test.iso")))],
4506    "compute MD5, SHAx or CRC checksum of the contents of a device",
4507    "\
4508 This call computes the MD5, SHAx or CRC checksum of the
4509 contents of the device named C<device>.  For the types of
4510 checksums supported see the C<guestfs_checksum> command.");
4511
4512   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4513    [InitNone, Always, TestRun (
4514       [["part_disk"; "/dev/sda"; "mbr"];
4515        ["pvcreate"; "/dev/sda1"];
4516        ["vgcreate"; "VG"; "/dev/sda1"];
4517        ["lvcreate"; "LV"; "VG"; "10"];
4518        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4519    "expand an LV to fill free space",
4520    "\
4521 This expands an existing logical volume C<lv> so that it fills
4522 C<pc>% of the remaining free space in the volume group.  Commonly
4523 you would call this with pc = 100 which expands the logical volume
4524 as much as possible, using all remaining free space in the volume
4525 group.");
4526
4527   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4528    [], (* XXX Augeas code needs tests. *)
4529    "clear Augeas path",
4530    "\
4531 Set the value associated with C<path> to C<NULL>.  This
4532 is the same as the L<augtool(1)> C<clear> command.");
4533
4534   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4535    [InitEmpty, Always, TestOutputInt (
4536       [["get_umask"]], 0o22)],
4537    "get the current umask",
4538    "\
4539 Return the current umask.  By default the umask is C<022>
4540 unless it has been set by calling C<guestfs_umask>.");
4541
4542   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4543    [],
4544    "upload a file to the appliance (internal use only)",
4545    "\
4546 The C<guestfs_debug_upload> command uploads a file to
4547 the libguestfs appliance.
4548
4549 There is no comprehensive help for this command.  You have
4550 to look at the file C<daemon/debug.c> in the libguestfs source
4551 to find out what it is for.");
4552
4553   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4554    [InitBasicFS, Always, TestOutput (
4555       [["base64_in"; "../images/hello.b64"; "/hello"];
4556        ["cat"; "/hello"]], "hello\n")],
4557    "upload base64-encoded data to file",
4558    "\
4559 This command uploads base64-encoded data from C<base64file>
4560 to C<filename>.");
4561
4562   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4563    [],
4564    "download file and encode as base64",
4565    "\
4566 This command downloads the contents of C<filename>, writing
4567 it out to local file C<base64file> encoded as base64.");
4568
4569   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4570    [],
4571    "compute MD5, SHAx or CRC checksum of files in a directory",
4572    "\
4573 This command computes the checksums of all regular files in
4574 C<directory> and then emits a list of those checksums to
4575 the local output file C<sumsfile>.
4576
4577 This can be used for verifying the integrity of a virtual
4578 machine.  However to be properly secure you should pay
4579 attention to the output of the checksum command (it uses
4580 the ones from GNU coreutils).  In particular when the
4581 filename is not printable, coreutils uses a special
4582 backslash syntax.  For more information, see the GNU
4583 coreutils info file.");
4584
4585 ]
4586
4587 let all_functions = non_daemon_functions @ daemon_functions
4588
4589 (* In some places we want the functions to be displayed sorted
4590  * alphabetically, so this is useful:
4591  *)
4592 let all_functions_sorted =
4593   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4594                compare n1 n2) all_functions
4595
4596 (* Field types for structures. *)
4597 type field =
4598   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4599   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4600   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4601   | FUInt32
4602   | FInt32
4603   | FUInt64
4604   | FInt64
4605   | FBytes                      (* Any int measure that counts bytes. *)
4606   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4607   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4608
4609 (* Because we generate extra parsing code for LVM command line tools,
4610  * we have to pull out the LVM columns separately here.
4611  *)
4612 let lvm_pv_cols = [
4613   "pv_name", FString;
4614   "pv_uuid", FUUID;
4615   "pv_fmt", FString;
4616   "pv_size", FBytes;
4617   "dev_size", FBytes;
4618   "pv_free", FBytes;
4619   "pv_used", FBytes;
4620   "pv_attr", FString (* XXX *);
4621   "pv_pe_count", FInt64;
4622   "pv_pe_alloc_count", FInt64;
4623   "pv_tags", FString;
4624   "pe_start", FBytes;
4625   "pv_mda_count", FInt64;
4626   "pv_mda_free", FBytes;
4627   (* Not in Fedora 10:
4628      "pv_mda_size", FBytes;
4629   *)
4630 ]
4631 let lvm_vg_cols = [
4632   "vg_name", FString;
4633   "vg_uuid", FUUID;
4634   "vg_fmt", FString;
4635   "vg_attr", FString (* XXX *);
4636   "vg_size", FBytes;
4637   "vg_free", FBytes;
4638   "vg_sysid", FString;
4639   "vg_extent_size", FBytes;
4640   "vg_extent_count", FInt64;
4641   "vg_free_count", FInt64;
4642   "max_lv", FInt64;
4643   "max_pv", FInt64;
4644   "pv_count", FInt64;
4645   "lv_count", FInt64;
4646   "snap_count", FInt64;
4647   "vg_seqno", FInt64;
4648   "vg_tags", FString;
4649   "vg_mda_count", FInt64;
4650   "vg_mda_free", FBytes;
4651   (* Not in Fedora 10:
4652      "vg_mda_size", FBytes;
4653   *)
4654 ]
4655 let lvm_lv_cols = [
4656   "lv_name", FString;
4657   "lv_uuid", FUUID;
4658   "lv_attr", FString (* XXX *);
4659   "lv_major", FInt64;
4660   "lv_minor", FInt64;
4661   "lv_kernel_major", FInt64;
4662   "lv_kernel_minor", FInt64;
4663   "lv_size", FBytes;
4664   "seg_count", FInt64;
4665   "origin", FString;
4666   "snap_percent", FOptPercent;
4667   "copy_percent", FOptPercent;
4668   "move_pv", FString;
4669   "lv_tags", FString;
4670   "mirror_log", FString;
4671   "modules", FString;
4672 ]
4673
4674 (* Names and fields in all structures (in RStruct and RStructList)
4675  * that we support.
4676  *)
4677 let structs = [
4678   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4679    * not use this struct in any new code.
4680    *)
4681   "int_bool", [
4682     "i", FInt32;                (* for historical compatibility *)
4683     "b", FInt32;                (* for historical compatibility *)
4684   ];
4685
4686   (* LVM PVs, VGs, LVs. *)
4687   "lvm_pv", lvm_pv_cols;
4688   "lvm_vg", lvm_vg_cols;
4689   "lvm_lv", lvm_lv_cols;
4690
4691   (* Column names and types from stat structures.
4692    * NB. Can't use things like 'st_atime' because glibc header files
4693    * define some of these as macros.  Ugh.
4694    *)
4695   "stat", [
4696     "dev", FInt64;
4697     "ino", FInt64;
4698     "mode", FInt64;
4699     "nlink", FInt64;
4700     "uid", FInt64;
4701     "gid", FInt64;
4702     "rdev", FInt64;
4703     "size", FInt64;
4704     "blksize", FInt64;
4705     "blocks", FInt64;
4706     "atime", FInt64;
4707     "mtime", FInt64;
4708     "ctime", FInt64;
4709   ];
4710   "statvfs", [
4711     "bsize", FInt64;
4712     "frsize", FInt64;
4713     "blocks", FInt64;
4714     "bfree", FInt64;
4715     "bavail", FInt64;
4716     "files", FInt64;
4717     "ffree", FInt64;
4718     "favail", FInt64;
4719     "fsid", FInt64;
4720     "flag", FInt64;
4721     "namemax", FInt64;
4722   ];
4723
4724   (* Column names in dirent structure. *)
4725   "dirent", [
4726     "ino", FInt64;
4727     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4728     "ftyp", FChar;
4729     "name", FString;
4730   ];
4731
4732   (* Version numbers. *)
4733   "version", [
4734     "major", FInt64;
4735     "minor", FInt64;
4736     "release", FInt64;
4737     "extra", FString;
4738   ];
4739
4740   (* Extended attribute. *)
4741   "xattr", [
4742     "attrname", FString;
4743     "attrval", FBuffer;
4744   ];
4745
4746   (* Inotify events. *)
4747   "inotify_event", [
4748     "in_wd", FInt64;
4749     "in_mask", FUInt32;
4750     "in_cookie", FUInt32;
4751     "in_name", FString;
4752   ];
4753
4754   (* Partition table entry. *)
4755   "partition", [
4756     "part_num", FInt32;
4757     "part_start", FBytes;
4758     "part_end", FBytes;
4759     "part_size", FBytes;
4760   ];
4761 ] (* end of structs *)
4762
4763 (* Ugh, Java has to be different ..
4764  * These names are also used by the Haskell bindings.
4765  *)
4766 let java_structs = [
4767   "int_bool", "IntBool";
4768   "lvm_pv", "PV";
4769   "lvm_vg", "VG";
4770   "lvm_lv", "LV";
4771   "stat", "Stat";
4772   "statvfs", "StatVFS";
4773   "dirent", "Dirent";
4774   "version", "Version";
4775   "xattr", "XAttr";
4776   "inotify_event", "INotifyEvent";
4777   "partition", "Partition";
4778 ]
4779
4780 (* What structs are actually returned. *)
4781 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4782
4783 (* Returns a list of RStruct/RStructList structs that are returned
4784  * by any function.  Each element of returned list is a pair:
4785  *
4786  * (structname, RStructOnly)
4787  *    == there exists function which returns RStruct (_, structname)
4788  * (structname, RStructListOnly)
4789  *    == there exists function which returns RStructList (_, structname)
4790  * (structname, RStructAndList)
4791  *    == there are functions returning both RStruct (_, structname)
4792  *                                      and RStructList (_, structname)
4793  *)
4794 let rstructs_used_by functions =
4795   (* ||| is a "logical OR" for rstructs_used_t *)
4796   let (|||) a b =
4797     match a, b with
4798     | RStructAndList, _
4799     | _, RStructAndList -> RStructAndList
4800     | RStructOnly, RStructListOnly
4801     | RStructListOnly, RStructOnly -> RStructAndList
4802     | RStructOnly, RStructOnly -> RStructOnly
4803     | RStructListOnly, RStructListOnly -> RStructListOnly
4804   in
4805
4806   let h = Hashtbl.create 13 in
4807
4808   (* if elem->oldv exists, update entry using ||| operator,
4809    * else just add elem->newv to the hash
4810    *)
4811   let update elem newv =
4812     try  let oldv = Hashtbl.find h elem in
4813          Hashtbl.replace h elem (newv ||| oldv)
4814     with Not_found -> Hashtbl.add h elem newv
4815   in
4816
4817   List.iter (
4818     fun (_, style, _, _, _, _, _) ->
4819       match fst style with
4820       | RStruct (_, structname) -> update structname RStructOnly
4821       | RStructList (_, structname) -> update structname RStructListOnly
4822       | _ -> ()
4823   ) functions;
4824
4825   (* return key->values as a list of (key,value) *)
4826   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4827
4828 (* Used for testing language bindings. *)
4829 type callt =
4830   | CallString of string
4831   | CallOptString of string option
4832   | CallStringList of string list
4833   | CallInt of int
4834   | CallInt64 of int64
4835   | CallBool of bool
4836
4837 (* Used to memoize the result of pod2text. *)
4838 let pod2text_memo_filename = "src/.pod2text.data"
4839 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4840   try
4841     let chan = open_in pod2text_memo_filename in
4842     let v = input_value chan in
4843     close_in chan;
4844     v
4845   with
4846     _ -> Hashtbl.create 13
4847 let pod2text_memo_updated () =
4848   let chan = open_out pod2text_memo_filename in
4849   output_value chan pod2text_memo;
4850   close_out chan
4851
4852 (* Useful functions.
4853  * Note we don't want to use any external OCaml libraries which
4854  * makes this a bit harder than it should be.
4855  *)
4856 module StringMap = Map.Make (String)
4857
4858 let failwithf fs = ksprintf failwith fs
4859
4860 let unique = let i = ref 0 in fun () -> incr i; !i
4861
4862 let replace_char s c1 c2 =
4863   let s2 = String.copy s in
4864   let r = ref false in
4865   for i = 0 to String.length s2 - 1 do
4866     if String.unsafe_get s2 i = c1 then (
4867       String.unsafe_set s2 i c2;
4868       r := true
4869     )
4870   done;
4871   if not !r then s else s2
4872
4873 let isspace c =
4874   c = ' '
4875   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4876
4877 let triml ?(test = isspace) str =
4878   let i = ref 0 in
4879   let n = ref (String.length str) in
4880   while !n > 0 && test str.[!i]; do
4881     decr n;
4882     incr i
4883   done;
4884   if !i = 0 then str
4885   else String.sub str !i !n
4886
4887 let trimr ?(test = isspace) str =
4888   let n = ref (String.length str) in
4889   while !n > 0 && test str.[!n-1]; do
4890     decr n
4891   done;
4892   if !n = String.length str then str
4893   else String.sub str 0 !n
4894
4895 let trim ?(test = isspace) str =
4896   trimr ~test (triml ~test str)
4897
4898 let rec find s sub =
4899   let len = String.length s in
4900   let sublen = String.length sub in
4901   let rec loop i =
4902     if i <= len-sublen then (
4903       let rec loop2 j =
4904         if j < sublen then (
4905           if s.[i+j] = sub.[j] then loop2 (j+1)
4906           else -1
4907         ) else
4908           i (* found *)
4909       in
4910       let r = loop2 0 in
4911       if r = -1 then loop (i+1) else r
4912     ) else
4913       -1 (* not found *)
4914   in
4915   loop 0
4916
4917 let rec replace_str s s1 s2 =
4918   let len = String.length s in
4919   let sublen = String.length s1 in
4920   let i = find s s1 in
4921   if i = -1 then s
4922   else (
4923     let s' = String.sub s 0 i in
4924     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4925     s' ^ s2 ^ replace_str s'' s1 s2
4926   )
4927
4928 let rec string_split sep str =
4929   let len = String.length str in
4930   let seplen = String.length sep in
4931   let i = find str sep in
4932   if i = -1 then [str]
4933   else (
4934     let s' = String.sub str 0 i in
4935     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4936     s' :: string_split sep s''
4937   )
4938
4939 let files_equal n1 n2 =
4940   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4941   match Sys.command cmd with
4942   | 0 -> true
4943   | 1 -> false
4944   | i -> failwithf "%s: failed with error code %d" cmd i
4945
4946 let rec filter_map f = function
4947   | [] -> []
4948   | x :: xs ->
4949       match f x with
4950       | Some y -> y :: filter_map f xs
4951       | None -> filter_map f xs
4952
4953 let rec find_map f = function
4954   | [] -> raise Not_found
4955   | x :: xs ->
4956       match f x with
4957       | Some y -> y
4958       | None -> find_map f xs
4959
4960 let iteri f xs =
4961   let rec loop i = function
4962     | [] -> ()
4963     | x :: xs -> f i x; loop (i+1) xs
4964   in
4965   loop 0 xs
4966
4967 let mapi f xs =
4968   let rec loop i = function
4969     | [] -> []
4970     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4971   in
4972   loop 0 xs
4973
4974 let count_chars c str =
4975   let count = ref 0 in
4976   for i = 0 to String.length str - 1 do
4977     if c = String.unsafe_get str i then incr count
4978   done;
4979   !count
4980
4981 let name_of_argt = function
4982   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4983   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4984   | FileIn n | FileOut n -> n
4985
4986 let java_name_of_struct typ =
4987   try List.assoc typ java_structs
4988   with Not_found ->
4989     failwithf
4990       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4991
4992 let cols_of_struct typ =
4993   try List.assoc typ structs
4994   with Not_found ->
4995     failwithf "cols_of_struct: unknown struct %s" typ
4996
4997 let seq_of_test = function
4998   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4999   | TestOutputListOfDevices (s, _)
5000   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5001   | TestOutputTrue s | TestOutputFalse s
5002   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5003   | TestOutputStruct (s, _)
5004   | TestLastFail s -> s
5005
5006 (* Handling for function flags. *)
5007 let protocol_limit_warning =
5008   "Because of the message protocol, there is a transfer limit
5009 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5010
5011 let danger_will_robinson =
5012   "B<This command is dangerous.  Without careful use you
5013 can easily destroy all your data>."
5014
5015 let deprecation_notice flags =
5016   try
5017     let alt =
5018       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5019     let txt =
5020       sprintf "This function is deprecated.
5021 In new code, use the C<%s> call instead.
5022
5023 Deprecated functions will not be removed from the API, but the
5024 fact that they are deprecated indicates that there are problems
5025 with correct use of these functions." alt in
5026     Some txt
5027   with
5028     Not_found -> None
5029
5030 (* Create list of optional groups. *)
5031 let optgroups =
5032   let h = Hashtbl.create 13 in
5033   List.iter (
5034     fun (name, _, _, flags, _, _, _) ->
5035       List.iter (
5036         function
5037         | Optional group ->
5038             let names = try Hashtbl.find h group with Not_found -> [] in
5039             Hashtbl.replace h group (name :: names)
5040         | _ -> ()
5041       ) flags
5042   ) daemon_functions;
5043   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5044   let groups =
5045     List.map (
5046       fun group -> group, List.sort compare (Hashtbl.find h group)
5047     ) groups in
5048   List.sort (fun x y -> compare (fst x) (fst y)) groups
5049
5050 (* Check function names etc. for consistency. *)
5051 let check_functions () =
5052   let contains_uppercase str =
5053     let len = String.length str in
5054     let rec loop i =
5055       if i >= len then false
5056       else (
5057         let c = str.[i] in
5058         if c >= 'A' && c <= 'Z' then true
5059         else loop (i+1)
5060       )
5061     in
5062     loop 0
5063   in
5064
5065   (* Check function names. *)
5066   List.iter (
5067     fun (name, _, _, _, _, _, _) ->
5068       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5069         failwithf "function name %s does not need 'guestfs' prefix" name;
5070       if name = "" then
5071         failwithf "function name is empty";
5072       if name.[0] < 'a' || name.[0] > 'z' then
5073         failwithf "function name %s must start with lowercase a-z" name;
5074       if String.contains name '-' then
5075         failwithf "function name %s should not contain '-', use '_' instead."
5076           name
5077   ) all_functions;
5078
5079   (* Check function parameter/return names. *)
5080   List.iter (
5081     fun (name, style, _, _, _, _, _) ->
5082       let check_arg_ret_name n =
5083         if contains_uppercase n then
5084           failwithf "%s param/ret %s should not contain uppercase chars"
5085             name n;
5086         if String.contains n '-' || String.contains n '_' then
5087           failwithf "%s param/ret %s should not contain '-' or '_'"
5088             name n;
5089         if n = "value" then
5090           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;
5091         if n = "int" || n = "char" || n = "short" || n = "long" then
5092           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5093         if n = "i" || n = "n" then
5094           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5095         if n = "argv" || n = "args" then
5096           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5097
5098         (* List Haskell, OCaml and C keywords here.
5099          * http://www.haskell.org/haskellwiki/Keywords
5100          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5101          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5102          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5103          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5104          * Omitting _-containing words, since they're handled above.
5105          * Omitting the OCaml reserved word, "val", is ok,
5106          * and saves us from renaming several parameters.
5107          *)
5108         let reserved = [
5109           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5110           "char"; "class"; "const"; "constraint"; "continue"; "data";
5111           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5112           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5113           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5114           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5115           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5116           "interface";
5117           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5118           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5119           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5120           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5121           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5122           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5123           "volatile"; "when"; "where"; "while";
5124           ] in
5125         if List.mem n reserved then
5126           failwithf "%s has param/ret using reserved word %s" name n;
5127       in
5128
5129       (match fst style with
5130        | RErr -> ()
5131        | RInt n | RInt64 n | RBool n
5132        | RConstString n | RConstOptString n | RString n
5133        | RStringList n | RStruct (n, _) | RStructList (n, _)
5134        | RHashtable n | RBufferOut n ->
5135            check_arg_ret_name n
5136       );
5137       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5138   ) all_functions;
5139
5140   (* Check short descriptions. *)
5141   List.iter (
5142     fun (name, _, _, _, _, shortdesc, _) ->
5143       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5144         failwithf "short description of %s should begin with lowercase." name;
5145       let c = shortdesc.[String.length shortdesc-1] in
5146       if c = '\n' || c = '.' then
5147         failwithf "short description of %s should not end with . or \\n." name
5148   ) all_functions;
5149
5150   (* Check long descriptions. *)
5151   List.iter (
5152     fun (name, _, _, _, _, _, longdesc) ->
5153       if longdesc.[String.length longdesc-1] = '\n' then
5154         failwithf "long description of %s should not end with \\n." name
5155   ) all_functions;
5156
5157   (* Check proc_nrs. *)
5158   List.iter (
5159     fun (name, _, proc_nr, _, _, _, _) ->
5160       if proc_nr <= 0 then
5161         failwithf "daemon function %s should have proc_nr > 0" name
5162   ) daemon_functions;
5163
5164   List.iter (
5165     fun (name, _, proc_nr, _, _, _, _) ->
5166       if proc_nr <> -1 then
5167         failwithf "non-daemon function %s should have proc_nr -1" name
5168   ) non_daemon_functions;
5169
5170   let proc_nrs =
5171     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5172       daemon_functions in
5173   let proc_nrs =
5174     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5175   let rec loop = function
5176     | [] -> ()
5177     | [_] -> ()
5178     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5179         loop rest
5180     | (name1,nr1) :: (name2,nr2) :: _ ->
5181         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5182           name1 name2 nr1 nr2
5183   in
5184   loop proc_nrs;
5185
5186   (* Check tests. *)
5187   List.iter (
5188     function
5189       (* Ignore functions that have no tests.  We generate a
5190        * warning when the user does 'make check' instead.
5191        *)
5192     | name, _, _, _, [], _, _ -> ()
5193     | name, _, _, _, tests, _, _ ->
5194         let funcs =
5195           List.map (
5196             fun (_, _, test) ->
5197               match seq_of_test test with
5198               | [] ->
5199                   failwithf "%s has a test containing an empty sequence" name
5200               | cmds -> List.map List.hd cmds
5201           ) tests in
5202         let funcs = List.flatten funcs in
5203
5204         let tested = List.mem name funcs in
5205
5206         if not tested then
5207           failwithf "function %s has tests but does not test itself" name
5208   ) all_functions
5209
5210 (* 'pr' prints to the current output file. *)
5211 let chan = ref Pervasives.stdout
5212 let lines = ref 0
5213 let pr fs =
5214   ksprintf
5215     (fun str ->
5216        let i = count_chars '\n' str in
5217        lines := !lines + i;
5218        output_string !chan str
5219     ) fs
5220
5221 let copyright_years =
5222   let this_year = 1900 + (localtime (time ())).tm_year in
5223   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5224
5225 (* Generate a header block in a number of standard styles. *)
5226 type comment_style =
5227     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5228 type license = GPLv2plus | LGPLv2plus
5229
5230 let generate_header ?(extra_inputs = []) comment license =
5231   let inputs = "src/generator.ml" :: extra_inputs in
5232   let c = match comment with
5233     | CStyle ->         pr "/* "; " *"
5234     | CPlusPlusStyle -> pr "// "; "//"
5235     | HashStyle ->      pr "# ";  "#"
5236     | OCamlStyle ->     pr "(* "; " *"
5237     | HaskellStyle ->   pr "{- "; "  " in
5238   pr "libguestfs generated file\n";
5239   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5240   List.iter (pr "%s   %s\n" c) inputs;
5241   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5242   pr "%s\n" c;
5243   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5244   pr "%s\n" c;
5245   (match license with
5246    | GPLv2plus ->
5247        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5248        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5249        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5250        pr "%s (at your option) any later version.\n" c;
5251        pr "%s\n" c;
5252        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5253        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5254        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5255        pr "%s GNU General Public License for more details.\n" c;
5256        pr "%s\n" c;
5257        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5258        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5259        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5260
5261    | LGPLv2plus ->
5262        pr "%s This library is free software; you can redistribute it and/or\n" c;
5263        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5264        pr "%s License as published by the Free Software Foundation; either\n" c;
5265        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5266        pr "%s\n" c;
5267        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5268        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5269        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5270        pr "%s Lesser General Public License for more details.\n" c;
5271        pr "%s\n" c;
5272        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5273        pr "%s License along with this library; if not, write to the Free Software\n" c;
5274        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5275   );
5276   (match comment with
5277    | CStyle -> pr " */\n"
5278    | CPlusPlusStyle
5279    | HashStyle -> ()
5280    | OCamlStyle -> pr " *)\n"
5281    | HaskellStyle -> pr "-}\n"
5282   );
5283   pr "\n"
5284
5285 (* Start of main code generation functions below this line. *)
5286
5287 (* Generate the pod documentation for the C API. *)
5288 let rec generate_actions_pod () =
5289   List.iter (
5290     fun (shortname, style, _, flags, _, _, longdesc) ->
5291       if not (List.mem NotInDocs flags) then (
5292         let name = "guestfs_" ^ shortname in
5293         pr "=head2 %s\n\n" name;
5294         pr " ";
5295         generate_prototype ~extern:false ~handle:"g" name style;
5296         pr "\n\n";
5297         pr "%s\n\n" longdesc;
5298         (match fst style with
5299          | RErr ->
5300              pr "This function returns 0 on success or -1 on error.\n\n"
5301          | RInt _ ->
5302              pr "On error this function returns -1.\n\n"
5303          | RInt64 _ ->
5304              pr "On error this function returns -1.\n\n"
5305          | RBool _ ->
5306              pr "This function returns a C truth value on success or -1 on error.\n\n"
5307          | RConstString _ ->
5308              pr "This function returns a string, or NULL on error.
5309 The string is owned by the guest handle and must I<not> be freed.\n\n"
5310          | RConstOptString _ ->
5311              pr "This function returns a string which may be NULL.
5312 There is way to return an error from this function.
5313 The string is owned by the guest handle and must I<not> be freed.\n\n"
5314          | RString _ ->
5315              pr "This function returns a string, or NULL on error.
5316 I<The caller must free the returned string after use>.\n\n"
5317          | RStringList _ ->
5318              pr "This function returns a NULL-terminated array of strings
5319 (like L<environ(3)>), or NULL if there was an error.
5320 I<The caller must free the strings and the array after use>.\n\n"
5321          | RStruct (_, typ) ->
5322              pr "This function returns a C<struct guestfs_%s *>,
5323 or NULL if there was an error.
5324 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5325          | RStructList (_, typ) ->
5326              pr "This function returns a C<struct guestfs_%s_list *>
5327 (see E<lt>guestfs-structs.hE<gt>),
5328 or NULL if there was an error.
5329 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5330          | RHashtable _ ->
5331              pr "This function returns a NULL-terminated array of
5332 strings, or NULL if there was an error.
5333 The array of strings will always have length C<2n+1>, where
5334 C<n> keys and values alternate, followed by the trailing NULL entry.
5335 I<The caller must free the strings and the array after use>.\n\n"
5336          | RBufferOut _ ->
5337              pr "This function returns a buffer, or NULL on error.
5338 The size of the returned buffer is written to C<*size_r>.
5339 I<The caller must free the returned buffer after use>.\n\n"
5340         );
5341         if List.mem ProtocolLimitWarning flags then
5342           pr "%s\n\n" protocol_limit_warning;
5343         if List.mem DangerWillRobinson flags then
5344           pr "%s\n\n" danger_will_robinson;
5345         match deprecation_notice flags with
5346         | None -> ()
5347         | Some txt -> pr "%s\n\n" txt
5348       )
5349   ) all_functions_sorted
5350
5351 and generate_structs_pod () =
5352   (* Structs documentation. *)
5353   List.iter (
5354     fun (typ, cols) ->
5355       pr "=head2 guestfs_%s\n" typ;
5356       pr "\n";
5357       pr " struct guestfs_%s {\n" typ;
5358       List.iter (
5359         function
5360         | name, FChar -> pr "   char %s;\n" name
5361         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5362         | name, FInt32 -> pr "   int32_t %s;\n" name
5363         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5364         | name, FInt64 -> pr "   int64_t %s;\n" name
5365         | name, FString -> pr "   char *%s;\n" name
5366         | name, FBuffer ->
5367             pr "   /* The next two fields describe a byte array. */\n";
5368             pr "   uint32_t %s_len;\n" name;
5369             pr "   char *%s;\n" name
5370         | name, FUUID ->
5371             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5372             pr "   char %s[32];\n" name
5373         | name, FOptPercent ->
5374             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5375             pr "   float %s;\n" name
5376       ) cols;
5377       pr " };\n";
5378       pr " \n";
5379       pr " struct guestfs_%s_list {\n" typ;
5380       pr "   uint32_t len; /* Number of elements in list. */\n";
5381       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5382       pr " };\n";
5383       pr " \n";
5384       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5385       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5386         typ typ;
5387       pr "\n"
5388   ) structs
5389
5390 and generate_availability_pod () =
5391   (* Availability documentation. *)
5392   pr "=over 4\n";
5393   pr "\n";
5394   List.iter (
5395     fun (group, functions) ->
5396       pr "=item B<%s>\n" group;
5397       pr "\n";
5398       pr "The following functions:\n";
5399       List.iter (pr "L</guestfs_%s>\n") functions;
5400       pr "\n"
5401   ) optgroups;
5402   pr "=back\n";
5403   pr "\n"
5404
5405 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5406  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5407  *
5408  * We have to use an underscore instead of a dash because otherwise
5409  * rpcgen generates incorrect code.
5410  *
5411  * This header is NOT exported to clients, but see also generate_structs_h.
5412  *)
5413 and generate_xdr () =
5414   generate_header CStyle LGPLv2plus;
5415
5416   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5417   pr "typedef string str<>;\n";
5418   pr "\n";
5419
5420   (* Internal structures. *)
5421   List.iter (
5422     function
5423     | typ, cols ->
5424         pr "struct guestfs_int_%s {\n" typ;
5425         List.iter (function
5426                    | name, FChar -> pr "  char %s;\n" name
5427                    | name, FString -> pr "  string %s<>;\n" name
5428                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5429                    | name, FUUID -> pr "  opaque %s[32];\n" name
5430                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5431                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5432                    | name, FOptPercent -> pr "  float %s;\n" name
5433                   ) cols;
5434         pr "};\n";
5435         pr "\n";
5436         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5437         pr "\n";
5438   ) structs;
5439
5440   List.iter (
5441     fun (shortname, style, _, _, _, _, _) ->
5442       let name = "guestfs_" ^ shortname in
5443
5444       (match snd style with
5445        | [] -> ()
5446        | args ->
5447            pr "struct %s_args {\n" name;
5448            List.iter (
5449              function
5450              | Pathname n | Device n | Dev_or_Path n | String n ->
5451                  pr "  string %s<>;\n" n
5452              | OptString n -> pr "  str *%s;\n" n
5453              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5454              | Bool n -> pr "  bool %s;\n" n
5455              | Int n -> pr "  int %s;\n" n
5456              | Int64 n -> pr "  hyper %s;\n" n
5457              | FileIn _ | FileOut _ -> ()
5458            ) args;
5459            pr "};\n\n"
5460       );
5461       (match fst style with
5462        | RErr -> ()
5463        | RInt n ->
5464            pr "struct %s_ret {\n" name;
5465            pr "  int %s;\n" n;
5466            pr "};\n\n"
5467        | RInt64 n ->
5468            pr "struct %s_ret {\n" name;
5469            pr "  hyper %s;\n" n;
5470            pr "};\n\n"
5471        | RBool n ->
5472            pr "struct %s_ret {\n" name;
5473            pr "  bool %s;\n" n;
5474            pr "};\n\n"
5475        | RConstString _ | RConstOptString _ ->
5476            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5477        | RString n ->
5478            pr "struct %s_ret {\n" name;
5479            pr "  string %s<>;\n" n;
5480            pr "};\n\n"
5481        | RStringList n ->
5482            pr "struct %s_ret {\n" name;
5483            pr "  str %s<>;\n" n;
5484            pr "};\n\n"
5485        | RStruct (n, typ) ->
5486            pr "struct %s_ret {\n" name;
5487            pr "  guestfs_int_%s %s;\n" typ n;
5488            pr "};\n\n"
5489        | RStructList (n, typ) ->
5490            pr "struct %s_ret {\n" name;
5491            pr "  guestfs_int_%s_list %s;\n" typ n;
5492            pr "};\n\n"
5493        | RHashtable n ->
5494            pr "struct %s_ret {\n" name;
5495            pr "  str %s<>;\n" n;
5496            pr "};\n\n"
5497        | RBufferOut n ->
5498            pr "struct %s_ret {\n" name;
5499            pr "  opaque %s<>;\n" n;
5500            pr "};\n\n"
5501       );
5502   ) daemon_functions;
5503
5504   (* Table of procedure numbers. *)
5505   pr "enum guestfs_procedure {\n";
5506   List.iter (
5507     fun (shortname, _, proc_nr, _, _, _, _) ->
5508       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5509   ) daemon_functions;
5510   pr "  GUESTFS_PROC_NR_PROCS\n";
5511   pr "};\n";
5512   pr "\n";
5513
5514   (* Having to choose a maximum message size is annoying for several
5515    * reasons (it limits what we can do in the API), but it (a) makes
5516    * the protocol a lot simpler, and (b) provides a bound on the size
5517    * of the daemon which operates in limited memory space.
5518    *)
5519   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5520   pr "\n";
5521
5522   (* Message header, etc. *)
5523   pr "\
5524 /* The communication protocol is now documented in the guestfs(3)
5525  * manpage.
5526  */
5527
5528 const GUESTFS_PROGRAM = 0x2000F5F5;
5529 const GUESTFS_PROTOCOL_VERSION = 1;
5530
5531 /* These constants must be larger than any possible message length. */
5532 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5533 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5534
5535 enum guestfs_message_direction {
5536   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5537   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5538 };
5539
5540 enum guestfs_message_status {
5541   GUESTFS_STATUS_OK = 0,
5542   GUESTFS_STATUS_ERROR = 1
5543 };
5544
5545 const GUESTFS_ERROR_LEN = 256;
5546
5547 struct guestfs_message_error {
5548   string error_message<GUESTFS_ERROR_LEN>;
5549 };
5550
5551 struct guestfs_message_header {
5552   unsigned prog;                     /* GUESTFS_PROGRAM */
5553   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5554   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5555   guestfs_message_direction direction;
5556   unsigned serial;                   /* message serial number */
5557   guestfs_message_status status;
5558 };
5559
5560 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5561
5562 struct guestfs_chunk {
5563   int cancel;                        /* if non-zero, transfer is cancelled */
5564   /* data size is 0 bytes if the transfer has finished successfully */
5565   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5566 };
5567 "
5568
5569 (* Generate the guestfs-structs.h file. *)
5570 and generate_structs_h () =
5571   generate_header CStyle LGPLv2plus;
5572
5573   (* This is a public exported header file containing various
5574    * structures.  The structures are carefully written to have
5575    * exactly the same in-memory format as the XDR structures that
5576    * we use on the wire to the daemon.  The reason for creating
5577    * copies of these structures here is just so we don't have to
5578    * export the whole of guestfs_protocol.h (which includes much
5579    * unrelated and XDR-dependent stuff that we don't want to be
5580    * public, or required by clients).
5581    *
5582    * To reiterate, we will pass these structures to and from the
5583    * client with a simple assignment or memcpy, so the format
5584    * must be identical to what rpcgen / the RFC defines.
5585    *)
5586
5587   (* Public structures. *)
5588   List.iter (
5589     fun (typ, cols) ->
5590       pr "struct guestfs_%s {\n" typ;
5591       List.iter (
5592         function
5593         | name, FChar -> pr "  char %s;\n" name
5594         | name, FString -> pr "  char *%s;\n" name
5595         | name, FBuffer ->
5596             pr "  uint32_t %s_len;\n" name;
5597             pr "  char *%s;\n" name
5598         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5599         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5600         | name, FInt32 -> pr "  int32_t %s;\n" name
5601         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5602         | name, FInt64 -> pr "  int64_t %s;\n" name
5603         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5604       ) cols;
5605       pr "};\n";
5606       pr "\n";
5607       pr "struct guestfs_%s_list {\n" typ;
5608       pr "  uint32_t len;\n";
5609       pr "  struct guestfs_%s *val;\n" typ;
5610       pr "};\n";
5611       pr "\n";
5612       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5613       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5614       pr "\n"
5615   ) structs
5616
5617 (* Generate the guestfs-actions.h file. *)
5618 and generate_actions_h () =
5619   generate_header CStyle LGPLv2plus;
5620   List.iter (
5621     fun (shortname, style, _, _, _, _, _) ->
5622       let name = "guestfs_" ^ shortname in
5623       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5624         name style
5625   ) all_functions
5626
5627 (* Generate the guestfs-internal-actions.h file. *)
5628 and generate_internal_actions_h () =
5629   generate_header CStyle LGPLv2plus;
5630   List.iter (
5631     fun (shortname, style, _, _, _, _, _) ->
5632       let name = "guestfs__" ^ shortname in
5633       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5634         name style
5635   ) non_daemon_functions
5636
5637 (* Generate the client-side dispatch stubs. *)
5638 and generate_client_actions () =
5639   generate_header CStyle LGPLv2plus;
5640
5641   pr "\
5642 #include <stdio.h>
5643 #include <stdlib.h>
5644 #include <stdint.h>
5645 #include <string.h>
5646 #include <inttypes.h>
5647
5648 #include \"guestfs.h\"
5649 #include \"guestfs-internal.h\"
5650 #include \"guestfs-internal-actions.h\"
5651 #include \"guestfs_protocol.h\"
5652
5653 #define error guestfs_error
5654 //#define perrorf guestfs_perrorf
5655 #define safe_malloc guestfs_safe_malloc
5656 #define safe_realloc guestfs_safe_realloc
5657 //#define safe_strdup guestfs_safe_strdup
5658 #define safe_memdup guestfs_safe_memdup
5659
5660 /* Check the return message from a call for validity. */
5661 static int
5662 check_reply_header (guestfs_h *g,
5663                     const struct guestfs_message_header *hdr,
5664                     unsigned int proc_nr, unsigned int serial)
5665 {
5666   if (hdr->prog != GUESTFS_PROGRAM) {
5667     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5668     return -1;
5669   }
5670   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5671     error (g, \"wrong protocol version (%%d/%%d)\",
5672            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5673     return -1;
5674   }
5675   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5676     error (g, \"unexpected message direction (%%d/%%d)\",
5677            hdr->direction, GUESTFS_DIRECTION_REPLY);
5678     return -1;
5679   }
5680   if (hdr->proc != proc_nr) {
5681     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5682     return -1;
5683   }
5684   if (hdr->serial != serial) {
5685     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5686     return -1;
5687   }
5688
5689   return 0;
5690 }
5691
5692 /* Check we are in the right state to run a high-level action. */
5693 static int
5694 check_state (guestfs_h *g, const char *caller)
5695 {
5696   if (!guestfs__is_ready (g)) {
5697     if (guestfs__is_config (g) || guestfs__is_launching (g))
5698       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5699         caller);
5700     else
5701       error (g, \"%%s called from the wrong state, %%d != READY\",
5702         caller, guestfs__get_state (g));
5703     return -1;
5704   }
5705   return 0;
5706 }
5707
5708 ";
5709
5710   (* Generate code to generate guestfish call traces. *)
5711   let trace_call shortname style =
5712     pr "  if (guestfs__get_trace (g)) {\n";
5713
5714     let needs_i =
5715       List.exists (function
5716                    | StringList _ | DeviceList _ -> true
5717                    | _ -> false) (snd style) in
5718     if needs_i then (
5719       pr "    int i;\n";
5720       pr "\n"
5721     );
5722
5723     pr "    printf (\"%s\");\n" shortname;
5724     List.iter (
5725       function
5726       | String n                        (* strings *)
5727       | Device n
5728       | Pathname n
5729       | Dev_or_Path n
5730       | FileIn n
5731       | FileOut n ->
5732           (* guestfish doesn't support string escaping, so neither do we *)
5733           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5734       | OptString n ->                  (* string option *)
5735           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5736           pr "    else printf (\" null\");\n"
5737       | StringList n
5738       | DeviceList n ->                 (* string list *)
5739           pr "    putchar (' ');\n";
5740           pr "    putchar ('\"');\n";
5741           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5742           pr "      if (i > 0) putchar (' ');\n";
5743           pr "      fputs (%s[i], stdout);\n" n;
5744           pr "    }\n";
5745           pr "    putchar ('\"');\n";
5746       | Bool n ->                       (* boolean *)
5747           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5748       | Int n ->                        (* int *)
5749           pr "    printf (\" %%d\", %s);\n" n
5750       | Int64 n ->
5751           pr "    printf (\" %%\" PRIi64, %s);\n" n
5752     ) (snd style);
5753     pr "    putchar ('\\n');\n";
5754     pr "  }\n";
5755     pr "\n";
5756   in
5757
5758   (* For non-daemon functions, generate a wrapper around each function. *)
5759   List.iter (
5760     fun (shortname, style, _, _, _, _, _) ->
5761       let name = "guestfs_" ^ shortname in
5762
5763       generate_prototype ~extern:false ~semicolon:false ~newline:true
5764         ~handle:"g" name style;
5765       pr "{\n";
5766       trace_call shortname style;
5767       pr "  return guestfs__%s " shortname;
5768       generate_c_call_args ~handle:"g" style;
5769       pr ";\n";
5770       pr "}\n";
5771       pr "\n"
5772   ) non_daemon_functions;
5773
5774   (* Client-side stubs for each function. *)
5775   List.iter (
5776     fun (shortname, style, _, _, _, _, _) ->
5777       let name = "guestfs_" ^ shortname in
5778
5779       (* Generate the action stub. *)
5780       generate_prototype ~extern:false ~semicolon:false ~newline:true
5781         ~handle:"g" name style;
5782
5783       let error_code =
5784         match fst style with
5785         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5786         | RConstString _ | RConstOptString _ ->
5787             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5788         | RString _ | RStringList _
5789         | RStruct _ | RStructList _
5790         | RHashtable _ | RBufferOut _ ->
5791             "NULL" in
5792
5793       pr "{\n";
5794
5795       (match snd style with
5796        | [] -> ()
5797        | _ -> pr "  struct %s_args args;\n" name
5798       );
5799
5800       pr "  guestfs_message_header hdr;\n";
5801       pr "  guestfs_message_error err;\n";
5802       let has_ret =
5803         match fst style with
5804         | RErr -> false
5805         | RConstString _ | RConstOptString _ ->
5806             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5807         | RInt _ | RInt64 _
5808         | RBool _ | RString _ | RStringList _
5809         | RStruct _ | RStructList _
5810         | RHashtable _ | RBufferOut _ ->
5811             pr "  struct %s_ret ret;\n" name;
5812             true in
5813
5814       pr "  int serial;\n";
5815       pr "  int r;\n";
5816       pr "\n";
5817       trace_call shortname style;
5818       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5819         shortname error_code;
5820       pr "  guestfs___set_busy (g);\n";
5821       pr "\n";
5822
5823       (* Send the main header and arguments. *)
5824       (match snd style with
5825        | [] ->
5826            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5827              (String.uppercase shortname)
5828        | args ->
5829            List.iter (
5830              function
5831              | Pathname n | Device n | Dev_or_Path n | String n ->
5832                  pr "  args.%s = (char *) %s;\n" n n
5833              | OptString n ->
5834                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5835              | StringList n | DeviceList n ->
5836                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5837                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5838              | Bool n ->
5839                  pr "  args.%s = %s;\n" n n
5840              | Int n ->
5841                  pr "  args.%s = %s;\n" n n
5842              | Int64 n ->
5843                  pr "  args.%s = %s;\n" n n
5844              | FileIn _ | FileOut _ -> ()
5845            ) args;
5846            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5847              (String.uppercase shortname);
5848            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5849              name;
5850       );
5851       pr "  if (serial == -1) {\n";
5852       pr "    guestfs___end_busy (g);\n";
5853       pr "    return %s;\n" error_code;
5854       pr "  }\n";
5855       pr "\n";
5856
5857       (* Send any additional files (FileIn) requested. *)
5858       let need_read_reply_label = ref false in
5859       List.iter (
5860         function
5861         | FileIn n ->
5862             pr "  r = guestfs___send_file (g, %s);\n" n;
5863             pr "  if (r == -1) {\n";
5864             pr "    guestfs___end_busy (g);\n";
5865             pr "    return %s;\n" error_code;
5866             pr "  }\n";
5867             pr "  if (r == -2) /* daemon cancelled */\n";
5868             pr "    goto read_reply;\n";
5869             need_read_reply_label := true;
5870             pr "\n";
5871         | _ -> ()
5872       ) (snd style);
5873
5874       (* Wait for the reply from the remote end. *)
5875       if !need_read_reply_label then pr " read_reply:\n";
5876       pr "  memset (&hdr, 0, sizeof hdr);\n";
5877       pr "  memset (&err, 0, sizeof err);\n";
5878       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5879       pr "\n";
5880       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5881       if not has_ret then
5882         pr "NULL, NULL"
5883       else
5884         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5885       pr ");\n";
5886
5887       pr "  if (r == -1) {\n";
5888       pr "    guestfs___end_busy (g);\n";
5889       pr "    return %s;\n" error_code;
5890       pr "  }\n";
5891       pr "\n";
5892
5893       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5894         (String.uppercase shortname);
5895       pr "    guestfs___end_busy (g);\n";
5896       pr "    return %s;\n" error_code;
5897       pr "  }\n";
5898       pr "\n";
5899
5900       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5901       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5902       pr "    free (err.error_message);\n";
5903       pr "    guestfs___end_busy (g);\n";
5904       pr "    return %s;\n" error_code;
5905       pr "  }\n";
5906       pr "\n";
5907
5908       (* Expecting to receive further files (FileOut)? *)
5909       List.iter (
5910         function
5911         | FileOut n ->
5912             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5913             pr "    guestfs___end_busy (g);\n";
5914             pr "    return %s;\n" error_code;
5915             pr "  }\n";
5916             pr "\n";
5917         | _ -> ()
5918       ) (snd style);
5919
5920       pr "  guestfs___end_busy (g);\n";
5921
5922       (match fst style with
5923        | RErr -> pr "  return 0;\n"
5924        | RInt n | RInt64 n | RBool n ->
5925            pr "  return ret.%s;\n" n
5926        | RConstString _ | RConstOptString _ ->
5927            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5928        | RString n ->
5929            pr "  return ret.%s; /* caller will free */\n" n
5930        | RStringList n | RHashtable n ->
5931            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5932            pr "  ret.%s.%s_val =\n" n n;
5933            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5934            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5935              n n;
5936            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5937            pr "  return ret.%s.%s_val;\n" n n
5938        | RStruct (n, _) ->
5939            pr "  /* caller will free this */\n";
5940            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5941        | RStructList (n, _) ->
5942            pr "  /* caller will free this */\n";
5943            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5944        | RBufferOut n ->
5945            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5946            pr "   * _val might be NULL here.  To make the API saner for\n";
5947            pr "   * callers, we turn this case into a unique pointer (using\n";
5948            pr "   * malloc(1)).\n";
5949            pr "   */\n";
5950            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5951            pr "    *size_r = ret.%s.%s_len;\n" n n;
5952            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5953            pr "  } else {\n";
5954            pr "    free (ret.%s.%s_val);\n" n n;
5955            pr "    char *p = safe_malloc (g, 1);\n";
5956            pr "    *size_r = ret.%s.%s_len;\n" n n;
5957            pr "    return p;\n";
5958            pr "  }\n";
5959       );
5960
5961       pr "}\n\n"
5962   ) daemon_functions;
5963
5964   (* Functions to free structures. *)
5965   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5966   pr " * structure format is identical to the XDR format.  See note in\n";
5967   pr " * generator.ml.\n";
5968   pr " */\n";
5969   pr "\n";
5970
5971   List.iter (
5972     fun (typ, _) ->
5973       pr "void\n";
5974       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5975       pr "{\n";
5976       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5977       pr "  free (x);\n";
5978       pr "}\n";
5979       pr "\n";
5980
5981       pr "void\n";
5982       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5983       pr "{\n";
5984       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5985       pr "  free (x);\n";
5986       pr "}\n";
5987       pr "\n";
5988
5989   ) structs;
5990
5991 (* Generate daemon/actions.h. *)
5992 and generate_daemon_actions_h () =
5993   generate_header CStyle GPLv2plus;
5994
5995   pr "#include \"../src/guestfs_protocol.h\"\n";
5996   pr "\n";
5997
5998   List.iter (
5999     fun (name, style, _, _, _, _, _) ->
6000       generate_prototype
6001         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6002         name style;
6003   ) daemon_functions
6004
6005 (* Generate the linker script which controls the visibility of
6006  * symbols in the public ABI and ensures no other symbols get
6007  * exported accidentally.
6008  *)
6009 and generate_linker_script () =
6010   generate_header HashStyle GPLv2plus;
6011
6012   let globals = [
6013     "guestfs_create";
6014     "guestfs_close";
6015     "guestfs_get_error_handler";
6016     "guestfs_get_out_of_memory_handler";
6017     "guestfs_last_error";
6018     "guestfs_set_error_handler";
6019     "guestfs_set_launch_done_callback";
6020     "guestfs_set_log_message_callback";
6021     "guestfs_set_out_of_memory_handler";
6022     "guestfs_set_subprocess_quit_callback";
6023
6024     (* Unofficial parts of the API: the bindings code use these
6025      * functions, so it is useful to export them.
6026      *)
6027     "guestfs_safe_calloc";
6028     "guestfs_safe_malloc";
6029   ] in
6030   let functions =
6031     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6032       all_functions in
6033   let structs =
6034     List.concat (
6035       List.map (fun (typ, _) ->
6036                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6037         structs
6038     ) in
6039   let globals = List.sort compare (globals @ functions @ structs) in
6040
6041   pr "{\n";
6042   pr "    global:\n";
6043   List.iter (pr "        %s;\n") globals;
6044   pr "\n";
6045
6046   pr "    local:\n";
6047   pr "        *;\n";
6048   pr "};\n"
6049
6050 (* Generate the server-side stubs. *)
6051 and generate_daemon_actions () =
6052   generate_header CStyle GPLv2plus;
6053
6054   pr "#include <config.h>\n";
6055   pr "\n";
6056   pr "#include <stdio.h>\n";
6057   pr "#include <stdlib.h>\n";
6058   pr "#include <string.h>\n";
6059   pr "#include <inttypes.h>\n";
6060   pr "#include <rpc/types.h>\n";
6061   pr "#include <rpc/xdr.h>\n";
6062   pr "\n";
6063   pr "#include \"daemon.h\"\n";
6064   pr "#include \"c-ctype.h\"\n";
6065   pr "#include \"../src/guestfs_protocol.h\"\n";
6066   pr "#include \"actions.h\"\n";
6067   pr "\n";
6068
6069   List.iter (
6070     fun (name, style, _, _, _, _, _) ->
6071       (* Generate server-side stubs. *)
6072       pr "static void %s_stub (XDR *xdr_in)\n" name;
6073       pr "{\n";
6074       let error_code =
6075         match fst style with
6076         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6077         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6078         | RBool _ -> pr "  int r;\n"; "-1"
6079         | RConstString _ | RConstOptString _ ->
6080             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6081         | RString _ -> pr "  char *r;\n"; "NULL"
6082         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6083         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6084         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6085         | RBufferOut _ ->
6086             pr "  size_t size = 1;\n";
6087             pr "  char *r;\n";
6088             "NULL" in
6089
6090       (match snd style with
6091        | [] -> ()
6092        | args ->
6093            pr "  struct guestfs_%s_args args;\n" name;
6094            List.iter (
6095              function
6096              | Device n | Dev_or_Path n
6097              | Pathname n
6098              | String n -> ()
6099              | OptString n -> pr "  char *%s;\n" n
6100              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6101              | Bool n -> pr "  int %s;\n" n
6102              | Int n -> pr "  int %s;\n" n
6103              | Int64 n -> pr "  int64_t %s;\n" n
6104              | FileIn _ | FileOut _ -> ()
6105            ) args
6106       );
6107       pr "\n";
6108
6109       let is_filein =
6110         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6111
6112       (match snd style with
6113        | [] -> ()
6114        | args ->
6115            pr "  memset (&args, 0, sizeof args);\n";
6116            pr "\n";
6117            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6118            if is_filein then
6119              pr "    cancel_receive ();\n";
6120            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6121            pr "    goto done;\n";
6122            pr "  }\n";
6123            let pr_args n =
6124              pr "  char *%s = args.%s;\n" n n
6125            in
6126            let pr_list_handling_code n =
6127              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6128              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6129              pr "  if (%s == NULL) {\n" n;
6130              if is_filein then
6131                pr "    cancel_receive ();\n";
6132              pr "    reply_with_perror (\"realloc\");\n";
6133              pr "    goto done;\n";
6134              pr "  }\n";
6135              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6136              pr "  args.%s.%s_val = %s;\n" n n n;
6137            in
6138            List.iter (
6139              function
6140              | Pathname n ->
6141                  pr_args n;
6142                  pr "  ABS_PATH (%s, %s, goto done);\n"
6143                    n (if is_filein then "cancel_receive ()" else "");
6144              | Device n ->
6145                  pr_args n;
6146                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6147                    n (if is_filein then "cancel_receive ()" else "");
6148              | Dev_or_Path n ->
6149                  pr_args n;
6150                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6151                    n (if is_filein then "cancel_receive ()" else "");
6152              | String n -> pr_args n
6153              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6154              | StringList n ->
6155                  pr_list_handling_code n;
6156              | DeviceList n ->
6157                  pr_list_handling_code n;
6158                  pr "  /* Ensure that each is a device,\n";
6159                  pr "   * and perform device name translation. */\n";
6160                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6161                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6162                    (if is_filein then "cancel_receive ()" else "");
6163                  pr "  }\n";
6164              | Bool n -> pr "  %s = args.%s;\n" n n
6165              | Int n -> pr "  %s = args.%s;\n" n n
6166              | Int64 n -> pr "  %s = args.%s;\n" n n
6167              | FileIn _ | FileOut _ -> ()
6168            ) args;
6169            pr "\n"
6170       );
6171
6172
6173       (* this is used at least for do_equal *)
6174       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6175         (* Emit NEED_ROOT just once, even when there are two or
6176            more Pathname args *)
6177         pr "  NEED_ROOT (%s, goto done);\n"
6178           (if is_filein then "cancel_receive ()" else "");
6179       );
6180
6181       (* Don't want to call the impl with any FileIn or FileOut
6182        * parameters, since these go "outside" the RPC protocol.
6183        *)
6184       let args' =
6185         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6186           (snd style) in
6187       pr "  r = do_%s " name;
6188       generate_c_call_args (fst style, args');
6189       pr ";\n";
6190
6191       (match fst style with
6192        | RErr | RInt _ | RInt64 _ | RBool _
6193        | RConstString _ | RConstOptString _
6194        | RString _ | RStringList _ | RHashtable _
6195        | RStruct (_, _) | RStructList (_, _) ->
6196            pr "  if (r == %s)\n" error_code;
6197            pr "    /* do_%s has already called reply_with_error */\n" name;
6198            pr "    goto done;\n";
6199            pr "\n"
6200        | RBufferOut _ ->
6201            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6202            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6203            pr "   */\n";
6204            pr "  if (size == 1 && r == %s)\n" error_code;
6205            pr "    /* do_%s has already called reply_with_error */\n" name;
6206            pr "    goto done;\n";
6207            pr "\n"
6208       );
6209
6210       (* If there are any FileOut parameters, then the impl must
6211        * send its own reply.
6212        *)
6213       let no_reply =
6214         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6215       if no_reply then
6216         pr "  /* do_%s has already sent a reply */\n" name
6217       else (
6218         match fst style with
6219         | RErr -> pr "  reply (NULL, NULL);\n"
6220         | RInt n | RInt64 n | RBool n ->
6221             pr "  struct guestfs_%s_ret ret;\n" name;
6222             pr "  ret.%s = r;\n" n;
6223             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6224               name
6225         | RConstString _ | RConstOptString _ ->
6226             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6227         | RString n ->
6228             pr "  struct guestfs_%s_ret ret;\n" name;
6229             pr "  ret.%s = r;\n" n;
6230             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6231               name;
6232             pr "  free (r);\n"
6233         | RStringList n | RHashtable n ->
6234             pr "  struct guestfs_%s_ret ret;\n" name;
6235             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6236             pr "  ret.%s.%s_val = r;\n" n n;
6237             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6238               name;
6239             pr "  free_strings (r);\n"
6240         | RStruct (n, _) ->
6241             pr "  struct guestfs_%s_ret ret;\n" name;
6242             pr "  ret.%s = *r;\n" n;
6243             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6244               name;
6245             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6246               name
6247         | RStructList (n, _) ->
6248             pr "  struct guestfs_%s_ret ret;\n" name;
6249             pr "  ret.%s = *r;\n" n;
6250             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6251               name;
6252             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6253               name
6254         | RBufferOut n ->
6255             pr "  struct guestfs_%s_ret ret;\n" name;
6256             pr "  ret.%s.%s_val = r;\n" n n;
6257             pr "  ret.%s.%s_len = size;\n" n n;
6258             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6259               name;
6260             pr "  free (r);\n"
6261       );
6262
6263       (* Free the args. *)
6264       pr "done:\n";
6265       (match snd style with
6266        | [] -> ()
6267        | _ ->
6268            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6269              name
6270       );
6271       pr "  return;\n";
6272       pr "}\n\n";
6273   ) daemon_functions;
6274
6275   (* Dispatch function. *)
6276   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6277   pr "{\n";
6278   pr "  switch (proc_nr) {\n";
6279
6280   List.iter (
6281     fun (name, style, _, _, _, _, _) ->
6282       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6283       pr "      %s_stub (xdr_in);\n" name;
6284       pr "      break;\n"
6285   ) daemon_functions;
6286
6287   pr "    default:\n";
6288   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";
6289   pr "  }\n";
6290   pr "}\n";
6291   pr "\n";
6292
6293   (* LVM columns and tokenization functions. *)
6294   (* XXX This generates crap code.  We should rethink how we
6295    * do this parsing.
6296    *)
6297   List.iter (
6298     function
6299     | typ, cols ->
6300         pr "static const char *lvm_%s_cols = \"%s\";\n"
6301           typ (String.concat "," (List.map fst cols));
6302         pr "\n";
6303
6304         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6305         pr "{\n";
6306         pr "  char *tok, *p, *next;\n";
6307         pr "  int i, j;\n";
6308         pr "\n";
6309         (*
6310           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6311           pr "\n";
6312         *)
6313         pr "  if (!str) {\n";
6314         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6315         pr "    return -1;\n";
6316         pr "  }\n";
6317         pr "  if (!*str || c_isspace (*str)) {\n";
6318         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6319         pr "    return -1;\n";
6320         pr "  }\n";
6321         pr "  tok = str;\n";
6322         List.iter (
6323           fun (name, coltype) ->
6324             pr "  if (!tok) {\n";
6325             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6326             pr "    return -1;\n";
6327             pr "  }\n";
6328             pr "  p = strchrnul (tok, ',');\n";
6329             pr "  if (*p) next = p+1; else next = NULL;\n";
6330             pr "  *p = '\\0';\n";
6331             (match coltype with
6332              | FString ->
6333                  pr "  r->%s = strdup (tok);\n" name;
6334                  pr "  if (r->%s == NULL) {\n" name;
6335                  pr "    perror (\"strdup\");\n";
6336                  pr "    return -1;\n";
6337                  pr "  }\n"
6338              | FUUID ->
6339                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6340                  pr "    if (tok[j] == '\\0') {\n";
6341                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6342                  pr "      return -1;\n";
6343                  pr "    } else if (tok[j] != '-')\n";
6344                  pr "      r->%s[i++] = tok[j];\n" name;
6345                  pr "  }\n";
6346              | FBytes ->
6347                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6348                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6349                  pr "    return -1;\n";
6350                  pr "  }\n";
6351              | FInt64 ->
6352                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6353                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6354                  pr "    return -1;\n";
6355                  pr "  }\n";
6356              | FOptPercent ->
6357                  pr "  if (tok[0] == '\\0')\n";
6358                  pr "    r->%s = -1;\n" name;
6359                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6360                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6361                  pr "    return -1;\n";
6362                  pr "  }\n";
6363              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6364                  assert false (* can never be an LVM column *)
6365             );
6366             pr "  tok = next;\n";
6367         ) cols;
6368
6369         pr "  if (tok != NULL) {\n";
6370         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6371         pr "    return -1;\n";
6372         pr "  }\n";
6373         pr "  return 0;\n";
6374         pr "}\n";
6375         pr "\n";
6376
6377         pr "guestfs_int_lvm_%s_list *\n" typ;
6378         pr "parse_command_line_%ss (void)\n" typ;
6379         pr "{\n";
6380         pr "  char *out, *err;\n";
6381         pr "  char *p, *pend;\n";
6382         pr "  int r, i;\n";
6383         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6384         pr "  void *newp;\n";
6385         pr "\n";
6386         pr "  ret = malloc (sizeof *ret);\n";
6387         pr "  if (!ret) {\n";
6388         pr "    reply_with_perror (\"malloc\");\n";
6389         pr "    return NULL;\n";
6390         pr "  }\n";
6391         pr "\n";
6392         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6393         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6394         pr "\n";
6395         pr "  r = command (&out, &err,\n";
6396         pr "           \"lvm\", \"%ss\",\n" typ;
6397         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6398         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6399         pr "  if (r == -1) {\n";
6400         pr "    reply_with_error (\"%%s\", err);\n";
6401         pr "    free (out);\n";
6402         pr "    free (err);\n";
6403         pr "    free (ret);\n";
6404         pr "    return NULL;\n";
6405         pr "  }\n";
6406         pr "\n";
6407         pr "  free (err);\n";
6408         pr "\n";
6409         pr "  /* Tokenize each line of the output. */\n";
6410         pr "  p = out;\n";
6411         pr "  i = 0;\n";
6412         pr "  while (p) {\n";
6413         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6414         pr "    if (pend) {\n";
6415         pr "      *pend = '\\0';\n";
6416         pr "      pend++;\n";
6417         pr "    }\n";
6418         pr "\n";
6419         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6420         pr "      p++;\n";
6421         pr "\n";
6422         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6423         pr "      p = pend;\n";
6424         pr "      continue;\n";
6425         pr "    }\n";
6426         pr "\n";
6427         pr "    /* Allocate some space to store this next entry. */\n";
6428         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6429         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6430         pr "    if (newp == NULL) {\n";
6431         pr "      reply_with_perror (\"realloc\");\n";
6432         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6433         pr "      free (ret);\n";
6434         pr "      free (out);\n";
6435         pr "      return NULL;\n";
6436         pr "    }\n";
6437         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6438         pr "\n";
6439         pr "    /* Tokenize the next entry. */\n";
6440         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6441         pr "    if (r == -1) {\n";
6442         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6443         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6444         pr "      free (ret);\n";
6445         pr "      free (out);\n";
6446         pr "      return NULL;\n";
6447         pr "    }\n";
6448         pr "\n";
6449         pr "    ++i;\n";
6450         pr "    p = pend;\n";
6451         pr "  }\n";
6452         pr "\n";
6453         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6454         pr "\n";
6455         pr "  free (out);\n";
6456         pr "  return ret;\n";
6457         pr "}\n"
6458
6459   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6460
6461 (* Generate a list of function names, for debugging in the daemon.. *)
6462 and generate_daemon_names () =
6463   generate_header CStyle GPLv2plus;
6464
6465   pr "#include <config.h>\n";
6466   pr "\n";
6467   pr "#include \"daemon.h\"\n";
6468   pr "\n";
6469
6470   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6471   pr "const char *function_names[] = {\n";
6472   List.iter (
6473     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6474   ) daemon_functions;
6475   pr "};\n";
6476
6477 (* Generate the optional groups for the daemon to implement
6478  * guestfs_available.
6479  *)
6480 and generate_daemon_optgroups_c () =
6481   generate_header CStyle GPLv2plus;
6482
6483   pr "#include <config.h>\n";
6484   pr "\n";
6485   pr "#include \"daemon.h\"\n";
6486   pr "#include \"optgroups.h\"\n";
6487   pr "\n";
6488
6489   pr "struct optgroup optgroups[] = {\n";
6490   List.iter (
6491     fun (group, _) ->
6492       pr "  { \"%s\", optgroup_%s_available },\n" group group
6493   ) optgroups;
6494   pr "  { NULL, NULL }\n";
6495   pr "};\n"
6496
6497 and generate_daemon_optgroups_h () =
6498   generate_header CStyle GPLv2plus;
6499
6500   List.iter (
6501     fun (group, _) ->
6502       pr "extern int optgroup_%s_available (void);\n" group
6503   ) optgroups
6504
6505 (* Generate the tests. *)
6506 and generate_tests () =
6507   generate_header CStyle GPLv2plus;
6508
6509   pr "\
6510 #include <stdio.h>
6511 #include <stdlib.h>
6512 #include <string.h>
6513 #include <unistd.h>
6514 #include <sys/types.h>
6515 #include <fcntl.h>
6516
6517 #include \"guestfs.h\"
6518 #include \"guestfs-internal.h\"
6519
6520 static guestfs_h *g;
6521 static int suppress_error = 0;
6522
6523 static void print_error (guestfs_h *g, void *data, const char *msg)
6524 {
6525   if (!suppress_error)
6526     fprintf (stderr, \"%%s\\n\", msg);
6527 }
6528
6529 /* FIXME: nearly identical code appears in fish.c */
6530 static void print_strings (char *const *argv)
6531 {
6532   int argc;
6533
6534   for (argc = 0; argv[argc] != NULL; ++argc)
6535     printf (\"\\t%%s\\n\", argv[argc]);
6536 }
6537
6538 /*
6539 static void print_table (char const *const *argv)
6540 {
6541   int i;
6542
6543   for (i = 0; argv[i] != NULL; i += 2)
6544     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6545 }
6546 */
6547
6548 ";
6549
6550   (* Generate a list of commands which are not tested anywhere. *)
6551   pr "static void no_test_warnings (void)\n";
6552   pr "{\n";
6553
6554   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6555   List.iter (
6556     fun (_, _, _, _, tests, _, _) ->
6557       let tests = filter_map (
6558         function
6559         | (_, (Always|If _|Unless _), test) -> Some test
6560         | (_, Disabled, _) -> None
6561       ) tests in
6562       let seq = List.concat (List.map seq_of_test tests) in
6563       let cmds_tested = List.map List.hd seq in
6564       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6565   ) all_functions;
6566
6567   List.iter (
6568     fun (name, _, _, _, _, _, _) ->
6569       if not (Hashtbl.mem hash name) then
6570         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6571   ) all_functions;
6572
6573   pr "}\n";
6574   pr "\n";
6575
6576   (* Generate the actual tests.  Note that we generate the tests
6577    * in reverse order, deliberately, so that (in general) the
6578    * newest tests run first.  This makes it quicker and easier to
6579    * debug them.
6580    *)
6581   let test_names =
6582     List.map (
6583       fun (name, _, _, flags, tests, _, _) ->
6584         mapi (generate_one_test name flags) tests
6585     ) (List.rev all_functions) in
6586   let test_names = List.concat test_names in
6587   let nr_tests = List.length test_names in
6588
6589   pr "\
6590 int main (int argc, char *argv[])
6591 {
6592   char c = 0;
6593   unsigned long int n_failed = 0;
6594   const char *filename;
6595   int fd;
6596   int nr_tests, test_num = 0;
6597
6598   setbuf (stdout, NULL);
6599
6600   no_test_warnings ();
6601
6602   g = guestfs_create ();
6603   if (g == NULL) {
6604     printf (\"guestfs_create FAILED\\n\");
6605     exit (EXIT_FAILURE);
6606   }
6607
6608   guestfs_set_error_handler (g, print_error, NULL);
6609
6610   guestfs_set_path (g, \"../appliance\");
6611
6612   filename = \"test1.img\";
6613   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6614   if (fd == -1) {
6615     perror (filename);
6616     exit (EXIT_FAILURE);
6617   }
6618   if (lseek (fd, %d, SEEK_SET) == -1) {
6619     perror (\"lseek\");
6620     close (fd);
6621     unlink (filename);
6622     exit (EXIT_FAILURE);
6623   }
6624   if (write (fd, &c, 1) == -1) {
6625     perror (\"write\");
6626     close (fd);
6627     unlink (filename);
6628     exit (EXIT_FAILURE);
6629   }
6630   if (close (fd) == -1) {
6631     perror (filename);
6632     unlink (filename);
6633     exit (EXIT_FAILURE);
6634   }
6635   if (guestfs_add_drive (g, filename) == -1) {
6636     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6637     exit (EXIT_FAILURE);
6638   }
6639
6640   filename = \"test2.img\";
6641   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6642   if (fd == -1) {
6643     perror (filename);
6644     exit (EXIT_FAILURE);
6645   }
6646   if (lseek (fd, %d, SEEK_SET) == -1) {
6647     perror (\"lseek\");
6648     close (fd);
6649     unlink (filename);
6650     exit (EXIT_FAILURE);
6651   }
6652   if (write (fd, &c, 1) == -1) {
6653     perror (\"write\");
6654     close (fd);
6655     unlink (filename);
6656     exit (EXIT_FAILURE);
6657   }
6658   if (close (fd) == -1) {
6659     perror (filename);
6660     unlink (filename);
6661     exit (EXIT_FAILURE);
6662   }
6663   if (guestfs_add_drive (g, filename) == -1) {
6664     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6665     exit (EXIT_FAILURE);
6666   }
6667
6668   filename = \"test3.img\";
6669   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6670   if (fd == -1) {
6671     perror (filename);
6672     exit (EXIT_FAILURE);
6673   }
6674   if (lseek (fd, %d, SEEK_SET) == -1) {
6675     perror (\"lseek\");
6676     close (fd);
6677     unlink (filename);
6678     exit (EXIT_FAILURE);
6679   }
6680   if (write (fd, &c, 1) == -1) {
6681     perror (\"write\");
6682     close (fd);
6683     unlink (filename);
6684     exit (EXIT_FAILURE);
6685   }
6686   if (close (fd) == -1) {
6687     perror (filename);
6688     unlink (filename);
6689     exit (EXIT_FAILURE);
6690   }
6691   if (guestfs_add_drive (g, filename) == -1) {
6692     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6693     exit (EXIT_FAILURE);
6694   }
6695
6696   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6697     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6698     exit (EXIT_FAILURE);
6699   }
6700
6701   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6702   alarm (600);
6703
6704   if (guestfs_launch (g) == -1) {
6705     printf (\"guestfs_launch FAILED\\n\");
6706     exit (EXIT_FAILURE);
6707   }
6708
6709   /* Cancel previous alarm. */
6710   alarm (0);
6711
6712   nr_tests = %d;
6713
6714 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6715
6716   iteri (
6717     fun i test_name ->
6718       pr "  test_num++;\n";
6719       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6720       pr "  if (%s () == -1) {\n" test_name;
6721       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6722       pr "    n_failed++;\n";
6723       pr "  }\n";
6724   ) test_names;
6725   pr "\n";
6726
6727   pr "  guestfs_close (g);\n";
6728   pr "  unlink (\"test1.img\");\n";
6729   pr "  unlink (\"test2.img\");\n";
6730   pr "  unlink (\"test3.img\");\n";
6731   pr "\n";
6732
6733   pr "  if (n_failed > 0) {\n";
6734   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6735   pr "    exit (EXIT_FAILURE);\n";
6736   pr "  }\n";
6737   pr "\n";
6738
6739   pr "  exit (EXIT_SUCCESS);\n";
6740   pr "}\n"
6741
6742 and generate_one_test name flags i (init, prereq, test) =
6743   let test_name = sprintf "test_%s_%d" name i in
6744
6745   pr "\
6746 static int %s_skip (void)
6747 {
6748   const char *str;
6749
6750   str = getenv (\"TEST_ONLY\");
6751   if (str)
6752     return strstr (str, \"%s\") == NULL;
6753   str = getenv (\"SKIP_%s\");
6754   if (str && STREQ (str, \"1\")) return 1;
6755   str = getenv (\"SKIP_TEST_%s\");
6756   if (str && STREQ (str, \"1\")) return 1;
6757   return 0;
6758 }
6759
6760 " test_name name (String.uppercase test_name) (String.uppercase name);
6761
6762   (match prereq with
6763    | Disabled | Always -> ()
6764    | If code | Unless code ->
6765        pr "static int %s_prereq (void)\n" test_name;
6766        pr "{\n";
6767        pr "  %s\n" code;
6768        pr "}\n";
6769        pr "\n";
6770   );
6771
6772   pr "\
6773 static int %s (void)
6774 {
6775   if (%s_skip ()) {
6776     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6777     return 0;
6778   }
6779
6780 " test_name test_name test_name;
6781
6782   (* Optional functions should only be tested if the relevant
6783    * support is available in the daemon.
6784    *)
6785   List.iter (
6786     function
6787     | Optional group ->
6788         pr "  {\n";
6789         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6790         pr "    int r;\n";
6791         pr "    suppress_error = 1;\n";
6792         pr "    r = guestfs_available (g, (char **) groups);\n";
6793         pr "    suppress_error = 0;\n";
6794         pr "    if (r == -1) {\n";
6795         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6796         pr "      return 0;\n";
6797         pr "    }\n";
6798         pr "  }\n";
6799     | _ -> ()
6800   ) flags;
6801
6802   (match prereq with
6803    | Disabled ->
6804        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6805    | If _ ->
6806        pr "  if (! %s_prereq ()) {\n" test_name;
6807        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6808        pr "    return 0;\n";
6809        pr "  }\n";
6810        pr "\n";
6811        generate_one_test_body name i test_name init test;
6812    | Unless _ ->
6813        pr "  if (%s_prereq ()) {\n" test_name;
6814        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6815        pr "    return 0;\n";
6816        pr "  }\n";
6817        pr "\n";
6818        generate_one_test_body name i test_name init test;
6819    | Always ->
6820        generate_one_test_body name i test_name init test
6821   );
6822
6823   pr "  return 0;\n";
6824   pr "}\n";
6825   pr "\n";
6826   test_name
6827
6828 and generate_one_test_body name i test_name init test =
6829   (match init with
6830    | InitNone (* XXX at some point, InitNone and InitEmpty became
6831                * folded together as the same thing.  Really we should
6832                * make InitNone do nothing at all, but the tests may
6833                * need to be checked to make sure this is OK.
6834                *)
6835    | InitEmpty ->
6836        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6837        List.iter (generate_test_command_call test_name)
6838          [["blockdev_setrw"; "/dev/sda"];
6839           ["umount_all"];
6840           ["lvm_remove_all"]]
6841    | InitPartition ->
6842        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6843        List.iter (generate_test_command_call test_name)
6844          [["blockdev_setrw"; "/dev/sda"];
6845           ["umount_all"];
6846           ["lvm_remove_all"];
6847           ["part_disk"; "/dev/sda"; "mbr"]]
6848    | InitBasicFS ->
6849        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6850        List.iter (generate_test_command_call test_name)
6851          [["blockdev_setrw"; "/dev/sda"];
6852           ["umount_all"];
6853           ["lvm_remove_all"];
6854           ["part_disk"; "/dev/sda"; "mbr"];
6855           ["mkfs"; "ext2"; "/dev/sda1"];
6856           ["mount_options"; ""; "/dev/sda1"; "/"]]
6857    | InitBasicFSonLVM ->
6858        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6859          test_name;
6860        List.iter (generate_test_command_call test_name)
6861          [["blockdev_setrw"; "/dev/sda"];
6862           ["umount_all"];
6863           ["lvm_remove_all"];
6864           ["part_disk"; "/dev/sda"; "mbr"];
6865           ["pvcreate"; "/dev/sda1"];
6866           ["vgcreate"; "VG"; "/dev/sda1"];
6867           ["lvcreate"; "LV"; "VG"; "8"];
6868           ["mkfs"; "ext2"; "/dev/VG/LV"];
6869           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6870    | InitISOFS ->
6871        pr "  /* InitISOFS for %s */\n" test_name;
6872        List.iter (generate_test_command_call test_name)
6873          [["blockdev_setrw"; "/dev/sda"];
6874           ["umount_all"];
6875           ["lvm_remove_all"];
6876           ["mount_ro"; "/dev/sdd"; "/"]]
6877   );
6878
6879   let get_seq_last = function
6880     | [] ->
6881         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6882           test_name
6883     | seq ->
6884         let seq = List.rev seq in
6885         List.rev (List.tl seq), List.hd seq
6886   in
6887
6888   match test with
6889   | TestRun seq ->
6890       pr "  /* TestRun for %s (%d) */\n" name i;
6891       List.iter (generate_test_command_call test_name) seq
6892   | TestOutput (seq, expected) ->
6893       pr "  /* TestOutput for %s (%d) */\n" name i;
6894       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6895       let seq, last = get_seq_last seq in
6896       let test () =
6897         pr "    if (STRNEQ (r, expected)) {\n";
6898         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6899         pr "      return -1;\n";
6900         pr "    }\n"
6901       in
6902       List.iter (generate_test_command_call test_name) seq;
6903       generate_test_command_call ~test test_name last
6904   | TestOutputList (seq, expected) ->
6905       pr "  /* TestOutputList for %s (%d) */\n" name i;
6906       let seq, last = get_seq_last seq in
6907       let test () =
6908         iteri (
6909           fun i str ->
6910             pr "    if (!r[%d]) {\n" i;
6911             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6912             pr "      print_strings (r);\n";
6913             pr "      return -1;\n";
6914             pr "    }\n";
6915             pr "    {\n";
6916             pr "      const char *expected = \"%s\";\n" (c_quote str);
6917             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6918             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6919             pr "        return -1;\n";
6920             pr "      }\n";
6921             pr "    }\n"
6922         ) expected;
6923         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6924         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6925           test_name;
6926         pr "      print_strings (r);\n";
6927         pr "      return -1;\n";
6928         pr "    }\n"
6929       in
6930       List.iter (generate_test_command_call test_name) seq;
6931       generate_test_command_call ~test test_name last
6932   | TestOutputListOfDevices (seq, expected) ->
6933       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6934       let seq, last = get_seq_last seq in
6935       let test () =
6936         iteri (
6937           fun i str ->
6938             pr "    if (!r[%d]) {\n" i;
6939             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6940             pr "      print_strings (r);\n";
6941             pr "      return -1;\n";
6942             pr "    }\n";
6943             pr "    {\n";
6944             pr "      const char *expected = \"%s\";\n" (c_quote str);
6945             pr "      r[%d][5] = 's';\n" i;
6946             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6947             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6948             pr "        return -1;\n";
6949             pr "      }\n";
6950             pr "    }\n"
6951         ) expected;
6952         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6953         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6954           test_name;
6955         pr "      print_strings (r);\n";
6956         pr "      return -1;\n";
6957         pr "    }\n"
6958       in
6959       List.iter (generate_test_command_call test_name) seq;
6960       generate_test_command_call ~test test_name last
6961   | TestOutputInt (seq, expected) ->
6962       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6963       let seq, last = get_seq_last seq in
6964       let test () =
6965         pr "    if (r != %d) {\n" expected;
6966         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6967           test_name expected;
6968         pr "               (int) r);\n";
6969         pr "      return -1;\n";
6970         pr "    }\n"
6971       in
6972       List.iter (generate_test_command_call test_name) seq;
6973       generate_test_command_call ~test test_name last
6974   | TestOutputIntOp (seq, op, expected) ->
6975       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6976       let seq, last = get_seq_last seq in
6977       let test () =
6978         pr "    if (! (r %s %d)) {\n" op expected;
6979         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6980           test_name op expected;
6981         pr "               (int) r);\n";
6982         pr "      return -1;\n";
6983         pr "    }\n"
6984       in
6985       List.iter (generate_test_command_call test_name) seq;
6986       generate_test_command_call ~test test_name last
6987   | TestOutputTrue seq ->
6988       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6989       let seq, last = get_seq_last seq in
6990       let test () =
6991         pr "    if (!r) {\n";
6992         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6993           test_name;
6994         pr "      return -1;\n";
6995         pr "    }\n"
6996       in
6997       List.iter (generate_test_command_call test_name) seq;
6998       generate_test_command_call ~test test_name last
6999   | TestOutputFalse seq ->
7000       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7001       let seq, last = get_seq_last seq in
7002       let test () =
7003         pr "    if (r) {\n";
7004         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7005           test_name;
7006         pr "      return -1;\n";
7007         pr "    }\n"
7008       in
7009       List.iter (generate_test_command_call test_name) seq;
7010       generate_test_command_call ~test test_name last
7011   | TestOutputLength (seq, expected) ->
7012       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7013       let seq, last = get_seq_last seq in
7014       let test () =
7015         pr "    int j;\n";
7016         pr "    for (j = 0; j < %d; ++j)\n" expected;
7017         pr "      if (r[j] == NULL) {\n";
7018         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7019           test_name;
7020         pr "        print_strings (r);\n";
7021         pr "        return -1;\n";
7022         pr "      }\n";
7023         pr "    if (r[j] != NULL) {\n";
7024         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7025           test_name;
7026         pr "      print_strings (r);\n";
7027         pr "      return -1;\n";
7028         pr "    }\n"
7029       in
7030       List.iter (generate_test_command_call test_name) seq;
7031       generate_test_command_call ~test test_name last
7032   | TestOutputBuffer (seq, expected) ->
7033       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7034       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7035       let seq, last = get_seq_last seq in
7036       let len = String.length expected in
7037       let test () =
7038         pr "    if (size != %d) {\n" len;
7039         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7040         pr "      return -1;\n";
7041         pr "    }\n";
7042         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7043         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7044         pr "      return -1;\n";
7045         pr "    }\n"
7046       in
7047       List.iter (generate_test_command_call test_name) seq;
7048       generate_test_command_call ~test test_name last
7049   | TestOutputStruct (seq, checks) ->
7050       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7051       let seq, last = get_seq_last seq in
7052       let test () =
7053         List.iter (
7054           function
7055           | CompareWithInt (field, expected) ->
7056               pr "    if (r->%s != %d) {\n" field expected;
7057               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7058                 test_name field expected;
7059               pr "               (int) r->%s);\n" field;
7060               pr "      return -1;\n";
7061               pr "    }\n"
7062           | CompareWithIntOp (field, op, expected) ->
7063               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7064               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7065                 test_name field op expected;
7066               pr "               (int) r->%s);\n" field;
7067               pr "      return -1;\n";
7068               pr "    }\n"
7069           | CompareWithString (field, expected) ->
7070               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7071               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7072                 test_name field expected;
7073               pr "               r->%s);\n" field;
7074               pr "      return -1;\n";
7075               pr "    }\n"
7076           | CompareFieldsIntEq (field1, field2) ->
7077               pr "    if (r->%s != r->%s) {\n" field1 field2;
7078               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7079                 test_name field1 field2;
7080               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7081               pr "      return -1;\n";
7082               pr "    }\n"
7083           | CompareFieldsStrEq (field1, field2) ->
7084               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7085               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7086                 test_name field1 field2;
7087               pr "               r->%s, r->%s);\n" field1 field2;
7088               pr "      return -1;\n";
7089               pr "    }\n"
7090         ) checks
7091       in
7092       List.iter (generate_test_command_call test_name) seq;
7093       generate_test_command_call ~test test_name last
7094   | TestLastFail seq ->
7095       pr "  /* TestLastFail for %s (%d) */\n" name i;
7096       let seq, last = get_seq_last seq in
7097       List.iter (generate_test_command_call test_name) seq;
7098       generate_test_command_call test_name ~expect_error:true last
7099
7100 (* Generate the code to run a command, leaving the result in 'r'.
7101  * If you expect to get an error then you should set expect_error:true.
7102  *)
7103 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7104   match cmd with
7105   | [] -> assert false
7106   | name :: args ->
7107       (* Look up the command to find out what args/ret it has. *)
7108       let style =
7109         try
7110           let _, style, _, _, _, _, _ =
7111             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7112           style
7113         with Not_found ->
7114           failwithf "%s: in test, command %s was not found" test_name name in
7115
7116       if List.length (snd style) <> List.length args then
7117         failwithf "%s: in test, wrong number of args given to %s"
7118           test_name name;
7119
7120       pr "  {\n";
7121
7122       List.iter (
7123         function
7124         | OptString n, "NULL" -> ()
7125         | Pathname n, arg
7126         | Device n, arg
7127         | Dev_or_Path n, arg
7128         | String n, arg
7129         | OptString n, arg ->
7130             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7131         | Int _, _
7132         | Int64 _, _
7133         | Bool _, _
7134         | FileIn _, _ | FileOut _, _ -> ()
7135         | StringList n, "" | DeviceList n, "" ->
7136             pr "    const char *const %s[1] = { NULL };\n" n
7137         | StringList n, arg | DeviceList n, arg ->
7138             let strs = string_split " " arg in
7139             iteri (
7140               fun i str ->
7141                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7142             ) strs;
7143             pr "    const char *const %s[] = {\n" n;
7144             iteri (
7145               fun i _ -> pr "      %s_%d,\n" n i
7146             ) strs;
7147             pr "      NULL\n";
7148             pr "    };\n";
7149       ) (List.combine (snd style) args);
7150
7151       let error_code =
7152         match fst style with
7153         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7154         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7155         | RConstString _ | RConstOptString _ ->
7156             pr "    const char *r;\n"; "NULL"
7157         | RString _ -> pr "    char *r;\n"; "NULL"
7158         | RStringList _ | RHashtable _ ->
7159             pr "    char **r;\n";
7160             pr "    int i;\n";
7161             "NULL"
7162         | RStruct (_, typ) ->
7163             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7164         | RStructList (_, typ) ->
7165             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7166         | RBufferOut _ ->
7167             pr "    char *r;\n";
7168             pr "    size_t size;\n";
7169             "NULL" in
7170
7171       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7172       pr "    r = guestfs_%s (g" name;
7173
7174       (* Generate the parameters. *)
7175       List.iter (
7176         function
7177         | OptString _, "NULL" -> pr ", NULL"
7178         | Pathname n, _
7179         | Device n, _ | Dev_or_Path n, _
7180         | String n, _
7181         | OptString n, _ ->
7182             pr ", %s" n
7183         | FileIn _, arg | FileOut _, arg ->
7184             pr ", \"%s\"" (c_quote arg)
7185         | StringList n, _ | DeviceList n, _ ->
7186             pr ", (char **) %s" n
7187         | Int _, arg ->
7188             let i =
7189               try int_of_string arg
7190               with Failure "int_of_string" ->
7191                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7192             pr ", %d" i
7193         | Int64 _, arg ->
7194             let i =
7195               try Int64.of_string arg
7196               with Failure "int_of_string" ->
7197                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7198             pr ", %Ld" i
7199         | Bool _, arg ->
7200             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7201       ) (List.combine (snd style) args);
7202
7203       (match fst style with
7204        | RBufferOut _ -> pr ", &size"
7205        | _ -> ()
7206       );
7207
7208       pr ");\n";
7209
7210       if not expect_error then
7211         pr "    if (r == %s)\n" error_code
7212       else
7213         pr "    if (r != %s)\n" error_code;
7214       pr "      return -1;\n";
7215
7216       (* Insert the test code. *)
7217       (match test with
7218        | None -> ()
7219        | Some f -> f ()
7220       );
7221
7222       (match fst style with
7223        | RErr | RInt _ | RInt64 _ | RBool _
7224        | RConstString _ | RConstOptString _ -> ()
7225        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7226        | RStringList _ | RHashtable _ ->
7227            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7228            pr "      free (r[i]);\n";
7229            pr "    free (r);\n"
7230        | RStruct (_, typ) ->
7231            pr "    guestfs_free_%s (r);\n" typ
7232        | RStructList (_, typ) ->
7233            pr "    guestfs_free_%s_list (r);\n" typ
7234       );
7235
7236       pr "  }\n"
7237
7238 and c_quote str =
7239   let str = replace_str str "\r" "\\r" in
7240   let str = replace_str str "\n" "\\n" in
7241   let str = replace_str str "\t" "\\t" in
7242   let str = replace_str str "\000" "\\0" in
7243   str
7244
7245 (* Generate a lot of different functions for guestfish. *)
7246 and generate_fish_cmds () =
7247   generate_header CStyle GPLv2plus;
7248
7249   let all_functions =
7250     List.filter (
7251       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7252     ) all_functions in
7253   let all_functions_sorted =
7254     List.filter (
7255       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7256     ) all_functions_sorted in
7257
7258   pr "#include <config.h>\n";
7259   pr "\n";
7260   pr "#include <stdio.h>\n";
7261   pr "#include <stdlib.h>\n";
7262   pr "#include <string.h>\n";
7263   pr "#include <inttypes.h>\n";
7264   pr "\n";
7265   pr "#include <guestfs.h>\n";
7266   pr "#include \"c-ctype.h\"\n";
7267   pr "#include \"full-write.h\"\n";
7268   pr "#include \"xstrtol.h\"\n";
7269   pr "#include \"fish.h\"\n";
7270   pr "\n";
7271
7272   (* list_commands function, which implements guestfish -h *)
7273   pr "void list_commands (void)\n";
7274   pr "{\n";
7275   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7276   pr "  list_builtin_commands ();\n";
7277   List.iter (
7278     fun (name, _, _, flags, _, shortdesc, _) ->
7279       let name = replace_char name '_' '-' in
7280       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7281         name shortdesc
7282   ) all_functions_sorted;
7283   pr "  printf (\"    %%s\\n\",";
7284   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7285   pr "}\n";
7286   pr "\n";
7287
7288   (* display_command function, which implements guestfish -h cmd *)
7289   pr "void display_command (const char *cmd)\n";
7290   pr "{\n";
7291   List.iter (
7292     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7293       let name2 = replace_char name '_' '-' in
7294       let alias =
7295         try find_map (function FishAlias n -> Some n | _ -> None) flags
7296         with Not_found -> name in
7297       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7298       let synopsis =
7299         match snd style with
7300         | [] -> name2
7301         | args ->
7302             sprintf "%s %s"
7303               name2 (String.concat " " (List.map name_of_argt args)) in
7304
7305       let warnings =
7306         if List.mem ProtocolLimitWarning flags then
7307           ("\n\n" ^ protocol_limit_warning)
7308         else "" in
7309
7310       (* For DangerWillRobinson commands, we should probably have
7311        * guestfish prompt before allowing you to use them (especially
7312        * in interactive mode). XXX
7313        *)
7314       let warnings =
7315         warnings ^
7316           if List.mem DangerWillRobinson flags then
7317             ("\n\n" ^ danger_will_robinson)
7318           else "" in
7319
7320       let warnings =
7321         warnings ^
7322           match deprecation_notice flags with
7323           | None -> ""
7324           | Some txt -> "\n\n" ^ txt in
7325
7326       let describe_alias =
7327         if name <> alias then
7328           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7329         else "" in
7330
7331       pr "  if (";
7332       pr "STRCASEEQ (cmd, \"%s\")" name;
7333       if name <> name2 then
7334         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7335       if name <> alias then
7336         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7337       pr ")\n";
7338       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7339         name2 shortdesc
7340         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7341          "=head1 DESCRIPTION\n\n" ^
7342          longdesc ^ warnings ^ describe_alias);
7343       pr "  else\n"
7344   ) all_functions;
7345   pr "    display_builtin_command (cmd);\n";
7346   pr "}\n";
7347   pr "\n";
7348
7349   let emit_print_list_function typ =
7350     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7351       typ typ typ;
7352     pr "{\n";
7353     pr "  unsigned int i;\n";
7354     pr "\n";
7355     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7356     pr "    printf (\"[%%d] = {\\n\", i);\n";
7357     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7358     pr "    printf (\"}\\n\");\n";
7359     pr "  }\n";
7360     pr "}\n";
7361     pr "\n";
7362   in
7363
7364   (* print_* functions *)
7365   List.iter (
7366     fun (typ, cols) ->
7367       let needs_i =
7368         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7369
7370       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7371       pr "{\n";
7372       if needs_i then (
7373         pr "  unsigned int i;\n";
7374         pr "\n"
7375       );
7376       List.iter (
7377         function
7378         | name, FString ->
7379             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7380         | name, FUUID ->
7381             pr "  printf (\"%%s%s: \", indent);\n" name;
7382             pr "  for (i = 0; i < 32; ++i)\n";
7383             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7384             pr "  printf (\"\\n\");\n"
7385         | name, FBuffer ->
7386             pr "  printf (\"%%s%s: \", indent);\n" name;
7387             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7388             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7389             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7390             pr "    else\n";
7391             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7392             pr "  printf (\"\\n\");\n"
7393         | name, (FUInt64|FBytes) ->
7394             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7395               name typ name
7396         | name, FInt64 ->
7397             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7398               name typ name
7399         | name, FUInt32 ->
7400             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7401               name typ name
7402         | name, FInt32 ->
7403             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7404               name typ name
7405         | name, FChar ->
7406             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7407               name typ name
7408         | name, FOptPercent ->
7409             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7410               typ name name typ name;
7411             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7412       ) cols;
7413       pr "}\n";
7414       pr "\n";
7415   ) structs;
7416
7417   (* Emit a print_TYPE_list function definition only if that function is used. *)
7418   List.iter (
7419     function
7420     | typ, (RStructListOnly | RStructAndList) ->
7421         (* generate the function for typ *)
7422         emit_print_list_function typ
7423     | typ, _ -> () (* empty *)
7424   ) (rstructs_used_by all_functions);
7425
7426   (* Emit a print_TYPE function definition only if that function is used. *)
7427   List.iter (
7428     function
7429     | typ, (RStructOnly | RStructAndList) ->
7430         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7431         pr "{\n";
7432         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7433         pr "}\n";
7434         pr "\n";
7435     | typ, _ -> () (* empty *)
7436   ) (rstructs_used_by all_functions);
7437
7438   (* run_<action> actions *)
7439   List.iter (
7440     fun (name, style, _, flags, _, _, _) ->
7441       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7442       pr "{\n";
7443       (match fst style with
7444        | RErr
7445        | RInt _
7446        | RBool _ -> pr "  int r;\n"
7447        | RInt64 _ -> pr "  int64_t r;\n"
7448        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7449        | RString _ -> pr "  char *r;\n"
7450        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7451        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7452        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7453        | RBufferOut _ ->
7454            pr "  char *r;\n";
7455            pr "  size_t size;\n";
7456       );
7457       List.iter (
7458         function
7459         | Device n
7460         | String n
7461         | OptString n -> pr "  const char *%s;\n" n
7462         | Pathname n
7463         | Dev_or_Path n
7464         | FileIn n
7465         | FileOut n -> pr "  char *%s;\n" n
7466         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7467         | Bool n -> pr "  int %s;\n" n
7468         | Int n -> pr "  int %s;\n" n
7469         | Int64 n -> pr "  int64_t %s;\n" n
7470       ) (snd style);
7471
7472       (* Check and convert parameters. *)
7473       let argc_expected = List.length (snd style) in
7474       pr "  if (argc != %d) {\n" argc_expected;
7475       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7476         argc_expected;
7477       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7478       pr "    return -1;\n";
7479       pr "  }\n";
7480
7481       let parse_integer fn fntyp rtyp range name i =
7482         pr "  {\n";
7483         pr "    strtol_error xerr;\n";
7484         pr "    %s r;\n" fntyp;
7485         pr "\n";
7486         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7487         pr "    if (xerr != LONGINT_OK) {\n";
7488         pr "      fprintf (stderr,\n";
7489         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7490         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7491         pr "      return -1;\n";
7492         pr "    }\n";
7493         (match range with
7494          | None -> ()
7495          | Some (min, max, comment) ->
7496              pr "    /* %s */\n" comment;
7497              pr "    if (r < %s || r > %s) {\n" min max;
7498              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7499                name;
7500              pr "      return -1;\n";
7501              pr "    }\n";
7502              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7503         );
7504         pr "    %s = r;\n" name;
7505         pr "  }\n";
7506       in
7507
7508       iteri (
7509         fun i ->
7510           function
7511           | Device name
7512           | String name ->
7513               pr "  %s = argv[%d];\n" name i
7514           | Pathname name
7515           | Dev_or_Path name ->
7516               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7517               pr "  if (%s == NULL) return -1;\n" name
7518           | OptString name ->
7519               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7520                 name i i
7521           | FileIn name ->
7522               pr "  %s = file_in (argv[%d]);\n" name i;
7523               pr "  if (%s == NULL) return -1;\n" name
7524           | FileOut name ->
7525               pr "  %s = file_out (argv[%d]);\n" name i;
7526               pr "  if (%s == NULL) return -1;\n" name
7527           | StringList name | DeviceList name ->
7528               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7529               pr "  if (%s == NULL) return -1;\n" name;
7530           | Bool name ->
7531               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7532           | Int name ->
7533               let range =
7534                 let min = "(-(2LL<<30))"
7535                 and max = "((2LL<<30)-1)"
7536                 and comment =
7537                   "The Int type in the generator is a signed 31 bit int." in
7538                 Some (min, max, comment) in
7539               parse_integer "xstrtoll" "long long" "int" range name i
7540           | Int64 name ->
7541               parse_integer "xstrtoll" "long long" "int64_t" None name i
7542       ) (snd style);
7543
7544       (* Call C API function. *)
7545       let fn =
7546         try find_map (function FishAction n -> Some n | _ -> None) flags
7547         with Not_found -> sprintf "guestfs_%s" name in
7548       pr "  r = %s " fn;
7549       generate_c_call_args ~handle:"g" style;
7550       pr ";\n";
7551
7552       List.iter (
7553         function
7554         | Device name | String name
7555         | OptString name | Bool name
7556         | Int name | Int64 name -> ()
7557         | Pathname name | Dev_or_Path name | FileOut name ->
7558             pr "  free (%s);\n" name
7559         | FileIn name ->
7560             pr "  free_file_in (%s);\n" name
7561         | StringList name | DeviceList name ->
7562             pr "  free_strings (%s);\n" name
7563       ) (snd style);
7564
7565       (* Any output flags? *)
7566       let fish_output =
7567         let flags = filter_map (
7568           function FishOutput flag -> Some flag | _ -> None
7569         ) flags in
7570         match flags with
7571         | [] -> None
7572         | [f] -> Some f
7573         | _ ->
7574             failwithf "%s: more than one FishOutput flag is not allowed" name in
7575
7576       (* Check return value for errors and display command results. *)
7577       (match fst style with
7578        | RErr -> pr "  return r;\n"
7579        | RInt _ ->
7580            pr "  if (r == -1) return -1;\n";
7581            (match fish_output with
7582             | None ->
7583                 pr "  printf (\"%%d\\n\", r);\n";
7584             | Some FishOutputOctal ->
7585                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7586             | Some FishOutputHexadecimal ->
7587                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7588            pr "  return 0;\n"
7589        | RInt64 _ ->
7590            pr "  if (r == -1) return -1;\n";
7591            (match fish_output with
7592             | None ->
7593                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7594             | Some FishOutputOctal ->
7595                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7596             | Some FishOutputHexadecimal ->
7597                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7598            pr "  return 0;\n"
7599        | RBool _ ->
7600            pr "  if (r == -1) return -1;\n";
7601            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7602            pr "  return 0;\n"
7603        | RConstString _ ->
7604            pr "  if (r == NULL) return -1;\n";
7605            pr "  printf (\"%%s\\n\", r);\n";
7606            pr "  return 0;\n"
7607        | RConstOptString _ ->
7608            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7609            pr "  return 0;\n"
7610        | RString _ ->
7611            pr "  if (r == NULL) return -1;\n";
7612            pr "  printf (\"%%s\\n\", r);\n";
7613            pr "  free (r);\n";
7614            pr "  return 0;\n"
7615        | RStringList _ ->
7616            pr "  if (r == NULL) return -1;\n";
7617            pr "  print_strings (r);\n";
7618            pr "  free_strings (r);\n";
7619            pr "  return 0;\n"
7620        | RStruct (_, typ) ->
7621            pr "  if (r == NULL) return -1;\n";
7622            pr "  print_%s (r);\n" typ;
7623            pr "  guestfs_free_%s (r);\n" typ;
7624            pr "  return 0;\n"
7625        | RStructList (_, typ) ->
7626            pr "  if (r == NULL) return -1;\n";
7627            pr "  print_%s_list (r);\n" typ;
7628            pr "  guestfs_free_%s_list (r);\n" typ;
7629            pr "  return 0;\n"
7630        | RHashtable _ ->
7631            pr "  if (r == NULL) return -1;\n";
7632            pr "  print_table (r);\n";
7633            pr "  free_strings (r);\n";
7634            pr "  return 0;\n"
7635        | RBufferOut _ ->
7636            pr "  if (r == NULL) return -1;\n";
7637            pr "  if (full_write (1, r, size) != size) {\n";
7638            pr "    perror (\"write\");\n";
7639            pr "    free (r);\n";
7640            pr "    return -1;\n";
7641            pr "  }\n";
7642            pr "  free (r);\n";
7643            pr "  return 0;\n"
7644       );
7645       pr "}\n";
7646       pr "\n"
7647   ) all_functions;
7648
7649   (* run_action function *)
7650   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7651   pr "{\n";
7652   List.iter (
7653     fun (name, _, _, flags, _, _, _) ->
7654       let name2 = replace_char name '_' '-' in
7655       let alias =
7656         try find_map (function FishAlias n -> Some n | _ -> None) flags
7657         with Not_found -> name in
7658       pr "  if (";
7659       pr "STRCASEEQ (cmd, \"%s\")" name;
7660       if name <> name2 then
7661         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7662       if name <> alias then
7663         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7664       pr ")\n";
7665       pr "    return run_%s (cmd, argc, argv);\n" name;
7666       pr "  else\n";
7667   ) all_functions;
7668   pr "    {\n";
7669   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7670   pr "      if (command_num == 1)\n";
7671   pr "        extended_help_message ();\n";
7672   pr "      return -1;\n";
7673   pr "    }\n";
7674   pr "  return 0;\n";
7675   pr "}\n";
7676   pr "\n"
7677
7678 (* Readline completion for guestfish. *)
7679 and generate_fish_completion () =
7680   generate_header CStyle GPLv2plus;
7681
7682   let all_functions =
7683     List.filter (
7684       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7685     ) all_functions in
7686
7687   pr "\
7688 #include <config.h>
7689
7690 #include <stdio.h>
7691 #include <stdlib.h>
7692 #include <string.h>
7693
7694 #ifdef HAVE_LIBREADLINE
7695 #include <readline/readline.h>
7696 #endif
7697
7698 #include \"fish.h\"
7699
7700 #ifdef HAVE_LIBREADLINE
7701
7702 static const char *const commands[] = {
7703   BUILTIN_COMMANDS_FOR_COMPLETION,
7704 ";
7705
7706   (* Get the commands, including the aliases.  They don't need to be
7707    * sorted - the generator() function just does a dumb linear search.
7708    *)
7709   let commands =
7710     List.map (
7711       fun (name, _, _, flags, _, _, _) ->
7712         let name2 = replace_char name '_' '-' in
7713         let alias =
7714           try find_map (function FishAlias n -> Some n | _ -> None) flags
7715           with Not_found -> name in
7716
7717         if name <> alias then [name2; alias] else [name2]
7718     ) all_functions in
7719   let commands = List.flatten commands in
7720
7721   List.iter (pr "  \"%s\",\n") commands;
7722
7723   pr "  NULL
7724 };
7725
7726 static char *
7727 generator (const char *text, int state)
7728 {
7729   static int index, len;
7730   const char *name;
7731
7732   if (!state) {
7733     index = 0;
7734     len = strlen (text);
7735   }
7736
7737   rl_attempted_completion_over = 1;
7738
7739   while ((name = commands[index]) != NULL) {
7740     index++;
7741     if (STRCASEEQLEN (name, text, len))
7742       return strdup (name);
7743   }
7744
7745   return NULL;
7746 }
7747
7748 #endif /* HAVE_LIBREADLINE */
7749
7750 #ifdef HAVE_RL_COMPLETION_MATCHES
7751 #define RL_COMPLETION_MATCHES rl_completion_matches
7752 #else
7753 #ifdef HAVE_COMPLETION_MATCHES
7754 #define RL_COMPLETION_MATCHES completion_matches
7755 #endif
7756 #endif /* else just fail if we don't have either symbol */
7757
7758 char **
7759 do_completion (const char *text, int start, int end)
7760 {
7761   char **matches = NULL;
7762
7763 #ifdef HAVE_LIBREADLINE
7764   rl_completion_append_character = ' ';
7765
7766   if (start == 0)
7767     matches = RL_COMPLETION_MATCHES (text, generator);
7768   else if (complete_dest_paths)
7769     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7770 #endif
7771
7772   return matches;
7773 }
7774 ";
7775
7776 (* Generate the POD documentation for guestfish. *)
7777 and generate_fish_actions_pod () =
7778   let all_functions_sorted =
7779     List.filter (
7780       fun (_, _, _, flags, _, _, _) ->
7781         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7782     ) all_functions_sorted in
7783
7784   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7785
7786   List.iter (
7787     fun (name, style, _, flags, _, _, longdesc) ->
7788       let longdesc =
7789         Str.global_substitute rex (
7790           fun s ->
7791             let sub =
7792               try Str.matched_group 1 s
7793               with Not_found ->
7794                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7795             "C<" ^ replace_char sub '_' '-' ^ ">"
7796         ) longdesc in
7797       let name = replace_char name '_' '-' in
7798       let alias =
7799         try find_map (function FishAlias n -> Some n | _ -> None) flags
7800         with Not_found -> name in
7801
7802       pr "=head2 %s" name;
7803       if name <> alias then
7804         pr " | %s" alias;
7805       pr "\n";
7806       pr "\n";
7807       pr " %s" name;
7808       List.iter (
7809         function
7810         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7811         | OptString n -> pr " %s" n
7812         | StringList n | DeviceList n -> pr " '%s ...'" n
7813         | Bool _ -> pr " true|false"
7814         | Int n -> pr " %s" n
7815         | Int64 n -> pr " %s" n
7816         | FileIn n | FileOut n -> pr " (%s|-)" n
7817       ) (snd style);
7818       pr "\n";
7819       pr "\n";
7820       pr "%s\n\n" longdesc;
7821
7822       if List.exists (function FileIn _ | FileOut _ -> true
7823                       | _ -> false) (snd style) then
7824         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7825
7826       if List.mem ProtocolLimitWarning flags then
7827         pr "%s\n\n" protocol_limit_warning;
7828
7829       if List.mem DangerWillRobinson flags then
7830         pr "%s\n\n" danger_will_robinson;
7831
7832       match deprecation_notice flags with
7833       | None -> ()
7834       | Some txt -> pr "%s\n\n" txt
7835   ) all_functions_sorted
7836
7837 (* Generate a C function prototype. *)
7838 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7839     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7840     ?(prefix = "")
7841     ?handle name style =
7842   if extern then pr "extern ";
7843   if static then pr "static ";
7844   (match fst style with
7845    | RErr -> pr "int "
7846    | RInt _ -> pr "int "
7847    | RInt64 _ -> pr "int64_t "
7848    | RBool _ -> pr "int "
7849    | RConstString _ | RConstOptString _ -> pr "const char *"
7850    | RString _ | RBufferOut _ -> pr "char *"
7851    | RStringList _ | RHashtable _ -> pr "char **"
7852    | RStruct (_, typ) ->
7853        if not in_daemon then pr "struct guestfs_%s *" typ
7854        else pr "guestfs_int_%s *" typ
7855    | RStructList (_, typ) ->
7856        if not in_daemon then pr "struct guestfs_%s_list *" typ
7857        else pr "guestfs_int_%s_list *" typ
7858   );
7859   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7860   pr "%s%s (" prefix name;
7861   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7862     pr "void"
7863   else (
7864     let comma = ref false in
7865     (match handle with
7866      | None -> ()
7867      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7868     );
7869     let next () =
7870       if !comma then (
7871         if single_line then pr ", " else pr ",\n\t\t"
7872       );
7873       comma := true
7874     in
7875     List.iter (
7876       function
7877       | Pathname n
7878       | Device n | Dev_or_Path n
7879       | String n
7880       | OptString n ->
7881           next ();
7882           pr "const char *%s" n
7883       | StringList n | DeviceList n ->
7884           next ();
7885           pr "char *const *%s" n
7886       | Bool n -> next (); pr "int %s" n
7887       | Int n -> next (); pr "int %s" n
7888       | Int64 n -> next (); pr "int64_t %s" n
7889       | FileIn n
7890       | FileOut n ->
7891           if not in_daemon then (next (); pr "const char *%s" n)
7892     ) (snd style);
7893     if is_RBufferOut then (next (); pr "size_t *size_r");
7894   );
7895   pr ")";
7896   if semicolon then pr ";";
7897   if newline then pr "\n"
7898
7899 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7900 and generate_c_call_args ?handle ?(decl = false) style =
7901   pr "(";
7902   let comma = ref false in
7903   let next () =
7904     if !comma then pr ", ";
7905     comma := true
7906   in
7907   (match handle with
7908    | None -> ()
7909    | Some handle -> pr "%s" handle; comma := true
7910   );
7911   List.iter (
7912     fun arg ->
7913       next ();
7914       pr "%s" (name_of_argt arg)
7915   ) (snd style);
7916   (* For RBufferOut calls, add implicit &size parameter. *)
7917   if not decl then (
7918     match fst style with
7919     | RBufferOut _ ->
7920         next ();
7921         pr "&size"
7922     | _ -> ()
7923   );
7924   pr ")"
7925
7926 (* Generate the OCaml bindings interface. *)
7927 and generate_ocaml_mli () =
7928   generate_header OCamlStyle LGPLv2plus;
7929
7930   pr "\
7931 (** For API documentation you should refer to the C API
7932     in the guestfs(3) manual page.  The OCaml API uses almost
7933     exactly the same calls. *)
7934
7935 type t
7936 (** A [guestfs_h] handle. *)
7937
7938 exception Error of string
7939 (** This exception is raised when there is an error. *)
7940
7941 exception Handle_closed of string
7942 (** This exception is raised if you use a {!Guestfs.t} handle
7943     after calling {!close} on it.  The string is the name of
7944     the function. *)
7945
7946 val create : unit -> t
7947 (** Create a {!Guestfs.t} handle. *)
7948
7949 val close : t -> unit
7950 (** Close the {!Guestfs.t} handle and free up all resources used
7951     by it immediately.
7952
7953     Handles are closed by the garbage collector when they become
7954     unreferenced, but callers can call this in order to provide
7955     predictable cleanup. *)
7956
7957 ";
7958   generate_ocaml_structure_decls ();
7959
7960   (* The actions. *)
7961   List.iter (
7962     fun (name, style, _, _, _, shortdesc, _) ->
7963       generate_ocaml_prototype name style;
7964       pr "(** %s *)\n" shortdesc;
7965       pr "\n"
7966   ) all_functions_sorted
7967
7968 (* Generate the OCaml bindings implementation. *)
7969 and generate_ocaml_ml () =
7970   generate_header OCamlStyle LGPLv2plus;
7971
7972   pr "\
7973 type t
7974
7975 exception Error of string
7976 exception Handle_closed of string
7977
7978 external create : unit -> t = \"ocaml_guestfs_create\"
7979 external close : t -> unit = \"ocaml_guestfs_close\"
7980
7981 (* Give the exceptions names, so they can be raised from the C code. *)
7982 let () =
7983   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7984   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7985
7986 ";
7987
7988   generate_ocaml_structure_decls ();
7989
7990   (* The actions. *)
7991   List.iter (
7992     fun (name, style, _, _, _, shortdesc, _) ->
7993       generate_ocaml_prototype ~is_external:true name style;
7994   ) all_functions_sorted
7995
7996 (* Generate the OCaml bindings C implementation. *)
7997 and generate_ocaml_c () =
7998   generate_header CStyle LGPLv2plus;
7999
8000   pr "\
8001 #include <stdio.h>
8002 #include <stdlib.h>
8003 #include <string.h>
8004
8005 #include <caml/config.h>
8006 #include <caml/alloc.h>
8007 #include <caml/callback.h>
8008 #include <caml/fail.h>
8009 #include <caml/memory.h>
8010 #include <caml/mlvalues.h>
8011 #include <caml/signals.h>
8012
8013 #include <guestfs.h>
8014
8015 #include \"guestfs_c.h\"
8016
8017 /* Copy a hashtable of string pairs into an assoc-list.  We return
8018  * the list in reverse order, but hashtables aren't supposed to be
8019  * ordered anyway.
8020  */
8021 static CAMLprim value
8022 copy_table (char * const * argv)
8023 {
8024   CAMLparam0 ();
8025   CAMLlocal5 (rv, pairv, kv, vv, cons);
8026   int i;
8027
8028   rv = Val_int (0);
8029   for (i = 0; argv[i] != NULL; i += 2) {
8030     kv = caml_copy_string (argv[i]);
8031     vv = caml_copy_string (argv[i+1]);
8032     pairv = caml_alloc (2, 0);
8033     Store_field (pairv, 0, kv);
8034     Store_field (pairv, 1, vv);
8035     cons = caml_alloc (2, 0);
8036     Store_field (cons, 1, rv);
8037     rv = cons;
8038     Store_field (cons, 0, pairv);
8039   }
8040
8041   CAMLreturn (rv);
8042 }
8043
8044 ";
8045
8046   (* Struct copy functions. *)
8047
8048   let emit_ocaml_copy_list_function typ =
8049     pr "static CAMLprim value\n";
8050     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8051     pr "{\n";
8052     pr "  CAMLparam0 ();\n";
8053     pr "  CAMLlocal2 (rv, v);\n";
8054     pr "  unsigned int i;\n";
8055     pr "\n";
8056     pr "  if (%ss->len == 0)\n" typ;
8057     pr "    CAMLreturn (Atom (0));\n";
8058     pr "  else {\n";
8059     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8060     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8061     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8062     pr "      caml_modify (&Field (rv, i), v);\n";
8063     pr "    }\n";
8064     pr "    CAMLreturn (rv);\n";
8065     pr "  }\n";
8066     pr "}\n";
8067     pr "\n";
8068   in
8069
8070   List.iter (
8071     fun (typ, cols) ->
8072       let has_optpercent_col =
8073         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8074
8075       pr "static CAMLprim value\n";
8076       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8077       pr "{\n";
8078       pr "  CAMLparam0 ();\n";
8079       if has_optpercent_col then
8080         pr "  CAMLlocal3 (rv, v, v2);\n"
8081       else
8082         pr "  CAMLlocal2 (rv, v);\n";
8083       pr "\n";
8084       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8085       iteri (
8086         fun i col ->
8087           (match col with
8088            | name, FString ->
8089                pr "  v = caml_copy_string (%s->%s);\n" typ name
8090            | name, FBuffer ->
8091                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8092                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8093                  typ name typ name
8094            | name, FUUID ->
8095                pr "  v = caml_alloc_string (32);\n";
8096                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8097            | name, (FBytes|FInt64|FUInt64) ->
8098                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8099            | name, (FInt32|FUInt32) ->
8100                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8101            | name, FOptPercent ->
8102                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8103                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8104                pr "    v = caml_alloc (1, 0);\n";
8105                pr "    Store_field (v, 0, v2);\n";
8106                pr "  } else /* None */\n";
8107                pr "    v = Val_int (0);\n";
8108            | name, FChar ->
8109                pr "  v = Val_int (%s->%s);\n" typ name
8110           );
8111           pr "  Store_field (rv, %d, v);\n" i
8112       ) cols;
8113       pr "  CAMLreturn (rv);\n";
8114       pr "}\n";
8115       pr "\n";
8116   ) structs;
8117
8118   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8119   List.iter (
8120     function
8121     | typ, (RStructListOnly | RStructAndList) ->
8122         (* generate the function for typ *)
8123         emit_ocaml_copy_list_function typ
8124     | typ, _ -> () (* empty *)
8125   ) (rstructs_used_by all_functions);
8126
8127   (* The wrappers. *)
8128   List.iter (
8129     fun (name, style, _, _, _, _, _) ->
8130       pr "/* Automatically generated wrapper for function\n";
8131       pr " * ";
8132       generate_ocaml_prototype name style;
8133       pr " */\n";
8134       pr "\n";
8135
8136       let params =
8137         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8138
8139       let needs_extra_vs =
8140         match fst style with RConstOptString _ -> true | _ -> false in
8141
8142       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8143       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8144       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8145       pr "\n";
8146
8147       pr "CAMLprim value\n";
8148       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8149       List.iter (pr ", value %s") (List.tl params);
8150       pr ")\n";
8151       pr "{\n";
8152
8153       (match params with
8154        | [p1; p2; p3; p4; p5] ->
8155            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8156        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8157            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8158            pr "  CAMLxparam%d (%s);\n"
8159              (List.length rest) (String.concat ", " rest)
8160        | ps ->
8161            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8162       );
8163       if not needs_extra_vs then
8164         pr "  CAMLlocal1 (rv);\n"
8165       else
8166         pr "  CAMLlocal3 (rv, v, v2);\n";
8167       pr "\n";
8168
8169       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8170       pr "  if (g == NULL)\n";
8171       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8172       pr "\n";
8173
8174       List.iter (
8175         function
8176         | Pathname n
8177         | Device n | Dev_or_Path n
8178         | String n
8179         | FileIn n
8180         | FileOut n ->
8181             pr "  const char *%s = String_val (%sv);\n" n n
8182         | OptString n ->
8183             pr "  const char *%s =\n" n;
8184             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8185               n n
8186         | StringList n | DeviceList n ->
8187             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8188         | Bool n ->
8189             pr "  int %s = Bool_val (%sv);\n" n n
8190         | Int n ->
8191             pr "  int %s = Int_val (%sv);\n" n n
8192         | Int64 n ->
8193             pr "  int64_t %s = Int64_val (%sv);\n" n n
8194       ) (snd style);
8195       let error_code =
8196         match fst style with
8197         | RErr -> pr "  int r;\n"; "-1"
8198         | RInt _ -> pr "  int r;\n"; "-1"
8199         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8200         | RBool _ -> pr "  int r;\n"; "-1"
8201         | RConstString _ | RConstOptString _ ->
8202             pr "  const char *r;\n"; "NULL"
8203         | RString _ -> pr "  char *r;\n"; "NULL"
8204         | RStringList _ ->
8205             pr "  int i;\n";
8206             pr "  char **r;\n";
8207             "NULL"
8208         | RStruct (_, typ) ->
8209             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8210         | RStructList (_, typ) ->
8211             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8212         | RHashtable _ ->
8213             pr "  int i;\n";
8214             pr "  char **r;\n";
8215             "NULL"
8216         | RBufferOut _ ->
8217             pr "  char *r;\n";
8218             pr "  size_t size;\n";
8219             "NULL" in
8220       pr "\n";
8221
8222       pr "  caml_enter_blocking_section ();\n";
8223       pr "  r = guestfs_%s " name;
8224       generate_c_call_args ~handle:"g" style;
8225       pr ";\n";
8226       pr "  caml_leave_blocking_section ();\n";
8227
8228       List.iter (
8229         function
8230         | StringList n | DeviceList n ->
8231             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8232         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8233         | Bool _ | Int _ | Int64 _
8234         | FileIn _ | FileOut _ -> ()
8235       ) (snd style);
8236
8237       pr "  if (r == %s)\n" error_code;
8238       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8239       pr "\n";
8240
8241       (match fst style with
8242        | RErr -> pr "  rv = Val_unit;\n"
8243        | RInt _ -> pr "  rv = Val_int (r);\n"
8244        | RInt64 _ ->
8245            pr "  rv = caml_copy_int64 (r);\n"
8246        | RBool _ -> pr "  rv = Val_bool (r);\n"
8247        | RConstString _ ->
8248            pr "  rv = caml_copy_string (r);\n"
8249        | RConstOptString _ ->
8250            pr "  if (r) { /* Some string */\n";
8251            pr "    v = caml_alloc (1, 0);\n";
8252            pr "    v2 = caml_copy_string (r);\n";
8253            pr "    Store_field (v, 0, v2);\n";
8254            pr "  } else /* None */\n";
8255            pr "    v = Val_int (0);\n";
8256        | RString _ ->
8257            pr "  rv = caml_copy_string (r);\n";
8258            pr "  free (r);\n"
8259        | RStringList _ ->
8260            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8261            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8262            pr "  free (r);\n"
8263        | RStruct (_, typ) ->
8264            pr "  rv = copy_%s (r);\n" typ;
8265            pr "  guestfs_free_%s (r);\n" typ;
8266        | RStructList (_, typ) ->
8267            pr "  rv = copy_%s_list (r);\n" typ;
8268            pr "  guestfs_free_%s_list (r);\n" typ;
8269        | RHashtable _ ->
8270            pr "  rv = copy_table (r);\n";
8271            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8272            pr "  free (r);\n";
8273        | RBufferOut _ ->
8274            pr "  rv = caml_alloc_string (size);\n";
8275            pr "  memcpy (String_val (rv), r, size);\n";
8276       );
8277
8278       pr "  CAMLreturn (rv);\n";
8279       pr "}\n";
8280       pr "\n";
8281
8282       if List.length params > 5 then (
8283         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8284         pr "CAMLprim value ";
8285         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8286         pr "CAMLprim value\n";
8287         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8288         pr "{\n";
8289         pr "  return ocaml_guestfs_%s (argv[0]" name;
8290         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8291         pr ");\n";
8292         pr "}\n";
8293         pr "\n"
8294       )
8295   ) all_functions_sorted
8296
8297 and generate_ocaml_structure_decls () =
8298   List.iter (
8299     fun (typ, cols) ->
8300       pr "type %s = {\n" typ;
8301       List.iter (
8302         function
8303         | name, FString -> pr "  %s : string;\n" name
8304         | name, FBuffer -> pr "  %s : string;\n" name
8305         | name, FUUID -> pr "  %s : string;\n" name
8306         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8307         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8308         | name, FChar -> pr "  %s : char;\n" name
8309         | name, FOptPercent -> pr "  %s : float option;\n" name
8310       ) cols;
8311       pr "}\n";
8312       pr "\n"
8313   ) structs
8314
8315 and generate_ocaml_prototype ?(is_external = false) name style =
8316   if is_external then pr "external " else pr "val ";
8317   pr "%s : t -> " name;
8318   List.iter (
8319     function
8320     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8321     | OptString _ -> pr "string option -> "
8322     | StringList _ | DeviceList _ -> pr "string array -> "
8323     | Bool _ -> pr "bool -> "
8324     | Int _ -> pr "int -> "
8325     | Int64 _ -> pr "int64 -> "
8326   ) (snd style);
8327   (match fst style with
8328    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8329    | RInt _ -> pr "int"
8330    | RInt64 _ -> pr "int64"
8331    | RBool _ -> pr "bool"
8332    | RConstString _ -> pr "string"
8333    | RConstOptString _ -> pr "string option"
8334    | RString _ | RBufferOut _ -> pr "string"
8335    | RStringList _ -> pr "string array"
8336    | RStruct (_, typ) -> pr "%s" typ
8337    | RStructList (_, typ) -> pr "%s array" typ
8338    | RHashtable _ -> pr "(string * string) list"
8339   );
8340   if is_external then (
8341     pr " = ";
8342     if List.length (snd style) + 1 > 5 then
8343       pr "\"ocaml_guestfs_%s_byte\" " name;
8344     pr "\"ocaml_guestfs_%s\"" name
8345   );
8346   pr "\n"
8347
8348 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8349 and generate_perl_xs () =
8350   generate_header CStyle LGPLv2plus;
8351
8352   pr "\
8353 #include \"EXTERN.h\"
8354 #include \"perl.h\"
8355 #include \"XSUB.h\"
8356
8357 #include <guestfs.h>
8358
8359 #ifndef PRId64
8360 #define PRId64 \"lld\"
8361 #endif
8362
8363 static SV *
8364 my_newSVll(long long val) {
8365 #ifdef USE_64_BIT_ALL
8366   return newSViv(val);
8367 #else
8368   char buf[100];
8369   int len;
8370   len = snprintf(buf, 100, \"%%\" PRId64, val);
8371   return newSVpv(buf, len);
8372 #endif
8373 }
8374
8375 #ifndef PRIu64
8376 #define PRIu64 \"llu\"
8377 #endif
8378
8379 static SV *
8380 my_newSVull(unsigned long long val) {
8381 #ifdef USE_64_BIT_ALL
8382   return newSVuv(val);
8383 #else
8384   char buf[100];
8385   int len;
8386   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8387   return newSVpv(buf, len);
8388 #endif
8389 }
8390
8391 /* http://www.perlmonks.org/?node_id=680842 */
8392 static char **
8393 XS_unpack_charPtrPtr (SV *arg) {
8394   char **ret;
8395   AV *av;
8396   I32 i;
8397
8398   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8399     croak (\"array reference expected\");
8400
8401   av = (AV *)SvRV (arg);
8402   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8403   if (!ret)
8404     croak (\"malloc failed\");
8405
8406   for (i = 0; i <= av_len (av); i++) {
8407     SV **elem = av_fetch (av, i, 0);
8408
8409     if (!elem || !*elem)
8410       croak (\"missing element in list\");
8411
8412     ret[i] = SvPV_nolen (*elem);
8413   }
8414
8415   ret[i] = NULL;
8416
8417   return ret;
8418 }
8419
8420 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8421
8422 PROTOTYPES: ENABLE
8423
8424 guestfs_h *
8425 _create ()
8426    CODE:
8427       RETVAL = guestfs_create ();
8428       if (!RETVAL)
8429         croak (\"could not create guestfs handle\");
8430       guestfs_set_error_handler (RETVAL, NULL, NULL);
8431  OUTPUT:
8432       RETVAL
8433
8434 void
8435 DESTROY (g)
8436       guestfs_h *g;
8437  PPCODE:
8438       guestfs_close (g);
8439
8440 ";
8441
8442   List.iter (
8443     fun (name, style, _, _, _, _, _) ->
8444       (match fst style with
8445        | RErr -> pr "void\n"
8446        | RInt _ -> pr "SV *\n"
8447        | RInt64 _ -> pr "SV *\n"
8448        | RBool _ -> pr "SV *\n"
8449        | RConstString _ -> pr "SV *\n"
8450        | RConstOptString _ -> pr "SV *\n"
8451        | RString _ -> pr "SV *\n"
8452        | RBufferOut _ -> pr "SV *\n"
8453        | RStringList _
8454        | RStruct _ | RStructList _
8455        | RHashtable _ ->
8456            pr "void\n" (* all lists returned implictly on the stack *)
8457       );
8458       (* Call and arguments. *)
8459       pr "%s " name;
8460       generate_c_call_args ~handle:"g" ~decl:true style;
8461       pr "\n";
8462       pr "      guestfs_h *g;\n";
8463       iteri (
8464         fun i ->
8465           function
8466           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8467               pr "      char *%s;\n" n
8468           | OptString n ->
8469               (* http://www.perlmonks.org/?node_id=554277
8470                * Note that the implicit handle argument means we have
8471                * to add 1 to the ST(x) operator.
8472                *)
8473               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8474           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8475           | Bool n -> pr "      int %s;\n" n
8476           | Int n -> pr "      int %s;\n" n
8477           | Int64 n -> pr "      int64_t %s;\n" n
8478       ) (snd style);
8479
8480       let do_cleanups () =
8481         List.iter (
8482           function
8483           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8484           | Bool _ | Int _ | Int64 _
8485           | FileIn _ | FileOut _ -> ()
8486           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8487         ) (snd style)
8488       in
8489
8490       (* Code. *)
8491       (match fst style with
8492        | RErr ->
8493            pr "PREINIT:\n";
8494            pr "      int r;\n";
8495            pr " PPCODE:\n";
8496            pr "      r = guestfs_%s " name;
8497            generate_c_call_args ~handle:"g" style;
8498            pr ";\n";
8499            do_cleanups ();
8500            pr "      if (r == -1)\n";
8501            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8502        | RInt n
8503        | RBool n ->
8504            pr "PREINIT:\n";
8505            pr "      int %s;\n" n;
8506            pr "   CODE:\n";
8507            pr "      %s = guestfs_%s " n name;
8508            generate_c_call_args ~handle:"g" style;
8509            pr ";\n";
8510            do_cleanups ();
8511            pr "      if (%s == -1)\n" n;
8512            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8513            pr "      RETVAL = newSViv (%s);\n" n;
8514            pr " OUTPUT:\n";
8515            pr "      RETVAL\n"
8516        | RInt64 n ->
8517            pr "PREINIT:\n";
8518            pr "      int64_t %s;\n" n;
8519            pr "   CODE:\n";
8520            pr "      %s = guestfs_%s " n name;
8521            generate_c_call_args ~handle:"g" style;
8522            pr ";\n";
8523            do_cleanups ();
8524            pr "      if (%s == -1)\n" n;
8525            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8526            pr "      RETVAL = my_newSVll (%s);\n" n;
8527            pr " OUTPUT:\n";
8528            pr "      RETVAL\n"
8529        | RConstString n ->
8530            pr "PREINIT:\n";
8531            pr "      const char *%s;\n" n;
8532            pr "   CODE:\n";
8533            pr "      %s = guestfs_%s " n name;
8534            generate_c_call_args ~handle:"g" style;
8535            pr ";\n";
8536            do_cleanups ();
8537            pr "      if (%s == NULL)\n" n;
8538            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8539            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8540            pr " OUTPUT:\n";
8541            pr "      RETVAL\n"
8542        | RConstOptString n ->
8543            pr "PREINIT:\n";
8544            pr "      const char *%s;\n" n;
8545            pr "   CODE:\n";
8546            pr "      %s = guestfs_%s " n name;
8547            generate_c_call_args ~handle:"g" style;
8548            pr ";\n";
8549            do_cleanups ();
8550            pr "      if (%s == NULL)\n" n;
8551            pr "        RETVAL = &PL_sv_undef;\n";
8552            pr "      else\n";
8553            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8554            pr " OUTPUT:\n";
8555            pr "      RETVAL\n"
8556        | RString n ->
8557            pr "PREINIT:\n";
8558            pr "      char *%s;\n" n;
8559            pr "   CODE:\n";
8560            pr "      %s = guestfs_%s " n name;
8561            generate_c_call_args ~handle:"g" style;
8562            pr ";\n";
8563            do_cleanups ();
8564            pr "      if (%s == NULL)\n" n;
8565            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8566            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8567            pr "      free (%s);\n" n;
8568            pr " OUTPUT:\n";
8569            pr "      RETVAL\n"
8570        | RStringList n | RHashtable n ->
8571            pr "PREINIT:\n";
8572            pr "      char **%s;\n" n;
8573            pr "      int i, n;\n";
8574            pr " PPCODE:\n";
8575            pr "      %s = guestfs_%s " n name;
8576            generate_c_call_args ~handle:"g" style;
8577            pr ";\n";
8578            do_cleanups ();
8579            pr "      if (%s == NULL)\n" n;
8580            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8581            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8582            pr "      EXTEND (SP, n);\n";
8583            pr "      for (i = 0; i < n; ++i) {\n";
8584            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8585            pr "        free (%s[i]);\n" n;
8586            pr "      }\n";
8587            pr "      free (%s);\n" n;
8588        | RStruct (n, typ) ->
8589            let cols = cols_of_struct typ in
8590            generate_perl_struct_code typ cols name style n do_cleanups
8591        | RStructList (n, typ) ->
8592            let cols = cols_of_struct typ in
8593            generate_perl_struct_list_code typ cols name style n do_cleanups
8594        | RBufferOut n ->
8595            pr "PREINIT:\n";
8596            pr "      char *%s;\n" n;
8597            pr "      size_t size;\n";
8598            pr "   CODE:\n";
8599            pr "      %s = guestfs_%s " n name;
8600            generate_c_call_args ~handle:"g" style;
8601            pr ";\n";
8602            do_cleanups ();
8603            pr "      if (%s == NULL)\n" n;
8604            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8605            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8606            pr "      free (%s);\n" n;
8607            pr " OUTPUT:\n";
8608            pr "      RETVAL\n"
8609       );
8610
8611       pr "\n"
8612   ) all_functions
8613
8614 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8615   pr "PREINIT:\n";
8616   pr "      struct guestfs_%s_list *%s;\n" typ n;
8617   pr "      int i;\n";
8618   pr "      HV *hv;\n";
8619   pr " PPCODE:\n";
8620   pr "      %s = guestfs_%s " n name;
8621   generate_c_call_args ~handle:"g" style;
8622   pr ";\n";
8623   do_cleanups ();
8624   pr "      if (%s == NULL)\n" n;
8625   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8626   pr "      EXTEND (SP, %s->len);\n" n;
8627   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8628   pr "        hv = newHV ();\n";
8629   List.iter (
8630     function
8631     | name, FString ->
8632         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8633           name (String.length name) n name
8634     | name, FUUID ->
8635         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8636           name (String.length name) n name
8637     | name, FBuffer ->
8638         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8639           name (String.length name) n name n name
8640     | name, (FBytes|FUInt64) ->
8641         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8642           name (String.length name) n name
8643     | name, FInt64 ->
8644         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8645           name (String.length name) n name
8646     | name, (FInt32|FUInt32) ->
8647         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8648           name (String.length name) n name
8649     | name, FChar ->
8650         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8651           name (String.length name) n name
8652     | name, FOptPercent ->
8653         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8654           name (String.length name) n name
8655   ) cols;
8656   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8657   pr "      }\n";
8658   pr "      guestfs_free_%s_list (%s);\n" typ n
8659
8660 and generate_perl_struct_code typ cols name style n do_cleanups =
8661   pr "PREINIT:\n";
8662   pr "      struct guestfs_%s *%s;\n" typ n;
8663   pr " PPCODE:\n";
8664   pr "      %s = guestfs_%s " n name;
8665   generate_c_call_args ~handle:"g" style;
8666   pr ";\n";
8667   do_cleanups ();
8668   pr "      if (%s == NULL)\n" n;
8669   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8670   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8671   List.iter (
8672     fun ((name, _) as col) ->
8673       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8674
8675       match col with
8676       | name, FString ->
8677           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8678             n name
8679       | name, FBuffer ->
8680           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8681             n name n name
8682       | name, FUUID ->
8683           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8684             n name
8685       | name, (FBytes|FUInt64) ->
8686           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8687             n name
8688       | name, FInt64 ->
8689           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8690             n name
8691       | name, (FInt32|FUInt32) ->
8692           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8693             n name
8694       | name, FChar ->
8695           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8696             n name
8697       | name, FOptPercent ->
8698           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8699             n name
8700   ) cols;
8701   pr "      free (%s);\n" n
8702
8703 (* Generate Sys/Guestfs.pm. *)
8704 and generate_perl_pm () =
8705   generate_header HashStyle LGPLv2plus;
8706
8707   pr "\
8708 =pod
8709
8710 =head1 NAME
8711
8712 Sys::Guestfs - Perl bindings for libguestfs
8713
8714 =head1 SYNOPSIS
8715
8716  use Sys::Guestfs;
8717
8718  my $h = Sys::Guestfs->new ();
8719  $h->add_drive ('guest.img');
8720  $h->launch ();
8721  $h->mount ('/dev/sda1', '/');
8722  $h->touch ('/hello');
8723  $h->sync ();
8724
8725 =head1 DESCRIPTION
8726
8727 The C<Sys::Guestfs> module provides a Perl XS binding to the
8728 libguestfs API for examining and modifying virtual machine
8729 disk images.
8730
8731 Amongst the things this is good for: making batch configuration
8732 changes to guests, getting disk used/free statistics (see also:
8733 virt-df), migrating between virtualization systems (see also:
8734 virt-p2v), performing partial backups, performing partial guest
8735 clones, cloning guests and changing registry/UUID/hostname info, and
8736 much else besides.
8737
8738 Libguestfs uses Linux kernel and qemu code, and can access any type of
8739 guest filesystem that Linux and qemu can, including but not limited
8740 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8741 schemes, qcow, qcow2, vmdk.
8742
8743 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8744 LVs, what filesystem is in each LV, etc.).  It can also run commands
8745 in the context of the guest.  Also you can access filesystems over
8746 FUSE.
8747
8748 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8749 functions for using libguestfs from Perl, including integration
8750 with libvirt.
8751
8752 =head1 ERRORS
8753
8754 All errors turn into calls to C<croak> (see L<Carp(3)>).
8755
8756 =head1 METHODS
8757
8758 =over 4
8759
8760 =cut
8761
8762 package Sys::Guestfs;
8763
8764 use strict;
8765 use warnings;
8766
8767 require XSLoader;
8768 XSLoader::load ('Sys::Guestfs');
8769
8770 =item $h = Sys::Guestfs->new ();
8771
8772 Create a new guestfs handle.
8773
8774 =cut
8775
8776 sub new {
8777   my $proto = shift;
8778   my $class = ref ($proto) || $proto;
8779
8780   my $self = Sys::Guestfs::_create ();
8781   bless $self, $class;
8782   return $self;
8783 }
8784
8785 ";
8786
8787   (* Actions.  We only need to print documentation for these as
8788    * they are pulled in from the XS code automatically.
8789    *)
8790   List.iter (
8791     fun (name, style, _, flags, _, _, longdesc) ->
8792       if not (List.mem NotInDocs flags) then (
8793         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8794         pr "=item ";
8795         generate_perl_prototype name style;
8796         pr "\n\n";
8797         pr "%s\n\n" longdesc;
8798         if List.mem ProtocolLimitWarning flags then
8799           pr "%s\n\n" protocol_limit_warning;
8800         if List.mem DangerWillRobinson flags then
8801           pr "%s\n\n" danger_will_robinson;
8802         match deprecation_notice flags with
8803         | None -> ()
8804         | Some txt -> pr "%s\n\n" txt
8805       )
8806   ) all_functions_sorted;
8807
8808   (* End of file. *)
8809   pr "\
8810 =cut
8811
8812 1;
8813
8814 =back
8815
8816 =head1 COPYRIGHT
8817
8818 Copyright (C) %s Red Hat Inc.
8819
8820 =head1 LICENSE
8821
8822 Please see the file COPYING.LIB for the full license.
8823
8824 =head1 SEE ALSO
8825
8826 L<guestfs(3)>,
8827 L<guestfish(1)>,
8828 L<http://libguestfs.org>,
8829 L<Sys::Guestfs::Lib(3)>.
8830
8831 =cut
8832 " copyright_years
8833
8834 and generate_perl_prototype name style =
8835   (match fst style with
8836    | RErr -> ()
8837    | RBool n
8838    | RInt n
8839    | RInt64 n
8840    | RConstString n
8841    | RConstOptString n
8842    | RString n
8843    | RBufferOut n -> pr "$%s = " n
8844    | RStruct (n,_)
8845    | RHashtable n -> pr "%%%s = " n
8846    | RStringList n
8847    | RStructList (n,_) -> pr "@%s = " n
8848   );
8849   pr "$h->%s (" name;
8850   let comma = ref false in
8851   List.iter (
8852     fun arg ->
8853       if !comma then pr ", ";
8854       comma := true;
8855       match arg with
8856       | Pathname n | Device n | Dev_or_Path n | String n
8857       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8858           pr "$%s" n
8859       | StringList n | DeviceList n ->
8860           pr "\\@%s" n
8861   ) (snd style);
8862   pr ");"
8863
8864 (* Generate Python C module. *)
8865 and generate_python_c () =
8866   generate_header CStyle LGPLv2plus;
8867
8868   pr "\
8869 #include <Python.h>
8870
8871 #include <stdio.h>
8872 #include <stdlib.h>
8873 #include <assert.h>
8874
8875 #include \"guestfs.h\"
8876
8877 typedef struct {
8878   PyObject_HEAD
8879   guestfs_h *g;
8880 } Pyguestfs_Object;
8881
8882 static guestfs_h *
8883 get_handle (PyObject *obj)
8884 {
8885   assert (obj);
8886   assert (obj != Py_None);
8887   return ((Pyguestfs_Object *) obj)->g;
8888 }
8889
8890 static PyObject *
8891 put_handle (guestfs_h *g)
8892 {
8893   assert (g);
8894   return
8895     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8896 }
8897
8898 /* This list should be freed (but not the strings) after use. */
8899 static char **
8900 get_string_list (PyObject *obj)
8901 {
8902   int i, len;
8903   char **r;
8904
8905   assert (obj);
8906
8907   if (!PyList_Check (obj)) {
8908     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8909     return NULL;
8910   }
8911
8912   len = PyList_Size (obj);
8913   r = malloc (sizeof (char *) * (len+1));
8914   if (r == NULL) {
8915     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8916     return NULL;
8917   }
8918
8919   for (i = 0; i < len; ++i)
8920     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8921   r[len] = NULL;
8922
8923   return r;
8924 }
8925
8926 static PyObject *
8927 put_string_list (char * const * const argv)
8928 {
8929   PyObject *list;
8930   int argc, i;
8931
8932   for (argc = 0; argv[argc] != NULL; ++argc)
8933     ;
8934
8935   list = PyList_New (argc);
8936   for (i = 0; i < argc; ++i)
8937     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8938
8939   return list;
8940 }
8941
8942 static PyObject *
8943 put_table (char * const * const argv)
8944 {
8945   PyObject *list, *item;
8946   int argc, i;
8947
8948   for (argc = 0; argv[argc] != NULL; ++argc)
8949     ;
8950
8951   list = PyList_New (argc >> 1);
8952   for (i = 0; i < argc; i += 2) {
8953     item = PyTuple_New (2);
8954     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8955     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8956     PyList_SetItem (list, i >> 1, item);
8957   }
8958
8959   return list;
8960 }
8961
8962 static void
8963 free_strings (char **argv)
8964 {
8965   int argc;
8966
8967   for (argc = 0; argv[argc] != NULL; ++argc)
8968     free (argv[argc]);
8969   free (argv);
8970 }
8971
8972 static PyObject *
8973 py_guestfs_create (PyObject *self, PyObject *args)
8974 {
8975   guestfs_h *g;
8976
8977   g = guestfs_create ();
8978   if (g == NULL) {
8979     PyErr_SetString (PyExc_RuntimeError,
8980                      \"guestfs.create: failed to allocate handle\");
8981     return NULL;
8982   }
8983   guestfs_set_error_handler (g, NULL, NULL);
8984   return put_handle (g);
8985 }
8986
8987 static PyObject *
8988 py_guestfs_close (PyObject *self, PyObject *args)
8989 {
8990   PyObject *py_g;
8991   guestfs_h *g;
8992
8993   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8994     return NULL;
8995   g = get_handle (py_g);
8996
8997   guestfs_close (g);
8998
8999   Py_INCREF (Py_None);
9000   return Py_None;
9001 }
9002
9003 ";
9004
9005   let emit_put_list_function typ =
9006     pr "static PyObject *\n";
9007     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9008     pr "{\n";
9009     pr "  PyObject *list;\n";
9010     pr "  int i;\n";
9011     pr "\n";
9012     pr "  list = PyList_New (%ss->len);\n" typ;
9013     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9014     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9015     pr "  return list;\n";
9016     pr "};\n";
9017     pr "\n"
9018   in
9019
9020   (* Structures, turned into Python dictionaries. *)
9021   List.iter (
9022     fun (typ, cols) ->
9023       pr "static PyObject *\n";
9024       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9025       pr "{\n";
9026       pr "  PyObject *dict;\n";
9027       pr "\n";
9028       pr "  dict = PyDict_New ();\n";
9029       List.iter (
9030         function
9031         | name, FString ->
9032             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9033             pr "                        PyString_FromString (%s->%s));\n"
9034               typ name
9035         | name, FBuffer ->
9036             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9037             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9038               typ name typ name
9039         | name, FUUID ->
9040             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9041             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9042               typ name
9043         | name, (FBytes|FUInt64) ->
9044             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9045             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9046               typ name
9047         | name, FInt64 ->
9048             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9049             pr "                        PyLong_FromLongLong (%s->%s));\n"
9050               typ name
9051         | name, FUInt32 ->
9052             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9053             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9054               typ name
9055         | name, FInt32 ->
9056             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9057             pr "                        PyLong_FromLong (%s->%s));\n"
9058               typ name
9059         | name, FOptPercent ->
9060             pr "  if (%s->%s >= 0)\n" typ name;
9061             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9062             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9063               typ name;
9064             pr "  else {\n";
9065             pr "    Py_INCREF (Py_None);\n";
9066             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9067             pr "  }\n"
9068         | name, FChar ->
9069             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9070             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9071       ) cols;
9072       pr "  return dict;\n";
9073       pr "};\n";
9074       pr "\n";
9075
9076   ) structs;
9077
9078   (* Emit a put_TYPE_list function definition only if that function is used. *)
9079   List.iter (
9080     function
9081     | typ, (RStructListOnly | RStructAndList) ->
9082         (* generate the function for typ *)
9083         emit_put_list_function typ
9084     | typ, _ -> () (* empty *)
9085   ) (rstructs_used_by all_functions);
9086
9087   (* Python wrapper functions. *)
9088   List.iter (
9089     fun (name, style, _, _, _, _, _) ->
9090       pr "static PyObject *\n";
9091       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9092       pr "{\n";
9093
9094       pr "  PyObject *py_g;\n";
9095       pr "  guestfs_h *g;\n";
9096       pr "  PyObject *py_r;\n";
9097
9098       let error_code =
9099         match fst style with
9100         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9101         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9102         | RConstString _ | RConstOptString _ ->
9103             pr "  const char *r;\n"; "NULL"
9104         | RString _ -> pr "  char *r;\n"; "NULL"
9105         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9106         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9107         | RStructList (_, typ) ->
9108             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9109         | RBufferOut _ ->
9110             pr "  char *r;\n";
9111             pr "  size_t size;\n";
9112             "NULL" in
9113
9114       List.iter (
9115         function
9116         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9117             pr "  const char *%s;\n" n
9118         | OptString n -> pr "  const char *%s;\n" n
9119         | StringList n | DeviceList n ->
9120             pr "  PyObject *py_%s;\n" n;
9121             pr "  char **%s;\n" n
9122         | Bool n -> pr "  int %s;\n" n
9123         | Int n -> pr "  int %s;\n" n
9124         | Int64 n -> pr "  long long %s;\n" n
9125       ) (snd style);
9126
9127       pr "\n";
9128
9129       (* Convert the parameters. *)
9130       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9131       List.iter (
9132         function
9133         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9134         | OptString _ -> pr "z"
9135         | StringList _ | DeviceList _ -> pr "O"
9136         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9137         | Int _ -> pr "i"
9138         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9139                              * emulate C's int/long/long long in Python?
9140                              *)
9141       ) (snd style);
9142       pr ":guestfs_%s\",\n" name;
9143       pr "                         &py_g";
9144       List.iter (
9145         function
9146         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9147         | OptString n -> pr ", &%s" n
9148         | StringList n | DeviceList n -> pr ", &py_%s" n
9149         | Bool n -> pr ", &%s" n
9150         | Int n -> pr ", &%s" n
9151         | Int64 n -> pr ", &%s" n
9152       ) (snd style);
9153
9154       pr "))\n";
9155       pr "    return NULL;\n";
9156
9157       pr "  g = get_handle (py_g);\n";
9158       List.iter (
9159         function
9160         | Pathname _ | Device _ | Dev_or_Path _ | String _
9161         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9162         | StringList n | DeviceList n ->
9163             pr "  %s = get_string_list (py_%s);\n" n n;
9164             pr "  if (!%s) return NULL;\n" n
9165       ) (snd style);
9166
9167       pr "\n";
9168
9169       pr "  r = guestfs_%s " name;
9170       generate_c_call_args ~handle:"g" style;
9171       pr ";\n";
9172
9173       List.iter (
9174         function
9175         | Pathname _ | Device _ | Dev_or_Path _ | String _
9176         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9177         | StringList n | DeviceList n ->
9178             pr "  free (%s);\n" n
9179       ) (snd style);
9180
9181       pr "  if (r == %s) {\n" error_code;
9182       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9183       pr "    return NULL;\n";
9184       pr "  }\n";
9185       pr "\n";
9186
9187       (match fst style with
9188        | RErr ->
9189            pr "  Py_INCREF (Py_None);\n";
9190            pr "  py_r = Py_None;\n"
9191        | RInt _
9192        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9193        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9194        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9195        | RConstOptString _ ->
9196            pr "  if (r)\n";
9197            pr "    py_r = PyString_FromString (r);\n";
9198            pr "  else {\n";
9199            pr "    Py_INCREF (Py_None);\n";
9200            pr "    py_r = Py_None;\n";
9201            pr "  }\n"
9202        | RString _ ->
9203            pr "  py_r = PyString_FromString (r);\n";
9204            pr "  free (r);\n"
9205        | RStringList _ ->
9206            pr "  py_r = put_string_list (r);\n";
9207            pr "  free_strings (r);\n"
9208        | RStruct (_, typ) ->
9209            pr "  py_r = put_%s (r);\n" typ;
9210            pr "  guestfs_free_%s (r);\n" typ
9211        | RStructList (_, typ) ->
9212            pr "  py_r = put_%s_list (r);\n" typ;
9213            pr "  guestfs_free_%s_list (r);\n" typ
9214        | RHashtable n ->
9215            pr "  py_r = put_table (r);\n";
9216            pr "  free_strings (r);\n"
9217        | RBufferOut _ ->
9218            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9219            pr "  free (r);\n"
9220       );
9221
9222       pr "  return py_r;\n";
9223       pr "}\n";
9224       pr "\n"
9225   ) all_functions;
9226
9227   (* Table of functions. *)
9228   pr "static PyMethodDef methods[] = {\n";
9229   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9230   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9231   List.iter (
9232     fun (name, _, _, _, _, _, _) ->
9233       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9234         name name
9235   ) all_functions;
9236   pr "  { NULL, NULL, 0, NULL }\n";
9237   pr "};\n";
9238   pr "\n";
9239
9240   (* Init function. *)
9241   pr "\
9242 void
9243 initlibguestfsmod (void)
9244 {
9245   static int initialized = 0;
9246
9247   if (initialized) return;
9248   Py_InitModule ((char *) \"libguestfsmod\", methods);
9249   initialized = 1;
9250 }
9251 "
9252
9253 (* Generate Python module. *)
9254 and generate_python_py () =
9255   generate_header HashStyle LGPLv2plus;
9256
9257   pr "\
9258 u\"\"\"Python bindings for libguestfs
9259
9260 import guestfs
9261 g = guestfs.GuestFS ()
9262 g.add_drive (\"guest.img\")
9263 g.launch ()
9264 parts = g.list_partitions ()
9265
9266 The guestfs module provides a Python binding to the libguestfs API
9267 for examining and modifying virtual machine disk images.
9268
9269 Amongst the things this is good for: making batch configuration
9270 changes to guests, getting disk used/free statistics (see also:
9271 virt-df), migrating between virtualization systems (see also:
9272 virt-p2v), performing partial backups, performing partial guest
9273 clones, cloning guests and changing registry/UUID/hostname info, and
9274 much else besides.
9275
9276 Libguestfs uses Linux kernel and qemu code, and can access any type of
9277 guest filesystem that Linux and qemu can, including but not limited
9278 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9279 schemes, qcow, qcow2, vmdk.
9280
9281 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9282 LVs, what filesystem is in each LV, etc.).  It can also run commands
9283 in the context of the guest.  Also you can access filesystems over
9284 FUSE.
9285
9286 Errors which happen while using the API are turned into Python
9287 RuntimeError exceptions.
9288
9289 To create a guestfs handle you usually have to perform the following
9290 sequence of calls:
9291
9292 # Create the handle, call add_drive at least once, and possibly
9293 # several times if the guest has multiple block devices:
9294 g = guestfs.GuestFS ()
9295 g.add_drive (\"guest.img\")
9296
9297 # Launch the qemu subprocess and wait for it to become ready:
9298 g.launch ()
9299
9300 # Now you can issue commands, for example:
9301 logvols = g.lvs ()
9302
9303 \"\"\"
9304
9305 import libguestfsmod
9306
9307 class GuestFS:
9308     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9309
9310     def __init__ (self):
9311         \"\"\"Create a new libguestfs handle.\"\"\"
9312         self._o = libguestfsmod.create ()
9313
9314     def __del__ (self):
9315         libguestfsmod.close (self._o)
9316
9317 ";
9318
9319   List.iter (
9320     fun (name, style, _, flags, _, _, longdesc) ->
9321       pr "    def %s " name;
9322       generate_py_call_args ~handle:"self" (snd style);
9323       pr ":\n";
9324
9325       if not (List.mem NotInDocs flags) then (
9326         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9327         let doc =
9328           match fst style with
9329           | RErr | RInt _ | RInt64 _ | RBool _
9330           | RConstOptString _ | RConstString _
9331           | RString _ | RBufferOut _ -> doc
9332           | RStringList _ ->
9333               doc ^ "\n\nThis function returns a list of strings."
9334           | RStruct (_, typ) ->
9335               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9336           | RStructList (_, typ) ->
9337               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9338           | RHashtable _ ->
9339               doc ^ "\n\nThis function returns a dictionary." in
9340         let doc =
9341           if List.mem ProtocolLimitWarning flags then
9342             doc ^ "\n\n" ^ protocol_limit_warning
9343           else doc in
9344         let doc =
9345           if List.mem DangerWillRobinson flags then
9346             doc ^ "\n\n" ^ danger_will_robinson
9347           else doc in
9348         let doc =
9349           match deprecation_notice flags with
9350           | None -> doc
9351           | Some txt -> doc ^ "\n\n" ^ txt in
9352         let doc = pod2text ~width:60 name doc in
9353         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9354         let doc = String.concat "\n        " doc in
9355         pr "        u\"\"\"%s\"\"\"\n" doc;
9356       );
9357       pr "        return libguestfsmod.%s " name;
9358       generate_py_call_args ~handle:"self._o" (snd style);
9359       pr "\n";
9360       pr "\n";
9361   ) all_functions
9362
9363 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9364 and generate_py_call_args ~handle args =
9365   pr "(%s" handle;
9366   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9367   pr ")"
9368
9369 (* Useful if you need the longdesc POD text as plain text.  Returns a
9370  * list of lines.
9371  *
9372  * Because this is very slow (the slowest part of autogeneration),
9373  * we memoize the results.
9374  *)
9375 and pod2text ~width name longdesc =
9376   let key = width, name, longdesc in
9377   try Hashtbl.find pod2text_memo key
9378   with Not_found ->
9379     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9380     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9381     close_out chan;
9382     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9383     let chan = open_process_in cmd in
9384     let lines = ref [] in
9385     let rec loop i =
9386       let line = input_line chan in
9387       if i = 1 then             (* discard the first line of output *)
9388         loop (i+1)
9389       else (
9390         let line = triml line in
9391         lines := line :: !lines;
9392         loop (i+1)
9393       ) in
9394     let lines = try loop 1 with End_of_file -> List.rev !lines in
9395     unlink filename;
9396     (match close_process_in chan with
9397      | WEXITED 0 -> ()
9398      | WEXITED i ->
9399          failwithf "pod2text: process exited with non-zero status (%d)" i
9400      | WSIGNALED i | WSTOPPED i ->
9401          failwithf "pod2text: process signalled or stopped by signal %d" i
9402     );
9403     Hashtbl.add pod2text_memo key lines;
9404     pod2text_memo_updated ();
9405     lines
9406
9407 (* Generate ruby bindings. *)
9408 and generate_ruby_c () =
9409   generate_header CStyle LGPLv2plus;
9410
9411   pr "\
9412 #include <stdio.h>
9413 #include <stdlib.h>
9414
9415 #include <ruby.h>
9416
9417 #include \"guestfs.h\"
9418
9419 #include \"extconf.h\"
9420
9421 /* For Ruby < 1.9 */
9422 #ifndef RARRAY_LEN
9423 #define RARRAY_LEN(r) (RARRAY((r))->len)
9424 #endif
9425
9426 static VALUE m_guestfs;                 /* guestfs module */
9427 static VALUE c_guestfs;                 /* guestfs_h handle */
9428 static VALUE e_Error;                   /* used for all errors */
9429
9430 static void ruby_guestfs_free (void *p)
9431 {
9432   if (!p) return;
9433   guestfs_close ((guestfs_h *) p);
9434 }
9435
9436 static VALUE ruby_guestfs_create (VALUE m)
9437 {
9438   guestfs_h *g;
9439
9440   g = guestfs_create ();
9441   if (!g)
9442     rb_raise (e_Error, \"failed to create guestfs handle\");
9443
9444   /* Don't print error messages to stderr by default. */
9445   guestfs_set_error_handler (g, NULL, NULL);
9446
9447   /* Wrap it, and make sure the close function is called when the
9448    * handle goes away.
9449    */
9450   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9451 }
9452
9453 static VALUE ruby_guestfs_close (VALUE gv)
9454 {
9455   guestfs_h *g;
9456   Data_Get_Struct (gv, guestfs_h, g);
9457
9458   ruby_guestfs_free (g);
9459   DATA_PTR (gv) = NULL;
9460
9461   return Qnil;
9462 }
9463
9464 ";
9465
9466   List.iter (
9467     fun (name, style, _, _, _, _, _) ->
9468       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9469       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9470       pr ")\n";
9471       pr "{\n";
9472       pr "  guestfs_h *g;\n";
9473       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9474       pr "  if (!g)\n";
9475       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9476         name;
9477       pr "\n";
9478
9479       List.iter (
9480         function
9481         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9482             pr "  Check_Type (%sv, T_STRING);\n" n;
9483             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9484             pr "  if (!%s)\n" n;
9485             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9486             pr "              \"%s\", \"%s\");\n" n name
9487         | OptString n ->
9488             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9489         | StringList n | DeviceList n ->
9490             pr "  char **%s;\n" n;
9491             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9492             pr "  {\n";
9493             pr "    int i, len;\n";
9494             pr "    len = RARRAY_LEN (%sv);\n" n;
9495             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9496               n;
9497             pr "    for (i = 0; i < len; ++i) {\n";
9498             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9499             pr "      %s[i] = StringValueCStr (v);\n" n;
9500             pr "    }\n";
9501             pr "    %s[len] = NULL;\n" n;
9502             pr "  }\n";
9503         | Bool n ->
9504             pr "  int %s = RTEST (%sv);\n" n n
9505         | Int n ->
9506             pr "  int %s = NUM2INT (%sv);\n" n n
9507         | Int64 n ->
9508             pr "  long long %s = NUM2LL (%sv);\n" n n
9509       ) (snd style);
9510       pr "\n";
9511
9512       let error_code =
9513         match fst style with
9514         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9515         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9516         | RConstString _ | RConstOptString _ ->
9517             pr "  const char *r;\n"; "NULL"
9518         | RString _ -> pr "  char *r;\n"; "NULL"
9519         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9520         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9521         | RStructList (_, typ) ->
9522             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9523         | RBufferOut _ ->
9524             pr "  char *r;\n";
9525             pr "  size_t size;\n";
9526             "NULL" in
9527       pr "\n";
9528
9529       pr "  r = guestfs_%s " name;
9530       generate_c_call_args ~handle:"g" style;
9531       pr ";\n";
9532
9533       List.iter (
9534         function
9535         | Pathname _ | Device _ | Dev_or_Path _ | String _
9536         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9537         | StringList n | DeviceList n ->
9538             pr "  free (%s);\n" n
9539       ) (snd style);
9540
9541       pr "  if (r == %s)\n" error_code;
9542       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9543       pr "\n";
9544
9545       (match fst style with
9546        | RErr ->
9547            pr "  return Qnil;\n"
9548        | RInt _ | RBool _ ->
9549            pr "  return INT2NUM (r);\n"
9550        | RInt64 _ ->
9551            pr "  return ULL2NUM (r);\n"
9552        | RConstString _ ->
9553            pr "  return rb_str_new2 (r);\n";
9554        | RConstOptString _ ->
9555            pr "  if (r)\n";
9556            pr "    return rb_str_new2 (r);\n";
9557            pr "  else\n";
9558            pr "    return Qnil;\n";
9559        | RString _ ->
9560            pr "  VALUE rv = rb_str_new2 (r);\n";
9561            pr "  free (r);\n";
9562            pr "  return rv;\n";
9563        | RStringList _ ->
9564            pr "  int i, len = 0;\n";
9565            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9566            pr "  VALUE rv = rb_ary_new2 (len);\n";
9567            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9568            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9569            pr "    free (r[i]);\n";
9570            pr "  }\n";
9571            pr "  free (r);\n";
9572            pr "  return rv;\n"
9573        | RStruct (_, typ) ->
9574            let cols = cols_of_struct typ in
9575            generate_ruby_struct_code typ cols
9576        | RStructList (_, typ) ->
9577            let cols = cols_of_struct typ in
9578            generate_ruby_struct_list_code typ cols
9579        | RHashtable _ ->
9580            pr "  VALUE rv = rb_hash_new ();\n";
9581            pr "  int i;\n";
9582            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9583            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9584            pr "    free (r[i]);\n";
9585            pr "    free (r[i+1]);\n";
9586            pr "  }\n";
9587            pr "  free (r);\n";
9588            pr "  return rv;\n"
9589        | RBufferOut _ ->
9590            pr "  VALUE rv = rb_str_new (r, size);\n";
9591            pr "  free (r);\n";
9592            pr "  return rv;\n";
9593       );
9594
9595       pr "}\n";
9596       pr "\n"
9597   ) all_functions;
9598
9599   pr "\
9600 /* Initialize the module. */
9601 void Init__guestfs ()
9602 {
9603   m_guestfs = rb_define_module (\"Guestfs\");
9604   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9605   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9606
9607   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9608   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9609
9610 ";
9611   (* Define the rest of the methods. *)
9612   List.iter (
9613     fun (name, style, _, _, _, _, _) ->
9614       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9615       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9616   ) all_functions;
9617
9618   pr "}\n"
9619
9620 (* Ruby code to return a struct. *)
9621 and generate_ruby_struct_code typ cols =
9622   pr "  VALUE rv = rb_hash_new ();\n";
9623   List.iter (
9624     function
9625     | name, FString ->
9626         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9627     | name, FBuffer ->
9628         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9629     | name, FUUID ->
9630         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9631     | name, (FBytes|FUInt64) ->
9632         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9633     | name, FInt64 ->
9634         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9635     | name, FUInt32 ->
9636         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9637     | name, FInt32 ->
9638         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9639     | name, FOptPercent ->
9640         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9641     | name, FChar -> (* XXX wrong? *)
9642         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9643   ) cols;
9644   pr "  guestfs_free_%s (r);\n" typ;
9645   pr "  return rv;\n"
9646
9647 (* Ruby code to return a struct list. *)
9648 and generate_ruby_struct_list_code typ cols =
9649   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9650   pr "  int i;\n";
9651   pr "  for (i = 0; i < r->len; ++i) {\n";
9652   pr "    VALUE hv = rb_hash_new ();\n";
9653   List.iter (
9654     function
9655     | name, FString ->
9656         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9657     | name, FBuffer ->
9658         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
9659     | name, FUUID ->
9660         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9661     | name, (FBytes|FUInt64) ->
9662         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9663     | name, FInt64 ->
9664         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9665     | name, FUInt32 ->
9666         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9667     | name, FInt32 ->
9668         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9669     | name, FOptPercent ->
9670         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9671     | name, FChar -> (* XXX wrong? *)
9672         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9673   ) cols;
9674   pr "    rb_ary_push (rv, hv);\n";
9675   pr "  }\n";
9676   pr "  guestfs_free_%s_list (r);\n" typ;
9677   pr "  return rv;\n"
9678
9679 (* Generate Java bindings GuestFS.java file. *)
9680 and generate_java_java () =
9681   generate_header CStyle LGPLv2plus;
9682
9683   pr "\
9684 package com.redhat.et.libguestfs;
9685
9686 import java.util.HashMap;
9687 import com.redhat.et.libguestfs.LibGuestFSException;
9688 import com.redhat.et.libguestfs.PV;
9689 import com.redhat.et.libguestfs.VG;
9690 import com.redhat.et.libguestfs.LV;
9691 import com.redhat.et.libguestfs.Stat;
9692 import com.redhat.et.libguestfs.StatVFS;
9693 import com.redhat.et.libguestfs.IntBool;
9694 import com.redhat.et.libguestfs.Dirent;
9695
9696 /**
9697  * The GuestFS object is a libguestfs handle.
9698  *
9699  * @author rjones
9700  */
9701 public class GuestFS {
9702   // Load the native code.
9703   static {
9704     System.loadLibrary (\"guestfs_jni\");
9705   }
9706
9707   /**
9708    * The native guestfs_h pointer.
9709    */
9710   long g;
9711
9712   /**
9713    * Create a libguestfs handle.
9714    *
9715    * @throws LibGuestFSException
9716    */
9717   public GuestFS () throws LibGuestFSException
9718   {
9719     g = _create ();
9720   }
9721   private native long _create () throws LibGuestFSException;
9722
9723   /**
9724    * Close a libguestfs handle.
9725    *
9726    * You can also leave handles to be collected by the garbage
9727    * collector, but this method ensures that the resources used
9728    * by the handle are freed up immediately.  If you call any
9729    * other methods after closing the handle, you will get an
9730    * exception.
9731    *
9732    * @throws LibGuestFSException
9733    */
9734   public void close () throws LibGuestFSException
9735   {
9736     if (g != 0)
9737       _close (g);
9738     g = 0;
9739   }
9740   private native void _close (long g) throws LibGuestFSException;
9741
9742   public void finalize () throws LibGuestFSException
9743   {
9744     close ();
9745   }
9746
9747 ";
9748
9749   List.iter (
9750     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9751       if not (List.mem NotInDocs flags); then (
9752         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9753         let doc =
9754           if List.mem ProtocolLimitWarning flags then
9755             doc ^ "\n\n" ^ protocol_limit_warning
9756           else doc in
9757         let doc =
9758           if List.mem DangerWillRobinson flags then
9759             doc ^ "\n\n" ^ danger_will_robinson
9760           else doc in
9761         let doc =
9762           match deprecation_notice flags with
9763           | None -> doc
9764           | Some txt -> doc ^ "\n\n" ^ txt in
9765         let doc = pod2text ~width:60 name doc in
9766         let doc = List.map (            (* RHBZ#501883 *)
9767           function
9768           | "" -> "<p>"
9769           | nonempty -> nonempty
9770         ) doc in
9771         let doc = String.concat "\n   * " doc in
9772
9773         pr "  /**\n";
9774         pr "   * %s\n" shortdesc;
9775         pr "   * <p>\n";
9776         pr "   * %s\n" doc;
9777         pr "   * @throws LibGuestFSException\n";
9778         pr "   */\n";
9779         pr "  ";
9780       );
9781       generate_java_prototype ~public:true ~semicolon:false name style;
9782       pr "\n";
9783       pr "  {\n";
9784       pr "    if (g == 0)\n";
9785       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9786         name;
9787       pr "    ";
9788       if fst style <> RErr then pr "return ";
9789       pr "_%s " name;
9790       generate_java_call_args ~handle:"g" (snd style);
9791       pr ";\n";
9792       pr "  }\n";
9793       pr "  ";
9794       generate_java_prototype ~privat:true ~native:true name style;
9795       pr "\n";
9796       pr "\n";
9797   ) all_functions;
9798
9799   pr "}\n"
9800
9801 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9802 and generate_java_call_args ~handle args =
9803   pr "(%s" handle;
9804   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9805   pr ")"
9806
9807 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9808     ?(semicolon=true) name style =
9809   if privat then pr "private ";
9810   if public then pr "public ";
9811   if native then pr "native ";
9812
9813   (* return type *)
9814   (match fst style with
9815    | RErr -> pr "void ";
9816    | RInt _ -> pr "int ";
9817    | RInt64 _ -> pr "long ";
9818    | RBool _ -> pr "boolean ";
9819    | RConstString _ | RConstOptString _ | RString _
9820    | RBufferOut _ -> pr "String ";
9821    | RStringList _ -> pr "String[] ";
9822    | RStruct (_, typ) ->
9823        let name = java_name_of_struct typ in
9824        pr "%s " name;
9825    | RStructList (_, typ) ->
9826        let name = java_name_of_struct typ in
9827        pr "%s[] " name;
9828    | RHashtable _ -> pr "HashMap<String,String> ";
9829   );
9830
9831   if native then pr "_%s " name else pr "%s " name;
9832   pr "(";
9833   let needs_comma = ref false in
9834   if native then (
9835     pr "long g";
9836     needs_comma := true
9837   );
9838
9839   (* args *)
9840   List.iter (
9841     fun arg ->
9842       if !needs_comma then pr ", ";
9843       needs_comma := true;
9844
9845       match arg with
9846       | Pathname n
9847       | Device n | Dev_or_Path n
9848       | String n
9849       | OptString n
9850       | FileIn n
9851       | FileOut n ->
9852           pr "String %s" n
9853       | StringList n | DeviceList n ->
9854           pr "String[] %s" n
9855       | Bool n ->
9856           pr "boolean %s" n
9857       | Int n ->
9858           pr "int %s" n
9859       | Int64 n ->
9860           pr "long %s" n
9861   ) (snd style);
9862
9863   pr ")\n";
9864   pr "    throws LibGuestFSException";
9865   if semicolon then pr ";"
9866
9867 and generate_java_struct jtyp cols () =
9868   generate_header CStyle LGPLv2plus;
9869
9870   pr "\
9871 package com.redhat.et.libguestfs;
9872
9873 /**
9874  * Libguestfs %s structure.
9875  *
9876  * @author rjones
9877  * @see GuestFS
9878  */
9879 public class %s {
9880 " jtyp jtyp;
9881
9882   List.iter (
9883     function
9884     | name, FString
9885     | name, FUUID
9886     | name, FBuffer -> pr "  public String %s;\n" name
9887     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9888     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9889     | name, FChar -> pr "  public char %s;\n" name
9890     | name, FOptPercent ->
9891         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9892         pr "  public float %s;\n" name
9893   ) cols;
9894
9895   pr "}\n"
9896
9897 and generate_java_c () =
9898   generate_header CStyle LGPLv2plus;
9899
9900   pr "\
9901 #include <stdio.h>
9902 #include <stdlib.h>
9903 #include <string.h>
9904
9905 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9906 #include \"guestfs.h\"
9907
9908 /* Note that this function returns.  The exception is not thrown
9909  * until after the wrapper function returns.
9910  */
9911 static void
9912 throw_exception (JNIEnv *env, const char *msg)
9913 {
9914   jclass cl;
9915   cl = (*env)->FindClass (env,
9916                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9917   (*env)->ThrowNew (env, cl, msg);
9918 }
9919
9920 JNIEXPORT jlong JNICALL
9921 Java_com_redhat_et_libguestfs_GuestFS__1create
9922   (JNIEnv *env, jobject obj)
9923 {
9924   guestfs_h *g;
9925
9926   g = guestfs_create ();
9927   if (g == NULL) {
9928     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9929     return 0;
9930   }
9931   guestfs_set_error_handler (g, NULL, NULL);
9932   return (jlong) (long) g;
9933 }
9934
9935 JNIEXPORT void JNICALL
9936 Java_com_redhat_et_libguestfs_GuestFS__1close
9937   (JNIEnv *env, jobject obj, jlong jg)
9938 {
9939   guestfs_h *g = (guestfs_h *) (long) jg;
9940   guestfs_close (g);
9941 }
9942
9943 ";
9944
9945   List.iter (
9946     fun (name, style, _, _, _, _, _) ->
9947       pr "JNIEXPORT ";
9948       (match fst style with
9949        | RErr -> pr "void ";
9950        | RInt _ -> pr "jint ";
9951        | RInt64 _ -> pr "jlong ";
9952        | RBool _ -> pr "jboolean ";
9953        | RConstString _ | RConstOptString _ | RString _
9954        | RBufferOut _ -> pr "jstring ";
9955        | RStruct _ | RHashtable _ ->
9956            pr "jobject ";
9957        | RStringList _ | RStructList _ ->
9958            pr "jobjectArray ";
9959       );
9960       pr "JNICALL\n";
9961       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9962       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9963       pr "\n";
9964       pr "  (JNIEnv *env, jobject obj, jlong jg";
9965       List.iter (
9966         function
9967         | Pathname n
9968         | Device n | Dev_or_Path n
9969         | String n
9970         | OptString n
9971         | FileIn n
9972         | FileOut n ->
9973             pr ", jstring j%s" n
9974         | StringList n | DeviceList n ->
9975             pr ", jobjectArray j%s" n
9976         | Bool n ->
9977             pr ", jboolean j%s" n
9978         | Int n ->
9979             pr ", jint j%s" n
9980         | Int64 n ->
9981             pr ", jlong j%s" n
9982       ) (snd style);
9983       pr ")\n";
9984       pr "{\n";
9985       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9986       let error_code, no_ret =
9987         match fst style with
9988         | RErr -> pr "  int r;\n"; "-1", ""
9989         | RBool _
9990         | RInt _ -> pr "  int r;\n"; "-1", "0"
9991         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9992         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9993         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9994         | RString _ ->
9995             pr "  jstring jr;\n";
9996             pr "  char *r;\n"; "NULL", "NULL"
9997         | RStringList _ ->
9998             pr "  jobjectArray jr;\n";
9999             pr "  int r_len;\n";
10000             pr "  jclass cl;\n";
10001             pr "  jstring jstr;\n";
10002             pr "  char **r;\n"; "NULL", "NULL"
10003         | RStruct (_, typ) ->
10004             pr "  jobject jr;\n";
10005             pr "  jclass cl;\n";
10006             pr "  jfieldID fl;\n";
10007             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10008         | RStructList (_, typ) ->
10009             pr "  jobjectArray jr;\n";
10010             pr "  jclass cl;\n";
10011             pr "  jfieldID fl;\n";
10012             pr "  jobject jfl;\n";
10013             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10014         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10015         | RBufferOut _ ->
10016             pr "  jstring jr;\n";
10017             pr "  char *r;\n";
10018             pr "  size_t size;\n";
10019             "NULL", "NULL" in
10020       List.iter (
10021         function
10022         | Pathname n
10023         | Device n | Dev_or_Path n
10024         | String n
10025         | OptString n
10026         | FileIn n
10027         | FileOut n ->
10028             pr "  const char *%s;\n" n
10029         | StringList n | DeviceList n ->
10030             pr "  int %s_len;\n" n;
10031             pr "  const char **%s;\n" n
10032         | Bool n
10033         | Int n ->
10034             pr "  int %s;\n" n
10035         | Int64 n ->
10036             pr "  int64_t %s;\n" n
10037       ) (snd style);
10038
10039       let needs_i =
10040         (match fst style with
10041          | RStringList _ | RStructList _ -> true
10042          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10043          | RConstOptString _
10044          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10045           List.exists (function
10046                        | StringList _ -> true
10047                        | DeviceList _ -> true
10048                        | _ -> false) (snd style) in
10049       if needs_i then
10050         pr "  int i;\n";
10051
10052       pr "\n";
10053
10054       (* Get the parameters. *)
10055       List.iter (
10056         function
10057         | Pathname n
10058         | Device n | Dev_or_Path n
10059         | String n
10060         | FileIn n
10061         | FileOut n ->
10062             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10063         | OptString n ->
10064             (* This is completely undocumented, but Java null becomes
10065              * a NULL parameter.
10066              *)
10067             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10068         | StringList n | DeviceList n ->
10069             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10070             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10071             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10072             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10073               n;
10074             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10075             pr "  }\n";
10076             pr "  %s[%s_len] = NULL;\n" n n;
10077         | Bool n
10078         | Int n
10079         | Int64 n ->
10080             pr "  %s = j%s;\n" n n
10081       ) (snd style);
10082
10083       (* Make the call. *)
10084       pr "  r = guestfs_%s " name;
10085       generate_c_call_args ~handle:"g" style;
10086       pr ";\n";
10087
10088       (* Release the parameters. *)
10089       List.iter (
10090         function
10091         | Pathname n
10092         | Device n | Dev_or_Path n
10093         | String n
10094         | FileIn n
10095         | FileOut n ->
10096             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10097         | OptString n ->
10098             pr "  if (j%s)\n" n;
10099             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10100         | StringList n | DeviceList n ->
10101             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10102             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10103               n;
10104             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10105             pr "  }\n";
10106             pr "  free (%s);\n" n
10107         | Bool n
10108         | Int n
10109         | Int64 n -> ()
10110       ) (snd style);
10111
10112       (* Check for errors. *)
10113       pr "  if (r == %s) {\n" error_code;
10114       pr "    throw_exception (env, guestfs_last_error (g));\n";
10115       pr "    return %s;\n" no_ret;
10116       pr "  }\n";
10117
10118       (* Return value. *)
10119       (match fst style with
10120        | RErr -> ()
10121        | RInt _ -> pr "  return (jint) r;\n"
10122        | RBool _ -> pr "  return (jboolean) r;\n"
10123        | RInt64 _ -> pr "  return (jlong) r;\n"
10124        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10125        | RConstOptString _ ->
10126            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10127        | RString _ ->
10128            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10129            pr "  free (r);\n";
10130            pr "  return jr;\n"
10131        | RStringList _ ->
10132            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10133            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10134            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10135            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10136            pr "  for (i = 0; i < r_len; ++i) {\n";
10137            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10138            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10139            pr "    free (r[i]);\n";
10140            pr "  }\n";
10141            pr "  free (r);\n";
10142            pr "  return jr;\n"
10143        | RStruct (_, typ) ->
10144            let jtyp = java_name_of_struct typ in
10145            let cols = cols_of_struct typ in
10146            generate_java_struct_return typ jtyp cols
10147        | RStructList (_, typ) ->
10148            let jtyp = java_name_of_struct typ in
10149            let cols = cols_of_struct typ in
10150            generate_java_struct_list_return typ jtyp cols
10151        | RHashtable _ ->
10152            (* XXX *)
10153            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10154            pr "  return NULL;\n"
10155        | RBufferOut _ ->
10156            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10157            pr "  free (r);\n";
10158            pr "  return jr;\n"
10159       );
10160
10161       pr "}\n";
10162       pr "\n"
10163   ) all_functions
10164
10165 and generate_java_struct_return typ jtyp cols =
10166   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10167   pr "  jr = (*env)->AllocObject (env, cl);\n";
10168   List.iter (
10169     function
10170     | name, FString ->
10171         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10172         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10173     | name, FUUID ->
10174         pr "  {\n";
10175         pr "    char s[33];\n";
10176         pr "    memcpy (s, r->%s, 32);\n" name;
10177         pr "    s[32] = 0;\n";
10178         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10179         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10180         pr "  }\n";
10181     | name, FBuffer ->
10182         pr "  {\n";
10183         pr "    int len = r->%s_len;\n" name;
10184         pr "    char s[len+1];\n";
10185         pr "    memcpy (s, r->%s, len);\n" name;
10186         pr "    s[len] = 0;\n";
10187         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10188         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10189         pr "  }\n";
10190     | name, (FBytes|FUInt64|FInt64) ->
10191         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10192         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10193     | name, (FUInt32|FInt32) ->
10194         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10195         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10196     | name, FOptPercent ->
10197         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10198         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10199     | name, FChar ->
10200         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10201         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10202   ) cols;
10203   pr "  free (r);\n";
10204   pr "  return jr;\n"
10205
10206 and generate_java_struct_list_return typ jtyp cols =
10207   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10208   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10209   pr "  for (i = 0; i < r->len; ++i) {\n";
10210   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10211   List.iter (
10212     function
10213     | name, FString ->
10214         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10215         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10216     | name, FUUID ->
10217         pr "    {\n";
10218         pr "      char s[33];\n";
10219         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10220         pr "      s[32] = 0;\n";
10221         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10222         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10223         pr "    }\n";
10224     | name, FBuffer ->
10225         pr "    {\n";
10226         pr "      int len = r->val[i].%s_len;\n" name;
10227         pr "      char s[len+1];\n";
10228         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10229         pr "      s[len] = 0;\n";
10230         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10231         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10232         pr "    }\n";
10233     | name, (FBytes|FUInt64|FInt64) ->
10234         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10235         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10236     | name, (FUInt32|FInt32) ->
10237         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10238         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10239     | name, FOptPercent ->
10240         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10241         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10242     | name, FChar ->
10243         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10244         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10245   ) cols;
10246   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10247   pr "  }\n";
10248   pr "  guestfs_free_%s_list (r);\n" typ;
10249   pr "  return jr;\n"
10250
10251 and generate_java_makefile_inc () =
10252   generate_header HashStyle GPLv2plus;
10253
10254   pr "java_built_sources = \\\n";
10255   List.iter (
10256     fun (typ, jtyp) ->
10257         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10258   ) java_structs;
10259   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10260
10261 and generate_haskell_hs () =
10262   generate_header HaskellStyle LGPLv2plus;
10263
10264   (* XXX We only know how to generate partial FFI for Haskell
10265    * at the moment.  Please help out!
10266    *)
10267   let can_generate style =
10268     match style with
10269     | RErr, _
10270     | RInt _, _
10271     | RInt64 _, _ -> true
10272     | RBool _, _
10273     | RConstString _, _
10274     | RConstOptString _, _
10275     | RString _, _
10276     | RStringList _, _
10277     | RStruct _, _
10278     | RStructList _, _
10279     | RHashtable _, _
10280     | RBufferOut _, _ -> false in
10281
10282   pr "\
10283 {-# INCLUDE <guestfs.h> #-}
10284 {-# LANGUAGE ForeignFunctionInterface #-}
10285
10286 module Guestfs (
10287   create";
10288
10289   (* List out the names of the actions we want to export. *)
10290   List.iter (
10291     fun (name, style, _, _, _, _, _) ->
10292       if can_generate style then pr ",\n  %s" name
10293   ) all_functions;
10294
10295   pr "
10296   ) where
10297
10298 -- Unfortunately some symbols duplicate ones already present
10299 -- in Prelude.  We don't know which, so we hard-code a list
10300 -- here.
10301 import Prelude hiding (truncate)
10302
10303 import Foreign
10304 import Foreign.C
10305 import Foreign.C.Types
10306 import IO
10307 import Control.Exception
10308 import Data.Typeable
10309
10310 data GuestfsS = GuestfsS            -- represents the opaque C struct
10311 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10312 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10313
10314 -- XXX define properly later XXX
10315 data PV = PV
10316 data VG = VG
10317 data LV = LV
10318 data IntBool = IntBool
10319 data Stat = Stat
10320 data StatVFS = StatVFS
10321 data Hashtable = Hashtable
10322
10323 foreign import ccall unsafe \"guestfs_create\" c_create
10324   :: IO GuestfsP
10325 foreign import ccall unsafe \"&guestfs_close\" c_close
10326   :: FunPtr (GuestfsP -> IO ())
10327 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10328   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10329
10330 create :: IO GuestfsH
10331 create = do
10332   p <- c_create
10333   c_set_error_handler p nullPtr nullPtr
10334   h <- newForeignPtr c_close p
10335   return h
10336
10337 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10338   :: GuestfsP -> IO CString
10339
10340 -- last_error :: GuestfsH -> IO (Maybe String)
10341 -- last_error h = do
10342 --   str <- withForeignPtr h (\\p -> c_last_error p)
10343 --   maybePeek peekCString str
10344
10345 last_error :: GuestfsH -> IO (String)
10346 last_error h = do
10347   str <- withForeignPtr h (\\p -> c_last_error p)
10348   if (str == nullPtr)
10349     then return \"no error\"
10350     else peekCString str
10351
10352 ";
10353
10354   (* Generate wrappers for each foreign function. *)
10355   List.iter (
10356     fun (name, style, _, _, _, _, _) ->
10357       if can_generate style then (
10358         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10359         pr "  :: ";
10360         generate_haskell_prototype ~handle:"GuestfsP" style;
10361         pr "\n";
10362         pr "\n";
10363         pr "%s :: " name;
10364         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10365         pr "\n";
10366         pr "%s %s = do\n" name
10367           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10368         pr "  r <- ";
10369         (* Convert pointer arguments using with* functions. *)
10370         List.iter (
10371           function
10372           | FileIn n
10373           | FileOut n
10374           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10375           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10376           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10377           | Bool _ | Int _ | Int64 _ -> ()
10378         ) (snd style);
10379         (* Convert integer arguments. *)
10380         let args =
10381           List.map (
10382             function
10383             | Bool n -> sprintf "(fromBool %s)" n
10384             | Int n -> sprintf "(fromIntegral %s)" n
10385             | Int64 n -> sprintf "(fromIntegral %s)" n
10386             | FileIn n | FileOut n
10387             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10388           ) (snd style) in
10389         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10390           (String.concat " " ("p" :: args));
10391         (match fst style with
10392          | RErr | RInt _ | RInt64 _ | RBool _ ->
10393              pr "  if (r == -1)\n";
10394              pr "    then do\n";
10395              pr "      err <- last_error h\n";
10396              pr "      fail err\n";
10397          | RConstString _ | RConstOptString _ | RString _
10398          | RStringList _ | RStruct _
10399          | RStructList _ | RHashtable _ | RBufferOut _ ->
10400              pr "  if (r == nullPtr)\n";
10401              pr "    then do\n";
10402              pr "      err <- last_error h\n";
10403              pr "      fail err\n";
10404         );
10405         (match fst style with
10406          | RErr ->
10407              pr "    else return ()\n"
10408          | RInt _ ->
10409              pr "    else return (fromIntegral r)\n"
10410          | RInt64 _ ->
10411              pr "    else return (fromIntegral r)\n"
10412          | RBool _ ->
10413              pr "    else return (toBool r)\n"
10414          | RConstString _
10415          | RConstOptString _
10416          | RString _
10417          | RStringList _
10418          | RStruct _
10419          | RStructList _
10420          | RHashtable _
10421          | RBufferOut _ ->
10422              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10423         );
10424         pr "\n";
10425       )
10426   ) all_functions
10427
10428 and generate_haskell_prototype ~handle ?(hs = false) style =
10429   pr "%s -> " handle;
10430   let string = if hs then "String" else "CString" in
10431   let int = if hs then "Int" else "CInt" in
10432   let bool = if hs then "Bool" else "CInt" in
10433   let int64 = if hs then "Integer" else "Int64" in
10434   List.iter (
10435     fun arg ->
10436       (match arg with
10437        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10438        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10439        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10440        | Bool _ -> pr "%s" bool
10441        | Int _ -> pr "%s" int
10442        | Int64 _ -> pr "%s" int
10443        | FileIn _ -> pr "%s" string
10444        | FileOut _ -> pr "%s" string
10445       );
10446       pr " -> ";
10447   ) (snd style);
10448   pr "IO (";
10449   (match fst style with
10450    | RErr -> if not hs then pr "CInt"
10451    | RInt _ -> pr "%s" int
10452    | RInt64 _ -> pr "%s" int64
10453    | RBool _ -> pr "%s" bool
10454    | RConstString _ -> pr "%s" string
10455    | RConstOptString _ -> pr "Maybe %s" string
10456    | RString _ -> pr "%s" string
10457    | RStringList _ -> pr "[%s]" string
10458    | RStruct (_, typ) ->
10459        let name = java_name_of_struct typ in
10460        pr "%s" name
10461    | RStructList (_, typ) ->
10462        let name = java_name_of_struct typ in
10463        pr "[%s]" name
10464    | RHashtable _ -> pr "Hashtable"
10465    | RBufferOut _ -> pr "%s" string
10466   );
10467   pr ")"
10468
10469 and generate_csharp () =
10470   generate_header CPlusPlusStyle LGPLv2plus;
10471
10472   (* XXX Make this configurable by the C# assembly users. *)
10473   let library = "libguestfs.so.0" in
10474
10475   pr "\
10476 // These C# bindings are highly experimental at present.
10477 //
10478 // Firstly they only work on Linux (ie. Mono).  In order to get them
10479 // to work on Windows (ie. .Net) you would need to port the library
10480 // itself to Windows first.
10481 //
10482 // The second issue is that some calls are known to be incorrect and
10483 // can cause Mono to segfault.  Particularly: calls which pass or
10484 // return string[], or return any structure value.  This is because
10485 // we haven't worked out the correct way to do this from C#.
10486 //
10487 // The third issue is that when compiling you get a lot of warnings.
10488 // We are not sure whether the warnings are important or not.
10489 //
10490 // Fourthly we do not routinely build or test these bindings as part
10491 // of the make && make check cycle, which means that regressions might
10492 // go unnoticed.
10493 //
10494 // Suggestions and patches are welcome.
10495
10496 // To compile:
10497 //
10498 // gmcs Libguestfs.cs
10499 // mono Libguestfs.exe
10500 //
10501 // (You'll probably want to add a Test class / static main function
10502 // otherwise this won't do anything useful).
10503
10504 using System;
10505 using System.IO;
10506 using System.Runtime.InteropServices;
10507 using System.Runtime.Serialization;
10508 using System.Collections;
10509
10510 namespace Guestfs
10511 {
10512   class Error : System.ApplicationException
10513   {
10514     public Error (string message) : base (message) {}
10515     protected Error (SerializationInfo info, StreamingContext context) {}
10516   }
10517
10518   class Guestfs
10519   {
10520     IntPtr _handle;
10521
10522     [DllImport (\"%s\")]
10523     static extern IntPtr guestfs_create ();
10524
10525     public Guestfs ()
10526     {
10527       _handle = guestfs_create ();
10528       if (_handle == IntPtr.Zero)
10529         throw new Error (\"could not create guestfs handle\");
10530     }
10531
10532     [DllImport (\"%s\")]
10533     static extern void guestfs_close (IntPtr h);
10534
10535     ~Guestfs ()
10536     {
10537       guestfs_close (_handle);
10538     }
10539
10540     [DllImport (\"%s\")]
10541     static extern string guestfs_last_error (IntPtr h);
10542
10543 " library library library;
10544
10545   (* Generate C# structure bindings.  We prefix struct names with
10546    * underscore because C# cannot have conflicting struct names and
10547    * method names (eg. "class stat" and "stat").
10548    *)
10549   List.iter (
10550     fun (typ, cols) ->
10551       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10552       pr "    public class _%s {\n" typ;
10553       List.iter (
10554         function
10555         | name, FChar -> pr "      char %s;\n" name
10556         | name, FString -> pr "      string %s;\n" name
10557         | name, FBuffer ->
10558             pr "      uint %s_len;\n" name;
10559             pr "      string %s;\n" name
10560         | name, FUUID ->
10561             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10562             pr "      string %s;\n" name
10563         | name, FUInt32 -> pr "      uint %s;\n" name
10564         | name, FInt32 -> pr "      int %s;\n" name
10565         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10566         | name, FInt64 -> pr "      long %s;\n" name
10567         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10568       ) cols;
10569       pr "    }\n";
10570       pr "\n"
10571   ) structs;
10572
10573   (* Generate C# function bindings. *)
10574   List.iter (
10575     fun (name, style, _, _, _, shortdesc, _) ->
10576       let rec csharp_return_type () =
10577         match fst style with
10578         | RErr -> "void"
10579         | RBool n -> "bool"
10580         | RInt n -> "int"
10581         | RInt64 n -> "long"
10582         | RConstString n
10583         | RConstOptString n
10584         | RString n
10585         | RBufferOut n -> "string"
10586         | RStruct (_,n) -> "_" ^ n
10587         | RHashtable n -> "Hashtable"
10588         | RStringList n -> "string[]"
10589         | RStructList (_,n) -> sprintf "_%s[]" n
10590
10591       and c_return_type () =
10592         match fst style with
10593         | RErr
10594         | RBool _
10595         | RInt _ -> "int"
10596         | RInt64 _ -> "long"
10597         | RConstString _
10598         | RConstOptString _
10599         | RString _
10600         | RBufferOut _ -> "string"
10601         | RStruct (_,n) -> "_" ^ n
10602         | RHashtable _
10603         | RStringList _ -> "string[]"
10604         | RStructList (_,n) -> sprintf "_%s[]" n
10605
10606       and c_error_comparison () =
10607         match fst style with
10608         | RErr
10609         | RBool _
10610         | RInt _
10611         | RInt64 _ -> "== -1"
10612         | RConstString _
10613         | RConstOptString _
10614         | RString _
10615         | RBufferOut _
10616         | RStruct (_,_)
10617         | RHashtable _
10618         | RStringList _
10619         | RStructList (_,_) -> "== null"
10620
10621       and generate_extern_prototype () =
10622         pr "    static extern %s guestfs_%s (IntPtr h"
10623           (c_return_type ()) name;
10624         List.iter (
10625           function
10626           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10627           | FileIn n | FileOut n ->
10628               pr ", [In] string %s" n
10629           | StringList n | DeviceList n ->
10630               pr ", [In] string[] %s" n
10631           | Bool n ->
10632               pr ", bool %s" n
10633           | Int n ->
10634               pr ", int %s" n
10635           | Int64 n ->
10636               pr ", long %s" n
10637         ) (snd style);
10638         pr ");\n"
10639
10640       and generate_public_prototype () =
10641         pr "    public %s %s (" (csharp_return_type ()) name;
10642         let comma = ref false in
10643         let next () =
10644           if !comma then pr ", ";
10645           comma := true
10646         in
10647         List.iter (
10648           function
10649           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10650           | FileIn n | FileOut n ->
10651               next (); pr "string %s" n
10652           | StringList n | DeviceList n ->
10653               next (); pr "string[] %s" n
10654           | Bool n ->
10655               next (); pr "bool %s" n
10656           | Int n ->
10657               next (); pr "int %s" n
10658           | Int64 n ->
10659               next (); pr "long %s" n
10660         ) (snd style);
10661         pr ")\n"
10662
10663       and generate_call () =
10664         pr "guestfs_%s (_handle" name;
10665         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10666         pr ");\n";
10667       in
10668
10669       pr "    [DllImport (\"%s\")]\n" library;
10670       generate_extern_prototype ();
10671       pr "\n";
10672       pr "    /// <summary>\n";
10673       pr "    /// %s\n" shortdesc;
10674       pr "    /// </summary>\n";
10675       generate_public_prototype ();
10676       pr "    {\n";
10677       pr "      %s r;\n" (c_return_type ());
10678       pr "      r = ";
10679       generate_call ();
10680       pr "      if (r %s)\n" (c_error_comparison ());
10681       pr "        throw new Error (guestfs_last_error (_handle));\n";
10682       (match fst style with
10683        | RErr -> ()
10684        | RBool _ ->
10685            pr "      return r != 0 ? true : false;\n"
10686        | RHashtable _ ->
10687            pr "      Hashtable rr = new Hashtable ();\n";
10688            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10689            pr "        rr.Add (r[i], r[i+1]);\n";
10690            pr "      return rr;\n"
10691        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10692        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10693        | RStructList _ ->
10694            pr "      return r;\n"
10695       );
10696       pr "    }\n";
10697       pr "\n";
10698   ) all_functions_sorted;
10699
10700   pr "  }
10701 }
10702 "
10703
10704 and generate_bindtests () =
10705   generate_header CStyle LGPLv2plus;
10706
10707   pr "\
10708 #include <stdio.h>
10709 #include <stdlib.h>
10710 #include <inttypes.h>
10711 #include <string.h>
10712
10713 #include \"guestfs.h\"
10714 #include \"guestfs-internal.h\"
10715 #include \"guestfs-internal-actions.h\"
10716 #include \"guestfs_protocol.h\"
10717
10718 #define error guestfs_error
10719 #define safe_calloc guestfs_safe_calloc
10720 #define safe_malloc guestfs_safe_malloc
10721
10722 static void
10723 print_strings (char *const *argv)
10724 {
10725   int argc;
10726
10727   printf (\"[\");
10728   for (argc = 0; argv[argc] != NULL; ++argc) {
10729     if (argc > 0) printf (\", \");
10730     printf (\"\\\"%%s\\\"\", argv[argc]);
10731   }
10732   printf (\"]\\n\");
10733 }
10734
10735 /* The test0 function prints its parameters to stdout. */
10736 ";
10737
10738   let test0, tests =
10739     match test_functions with
10740     | [] -> assert false
10741     | test0 :: tests -> test0, tests in
10742
10743   let () =
10744     let (name, style, _, _, _, _, _) = test0 in
10745     generate_prototype ~extern:false ~semicolon:false ~newline:true
10746       ~handle:"g" ~prefix:"guestfs__" name style;
10747     pr "{\n";
10748     List.iter (
10749       function
10750       | Pathname n
10751       | Device n | Dev_or_Path n
10752       | String n
10753       | FileIn n
10754       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10755       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10756       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10757       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10758       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10759       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10760     ) (snd style);
10761     pr "  /* Java changes stdout line buffering so we need this: */\n";
10762     pr "  fflush (stdout);\n";
10763     pr "  return 0;\n";
10764     pr "}\n";
10765     pr "\n" in
10766
10767   List.iter (
10768     fun (name, style, _, _, _, _, _) ->
10769       if String.sub name (String.length name - 3) 3 <> "err" then (
10770         pr "/* Test normal return. */\n";
10771         generate_prototype ~extern:false ~semicolon:false ~newline:true
10772           ~handle:"g" ~prefix:"guestfs__" name style;
10773         pr "{\n";
10774         (match fst style with
10775          | RErr ->
10776              pr "  return 0;\n"
10777          | RInt _ ->
10778              pr "  int r;\n";
10779              pr "  sscanf (val, \"%%d\", &r);\n";
10780              pr "  return r;\n"
10781          | RInt64 _ ->
10782              pr "  int64_t r;\n";
10783              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10784              pr "  return r;\n"
10785          | RBool _ ->
10786              pr "  return STREQ (val, \"true\");\n"
10787          | RConstString _
10788          | RConstOptString _ ->
10789              (* Can't return the input string here.  Return a static
10790               * string so we ensure we get a segfault if the caller
10791               * tries to free it.
10792               *)
10793              pr "  return \"static string\";\n"
10794          | RString _ ->
10795              pr "  return strdup (val);\n"
10796          | RStringList _ ->
10797              pr "  char **strs;\n";
10798              pr "  int n, i;\n";
10799              pr "  sscanf (val, \"%%d\", &n);\n";
10800              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10801              pr "  for (i = 0; i < n; ++i) {\n";
10802              pr "    strs[i] = safe_malloc (g, 16);\n";
10803              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10804              pr "  }\n";
10805              pr "  strs[n] = NULL;\n";
10806              pr "  return strs;\n"
10807          | RStruct (_, typ) ->
10808              pr "  struct guestfs_%s *r;\n" typ;
10809              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10810              pr "  return r;\n"
10811          | RStructList (_, typ) ->
10812              pr "  struct guestfs_%s_list *r;\n" typ;
10813              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10814              pr "  sscanf (val, \"%%d\", &r->len);\n";
10815              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10816              pr "  return r;\n"
10817          | RHashtable _ ->
10818              pr "  char **strs;\n";
10819              pr "  int n, i;\n";
10820              pr "  sscanf (val, \"%%d\", &n);\n";
10821              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10822              pr "  for (i = 0; i < n; ++i) {\n";
10823              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10824              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10825              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10826              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10827              pr "  }\n";
10828              pr "  strs[n*2] = NULL;\n";
10829              pr "  return strs;\n"
10830          | RBufferOut _ ->
10831              pr "  return strdup (val);\n"
10832         );
10833         pr "}\n";
10834         pr "\n"
10835       ) else (
10836         pr "/* Test error return. */\n";
10837         generate_prototype ~extern:false ~semicolon:false ~newline:true
10838           ~handle:"g" ~prefix:"guestfs__" name style;
10839         pr "{\n";
10840         pr "  error (g, \"error\");\n";
10841         (match fst style with
10842          | RErr | RInt _ | RInt64 _ | RBool _ ->
10843              pr "  return -1;\n"
10844          | RConstString _ | RConstOptString _
10845          | RString _ | RStringList _ | RStruct _
10846          | RStructList _
10847          | RHashtable _
10848          | RBufferOut _ ->
10849              pr "  return NULL;\n"
10850         );
10851         pr "}\n";
10852         pr "\n"
10853       )
10854   ) tests
10855
10856 and generate_ocaml_bindtests () =
10857   generate_header OCamlStyle GPLv2plus;
10858
10859   pr "\
10860 let () =
10861   let g = Guestfs.create () in
10862 ";
10863
10864   let mkargs args =
10865     String.concat " " (
10866       List.map (
10867         function
10868         | CallString s -> "\"" ^ s ^ "\""
10869         | CallOptString None -> "None"
10870         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10871         | CallStringList xs ->
10872             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10873         | CallInt i when i >= 0 -> string_of_int i
10874         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10875         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10876         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10877         | CallBool b -> string_of_bool b
10878       ) args
10879     )
10880   in
10881
10882   generate_lang_bindtests (
10883     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10884   );
10885
10886   pr "print_endline \"EOF\"\n"
10887
10888 and generate_perl_bindtests () =
10889   pr "#!/usr/bin/perl -w\n";
10890   generate_header HashStyle GPLv2plus;
10891
10892   pr "\
10893 use strict;
10894
10895 use Sys::Guestfs;
10896
10897 my $g = Sys::Guestfs->new ();
10898 ";
10899
10900   let mkargs args =
10901     String.concat ", " (
10902       List.map (
10903         function
10904         | CallString s -> "\"" ^ s ^ "\""
10905         | CallOptString None -> "undef"
10906         | CallOptString (Some s) -> sprintf "\"%s\"" s
10907         | CallStringList xs ->
10908             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10909         | CallInt i -> string_of_int i
10910         | CallInt64 i -> Int64.to_string i
10911         | CallBool b -> if b then "1" else "0"
10912       ) args
10913     )
10914   in
10915
10916   generate_lang_bindtests (
10917     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10918   );
10919
10920   pr "print \"EOF\\n\"\n"
10921
10922 and generate_python_bindtests () =
10923   generate_header HashStyle GPLv2plus;
10924
10925   pr "\
10926 import guestfs
10927
10928 g = guestfs.GuestFS ()
10929 ";
10930
10931   let mkargs args =
10932     String.concat ", " (
10933       List.map (
10934         function
10935         | CallString s -> "\"" ^ s ^ "\""
10936         | CallOptString None -> "None"
10937         | CallOptString (Some s) -> sprintf "\"%s\"" s
10938         | CallStringList xs ->
10939             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10940         | CallInt i -> string_of_int i
10941         | CallInt64 i -> Int64.to_string i
10942         | CallBool b -> if b then "1" else "0"
10943       ) args
10944     )
10945   in
10946
10947   generate_lang_bindtests (
10948     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10949   );
10950
10951   pr "print \"EOF\"\n"
10952
10953 and generate_ruby_bindtests () =
10954   generate_header HashStyle GPLv2plus;
10955
10956   pr "\
10957 require 'guestfs'
10958
10959 g = Guestfs::create()
10960 ";
10961
10962   let mkargs args =
10963     String.concat ", " (
10964       List.map (
10965         function
10966         | CallString s -> "\"" ^ s ^ "\""
10967         | CallOptString None -> "nil"
10968         | CallOptString (Some s) -> sprintf "\"%s\"" s
10969         | CallStringList xs ->
10970             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10971         | CallInt i -> string_of_int i
10972         | CallInt64 i -> Int64.to_string i
10973         | CallBool b -> string_of_bool b
10974       ) args
10975     )
10976   in
10977
10978   generate_lang_bindtests (
10979     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10980   );
10981
10982   pr "print \"EOF\\n\"\n"
10983
10984 and generate_java_bindtests () =
10985   generate_header CStyle GPLv2plus;
10986
10987   pr "\
10988 import com.redhat.et.libguestfs.*;
10989
10990 public class Bindtests {
10991     public static void main (String[] argv)
10992     {
10993         try {
10994             GuestFS g = new GuestFS ();
10995 ";
10996
10997   let mkargs args =
10998     String.concat ", " (
10999       List.map (
11000         function
11001         | CallString s -> "\"" ^ s ^ "\""
11002         | CallOptString None -> "null"
11003         | CallOptString (Some s) -> sprintf "\"%s\"" s
11004         | CallStringList xs ->
11005             "new String[]{" ^
11006               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11007         | CallInt i -> string_of_int i
11008         | CallInt64 i -> Int64.to_string i
11009         | CallBool b -> string_of_bool b
11010       ) args
11011     )
11012   in
11013
11014   generate_lang_bindtests (
11015     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11016   );
11017
11018   pr "
11019             System.out.println (\"EOF\");
11020         }
11021         catch (Exception exn) {
11022             System.err.println (exn);
11023             System.exit (1);
11024         }
11025     }
11026 }
11027 "
11028
11029 and generate_haskell_bindtests () =
11030   generate_header HaskellStyle GPLv2plus;
11031
11032   pr "\
11033 module Bindtests where
11034 import qualified Guestfs
11035
11036 main = do
11037   g <- Guestfs.create
11038 ";
11039
11040   let mkargs args =
11041     String.concat " " (
11042       List.map (
11043         function
11044         | CallString s -> "\"" ^ s ^ "\""
11045         | CallOptString None -> "Nothing"
11046         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11047         | CallStringList xs ->
11048             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11049         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11050         | CallInt i -> string_of_int i
11051         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11052         | CallInt64 i -> Int64.to_string i
11053         | CallBool true -> "True"
11054         | CallBool false -> "False"
11055       ) args
11056     )
11057   in
11058
11059   generate_lang_bindtests (
11060     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11061   );
11062
11063   pr "  putStrLn \"EOF\"\n"
11064
11065 (* Language-independent bindings tests - we do it this way to
11066  * ensure there is parity in testing bindings across all languages.
11067  *)
11068 and generate_lang_bindtests call =
11069   call "test0" [CallString "abc"; CallOptString (Some "def");
11070                 CallStringList []; CallBool false;
11071                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11072   call "test0" [CallString "abc"; CallOptString None;
11073                 CallStringList []; CallBool false;
11074                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11075   call "test0" [CallString ""; CallOptString (Some "def");
11076                 CallStringList []; CallBool false;
11077                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11078   call "test0" [CallString ""; CallOptString (Some "");
11079                 CallStringList []; CallBool false;
11080                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11081   call "test0" [CallString "abc"; CallOptString (Some "def");
11082                 CallStringList ["1"]; CallBool false;
11083                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11084   call "test0" [CallString "abc"; CallOptString (Some "def");
11085                 CallStringList ["1"; "2"]; CallBool false;
11086                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11087   call "test0" [CallString "abc"; CallOptString (Some "def");
11088                 CallStringList ["1"]; CallBool true;
11089                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11090   call "test0" [CallString "abc"; CallOptString (Some "def");
11091                 CallStringList ["1"]; CallBool false;
11092                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11093   call "test0" [CallString "abc"; CallOptString (Some "def");
11094                 CallStringList ["1"]; CallBool false;
11095                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11096   call "test0" [CallString "abc"; CallOptString (Some "def");
11097                 CallStringList ["1"]; CallBool false;
11098                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11099   call "test0" [CallString "abc"; CallOptString (Some "def");
11100                 CallStringList ["1"]; CallBool false;
11101                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11102   call "test0" [CallString "abc"; CallOptString (Some "def");
11103                 CallStringList ["1"]; CallBool false;
11104                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11105   call "test0" [CallString "abc"; CallOptString (Some "def");
11106                 CallStringList ["1"]; CallBool false;
11107                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11108
11109 (* XXX Add here tests of the return and error functions. *)
11110
11111 (* Code to generator bindings for virt-inspector.  Currently only
11112  * implemented for OCaml code (for virt-p2v 2.0).
11113  *)
11114 let rng_input = "inspector/virt-inspector.rng"
11115
11116 (* Read the input file and parse it into internal structures.  This is
11117  * by no means a complete RELAX NG parser, but is just enough to be
11118  * able to parse the specific input file.
11119  *)
11120 type rng =
11121   | Element of string * rng list        (* <element name=name/> *)
11122   | Attribute of string * rng list        (* <attribute name=name/> *)
11123   | Interleave of rng list                (* <interleave/> *)
11124   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11125   | OneOrMore of rng                        (* <oneOrMore/> *)
11126   | Optional of rng                        (* <optional/> *)
11127   | Choice of string list                (* <choice><value/>*</choice> *)
11128   | Value of string                        (* <value>str</value> *)
11129   | Text                                (* <text/> *)
11130
11131 let rec string_of_rng = function
11132   | Element (name, xs) ->
11133       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11134   | Attribute (name, xs) ->
11135       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11136   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11137   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11138   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11139   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11140   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11141   | Value value -> "Value \"" ^ value ^ "\""
11142   | Text -> "Text"
11143
11144 and string_of_rng_list xs =
11145   String.concat ", " (List.map string_of_rng xs)
11146
11147 let rec parse_rng ?defines context = function
11148   | [] -> []
11149   | Xml.Element ("element", ["name", name], children) :: rest ->
11150       Element (name, parse_rng ?defines context children)
11151       :: parse_rng ?defines context rest
11152   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11153       Attribute (name, parse_rng ?defines context children)
11154       :: parse_rng ?defines context rest
11155   | Xml.Element ("interleave", [], children) :: rest ->
11156       Interleave (parse_rng ?defines context children)
11157       :: parse_rng ?defines context rest
11158   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11159       let rng = parse_rng ?defines context [child] in
11160       (match rng with
11161        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11162        | _ ->
11163            failwithf "%s: <zeroOrMore> contains more than one child element"
11164              context
11165       )
11166   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11167       let rng = parse_rng ?defines context [child] in
11168       (match rng with
11169        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11170        | _ ->
11171            failwithf "%s: <oneOrMore> contains more than one child element"
11172              context
11173       )
11174   | Xml.Element ("optional", [], [child]) :: rest ->
11175       let rng = parse_rng ?defines context [child] in
11176       (match rng with
11177        | [child] -> Optional child :: parse_rng ?defines context rest
11178        | _ ->
11179            failwithf "%s: <optional> contains more than one child element"
11180              context
11181       )
11182   | Xml.Element ("choice", [], children) :: rest ->
11183       let values = List.map (
11184         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11185         | _ ->
11186             failwithf "%s: can't handle anything except <value> in <choice>"
11187               context
11188       ) children in
11189       Choice values
11190       :: parse_rng ?defines context rest
11191   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11192       Value value :: parse_rng ?defines context rest
11193   | Xml.Element ("text", [], []) :: rest ->
11194       Text :: parse_rng ?defines context rest
11195   | Xml.Element ("ref", ["name", name], []) :: rest ->
11196       (* Look up the reference.  Because of limitations in this parser,
11197        * we can't handle arbitrarily nested <ref> yet.  You can only
11198        * use <ref> from inside <start>.
11199        *)
11200       (match defines with
11201        | None ->
11202            failwithf "%s: contains <ref>, but no refs are defined yet" context
11203        | Some map ->
11204            let rng = StringMap.find name map in
11205            rng @ parse_rng ?defines context rest
11206       )
11207   | x :: _ ->
11208       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11209
11210 let grammar =
11211   let xml = Xml.parse_file rng_input in
11212   match xml with
11213   | Xml.Element ("grammar", _,
11214                  Xml.Element ("start", _, gram) :: defines) ->
11215       (* The <define/> elements are referenced in the <start> section,
11216        * so build a map of those first.
11217        *)
11218       let defines = List.fold_left (
11219         fun map ->
11220           function Xml.Element ("define", ["name", name], defn) ->
11221             StringMap.add name defn map
11222           | _ ->
11223               failwithf "%s: expected <define name=name/>" rng_input
11224       ) StringMap.empty defines in
11225       let defines = StringMap.mapi parse_rng defines in
11226
11227       (* Parse the <start> clause, passing the defines. *)
11228       parse_rng ~defines "<start>" gram
11229   | _ ->
11230       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11231         rng_input
11232
11233 let name_of_field = function
11234   | Element (name, _) | Attribute (name, _)
11235   | ZeroOrMore (Element (name, _))
11236   | OneOrMore (Element (name, _))
11237   | Optional (Element (name, _)) -> name
11238   | Optional (Attribute (name, _)) -> name
11239   | Text -> (* an unnamed field in an element *)
11240       "data"
11241   | rng ->
11242       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11243
11244 (* At the moment this function only generates OCaml types.  However we
11245  * should parameterize it later so it can generate types/structs in a
11246  * variety of languages.
11247  *)
11248 let generate_types xs =
11249   (* A simple type is one that can be printed out directly, eg.
11250    * "string option".  A complex type is one which has a name and has
11251    * to be defined via another toplevel definition, eg. a struct.
11252    *
11253    * generate_type generates code for either simple or complex types.
11254    * In the simple case, it returns the string ("string option").  In
11255    * the complex case, it returns the name ("mountpoint").  In the
11256    * complex case it has to print out the definition before returning,
11257    * so it should only be called when we are at the beginning of a
11258    * new line (BOL context).
11259    *)
11260   let rec generate_type = function
11261     | Text ->                                (* string *)
11262         "string", true
11263     | Choice values ->                        (* [`val1|`val2|...] *)
11264         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11265     | ZeroOrMore rng ->                        (* <rng> list *)
11266         let t, is_simple = generate_type rng in
11267         t ^ " list (* 0 or more *)", is_simple
11268     | OneOrMore rng ->                        (* <rng> list *)
11269         let t, is_simple = generate_type rng in
11270         t ^ " list (* 1 or more *)", is_simple
11271                                         (* virt-inspector hack: bool *)
11272     | Optional (Attribute (name, [Value "1"])) ->
11273         "bool", true
11274     | Optional rng ->                        (* <rng> list *)
11275         let t, is_simple = generate_type rng in
11276         t ^ " option", is_simple
11277                                         (* type name = { fields ... } *)
11278     | Element (name, fields) when is_attrs_interleave fields ->
11279         generate_type_struct name (get_attrs_interleave fields)
11280     | Element (name, [field])                (* type name = field *)
11281     | Attribute (name, [field]) ->
11282         let t, is_simple = generate_type field in
11283         if is_simple then (t, true)
11284         else (
11285           pr "type %s = %s\n" name t;
11286           name, false
11287         )
11288     | Element (name, fields) ->              (* type name = { fields ... } *)
11289         generate_type_struct name fields
11290     | rng ->
11291         failwithf "generate_type failed at: %s" (string_of_rng rng)
11292
11293   and is_attrs_interleave = function
11294     | [Interleave _] -> true
11295     | Attribute _ :: fields -> is_attrs_interleave fields
11296     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11297     | _ -> false
11298
11299   and get_attrs_interleave = function
11300     | [Interleave fields] -> fields
11301     | ((Attribute _) as field) :: fields
11302     | ((Optional (Attribute _)) as field) :: fields ->
11303         field :: get_attrs_interleave fields
11304     | _ -> assert false
11305
11306   and generate_types xs =
11307     List.iter (fun x -> ignore (generate_type x)) xs
11308
11309   and generate_type_struct name fields =
11310     (* Calculate the types of the fields first.  We have to do this
11311      * before printing anything so we are still in BOL context.
11312      *)
11313     let types = List.map fst (List.map generate_type fields) in
11314
11315     (* Special case of a struct containing just a string and another
11316      * field.  Turn it into an assoc list.
11317      *)
11318     match types with
11319     | ["string"; other] ->
11320         let fname1, fname2 =
11321           match fields with
11322           | [f1; f2] -> name_of_field f1, name_of_field f2
11323           | _ -> assert false in
11324         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11325         name, false
11326
11327     | types ->
11328         pr "type %s = {\n" name;
11329         List.iter (
11330           fun (field, ftype) ->
11331             let fname = name_of_field field in
11332             pr "  %s_%s : %s;\n" name fname ftype
11333         ) (List.combine fields types);
11334         pr "}\n";
11335         (* Return the name of this type, and
11336          * false because it's not a simple type.
11337          *)
11338         name, false
11339   in
11340
11341   generate_types xs
11342
11343 let generate_parsers xs =
11344   (* As for generate_type above, generate_parser makes a parser for
11345    * some type, and returns the name of the parser it has generated.
11346    * Because it (may) need to print something, it should always be
11347    * called in BOL context.
11348    *)
11349   let rec generate_parser = function
11350     | Text ->                                (* string *)
11351         "string_child_or_empty"
11352     | Choice values ->                        (* [`val1|`val2|...] *)
11353         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11354           (String.concat "|"
11355              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11356     | ZeroOrMore rng ->                        (* <rng> list *)
11357         let pa = generate_parser rng in
11358         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11359     | OneOrMore rng ->                        (* <rng> list *)
11360         let pa = generate_parser rng in
11361         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11362                                         (* virt-inspector hack: bool *)
11363     | Optional (Attribute (name, [Value "1"])) ->
11364         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11365     | Optional rng ->                        (* <rng> list *)
11366         let pa = generate_parser rng in
11367         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11368                                         (* type name = { fields ... } *)
11369     | Element (name, fields) when is_attrs_interleave fields ->
11370         generate_parser_struct name (get_attrs_interleave fields)
11371     | Element (name, [field]) ->        (* type name = field *)
11372         let pa = generate_parser field in
11373         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11374         pr "let %s =\n" parser_name;
11375         pr "  %s\n" pa;
11376         pr "let parse_%s = %s\n" name parser_name;
11377         parser_name
11378     | Attribute (name, [field]) ->
11379         let pa = generate_parser field in
11380         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11381         pr "let %s =\n" parser_name;
11382         pr "  %s\n" pa;
11383         pr "let parse_%s = %s\n" name parser_name;
11384         parser_name
11385     | Element (name, fields) ->              (* type name = { fields ... } *)
11386         generate_parser_struct name ([], fields)
11387     | rng ->
11388         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11389
11390   and is_attrs_interleave = function
11391     | [Interleave _] -> true
11392     | Attribute _ :: fields -> is_attrs_interleave fields
11393     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11394     | _ -> false
11395
11396   and get_attrs_interleave = function
11397     | [Interleave fields] -> [], fields
11398     | ((Attribute _) as field) :: fields
11399     | ((Optional (Attribute _)) as field) :: fields ->
11400         let attrs, interleaves = get_attrs_interleave fields in
11401         (field :: attrs), interleaves
11402     | _ -> assert false
11403
11404   and generate_parsers xs =
11405     List.iter (fun x -> ignore (generate_parser x)) xs
11406
11407   and generate_parser_struct name (attrs, interleaves) =
11408     (* Generate parsers for the fields first.  We have to do this
11409      * before printing anything so we are still in BOL context.
11410      *)
11411     let fields = attrs @ interleaves in
11412     let pas = List.map generate_parser fields in
11413
11414     (* Generate an intermediate tuple from all the fields first.
11415      * If the type is just a string + another field, then we will
11416      * return this directly, otherwise it is turned into a record.
11417      *
11418      * RELAX NG note: This code treats <interleave> and plain lists of
11419      * fields the same.  In other words, it doesn't bother enforcing
11420      * any ordering of fields in the XML.
11421      *)
11422     pr "let parse_%s x =\n" name;
11423     pr "  let t = (\n    ";
11424     let comma = ref false in
11425     List.iter (
11426       fun x ->
11427         if !comma then pr ",\n    ";
11428         comma := true;
11429         match x with
11430         | Optional (Attribute (fname, [field])), pa ->
11431             pr "%s x" pa
11432         | Optional (Element (fname, [field])), pa ->
11433             pr "%s (optional_child %S x)" pa fname
11434         | Attribute (fname, [Text]), _ ->
11435             pr "attribute %S x" fname
11436         | (ZeroOrMore _ | OneOrMore _), pa ->
11437             pr "%s x" pa
11438         | Text, pa ->
11439             pr "%s x" pa
11440         | (field, pa) ->
11441             let fname = name_of_field field in
11442             pr "%s (child %S x)" pa fname
11443     ) (List.combine fields pas);
11444     pr "\n  ) in\n";
11445
11446     (match fields with
11447      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11448          pr "  t\n"
11449
11450      | _ ->
11451          pr "  (Obj.magic t : %s)\n" name
11452 (*
11453          List.iter (
11454            function
11455            | (Optional (Attribute (fname, [field])), pa) ->
11456                pr "  %s_%s =\n" name fname;
11457                pr "    %s x;\n" pa
11458            | (Optional (Element (fname, [field])), pa) ->
11459                pr "  %s_%s =\n" name fname;
11460                pr "    (let x = optional_child %S x in\n" fname;
11461                pr "     %s x);\n" pa
11462            | (field, pa) ->
11463                let fname = name_of_field field in
11464                pr "  %s_%s =\n" name fname;
11465                pr "    (let x = child %S x in\n" fname;
11466                pr "     %s x);\n" pa
11467          ) (List.combine fields pas);
11468          pr "}\n"
11469 *)
11470     );
11471     sprintf "parse_%s" name
11472   in
11473
11474   generate_parsers xs
11475
11476 (* Generate ocaml/guestfs_inspector.mli. *)
11477 let generate_ocaml_inspector_mli () =
11478   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11479
11480   pr "\
11481 (** This is an OCaml language binding to the external [virt-inspector]
11482     program.
11483
11484     For more information, please read the man page [virt-inspector(1)].
11485 *)
11486
11487 ";
11488
11489   generate_types grammar;
11490   pr "(** The nested information returned from the {!inspect} function. *)\n";
11491   pr "\n";
11492
11493   pr "\
11494 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11495 (** To inspect a libvirt domain called [name], pass a singleton
11496     list: [inspect [name]].  When using libvirt only, you may
11497     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11498
11499     To inspect a disk image or images, pass a list of the filenames
11500     of the disk images: [inspect filenames]
11501
11502     This function inspects the given guest or disk images and
11503     returns a list of operating system(s) found and a large amount
11504     of information about them.  In the vast majority of cases,
11505     a virtual machine only contains a single operating system.
11506
11507     If the optional [~xml] parameter is given, then this function
11508     skips running the external virt-inspector program and just
11509     parses the given XML directly (which is expected to be XML
11510     produced from a previous run of virt-inspector).  The list of
11511     names and connect URI are ignored in this case.
11512
11513     This function can throw a wide variety of exceptions, for example
11514     if the external virt-inspector program cannot be found, or if
11515     it doesn't generate valid XML.
11516 *)
11517 "
11518
11519 (* Generate ocaml/guestfs_inspector.ml. *)
11520 let generate_ocaml_inspector_ml () =
11521   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11522
11523   pr "open Unix\n";
11524   pr "\n";
11525
11526   generate_types grammar;
11527   pr "\n";
11528
11529   pr "\
11530 (* Misc functions which are used by the parser code below. *)
11531 let first_child = function
11532   | Xml.Element (_, _, c::_) -> c
11533   | Xml.Element (name, _, []) ->
11534       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11535   | Xml.PCData str ->
11536       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11537
11538 let string_child_or_empty = function
11539   | Xml.Element (_, _, [Xml.PCData s]) -> s
11540   | Xml.Element (_, _, []) -> \"\"
11541   | Xml.Element (x, _, _) ->
11542       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11543                 x ^ \" instead\")
11544   | Xml.PCData str ->
11545       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11546
11547 let optional_child name xml =
11548   let children = Xml.children xml in
11549   try
11550     Some (List.find (function
11551                      | Xml.Element (n, _, _) when n = name -> true
11552                      | _ -> false) children)
11553   with
11554     Not_found -> None
11555
11556 let child name xml =
11557   match optional_child name xml with
11558   | Some c -> c
11559   | None ->
11560       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11561
11562 let attribute name xml =
11563   try Xml.attrib xml name
11564   with Xml.No_attribute _ ->
11565     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11566
11567 ";
11568
11569   generate_parsers grammar;
11570   pr "\n";
11571
11572   pr "\
11573 (* Run external virt-inspector, then use parser to parse the XML. *)
11574 let inspect ?connect ?xml names =
11575   let xml =
11576     match xml with
11577     | None ->
11578         if names = [] then invalid_arg \"inspect: no names given\";
11579         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11580           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11581           names in
11582         let cmd = List.map Filename.quote cmd in
11583         let cmd = String.concat \" \" cmd in
11584         let chan = open_process_in cmd in
11585         let xml = Xml.parse_in chan in
11586         (match close_process_in chan with
11587          | WEXITED 0 -> ()
11588          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11589          | WSIGNALED i | WSTOPPED i ->
11590              failwith (\"external virt-inspector command died or stopped on sig \" ^
11591                        string_of_int i)
11592         );
11593         xml
11594     | Some doc ->
11595         Xml.parse_string doc in
11596   parse_operatingsystems xml
11597 "
11598
11599 (* This is used to generate the src/MAX_PROC_NR file which
11600  * contains the maximum procedure number, a surrogate for the
11601  * ABI version number.  See src/Makefile.am for the details.
11602  *)
11603 and generate_max_proc_nr () =
11604   let proc_nrs = List.map (
11605     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11606   ) daemon_functions in
11607
11608   let max_proc_nr = List.fold_left max 0 proc_nrs in
11609
11610   pr "%d\n" max_proc_nr
11611
11612 let output_to filename k =
11613   let filename_new = filename ^ ".new" in
11614   chan := open_out filename_new;
11615   k ();
11616   close_out !chan;
11617   chan := Pervasives.stdout;
11618
11619   (* Is the new file different from the current file? *)
11620   if Sys.file_exists filename && files_equal filename filename_new then
11621     unlink filename_new                 (* same, so skip it *)
11622   else (
11623     (* different, overwrite old one *)
11624     (try chmod filename 0o644 with Unix_error _ -> ());
11625     rename filename_new filename;
11626     chmod filename 0o444;
11627     printf "written %s\n%!" filename;
11628   )
11629
11630 let perror msg = function
11631   | Unix_error (err, _, _) ->
11632       eprintf "%s: %s\n" msg (error_message err)
11633   | exn ->
11634       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11635
11636 (* Main program. *)
11637 let () =
11638   let lock_fd =
11639     try openfile "HACKING" [O_RDWR] 0
11640     with
11641     | Unix_error (ENOENT, _, _) ->
11642         eprintf "\
11643 You are probably running this from the wrong directory.
11644 Run it from the top source directory using the command
11645   src/generator.ml
11646 ";
11647         exit 1
11648     | exn ->
11649         perror "open: HACKING" exn;
11650         exit 1 in
11651
11652   (* Acquire a lock so parallel builds won't try to run the generator
11653    * twice at the same time.  Subsequent builds will wait for the first
11654    * one to finish.  Note the lock is released implicitly when the
11655    * program exits.
11656    *)
11657   (try lockf lock_fd F_LOCK 1
11658    with exn ->
11659      perror "lock: HACKING" exn;
11660      exit 1);
11661
11662   check_functions ();
11663
11664   output_to "src/guestfs_protocol.x" generate_xdr;
11665   output_to "src/guestfs-structs.h" generate_structs_h;
11666   output_to "src/guestfs-actions.h" generate_actions_h;
11667   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11668   output_to "src/guestfs-actions.c" generate_client_actions;
11669   output_to "src/guestfs-bindtests.c" generate_bindtests;
11670   output_to "src/guestfs-structs.pod" generate_structs_pod;
11671   output_to "src/guestfs-actions.pod" generate_actions_pod;
11672   output_to "src/guestfs-availability.pod" generate_availability_pod;
11673   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11674   output_to "src/libguestfs.syms" generate_linker_script;
11675   output_to "daemon/actions.h" generate_daemon_actions_h;
11676   output_to "daemon/stubs.c" generate_daemon_actions;
11677   output_to "daemon/names.c" generate_daemon_names;
11678   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11679   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11680   output_to "capitests/tests.c" generate_tests;
11681   output_to "fish/cmds.c" generate_fish_cmds;
11682   output_to "fish/completion.c" generate_fish_completion;
11683   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11684   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11685   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11686   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11687   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11688   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11689   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11690   output_to "perl/Guestfs.xs" generate_perl_xs;
11691   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11692   output_to "perl/bindtests.pl" generate_perl_bindtests;
11693   output_to "python/guestfs-py.c" generate_python_c;
11694   output_to "python/guestfs.py" generate_python_py;
11695   output_to "python/bindtests.py" generate_python_bindtests;
11696   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11697   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11698   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11699
11700   List.iter (
11701     fun (typ, jtyp) ->
11702       let cols = cols_of_struct typ in
11703       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11704       output_to filename (generate_java_struct jtyp cols);
11705   ) java_structs;
11706
11707   output_to "java/Makefile.inc" generate_java_makefile_inc;
11708   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11709   output_to "java/Bindtests.java" generate_java_bindtests;
11710   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11711   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11712   output_to "csharp/Libguestfs.cs" generate_csharp;
11713
11714   (* Always generate this file last, and unconditionally.  It's used
11715    * by the Makefile to know when we must re-run the generator.
11716    *)
11717   let chan = open_out "src/stamp-generator" in
11718   fprintf chan "1\n";
11719   close_out chan;
11720
11721   printf "generated %d lines of code\n" !lines