cbed94b7a3048bcdb92e634769ed08431b2ef6e3
[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 "  if (guestfs_get_verbose (g))\n";
6720       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6721       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6722       pr "  if (%s () == -1) {\n" test_name;
6723       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6724       pr "    n_failed++;\n";
6725       pr "  }\n";
6726   ) test_names;
6727   pr "\n";
6728
6729   pr "  guestfs_close (g);\n";
6730   pr "  unlink (\"test1.img\");\n";
6731   pr "  unlink (\"test2.img\");\n";
6732   pr "  unlink (\"test3.img\");\n";
6733   pr "\n";
6734
6735   pr "  if (n_failed > 0) {\n";
6736   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6737   pr "    exit (EXIT_FAILURE);\n";
6738   pr "  }\n";
6739   pr "\n";
6740
6741   pr "  exit (EXIT_SUCCESS);\n";
6742   pr "}\n"
6743
6744 and generate_one_test name flags i (init, prereq, test) =
6745   let test_name = sprintf "test_%s_%d" name i in
6746
6747   pr "\
6748 static int %s_skip (void)
6749 {
6750   const char *str;
6751
6752   str = getenv (\"TEST_ONLY\");
6753   if (str)
6754     return strstr (str, \"%s\") == NULL;
6755   str = getenv (\"SKIP_%s\");
6756   if (str && STREQ (str, \"1\")) return 1;
6757   str = getenv (\"SKIP_TEST_%s\");
6758   if (str && STREQ (str, \"1\")) return 1;
6759   return 0;
6760 }
6761
6762 " test_name name (String.uppercase test_name) (String.uppercase name);
6763
6764   (match prereq with
6765    | Disabled | Always -> ()
6766    | If code | Unless code ->
6767        pr "static int %s_prereq (void)\n" test_name;
6768        pr "{\n";
6769        pr "  %s\n" code;
6770        pr "}\n";
6771        pr "\n";
6772   );
6773
6774   pr "\
6775 static int %s (void)
6776 {
6777   if (%s_skip ()) {
6778     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6779     return 0;
6780   }
6781
6782 " test_name test_name test_name;
6783
6784   (* Optional functions should only be tested if the relevant
6785    * support is available in the daemon.
6786    *)
6787   List.iter (
6788     function
6789     | Optional group ->
6790         pr "  {\n";
6791         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6792         pr "    int r;\n";
6793         pr "    suppress_error = 1;\n";
6794         pr "    r = guestfs_available (g, (char **) groups);\n";
6795         pr "    suppress_error = 0;\n";
6796         pr "    if (r == -1) {\n";
6797         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6798         pr "      return 0;\n";
6799         pr "    }\n";
6800         pr "  }\n";
6801     | _ -> ()
6802   ) flags;
6803
6804   (match prereq with
6805    | Disabled ->
6806        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6807    | If _ ->
6808        pr "  if (! %s_prereq ()) {\n" test_name;
6809        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6810        pr "    return 0;\n";
6811        pr "  }\n";
6812        pr "\n";
6813        generate_one_test_body name i test_name init test;
6814    | Unless _ ->
6815        pr "  if (%s_prereq ()) {\n" test_name;
6816        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6817        pr "    return 0;\n";
6818        pr "  }\n";
6819        pr "\n";
6820        generate_one_test_body name i test_name init test;
6821    | Always ->
6822        generate_one_test_body name i test_name init test
6823   );
6824
6825   pr "  return 0;\n";
6826   pr "}\n";
6827   pr "\n";
6828   test_name
6829
6830 and generate_one_test_body name i test_name init test =
6831   (match init with
6832    | InitNone (* XXX at some point, InitNone and InitEmpty became
6833                * folded together as the same thing.  Really we should
6834                * make InitNone do nothing at all, but the tests may
6835                * need to be checked to make sure this is OK.
6836                *)
6837    | InitEmpty ->
6838        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6839        List.iter (generate_test_command_call test_name)
6840          [["blockdev_setrw"; "/dev/sda"];
6841           ["umount_all"];
6842           ["lvm_remove_all"]]
6843    | InitPartition ->
6844        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6845        List.iter (generate_test_command_call test_name)
6846          [["blockdev_setrw"; "/dev/sda"];
6847           ["umount_all"];
6848           ["lvm_remove_all"];
6849           ["part_disk"; "/dev/sda"; "mbr"]]
6850    | InitBasicFS ->
6851        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6852        List.iter (generate_test_command_call test_name)
6853          [["blockdev_setrw"; "/dev/sda"];
6854           ["umount_all"];
6855           ["lvm_remove_all"];
6856           ["part_disk"; "/dev/sda"; "mbr"];
6857           ["mkfs"; "ext2"; "/dev/sda1"];
6858           ["mount_options"; ""; "/dev/sda1"; "/"]]
6859    | InitBasicFSonLVM ->
6860        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6861          test_name;
6862        List.iter (generate_test_command_call test_name)
6863          [["blockdev_setrw"; "/dev/sda"];
6864           ["umount_all"];
6865           ["lvm_remove_all"];
6866           ["part_disk"; "/dev/sda"; "mbr"];
6867           ["pvcreate"; "/dev/sda1"];
6868           ["vgcreate"; "VG"; "/dev/sda1"];
6869           ["lvcreate"; "LV"; "VG"; "8"];
6870           ["mkfs"; "ext2"; "/dev/VG/LV"];
6871           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6872    | InitISOFS ->
6873        pr "  /* InitISOFS for %s */\n" test_name;
6874        List.iter (generate_test_command_call test_name)
6875          [["blockdev_setrw"; "/dev/sda"];
6876           ["umount_all"];
6877           ["lvm_remove_all"];
6878           ["mount_ro"; "/dev/sdd"; "/"]]
6879   );
6880
6881   let get_seq_last = function
6882     | [] ->
6883         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6884           test_name
6885     | seq ->
6886         let seq = List.rev seq in
6887         List.rev (List.tl seq), List.hd seq
6888   in
6889
6890   match test with
6891   | TestRun seq ->
6892       pr "  /* TestRun for %s (%d) */\n" name i;
6893       List.iter (generate_test_command_call test_name) seq
6894   | TestOutput (seq, expected) ->
6895       pr "  /* TestOutput for %s (%d) */\n" name i;
6896       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6897       let seq, last = get_seq_last seq in
6898       let test () =
6899         pr "    if (STRNEQ (r, expected)) {\n";
6900         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6901         pr "      return -1;\n";
6902         pr "    }\n"
6903       in
6904       List.iter (generate_test_command_call test_name) seq;
6905       generate_test_command_call ~test test_name last
6906   | TestOutputList (seq, expected) ->
6907       pr "  /* TestOutputList for %s (%d) */\n" name i;
6908       let seq, last = get_seq_last seq in
6909       let test () =
6910         iteri (
6911           fun i str ->
6912             pr "    if (!r[%d]) {\n" i;
6913             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6914             pr "      print_strings (r);\n";
6915             pr "      return -1;\n";
6916             pr "    }\n";
6917             pr "    {\n";
6918             pr "      const char *expected = \"%s\";\n" (c_quote str);
6919             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6920             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6921             pr "        return -1;\n";
6922             pr "      }\n";
6923             pr "    }\n"
6924         ) expected;
6925         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6926         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6927           test_name;
6928         pr "      print_strings (r);\n";
6929         pr "      return -1;\n";
6930         pr "    }\n"
6931       in
6932       List.iter (generate_test_command_call test_name) seq;
6933       generate_test_command_call ~test test_name last
6934   | TestOutputListOfDevices (seq, expected) ->
6935       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6936       let seq, last = get_seq_last seq in
6937       let test () =
6938         iteri (
6939           fun i str ->
6940             pr "    if (!r[%d]) {\n" i;
6941             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6942             pr "      print_strings (r);\n";
6943             pr "      return -1;\n";
6944             pr "    }\n";
6945             pr "    {\n";
6946             pr "      const char *expected = \"%s\";\n" (c_quote str);
6947             pr "      r[%d][5] = 's';\n" i;
6948             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6949             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6950             pr "        return -1;\n";
6951             pr "      }\n";
6952             pr "    }\n"
6953         ) expected;
6954         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6955         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6956           test_name;
6957         pr "      print_strings (r);\n";
6958         pr "      return -1;\n";
6959         pr "    }\n"
6960       in
6961       List.iter (generate_test_command_call test_name) seq;
6962       generate_test_command_call ~test test_name last
6963   | TestOutputInt (seq, expected) ->
6964       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6965       let seq, last = get_seq_last seq in
6966       let test () =
6967         pr "    if (r != %d) {\n" expected;
6968         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6969           test_name expected;
6970         pr "               (int) r);\n";
6971         pr "      return -1;\n";
6972         pr "    }\n"
6973       in
6974       List.iter (generate_test_command_call test_name) seq;
6975       generate_test_command_call ~test test_name last
6976   | TestOutputIntOp (seq, op, expected) ->
6977       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6978       let seq, last = get_seq_last seq in
6979       let test () =
6980         pr "    if (! (r %s %d)) {\n" op expected;
6981         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6982           test_name op expected;
6983         pr "               (int) r);\n";
6984         pr "      return -1;\n";
6985         pr "    }\n"
6986       in
6987       List.iter (generate_test_command_call test_name) seq;
6988       generate_test_command_call ~test test_name last
6989   | TestOutputTrue seq ->
6990       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6991       let seq, last = get_seq_last seq in
6992       let test () =
6993         pr "    if (!r) {\n";
6994         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6995           test_name;
6996         pr "      return -1;\n";
6997         pr "    }\n"
6998       in
6999       List.iter (generate_test_command_call test_name) seq;
7000       generate_test_command_call ~test test_name last
7001   | TestOutputFalse seq ->
7002       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7003       let seq, last = get_seq_last seq in
7004       let test () =
7005         pr "    if (r) {\n";
7006         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7007           test_name;
7008         pr "      return -1;\n";
7009         pr "    }\n"
7010       in
7011       List.iter (generate_test_command_call test_name) seq;
7012       generate_test_command_call ~test test_name last
7013   | TestOutputLength (seq, expected) ->
7014       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7015       let seq, last = get_seq_last seq in
7016       let test () =
7017         pr "    int j;\n";
7018         pr "    for (j = 0; j < %d; ++j)\n" expected;
7019         pr "      if (r[j] == NULL) {\n";
7020         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7021           test_name;
7022         pr "        print_strings (r);\n";
7023         pr "        return -1;\n";
7024         pr "      }\n";
7025         pr "    if (r[j] != NULL) {\n";
7026         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7027           test_name;
7028         pr "      print_strings (r);\n";
7029         pr "      return -1;\n";
7030         pr "    }\n"
7031       in
7032       List.iter (generate_test_command_call test_name) seq;
7033       generate_test_command_call ~test test_name last
7034   | TestOutputBuffer (seq, expected) ->
7035       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7036       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7037       let seq, last = get_seq_last seq in
7038       let len = String.length expected in
7039       let test () =
7040         pr "    if (size != %d) {\n" len;
7041         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7042         pr "      return -1;\n";
7043         pr "    }\n";
7044         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7045         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7046         pr "      return -1;\n";
7047         pr "    }\n"
7048       in
7049       List.iter (generate_test_command_call test_name) seq;
7050       generate_test_command_call ~test test_name last
7051   | TestOutputStruct (seq, checks) ->
7052       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7053       let seq, last = get_seq_last seq in
7054       let test () =
7055         List.iter (
7056           function
7057           | CompareWithInt (field, expected) ->
7058               pr "    if (r->%s != %d) {\n" field expected;
7059               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7060                 test_name field expected;
7061               pr "               (int) r->%s);\n" field;
7062               pr "      return -1;\n";
7063               pr "    }\n"
7064           | CompareWithIntOp (field, op, expected) ->
7065               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7066               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7067                 test_name field op expected;
7068               pr "               (int) r->%s);\n" field;
7069               pr "      return -1;\n";
7070               pr "    }\n"
7071           | CompareWithString (field, expected) ->
7072               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7073               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7074                 test_name field expected;
7075               pr "               r->%s);\n" field;
7076               pr "      return -1;\n";
7077               pr "    }\n"
7078           | CompareFieldsIntEq (field1, field2) ->
7079               pr "    if (r->%s != r->%s) {\n" field1 field2;
7080               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7081                 test_name field1 field2;
7082               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7083               pr "      return -1;\n";
7084               pr "    }\n"
7085           | CompareFieldsStrEq (field1, field2) ->
7086               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7087               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7088                 test_name field1 field2;
7089               pr "               r->%s, r->%s);\n" field1 field2;
7090               pr "      return -1;\n";
7091               pr "    }\n"
7092         ) checks
7093       in
7094       List.iter (generate_test_command_call test_name) seq;
7095       generate_test_command_call ~test test_name last
7096   | TestLastFail seq ->
7097       pr "  /* TestLastFail for %s (%d) */\n" name i;
7098       let seq, last = get_seq_last seq in
7099       List.iter (generate_test_command_call test_name) seq;
7100       generate_test_command_call test_name ~expect_error:true last
7101
7102 (* Generate the code to run a command, leaving the result in 'r'.
7103  * If you expect to get an error then you should set expect_error:true.
7104  *)
7105 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7106   match cmd with
7107   | [] -> assert false
7108   | name :: args ->
7109       (* Look up the command to find out what args/ret it has. *)
7110       let style =
7111         try
7112           let _, style, _, _, _, _, _ =
7113             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7114           style
7115         with Not_found ->
7116           failwithf "%s: in test, command %s was not found" test_name name in
7117
7118       if List.length (snd style) <> List.length args then
7119         failwithf "%s: in test, wrong number of args given to %s"
7120           test_name name;
7121
7122       pr "  {\n";
7123
7124       List.iter (
7125         function
7126         | OptString n, "NULL" -> ()
7127         | Pathname n, arg
7128         | Device n, arg
7129         | Dev_or_Path n, arg
7130         | String n, arg
7131         | OptString n, arg ->
7132             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7133         | Int _, _
7134         | Int64 _, _
7135         | Bool _, _
7136         | FileIn _, _ | FileOut _, _ -> ()
7137         | StringList n, "" | DeviceList n, "" ->
7138             pr "    const char *const %s[1] = { NULL };\n" n
7139         | StringList n, arg | DeviceList n, arg ->
7140             let strs = string_split " " arg in
7141             iteri (
7142               fun i str ->
7143                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7144             ) strs;
7145             pr "    const char *const %s[] = {\n" n;
7146             iteri (
7147               fun i _ -> pr "      %s_%d,\n" n i
7148             ) strs;
7149             pr "      NULL\n";
7150             pr "    };\n";
7151       ) (List.combine (snd style) args);
7152
7153       let error_code =
7154         match fst style with
7155         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7156         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7157         | RConstString _ | RConstOptString _ ->
7158             pr "    const char *r;\n"; "NULL"
7159         | RString _ -> pr "    char *r;\n"; "NULL"
7160         | RStringList _ | RHashtable _ ->
7161             pr "    char **r;\n";
7162             pr "    int i;\n";
7163             "NULL"
7164         | RStruct (_, typ) ->
7165             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7166         | RStructList (_, typ) ->
7167             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7168         | RBufferOut _ ->
7169             pr "    char *r;\n";
7170             pr "    size_t size;\n";
7171             "NULL" in
7172
7173       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7174       pr "    r = guestfs_%s (g" name;
7175
7176       (* Generate the parameters. *)
7177       List.iter (
7178         function
7179         | OptString _, "NULL" -> pr ", NULL"
7180         | Pathname n, _
7181         | Device n, _ | Dev_or_Path n, _
7182         | String n, _
7183         | OptString n, _ ->
7184             pr ", %s" n
7185         | FileIn _, arg | FileOut _, arg ->
7186             pr ", \"%s\"" (c_quote arg)
7187         | StringList n, _ | DeviceList n, _ ->
7188             pr ", (char **) %s" n
7189         | Int _, arg ->
7190             let i =
7191               try int_of_string arg
7192               with Failure "int_of_string" ->
7193                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7194             pr ", %d" i
7195         | Int64 _, arg ->
7196             let i =
7197               try Int64.of_string arg
7198               with Failure "int_of_string" ->
7199                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7200             pr ", %Ld" i
7201         | Bool _, arg ->
7202             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7203       ) (List.combine (snd style) args);
7204
7205       (match fst style with
7206        | RBufferOut _ -> pr ", &size"
7207        | _ -> ()
7208       );
7209
7210       pr ");\n";
7211
7212       if not expect_error then
7213         pr "    if (r == %s)\n" error_code
7214       else
7215         pr "    if (r != %s)\n" error_code;
7216       pr "      return -1;\n";
7217
7218       (* Insert the test code. *)
7219       (match test with
7220        | None -> ()
7221        | Some f -> f ()
7222       );
7223
7224       (match fst style with
7225        | RErr | RInt _ | RInt64 _ | RBool _
7226        | RConstString _ | RConstOptString _ -> ()
7227        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7228        | RStringList _ | RHashtable _ ->
7229            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7230            pr "      free (r[i]);\n";
7231            pr "    free (r);\n"
7232        | RStruct (_, typ) ->
7233            pr "    guestfs_free_%s (r);\n" typ
7234        | RStructList (_, typ) ->
7235            pr "    guestfs_free_%s_list (r);\n" typ
7236       );
7237
7238       pr "  }\n"
7239
7240 and c_quote str =
7241   let str = replace_str str "\r" "\\r" in
7242   let str = replace_str str "\n" "\\n" in
7243   let str = replace_str str "\t" "\\t" in
7244   let str = replace_str str "\000" "\\0" in
7245   str
7246
7247 (* Generate a lot of different functions for guestfish. *)
7248 and generate_fish_cmds () =
7249   generate_header CStyle GPLv2plus;
7250
7251   let all_functions =
7252     List.filter (
7253       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7254     ) all_functions in
7255   let all_functions_sorted =
7256     List.filter (
7257       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7258     ) all_functions_sorted in
7259
7260   pr "#include <config.h>\n";
7261   pr "\n";
7262   pr "#include <stdio.h>\n";
7263   pr "#include <stdlib.h>\n";
7264   pr "#include <string.h>\n";
7265   pr "#include <inttypes.h>\n";
7266   pr "\n";
7267   pr "#include <guestfs.h>\n";
7268   pr "#include \"c-ctype.h\"\n";
7269   pr "#include \"full-write.h\"\n";
7270   pr "#include \"xstrtol.h\"\n";
7271   pr "#include \"fish.h\"\n";
7272   pr "\n";
7273
7274   (* list_commands function, which implements guestfish -h *)
7275   pr "void list_commands (void)\n";
7276   pr "{\n";
7277   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7278   pr "  list_builtin_commands ();\n";
7279   List.iter (
7280     fun (name, _, _, flags, _, shortdesc, _) ->
7281       let name = replace_char name '_' '-' in
7282       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7283         name shortdesc
7284   ) all_functions_sorted;
7285   pr "  printf (\"    %%s\\n\",";
7286   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7287   pr "}\n";
7288   pr "\n";
7289
7290   (* display_command function, which implements guestfish -h cmd *)
7291   pr "void display_command (const char *cmd)\n";
7292   pr "{\n";
7293   List.iter (
7294     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7295       let name2 = replace_char name '_' '-' in
7296       let alias =
7297         try find_map (function FishAlias n -> Some n | _ -> None) flags
7298         with Not_found -> name in
7299       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7300       let synopsis =
7301         match snd style with
7302         | [] -> name2
7303         | args ->
7304             sprintf "%s %s"
7305               name2 (String.concat " " (List.map name_of_argt args)) in
7306
7307       let warnings =
7308         if List.mem ProtocolLimitWarning flags then
7309           ("\n\n" ^ protocol_limit_warning)
7310         else "" in
7311
7312       (* For DangerWillRobinson commands, we should probably have
7313        * guestfish prompt before allowing you to use them (especially
7314        * in interactive mode). XXX
7315        *)
7316       let warnings =
7317         warnings ^
7318           if List.mem DangerWillRobinson flags then
7319             ("\n\n" ^ danger_will_robinson)
7320           else "" in
7321
7322       let warnings =
7323         warnings ^
7324           match deprecation_notice flags with
7325           | None -> ""
7326           | Some txt -> "\n\n" ^ txt in
7327
7328       let describe_alias =
7329         if name <> alias then
7330           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7331         else "" in
7332
7333       pr "  if (";
7334       pr "STRCASEEQ (cmd, \"%s\")" name;
7335       if name <> name2 then
7336         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7337       if name <> alias then
7338         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7339       pr ")\n";
7340       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7341         name2 shortdesc
7342         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7343          "=head1 DESCRIPTION\n\n" ^
7344          longdesc ^ warnings ^ describe_alias);
7345       pr "  else\n"
7346   ) all_functions;
7347   pr "    display_builtin_command (cmd);\n";
7348   pr "}\n";
7349   pr "\n";
7350
7351   let emit_print_list_function typ =
7352     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7353       typ typ typ;
7354     pr "{\n";
7355     pr "  unsigned int i;\n";
7356     pr "\n";
7357     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7358     pr "    printf (\"[%%d] = {\\n\", i);\n";
7359     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7360     pr "    printf (\"}\\n\");\n";
7361     pr "  }\n";
7362     pr "}\n";
7363     pr "\n";
7364   in
7365
7366   (* print_* functions *)
7367   List.iter (
7368     fun (typ, cols) ->
7369       let needs_i =
7370         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7371
7372       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7373       pr "{\n";
7374       if needs_i then (
7375         pr "  unsigned int i;\n";
7376         pr "\n"
7377       );
7378       List.iter (
7379         function
7380         | name, FString ->
7381             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7382         | name, FUUID ->
7383             pr "  printf (\"%%s%s: \", indent);\n" name;
7384             pr "  for (i = 0; i < 32; ++i)\n";
7385             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7386             pr "  printf (\"\\n\");\n"
7387         | name, FBuffer ->
7388             pr "  printf (\"%%s%s: \", indent);\n" name;
7389             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7390             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7391             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7392             pr "    else\n";
7393             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7394             pr "  printf (\"\\n\");\n"
7395         | name, (FUInt64|FBytes) ->
7396             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7397               name typ name
7398         | name, FInt64 ->
7399             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7400               name typ name
7401         | name, FUInt32 ->
7402             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7403               name typ name
7404         | name, FInt32 ->
7405             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7406               name typ name
7407         | name, FChar ->
7408             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7409               name typ name
7410         | name, FOptPercent ->
7411             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7412               typ name name typ name;
7413             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7414       ) cols;
7415       pr "}\n";
7416       pr "\n";
7417   ) structs;
7418
7419   (* Emit a print_TYPE_list function definition only if that function is used. *)
7420   List.iter (
7421     function
7422     | typ, (RStructListOnly | RStructAndList) ->
7423         (* generate the function for typ *)
7424         emit_print_list_function typ
7425     | typ, _ -> () (* empty *)
7426   ) (rstructs_used_by all_functions);
7427
7428   (* Emit a print_TYPE function definition only if that function is used. *)
7429   List.iter (
7430     function
7431     | typ, (RStructOnly | RStructAndList) ->
7432         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7433         pr "{\n";
7434         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7435         pr "}\n";
7436         pr "\n";
7437     | typ, _ -> () (* empty *)
7438   ) (rstructs_used_by all_functions);
7439
7440   (* run_<action> actions *)
7441   List.iter (
7442     fun (name, style, _, flags, _, _, _) ->
7443       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7444       pr "{\n";
7445       (match fst style with
7446        | RErr
7447        | RInt _
7448        | RBool _ -> pr "  int r;\n"
7449        | RInt64 _ -> pr "  int64_t r;\n"
7450        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7451        | RString _ -> pr "  char *r;\n"
7452        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7453        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7454        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7455        | RBufferOut _ ->
7456            pr "  char *r;\n";
7457            pr "  size_t size;\n";
7458       );
7459       List.iter (
7460         function
7461         | Device n
7462         | String n
7463         | OptString n -> pr "  const char *%s;\n" n
7464         | Pathname n
7465         | Dev_or_Path n
7466         | FileIn n
7467         | FileOut n -> pr "  char *%s;\n" n
7468         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7469         | Bool n -> pr "  int %s;\n" n
7470         | Int n -> pr "  int %s;\n" n
7471         | Int64 n -> pr "  int64_t %s;\n" n
7472       ) (snd style);
7473
7474       (* Check and convert parameters. *)
7475       let argc_expected = List.length (snd style) in
7476       pr "  if (argc != %d) {\n" argc_expected;
7477       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7478         argc_expected;
7479       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7480       pr "    return -1;\n";
7481       pr "  }\n";
7482
7483       let parse_integer fn fntyp rtyp range name i =
7484         pr "  {\n";
7485         pr "    strtol_error xerr;\n";
7486         pr "    %s r;\n" fntyp;
7487         pr "\n";
7488         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7489         pr "    if (xerr != LONGINT_OK) {\n";
7490         pr "      fprintf (stderr,\n";
7491         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7492         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7493         pr "      return -1;\n";
7494         pr "    }\n";
7495         (match range with
7496          | None -> ()
7497          | Some (min, max, comment) ->
7498              pr "    /* %s */\n" comment;
7499              pr "    if (r < %s || r > %s) {\n" min max;
7500              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7501                name;
7502              pr "      return -1;\n";
7503              pr "    }\n";
7504              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7505         );
7506         pr "    %s = r;\n" name;
7507         pr "  }\n";
7508       in
7509
7510       iteri (
7511         fun i ->
7512           function
7513           | Device name
7514           | String name ->
7515               pr "  %s = argv[%d];\n" name i
7516           | Pathname name
7517           | Dev_or_Path name ->
7518               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7519               pr "  if (%s == NULL) return -1;\n" name
7520           | OptString name ->
7521               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7522                 name i i
7523           | FileIn name ->
7524               pr "  %s = file_in (argv[%d]);\n" name i;
7525               pr "  if (%s == NULL) return -1;\n" name
7526           | FileOut name ->
7527               pr "  %s = file_out (argv[%d]);\n" name i;
7528               pr "  if (%s == NULL) return -1;\n" name
7529           | StringList name | DeviceList name ->
7530               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7531               pr "  if (%s == NULL) return -1;\n" name;
7532           | Bool name ->
7533               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7534           | Int name ->
7535               let range =
7536                 let min = "(-(2LL<<30))"
7537                 and max = "((2LL<<30)-1)"
7538                 and comment =
7539                   "The Int type in the generator is a signed 31 bit int." in
7540                 Some (min, max, comment) in
7541               parse_integer "xstrtoll" "long long" "int" range name i
7542           | Int64 name ->
7543               parse_integer "xstrtoll" "long long" "int64_t" None name i
7544       ) (snd style);
7545
7546       (* Call C API function. *)
7547       let fn =
7548         try find_map (function FishAction n -> Some n | _ -> None) flags
7549         with Not_found -> sprintf "guestfs_%s" name in
7550       pr "  r = %s " fn;
7551       generate_c_call_args ~handle:"g" style;
7552       pr ";\n";
7553
7554       List.iter (
7555         function
7556         | Device name | String name
7557         | OptString name | Bool name
7558         | Int name | Int64 name -> ()
7559         | Pathname name | Dev_or_Path name | FileOut name ->
7560             pr "  free (%s);\n" name
7561         | FileIn name ->
7562             pr "  free_file_in (%s);\n" name
7563         | StringList name | DeviceList name ->
7564             pr "  free_strings (%s);\n" name
7565       ) (snd style);
7566
7567       (* Any output flags? *)
7568       let fish_output =
7569         let flags = filter_map (
7570           function FishOutput flag -> Some flag | _ -> None
7571         ) flags in
7572         match flags with
7573         | [] -> None
7574         | [f] -> Some f
7575         | _ ->
7576             failwithf "%s: more than one FishOutput flag is not allowed" name in
7577
7578       (* Check return value for errors and display command results. *)
7579       (match fst style with
7580        | RErr -> pr "  return r;\n"
7581        | RInt _ ->
7582            pr "  if (r == -1) return -1;\n";
7583            (match fish_output with
7584             | None ->
7585                 pr "  printf (\"%%d\\n\", r);\n";
7586             | Some FishOutputOctal ->
7587                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7588             | Some FishOutputHexadecimal ->
7589                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7590            pr "  return 0;\n"
7591        | RInt64 _ ->
7592            pr "  if (r == -1) return -1;\n";
7593            (match fish_output with
7594             | None ->
7595                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7596             | Some FishOutputOctal ->
7597                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7598             | Some FishOutputHexadecimal ->
7599                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7600            pr "  return 0;\n"
7601        | RBool _ ->
7602            pr "  if (r == -1) return -1;\n";
7603            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7604            pr "  return 0;\n"
7605        | RConstString _ ->
7606            pr "  if (r == NULL) return -1;\n";
7607            pr "  printf (\"%%s\\n\", r);\n";
7608            pr "  return 0;\n"
7609        | RConstOptString _ ->
7610            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7611            pr "  return 0;\n"
7612        | RString _ ->
7613            pr "  if (r == NULL) return -1;\n";
7614            pr "  printf (\"%%s\\n\", r);\n";
7615            pr "  free (r);\n";
7616            pr "  return 0;\n"
7617        | RStringList _ ->
7618            pr "  if (r == NULL) return -1;\n";
7619            pr "  print_strings (r);\n";
7620            pr "  free_strings (r);\n";
7621            pr "  return 0;\n"
7622        | RStruct (_, typ) ->
7623            pr "  if (r == NULL) return -1;\n";
7624            pr "  print_%s (r);\n" typ;
7625            pr "  guestfs_free_%s (r);\n" typ;
7626            pr "  return 0;\n"
7627        | RStructList (_, typ) ->
7628            pr "  if (r == NULL) return -1;\n";
7629            pr "  print_%s_list (r);\n" typ;
7630            pr "  guestfs_free_%s_list (r);\n" typ;
7631            pr "  return 0;\n"
7632        | RHashtable _ ->
7633            pr "  if (r == NULL) return -1;\n";
7634            pr "  print_table (r);\n";
7635            pr "  free_strings (r);\n";
7636            pr "  return 0;\n"
7637        | RBufferOut _ ->
7638            pr "  if (r == NULL) return -1;\n";
7639            pr "  if (full_write (1, r, size) != size) {\n";
7640            pr "    perror (\"write\");\n";
7641            pr "    free (r);\n";
7642            pr "    return -1;\n";
7643            pr "  }\n";
7644            pr "  free (r);\n";
7645            pr "  return 0;\n"
7646       );
7647       pr "}\n";
7648       pr "\n"
7649   ) all_functions;
7650
7651   (* run_action function *)
7652   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7653   pr "{\n";
7654   List.iter (
7655     fun (name, _, _, flags, _, _, _) ->
7656       let name2 = replace_char name '_' '-' in
7657       let alias =
7658         try find_map (function FishAlias n -> Some n | _ -> None) flags
7659         with Not_found -> name in
7660       pr "  if (";
7661       pr "STRCASEEQ (cmd, \"%s\")" name;
7662       if name <> name2 then
7663         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7664       if name <> alias then
7665         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7666       pr ")\n";
7667       pr "    return run_%s (cmd, argc, argv);\n" name;
7668       pr "  else\n";
7669   ) all_functions;
7670   pr "    {\n";
7671   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7672   pr "      if (command_num == 1)\n";
7673   pr "        extended_help_message ();\n";
7674   pr "      return -1;\n";
7675   pr "    }\n";
7676   pr "  return 0;\n";
7677   pr "}\n";
7678   pr "\n"
7679
7680 (* Readline completion for guestfish. *)
7681 and generate_fish_completion () =
7682   generate_header CStyle GPLv2plus;
7683
7684   let all_functions =
7685     List.filter (
7686       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7687     ) all_functions in
7688
7689   pr "\
7690 #include <config.h>
7691
7692 #include <stdio.h>
7693 #include <stdlib.h>
7694 #include <string.h>
7695
7696 #ifdef HAVE_LIBREADLINE
7697 #include <readline/readline.h>
7698 #endif
7699
7700 #include \"fish.h\"
7701
7702 #ifdef HAVE_LIBREADLINE
7703
7704 static const char *const commands[] = {
7705   BUILTIN_COMMANDS_FOR_COMPLETION,
7706 ";
7707
7708   (* Get the commands, including the aliases.  They don't need to be
7709    * sorted - the generator() function just does a dumb linear search.
7710    *)
7711   let commands =
7712     List.map (
7713       fun (name, _, _, flags, _, _, _) ->
7714         let name2 = replace_char name '_' '-' in
7715         let alias =
7716           try find_map (function FishAlias n -> Some n | _ -> None) flags
7717           with Not_found -> name in
7718
7719         if name <> alias then [name2; alias] else [name2]
7720     ) all_functions in
7721   let commands = List.flatten commands in
7722
7723   List.iter (pr "  \"%s\",\n") commands;
7724
7725   pr "  NULL
7726 };
7727
7728 static char *
7729 generator (const char *text, int state)
7730 {
7731   static int index, len;
7732   const char *name;
7733
7734   if (!state) {
7735     index = 0;
7736     len = strlen (text);
7737   }
7738
7739   rl_attempted_completion_over = 1;
7740
7741   while ((name = commands[index]) != NULL) {
7742     index++;
7743     if (STRCASEEQLEN (name, text, len))
7744       return strdup (name);
7745   }
7746
7747   return NULL;
7748 }
7749
7750 #endif /* HAVE_LIBREADLINE */
7751
7752 #ifdef HAVE_RL_COMPLETION_MATCHES
7753 #define RL_COMPLETION_MATCHES rl_completion_matches
7754 #else
7755 #ifdef HAVE_COMPLETION_MATCHES
7756 #define RL_COMPLETION_MATCHES completion_matches
7757 #endif
7758 #endif /* else just fail if we don't have either symbol */
7759
7760 char **
7761 do_completion (const char *text, int start, int end)
7762 {
7763   char **matches = NULL;
7764
7765 #ifdef HAVE_LIBREADLINE
7766   rl_completion_append_character = ' ';
7767
7768   if (start == 0)
7769     matches = RL_COMPLETION_MATCHES (text, generator);
7770   else if (complete_dest_paths)
7771     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7772 #endif
7773
7774   return matches;
7775 }
7776 ";
7777
7778 (* Generate the POD documentation for guestfish. *)
7779 and generate_fish_actions_pod () =
7780   let all_functions_sorted =
7781     List.filter (
7782       fun (_, _, _, flags, _, _, _) ->
7783         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7784     ) all_functions_sorted in
7785
7786   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7787
7788   List.iter (
7789     fun (name, style, _, flags, _, _, longdesc) ->
7790       let longdesc =
7791         Str.global_substitute rex (
7792           fun s ->
7793             let sub =
7794               try Str.matched_group 1 s
7795               with Not_found ->
7796                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7797             "C<" ^ replace_char sub '_' '-' ^ ">"
7798         ) longdesc in
7799       let name = replace_char name '_' '-' in
7800       let alias =
7801         try find_map (function FishAlias n -> Some n | _ -> None) flags
7802         with Not_found -> name in
7803
7804       pr "=head2 %s" name;
7805       if name <> alias then
7806         pr " | %s" alias;
7807       pr "\n";
7808       pr "\n";
7809       pr " %s" name;
7810       List.iter (
7811         function
7812         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7813         | OptString n -> pr " %s" n
7814         | StringList n | DeviceList n -> pr " '%s ...'" n
7815         | Bool _ -> pr " true|false"
7816         | Int n -> pr " %s" n
7817         | Int64 n -> pr " %s" n
7818         | FileIn n | FileOut n -> pr " (%s|-)" n
7819       ) (snd style);
7820       pr "\n";
7821       pr "\n";
7822       pr "%s\n\n" longdesc;
7823
7824       if List.exists (function FileIn _ | FileOut _ -> true
7825                       | _ -> false) (snd style) then
7826         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7827
7828       if List.mem ProtocolLimitWarning flags then
7829         pr "%s\n\n" protocol_limit_warning;
7830
7831       if List.mem DangerWillRobinson flags then
7832         pr "%s\n\n" danger_will_robinson;
7833
7834       match deprecation_notice flags with
7835       | None -> ()
7836       | Some txt -> pr "%s\n\n" txt
7837   ) all_functions_sorted
7838
7839 (* Generate a C function prototype. *)
7840 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7841     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7842     ?(prefix = "")
7843     ?handle name style =
7844   if extern then pr "extern ";
7845   if static then pr "static ";
7846   (match fst style with
7847    | RErr -> pr "int "
7848    | RInt _ -> pr "int "
7849    | RInt64 _ -> pr "int64_t "
7850    | RBool _ -> pr "int "
7851    | RConstString _ | RConstOptString _ -> pr "const char *"
7852    | RString _ | RBufferOut _ -> pr "char *"
7853    | RStringList _ | RHashtable _ -> pr "char **"
7854    | RStruct (_, typ) ->
7855        if not in_daemon then pr "struct guestfs_%s *" typ
7856        else pr "guestfs_int_%s *" typ
7857    | RStructList (_, typ) ->
7858        if not in_daemon then pr "struct guestfs_%s_list *" typ
7859        else pr "guestfs_int_%s_list *" typ
7860   );
7861   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7862   pr "%s%s (" prefix name;
7863   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7864     pr "void"
7865   else (
7866     let comma = ref false in
7867     (match handle with
7868      | None -> ()
7869      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7870     );
7871     let next () =
7872       if !comma then (
7873         if single_line then pr ", " else pr ",\n\t\t"
7874       );
7875       comma := true
7876     in
7877     List.iter (
7878       function
7879       | Pathname n
7880       | Device n | Dev_or_Path n
7881       | String n
7882       | OptString n ->
7883           next ();
7884           pr "const char *%s" n
7885       | StringList n | DeviceList n ->
7886           next ();
7887           pr "char *const *%s" n
7888       | Bool n -> next (); pr "int %s" n
7889       | Int n -> next (); pr "int %s" n
7890       | Int64 n -> next (); pr "int64_t %s" n
7891       | FileIn n
7892       | FileOut n ->
7893           if not in_daemon then (next (); pr "const char *%s" n)
7894     ) (snd style);
7895     if is_RBufferOut then (next (); pr "size_t *size_r");
7896   );
7897   pr ")";
7898   if semicolon then pr ";";
7899   if newline then pr "\n"
7900
7901 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7902 and generate_c_call_args ?handle ?(decl = false) style =
7903   pr "(";
7904   let comma = ref false in
7905   let next () =
7906     if !comma then pr ", ";
7907     comma := true
7908   in
7909   (match handle with
7910    | None -> ()
7911    | Some handle -> pr "%s" handle; comma := true
7912   );
7913   List.iter (
7914     fun arg ->
7915       next ();
7916       pr "%s" (name_of_argt arg)
7917   ) (snd style);
7918   (* For RBufferOut calls, add implicit &size parameter. *)
7919   if not decl then (
7920     match fst style with
7921     | RBufferOut _ ->
7922         next ();
7923         pr "&size"
7924     | _ -> ()
7925   );
7926   pr ")"
7927
7928 (* Generate the OCaml bindings interface. *)
7929 and generate_ocaml_mli () =
7930   generate_header OCamlStyle LGPLv2plus;
7931
7932   pr "\
7933 (** For API documentation you should refer to the C API
7934     in the guestfs(3) manual page.  The OCaml API uses almost
7935     exactly the same calls. *)
7936
7937 type t
7938 (** A [guestfs_h] handle. *)
7939
7940 exception Error of string
7941 (** This exception is raised when there is an error. *)
7942
7943 exception Handle_closed of string
7944 (** This exception is raised if you use a {!Guestfs.t} handle
7945     after calling {!close} on it.  The string is the name of
7946     the function. *)
7947
7948 val create : unit -> t
7949 (** Create a {!Guestfs.t} handle. *)
7950
7951 val close : t -> unit
7952 (** Close the {!Guestfs.t} handle and free up all resources used
7953     by it immediately.
7954
7955     Handles are closed by the garbage collector when they become
7956     unreferenced, but callers can call this in order to provide
7957     predictable cleanup. *)
7958
7959 ";
7960   generate_ocaml_structure_decls ();
7961
7962   (* The actions. *)
7963   List.iter (
7964     fun (name, style, _, _, _, shortdesc, _) ->
7965       generate_ocaml_prototype name style;
7966       pr "(** %s *)\n" shortdesc;
7967       pr "\n"
7968   ) all_functions_sorted
7969
7970 (* Generate the OCaml bindings implementation. *)
7971 and generate_ocaml_ml () =
7972   generate_header OCamlStyle LGPLv2plus;
7973
7974   pr "\
7975 type t
7976
7977 exception Error of string
7978 exception Handle_closed of string
7979
7980 external create : unit -> t = \"ocaml_guestfs_create\"
7981 external close : t -> unit = \"ocaml_guestfs_close\"
7982
7983 (* Give the exceptions names, so they can be raised from the C code. *)
7984 let () =
7985   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7986   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7987
7988 ";
7989
7990   generate_ocaml_structure_decls ();
7991
7992   (* The actions. *)
7993   List.iter (
7994     fun (name, style, _, _, _, shortdesc, _) ->
7995       generate_ocaml_prototype ~is_external:true name style;
7996   ) all_functions_sorted
7997
7998 (* Generate the OCaml bindings C implementation. *)
7999 and generate_ocaml_c () =
8000   generate_header CStyle LGPLv2plus;
8001
8002   pr "\
8003 #include <stdio.h>
8004 #include <stdlib.h>
8005 #include <string.h>
8006
8007 #include <caml/config.h>
8008 #include <caml/alloc.h>
8009 #include <caml/callback.h>
8010 #include <caml/fail.h>
8011 #include <caml/memory.h>
8012 #include <caml/mlvalues.h>
8013 #include <caml/signals.h>
8014
8015 #include <guestfs.h>
8016
8017 #include \"guestfs_c.h\"
8018
8019 /* Copy a hashtable of string pairs into an assoc-list.  We return
8020  * the list in reverse order, but hashtables aren't supposed to be
8021  * ordered anyway.
8022  */
8023 static CAMLprim value
8024 copy_table (char * const * argv)
8025 {
8026   CAMLparam0 ();
8027   CAMLlocal5 (rv, pairv, kv, vv, cons);
8028   int i;
8029
8030   rv = Val_int (0);
8031   for (i = 0; argv[i] != NULL; i += 2) {
8032     kv = caml_copy_string (argv[i]);
8033     vv = caml_copy_string (argv[i+1]);
8034     pairv = caml_alloc (2, 0);
8035     Store_field (pairv, 0, kv);
8036     Store_field (pairv, 1, vv);
8037     cons = caml_alloc (2, 0);
8038     Store_field (cons, 1, rv);
8039     rv = cons;
8040     Store_field (cons, 0, pairv);
8041   }
8042
8043   CAMLreturn (rv);
8044 }
8045
8046 ";
8047
8048   (* Struct copy functions. *)
8049
8050   let emit_ocaml_copy_list_function typ =
8051     pr "static CAMLprim value\n";
8052     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8053     pr "{\n";
8054     pr "  CAMLparam0 ();\n";
8055     pr "  CAMLlocal2 (rv, v);\n";
8056     pr "  unsigned int i;\n";
8057     pr "\n";
8058     pr "  if (%ss->len == 0)\n" typ;
8059     pr "    CAMLreturn (Atom (0));\n";
8060     pr "  else {\n";
8061     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8062     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8063     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8064     pr "      caml_modify (&Field (rv, i), v);\n";
8065     pr "    }\n";
8066     pr "    CAMLreturn (rv);\n";
8067     pr "  }\n";
8068     pr "}\n";
8069     pr "\n";
8070   in
8071
8072   List.iter (
8073     fun (typ, cols) ->
8074       let has_optpercent_col =
8075         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8076
8077       pr "static CAMLprim value\n";
8078       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8079       pr "{\n";
8080       pr "  CAMLparam0 ();\n";
8081       if has_optpercent_col then
8082         pr "  CAMLlocal3 (rv, v, v2);\n"
8083       else
8084         pr "  CAMLlocal2 (rv, v);\n";
8085       pr "\n";
8086       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8087       iteri (
8088         fun i col ->
8089           (match col with
8090            | name, FString ->
8091                pr "  v = caml_copy_string (%s->%s);\n" typ name
8092            | name, FBuffer ->
8093                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8094                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8095                  typ name typ name
8096            | name, FUUID ->
8097                pr "  v = caml_alloc_string (32);\n";
8098                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8099            | name, (FBytes|FInt64|FUInt64) ->
8100                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8101            | name, (FInt32|FUInt32) ->
8102                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8103            | name, FOptPercent ->
8104                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8105                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8106                pr "    v = caml_alloc (1, 0);\n";
8107                pr "    Store_field (v, 0, v2);\n";
8108                pr "  } else /* None */\n";
8109                pr "    v = Val_int (0);\n";
8110            | name, FChar ->
8111                pr "  v = Val_int (%s->%s);\n" typ name
8112           );
8113           pr "  Store_field (rv, %d, v);\n" i
8114       ) cols;
8115       pr "  CAMLreturn (rv);\n";
8116       pr "}\n";
8117       pr "\n";
8118   ) structs;
8119
8120   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8121   List.iter (
8122     function
8123     | typ, (RStructListOnly | RStructAndList) ->
8124         (* generate the function for typ *)
8125         emit_ocaml_copy_list_function typ
8126     | typ, _ -> () (* empty *)
8127   ) (rstructs_used_by all_functions);
8128
8129   (* The wrappers. *)
8130   List.iter (
8131     fun (name, style, _, _, _, _, _) ->
8132       pr "/* Automatically generated wrapper for function\n";
8133       pr " * ";
8134       generate_ocaml_prototype name style;
8135       pr " */\n";
8136       pr "\n";
8137
8138       let params =
8139         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8140
8141       let needs_extra_vs =
8142         match fst style with RConstOptString _ -> true | _ -> false in
8143
8144       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8145       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8146       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8147       pr "\n";
8148
8149       pr "CAMLprim value\n";
8150       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8151       List.iter (pr ", value %s") (List.tl params);
8152       pr ")\n";
8153       pr "{\n";
8154
8155       (match params with
8156        | [p1; p2; p3; p4; p5] ->
8157            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8158        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8159            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8160            pr "  CAMLxparam%d (%s);\n"
8161              (List.length rest) (String.concat ", " rest)
8162        | ps ->
8163            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8164       );
8165       if not needs_extra_vs then
8166         pr "  CAMLlocal1 (rv);\n"
8167       else
8168         pr "  CAMLlocal3 (rv, v, v2);\n";
8169       pr "\n";
8170
8171       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8172       pr "  if (g == NULL)\n";
8173       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8174       pr "\n";
8175
8176       List.iter (
8177         function
8178         | Pathname n
8179         | Device n | Dev_or_Path n
8180         | String n
8181         | FileIn n
8182         | FileOut n ->
8183             pr "  const char *%s = String_val (%sv);\n" n n
8184         | OptString n ->
8185             pr "  const char *%s =\n" n;
8186             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8187               n n
8188         | StringList n | DeviceList n ->
8189             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8190         | Bool n ->
8191             pr "  int %s = Bool_val (%sv);\n" n n
8192         | Int n ->
8193             pr "  int %s = Int_val (%sv);\n" n n
8194         | Int64 n ->
8195             pr "  int64_t %s = Int64_val (%sv);\n" n n
8196       ) (snd style);
8197       let error_code =
8198         match fst style with
8199         | RErr -> pr "  int r;\n"; "-1"
8200         | RInt _ -> pr "  int r;\n"; "-1"
8201         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8202         | RBool _ -> pr "  int r;\n"; "-1"
8203         | RConstString _ | RConstOptString _ ->
8204             pr "  const char *r;\n"; "NULL"
8205         | RString _ -> pr "  char *r;\n"; "NULL"
8206         | RStringList _ ->
8207             pr "  int i;\n";
8208             pr "  char **r;\n";
8209             "NULL"
8210         | RStruct (_, typ) ->
8211             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8212         | RStructList (_, typ) ->
8213             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8214         | RHashtable _ ->
8215             pr "  int i;\n";
8216             pr "  char **r;\n";
8217             "NULL"
8218         | RBufferOut _ ->
8219             pr "  char *r;\n";
8220             pr "  size_t size;\n";
8221             "NULL" in
8222       pr "\n";
8223
8224       pr "  caml_enter_blocking_section ();\n";
8225       pr "  r = guestfs_%s " name;
8226       generate_c_call_args ~handle:"g" style;
8227       pr ";\n";
8228       pr "  caml_leave_blocking_section ();\n";
8229
8230       List.iter (
8231         function
8232         | StringList n | DeviceList n ->
8233             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8234         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8235         | Bool _ | Int _ | Int64 _
8236         | FileIn _ | FileOut _ -> ()
8237       ) (snd style);
8238
8239       pr "  if (r == %s)\n" error_code;
8240       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8241       pr "\n";
8242
8243       (match fst style with
8244        | RErr -> pr "  rv = Val_unit;\n"
8245        | RInt _ -> pr "  rv = Val_int (r);\n"
8246        | RInt64 _ ->
8247            pr "  rv = caml_copy_int64 (r);\n"
8248        | RBool _ -> pr "  rv = Val_bool (r);\n"
8249        | RConstString _ ->
8250            pr "  rv = caml_copy_string (r);\n"
8251        | RConstOptString _ ->
8252            pr "  if (r) { /* Some string */\n";
8253            pr "    v = caml_alloc (1, 0);\n";
8254            pr "    v2 = caml_copy_string (r);\n";
8255            pr "    Store_field (v, 0, v2);\n";
8256            pr "  } else /* None */\n";
8257            pr "    v = Val_int (0);\n";
8258        | RString _ ->
8259            pr "  rv = caml_copy_string (r);\n";
8260            pr "  free (r);\n"
8261        | RStringList _ ->
8262            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8263            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8264            pr "  free (r);\n"
8265        | RStruct (_, typ) ->
8266            pr "  rv = copy_%s (r);\n" typ;
8267            pr "  guestfs_free_%s (r);\n" typ;
8268        | RStructList (_, typ) ->
8269            pr "  rv = copy_%s_list (r);\n" typ;
8270            pr "  guestfs_free_%s_list (r);\n" typ;
8271        | RHashtable _ ->
8272            pr "  rv = copy_table (r);\n";
8273            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8274            pr "  free (r);\n";
8275        | RBufferOut _ ->
8276            pr "  rv = caml_alloc_string (size);\n";
8277            pr "  memcpy (String_val (rv), r, size);\n";
8278       );
8279
8280       pr "  CAMLreturn (rv);\n";
8281       pr "}\n";
8282       pr "\n";
8283
8284       if List.length params > 5 then (
8285         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8286         pr "CAMLprim value ";
8287         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8288         pr "CAMLprim value\n";
8289         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8290         pr "{\n";
8291         pr "  return ocaml_guestfs_%s (argv[0]" name;
8292         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8293         pr ");\n";
8294         pr "}\n";
8295         pr "\n"
8296       )
8297   ) all_functions_sorted
8298
8299 and generate_ocaml_structure_decls () =
8300   List.iter (
8301     fun (typ, cols) ->
8302       pr "type %s = {\n" typ;
8303       List.iter (
8304         function
8305         | name, FString -> pr "  %s : string;\n" name
8306         | name, FBuffer -> pr "  %s : string;\n" name
8307         | name, FUUID -> pr "  %s : string;\n" name
8308         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8309         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8310         | name, FChar -> pr "  %s : char;\n" name
8311         | name, FOptPercent -> pr "  %s : float option;\n" name
8312       ) cols;
8313       pr "}\n";
8314       pr "\n"
8315   ) structs
8316
8317 and generate_ocaml_prototype ?(is_external = false) name style =
8318   if is_external then pr "external " else pr "val ";
8319   pr "%s : t -> " name;
8320   List.iter (
8321     function
8322     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8323     | OptString _ -> pr "string option -> "
8324     | StringList _ | DeviceList _ -> pr "string array -> "
8325     | Bool _ -> pr "bool -> "
8326     | Int _ -> pr "int -> "
8327     | Int64 _ -> pr "int64 -> "
8328   ) (snd style);
8329   (match fst style with
8330    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8331    | RInt _ -> pr "int"
8332    | RInt64 _ -> pr "int64"
8333    | RBool _ -> pr "bool"
8334    | RConstString _ -> pr "string"
8335    | RConstOptString _ -> pr "string option"
8336    | RString _ | RBufferOut _ -> pr "string"
8337    | RStringList _ -> pr "string array"
8338    | RStruct (_, typ) -> pr "%s" typ
8339    | RStructList (_, typ) -> pr "%s array" typ
8340    | RHashtable _ -> pr "(string * string) list"
8341   );
8342   if is_external then (
8343     pr " = ";
8344     if List.length (snd style) + 1 > 5 then
8345       pr "\"ocaml_guestfs_%s_byte\" " name;
8346     pr "\"ocaml_guestfs_%s\"" name
8347   );
8348   pr "\n"
8349
8350 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8351 and generate_perl_xs () =
8352   generate_header CStyle LGPLv2plus;
8353
8354   pr "\
8355 #include \"EXTERN.h\"
8356 #include \"perl.h\"
8357 #include \"XSUB.h\"
8358
8359 #include <guestfs.h>
8360
8361 #ifndef PRId64
8362 #define PRId64 \"lld\"
8363 #endif
8364
8365 static SV *
8366 my_newSVll(long long val) {
8367 #ifdef USE_64_BIT_ALL
8368   return newSViv(val);
8369 #else
8370   char buf[100];
8371   int len;
8372   len = snprintf(buf, 100, \"%%\" PRId64, val);
8373   return newSVpv(buf, len);
8374 #endif
8375 }
8376
8377 #ifndef PRIu64
8378 #define PRIu64 \"llu\"
8379 #endif
8380
8381 static SV *
8382 my_newSVull(unsigned long long val) {
8383 #ifdef USE_64_BIT_ALL
8384   return newSVuv(val);
8385 #else
8386   char buf[100];
8387   int len;
8388   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8389   return newSVpv(buf, len);
8390 #endif
8391 }
8392
8393 /* http://www.perlmonks.org/?node_id=680842 */
8394 static char **
8395 XS_unpack_charPtrPtr (SV *arg) {
8396   char **ret;
8397   AV *av;
8398   I32 i;
8399
8400   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8401     croak (\"array reference expected\");
8402
8403   av = (AV *)SvRV (arg);
8404   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8405   if (!ret)
8406     croak (\"malloc failed\");
8407
8408   for (i = 0; i <= av_len (av); i++) {
8409     SV **elem = av_fetch (av, i, 0);
8410
8411     if (!elem || !*elem)
8412       croak (\"missing element in list\");
8413
8414     ret[i] = SvPV_nolen (*elem);
8415   }
8416
8417   ret[i] = NULL;
8418
8419   return ret;
8420 }
8421
8422 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8423
8424 PROTOTYPES: ENABLE
8425
8426 guestfs_h *
8427 _create ()
8428    CODE:
8429       RETVAL = guestfs_create ();
8430       if (!RETVAL)
8431         croak (\"could not create guestfs handle\");
8432       guestfs_set_error_handler (RETVAL, NULL, NULL);
8433  OUTPUT:
8434       RETVAL
8435
8436 void
8437 DESTROY (g)
8438       guestfs_h *g;
8439  PPCODE:
8440       guestfs_close (g);
8441
8442 ";
8443
8444   List.iter (
8445     fun (name, style, _, _, _, _, _) ->
8446       (match fst style with
8447        | RErr -> pr "void\n"
8448        | RInt _ -> pr "SV *\n"
8449        | RInt64 _ -> pr "SV *\n"
8450        | RBool _ -> pr "SV *\n"
8451        | RConstString _ -> pr "SV *\n"
8452        | RConstOptString _ -> pr "SV *\n"
8453        | RString _ -> pr "SV *\n"
8454        | RBufferOut _ -> pr "SV *\n"
8455        | RStringList _
8456        | RStruct _ | RStructList _
8457        | RHashtable _ ->
8458            pr "void\n" (* all lists returned implictly on the stack *)
8459       );
8460       (* Call and arguments. *)
8461       pr "%s " name;
8462       generate_c_call_args ~handle:"g" ~decl:true style;
8463       pr "\n";
8464       pr "      guestfs_h *g;\n";
8465       iteri (
8466         fun i ->
8467           function
8468           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8469               pr "      char *%s;\n" n
8470           | OptString n ->
8471               (* http://www.perlmonks.org/?node_id=554277
8472                * Note that the implicit handle argument means we have
8473                * to add 1 to the ST(x) operator.
8474                *)
8475               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8476           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8477           | Bool n -> pr "      int %s;\n" n
8478           | Int n -> pr "      int %s;\n" n
8479           | Int64 n -> pr "      int64_t %s;\n" n
8480       ) (snd style);
8481
8482       let do_cleanups () =
8483         List.iter (
8484           function
8485           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8486           | Bool _ | Int _ | Int64 _
8487           | FileIn _ | FileOut _ -> ()
8488           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8489         ) (snd style)
8490       in
8491
8492       (* Code. *)
8493       (match fst style with
8494        | RErr ->
8495            pr "PREINIT:\n";
8496            pr "      int r;\n";
8497            pr " PPCODE:\n";
8498            pr "      r = guestfs_%s " name;
8499            generate_c_call_args ~handle:"g" style;
8500            pr ";\n";
8501            do_cleanups ();
8502            pr "      if (r == -1)\n";
8503            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8504        | RInt n
8505        | RBool n ->
8506            pr "PREINIT:\n";
8507            pr "      int %s;\n" n;
8508            pr "   CODE:\n";
8509            pr "      %s = guestfs_%s " n name;
8510            generate_c_call_args ~handle:"g" style;
8511            pr ";\n";
8512            do_cleanups ();
8513            pr "      if (%s == -1)\n" n;
8514            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8515            pr "      RETVAL = newSViv (%s);\n" n;
8516            pr " OUTPUT:\n";
8517            pr "      RETVAL\n"
8518        | RInt64 n ->
8519            pr "PREINIT:\n";
8520            pr "      int64_t %s;\n" n;
8521            pr "   CODE:\n";
8522            pr "      %s = guestfs_%s " n name;
8523            generate_c_call_args ~handle:"g" style;
8524            pr ";\n";
8525            do_cleanups ();
8526            pr "      if (%s == -1)\n" n;
8527            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8528            pr "      RETVAL = my_newSVll (%s);\n" n;
8529            pr " OUTPUT:\n";
8530            pr "      RETVAL\n"
8531        | RConstString n ->
8532            pr "PREINIT:\n";
8533            pr "      const char *%s;\n" n;
8534            pr "   CODE:\n";
8535            pr "      %s = guestfs_%s " n name;
8536            generate_c_call_args ~handle:"g" style;
8537            pr ";\n";
8538            do_cleanups ();
8539            pr "      if (%s == NULL)\n" n;
8540            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8541            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8542            pr " OUTPUT:\n";
8543            pr "      RETVAL\n"
8544        | RConstOptString n ->
8545            pr "PREINIT:\n";
8546            pr "      const char *%s;\n" n;
8547            pr "   CODE:\n";
8548            pr "      %s = guestfs_%s " n name;
8549            generate_c_call_args ~handle:"g" style;
8550            pr ";\n";
8551            do_cleanups ();
8552            pr "      if (%s == NULL)\n" n;
8553            pr "        RETVAL = &PL_sv_undef;\n";
8554            pr "      else\n";
8555            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8556            pr " OUTPUT:\n";
8557            pr "      RETVAL\n"
8558        | RString n ->
8559            pr "PREINIT:\n";
8560            pr "      char *%s;\n" n;
8561            pr "   CODE:\n";
8562            pr "      %s = guestfs_%s " n name;
8563            generate_c_call_args ~handle:"g" style;
8564            pr ";\n";
8565            do_cleanups ();
8566            pr "      if (%s == NULL)\n" n;
8567            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8568            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8569            pr "      free (%s);\n" n;
8570            pr " OUTPUT:\n";
8571            pr "      RETVAL\n"
8572        | RStringList n | RHashtable n ->
8573            pr "PREINIT:\n";
8574            pr "      char **%s;\n" n;
8575            pr "      int i, n;\n";
8576            pr " PPCODE:\n";
8577            pr "      %s = guestfs_%s " n name;
8578            generate_c_call_args ~handle:"g" style;
8579            pr ";\n";
8580            do_cleanups ();
8581            pr "      if (%s == NULL)\n" n;
8582            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8583            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8584            pr "      EXTEND (SP, n);\n";
8585            pr "      for (i = 0; i < n; ++i) {\n";
8586            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8587            pr "        free (%s[i]);\n" n;
8588            pr "      }\n";
8589            pr "      free (%s);\n" n;
8590        | RStruct (n, typ) ->
8591            let cols = cols_of_struct typ in
8592            generate_perl_struct_code typ cols name style n do_cleanups
8593        | RStructList (n, typ) ->
8594            let cols = cols_of_struct typ in
8595            generate_perl_struct_list_code typ cols name style n do_cleanups
8596        | RBufferOut n ->
8597            pr "PREINIT:\n";
8598            pr "      char *%s;\n" n;
8599            pr "      size_t size;\n";
8600            pr "   CODE:\n";
8601            pr "      %s = guestfs_%s " n name;
8602            generate_c_call_args ~handle:"g" style;
8603            pr ";\n";
8604            do_cleanups ();
8605            pr "      if (%s == NULL)\n" n;
8606            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8607            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8608            pr "      free (%s);\n" n;
8609            pr " OUTPUT:\n";
8610            pr "      RETVAL\n"
8611       );
8612
8613       pr "\n"
8614   ) all_functions
8615
8616 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8617   pr "PREINIT:\n";
8618   pr "      struct guestfs_%s_list *%s;\n" typ n;
8619   pr "      int i;\n";
8620   pr "      HV *hv;\n";
8621   pr " PPCODE:\n";
8622   pr "      %s = guestfs_%s " n name;
8623   generate_c_call_args ~handle:"g" style;
8624   pr ";\n";
8625   do_cleanups ();
8626   pr "      if (%s == NULL)\n" n;
8627   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8628   pr "      EXTEND (SP, %s->len);\n" n;
8629   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8630   pr "        hv = newHV ();\n";
8631   List.iter (
8632     function
8633     | name, FString ->
8634         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8635           name (String.length name) n name
8636     | name, FUUID ->
8637         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8638           name (String.length name) n name
8639     | name, FBuffer ->
8640         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8641           name (String.length name) n name n name
8642     | name, (FBytes|FUInt64) ->
8643         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8644           name (String.length name) n name
8645     | name, FInt64 ->
8646         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8647           name (String.length name) n name
8648     | name, (FInt32|FUInt32) ->
8649         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8650           name (String.length name) n name
8651     | name, FChar ->
8652         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8653           name (String.length name) n name
8654     | name, FOptPercent ->
8655         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8656           name (String.length name) n name
8657   ) cols;
8658   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8659   pr "      }\n";
8660   pr "      guestfs_free_%s_list (%s);\n" typ n
8661
8662 and generate_perl_struct_code typ cols name style n do_cleanups =
8663   pr "PREINIT:\n";
8664   pr "      struct guestfs_%s *%s;\n" typ n;
8665   pr " PPCODE:\n";
8666   pr "      %s = guestfs_%s " n name;
8667   generate_c_call_args ~handle:"g" style;
8668   pr ";\n";
8669   do_cleanups ();
8670   pr "      if (%s == NULL)\n" n;
8671   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8672   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8673   List.iter (
8674     fun ((name, _) as col) ->
8675       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8676
8677       match col with
8678       | name, FString ->
8679           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8680             n name
8681       | name, FBuffer ->
8682           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8683             n name n name
8684       | name, FUUID ->
8685           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8686             n name
8687       | name, (FBytes|FUInt64) ->
8688           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8689             n name
8690       | name, FInt64 ->
8691           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8692             n name
8693       | name, (FInt32|FUInt32) ->
8694           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8695             n name
8696       | name, FChar ->
8697           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8698             n name
8699       | name, FOptPercent ->
8700           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8701             n name
8702   ) cols;
8703   pr "      free (%s);\n" n
8704
8705 (* Generate Sys/Guestfs.pm. *)
8706 and generate_perl_pm () =
8707   generate_header HashStyle LGPLv2plus;
8708
8709   pr "\
8710 =pod
8711
8712 =head1 NAME
8713
8714 Sys::Guestfs - Perl bindings for libguestfs
8715
8716 =head1 SYNOPSIS
8717
8718  use Sys::Guestfs;
8719
8720  my $h = Sys::Guestfs->new ();
8721  $h->add_drive ('guest.img');
8722  $h->launch ();
8723  $h->mount ('/dev/sda1', '/');
8724  $h->touch ('/hello');
8725  $h->sync ();
8726
8727 =head1 DESCRIPTION
8728
8729 The C<Sys::Guestfs> module provides a Perl XS binding to the
8730 libguestfs API for examining and modifying virtual machine
8731 disk images.
8732
8733 Amongst the things this is good for: making batch configuration
8734 changes to guests, getting disk used/free statistics (see also:
8735 virt-df), migrating between virtualization systems (see also:
8736 virt-p2v), performing partial backups, performing partial guest
8737 clones, cloning guests and changing registry/UUID/hostname info, and
8738 much else besides.
8739
8740 Libguestfs uses Linux kernel and qemu code, and can access any type of
8741 guest filesystem that Linux and qemu can, including but not limited
8742 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8743 schemes, qcow, qcow2, vmdk.
8744
8745 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8746 LVs, what filesystem is in each LV, etc.).  It can also run commands
8747 in the context of the guest.  Also you can access filesystems over
8748 FUSE.
8749
8750 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8751 functions for using libguestfs from Perl, including integration
8752 with libvirt.
8753
8754 =head1 ERRORS
8755
8756 All errors turn into calls to C<croak> (see L<Carp(3)>).
8757
8758 =head1 METHODS
8759
8760 =over 4
8761
8762 =cut
8763
8764 package Sys::Guestfs;
8765
8766 use strict;
8767 use warnings;
8768
8769 require XSLoader;
8770 XSLoader::load ('Sys::Guestfs');
8771
8772 =item $h = Sys::Guestfs->new ();
8773
8774 Create a new guestfs handle.
8775
8776 =cut
8777
8778 sub new {
8779   my $proto = shift;
8780   my $class = ref ($proto) || $proto;
8781
8782   my $self = Sys::Guestfs::_create ();
8783   bless $self, $class;
8784   return $self;
8785 }
8786
8787 ";
8788
8789   (* Actions.  We only need to print documentation for these as
8790    * they are pulled in from the XS code automatically.
8791    *)
8792   List.iter (
8793     fun (name, style, _, flags, _, _, longdesc) ->
8794       if not (List.mem NotInDocs flags) then (
8795         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8796         pr "=item ";
8797         generate_perl_prototype name style;
8798         pr "\n\n";
8799         pr "%s\n\n" longdesc;
8800         if List.mem ProtocolLimitWarning flags then
8801           pr "%s\n\n" protocol_limit_warning;
8802         if List.mem DangerWillRobinson flags then
8803           pr "%s\n\n" danger_will_robinson;
8804         match deprecation_notice flags with
8805         | None -> ()
8806         | Some txt -> pr "%s\n\n" txt
8807       )
8808   ) all_functions_sorted;
8809
8810   (* End of file. *)
8811   pr "\
8812 =cut
8813
8814 1;
8815
8816 =back
8817
8818 =head1 COPYRIGHT
8819
8820 Copyright (C) %s Red Hat Inc.
8821
8822 =head1 LICENSE
8823
8824 Please see the file COPYING.LIB for the full license.
8825
8826 =head1 SEE ALSO
8827
8828 L<guestfs(3)>,
8829 L<guestfish(1)>,
8830 L<http://libguestfs.org>,
8831 L<Sys::Guestfs::Lib(3)>.
8832
8833 =cut
8834 " copyright_years
8835
8836 and generate_perl_prototype name style =
8837   (match fst style with
8838    | RErr -> ()
8839    | RBool n
8840    | RInt n
8841    | RInt64 n
8842    | RConstString n
8843    | RConstOptString n
8844    | RString n
8845    | RBufferOut n -> pr "$%s = " n
8846    | RStruct (n,_)
8847    | RHashtable n -> pr "%%%s = " n
8848    | RStringList n
8849    | RStructList (n,_) -> pr "@%s = " n
8850   );
8851   pr "$h->%s (" name;
8852   let comma = ref false in
8853   List.iter (
8854     fun arg ->
8855       if !comma then pr ", ";
8856       comma := true;
8857       match arg with
8858       | Pathname n | Device n | Dev_or_Path n | String n
8859       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8860           pr "$%s" n
8861       | StringList n | DeviceList n ->
8862           pr "\\@%s" n
8863   ) (snd style);
8864   pr ");"
8865
8866 (* Generate Python C module. *)
8867 and generate_python_c () =
8868   generate_header CStyle LGPLv2plus;
8869
8870   pr "\
8871 #include <Python.h>
8872
8873 #include <stdio.h>
8874 #include <stdlib.h>
8875 #include <assert.h>
8876
8877 #include \"guestfs.h\"
8878
8879 typedef struct {
8880   PyObject_HEAD
8881   guestfs_h *g;
8882 } Pyguestfs_Object;
8883
8884 static guestfs_h *
8885 get_handle (PyObject *obj)
8886 {
8887   assert (obj);
8888   assert (obj != Py_None);
8889   return ((Pyguestfs_Object *) obj)->g;
8890 }
8891
8892 static PyObject *
8893 put_handle (guestfs_h *g)
8894 {
8895   assert (g);
8896   return
8897     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8898 }
8899
8900 /* This list should be freed (but not the strings) after use. */
8901 static char **
8902 get_string_list (PyObject *obj)
8903 {
8904   int i, len;
8905   char **r;
8906
8907   assert (obj);
8908
8909   if (!PyList_Check (obj)) {
8910     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8911     return NULL;
8912   }
8913
8914   len = PyList_Size (obj);
8915   r = malloc (sizeof (char *) * (len+1));
8916   if (r == NULL) {
8917     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8918     return NULL;
8919   }
8920
8921   for (i = 0; i < len; ++i)
8922     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8923   r[len] = NULL;
8924
8925   return r;
8926 }
8927
8928 static PyObject *
8929 put_string_list (char * const * const argv)
8930 {
8931   PyObject *list;
8932   int argc, i;
8933
8934   for (argc = 0; argv[argc] != NULL; ++argc)
8935     ;
8936
8937   list = PyList_New (argc);
8938   for (i = 0; i < argc; ++i)
8939     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8940
8941   return list;
8942 }
8943
8944 static PyObject *
8945 put_table (char * const * const argv)
8946 {
8947   PyObject *list, *item;
8948   int argc, i;
8949
8950   for (argc = 0; argv[argc] != NULL; ++argc)
8951     ;
8952
8953   list = PyList_New (argc >> 1);
8954   for (i = 0; i < argc; i += 2) {
8955     item = PyTuple_New (2);
8956     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8957     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8958     PyList_SetItem (list, i >> 1, item);
8959   }
8960
8961   return list;
8962 }
8963
8964 static void
8965 free_strings (char **argv)
8966 {
8967   int argc;
8968
8969   for (argc = 0; argv[argc] != NULL; ++argc)
8970     free (argv[argc]);
8971   free (argv);
8972 }
8973
8974 static PyObject *
8975 py_guestfs_create (PyObject *self, PyObject *args)
8976 {
8977   guestfs_h *g;
8978
8979   g = guestfs_create ();
8980   if (g == NULL) {
8981     PyErr_SetString (PyExc_RuntimeError,
8982                      \"guestfs.create: failed to allocate handle\");
8983     return NULL;
8984   }
8985   guestfs_set_error_handler (g, NULL, NULL);
8986   return put_handle (g);
8987 }
8988
8989 static PyObject *
8990 py_guestfs_close (PyObject *self, PyObject *args)
8991 {
8992   PyObject *py_g;
8993   guestfs_h *g;
8994
8995   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8996     return NULL;
8997   g = get_handle (py_g);
8998
8999   guestfs_close (g);
9000
9001   Py_INCREF (Py_None);
9002   return Py_None;
9003 }
9004
9005 ";
9006
9007   let emit_put_list_function typ =
9008     pr "static PyObject *\n";
9009     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9010     pr "{\n";
9011     pr "  PyObject *list;\n";
9012     pr "  int i;\n";
9013     pr "\n";
9014     pr "  list = PyList_New (%ss->len);\n" typ;
9015     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9016     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9017     pr "  return list;\n";
9018     pr "};\n";
9019     pr "\n"
9020   in
9021
9022   (* Structures, turned into Python dictionaries. *)
9023   List.iter (
9024     fun (typ, cols) ->
9025       pr "static PyObject *\n";
9026       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9027       pr "{\n";
9028       pr "  PyObject *dict;\n";
9029       pr "\n";
9030       pr "  dict = PyDict_New ();\n";
9031       List.iter (
9032         function
9033         | name, FString ->
9034             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9035             pr "                        PyString_FromString (%s->%s));\n"
9036               typ name
9037         | name, FBuffer ->
9038             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9039             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9040               typ name typ name
9041         | name, FUUID ->
9042             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9043             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9044               typ name
9045         | name, (FBytes|FUInt64) ->
9046             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9047             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9048               typ name
9049         | name, FInt64 ->
9050             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9051             pr "                        PyLong_FromLongLong (%s->%s));\n"
9052               typ name
9053         | name, FUInt32 ->
9054             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9055             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9056               typ name
9057         | name, FInt32 ->
9058             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9059             pr "                        PyLong_FromLong (%s->%s));\n"
9060               typ name
9061         | name, FOptPercent ->
9062             pr "  if (%s->%s >= 0)\n" typ name;
9063             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9064             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9065               typ name;
9066             pr "  else {\n";
9067             pr "    Py_INCREF (Py_None);\n";
9068             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9069             pr "  }\n"
9070         | name, FChar ->
9071             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9072             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9073       ) cols;
9074       pr "  return dict;\n";
9075       pr "};\n";
9076       pr "\n";
9077
9078   ) structs;
9079
9080   (* Emit a put_TYPE_list function definition only if that function is used. *)
9081   List.iter (
9082     function
9083     | typ, (RStructListOnly | RStructAndList) ->
9084         (* generate the function for typ *)
9085         emit_put_list_function typ
9086     | typ, _ -> () (* empty *)
9087   ) (rstructs_used_by all_functions);
9088
9089   (* Python wrapper functions. *)
9090   List.iter (
9091     fun (name, style, _, _, _, _, _) ->
9092       pr "static PyObject *\n";
9093       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9094       pr "{\n";
9095
9096       pr "  PyObject *py_g;\n";
9097       pr "  guestfs_h *g;\n";
9098       pr "  PyObject *py_r;\n";
9099
9100       let error_code =
9101         match fst style with
9102         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9103         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9104         | RConstString _ | RConstOptString _ ->
9105             pr "  const char *r;\n"; "NULL"
9106         | RString _ -> pr "  char *r;\n"; "NULL"
9107         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9108         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9109         | RStructList (_, typ) ->
9110             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9111         | RBufferOut _ ->
9112             pr "  char *r;\n";
9113             pr "  size_t size;\n";
9114             "NULL" in
9115
9116       List.iter (
9117         function
9118         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9119             pr "  const char *%s;\n" n
9120         | OptString n -> pr "  const char *%s;\n" n
9121         | StringList n | DeviceList n ->
9122             pr "  PyObject *py_%s;\n" n;
9123             pr "  char **%s;\n" n
9124         | Bool n -> pr "  int %s;\n" n
9125         | Int n -> pr "  int %s;\n" n
9126         | Int64 n -> pr "  long long %s;\n" n
9127       ) (snd style);
9128
9129       pr "\n";
9130
9131       (* Convert the parameters. *)
9132       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9133       List.iter (
9134         function
9135         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9136         | OptString _ -> pr "z"
9137         | StringList _ | DeviceList _ -> pr "O"
9138         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9139         | Int _ -> pr "i"
9140         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9141                              * emulate C's int/long/long long in Python?
9142                              *)
9143       ) (snd style);
9144       pr ":guestfs_%s\",\n" name;
9145       pr "                         &py_g";
9146       List.iter (
9147         function
9148         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9149         | OptString n -> pr ", &%s" n
9150         | StringList n | DeviceList n -> pr ", &py_%s" n
9151         | Bool n -> pr ", &%s" n
9152         | Int n -> pr ", &%s" n
9153         | Int64 n -> pr ", &%s" n
9154       ) (snd style);
9155
9156       pr "))\n";
9157       pr "    return NULL;\n";
9158
9159       pr "  g = get_handle (py_g);\n";
9160       List.iter (
9161         function
9162         | Pathname _ | Device _ | Dev_or_Path _ | String _
9163         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9164         | StringList n | DeviceList n ->
9165             pr "  %s = get_string_list (py_%s);\n" n n;
9166             pr "  if (!%s) return NULL;\n" n
9167       ) (snd style);
9168
9169       pr "\n";
9170
9171       pr "  r = guestfs_%s " name;
9172       generate_c_call_args ~handle:"g" style;
9173       pr ";\n";
9174
9175       List.iter (
9176         function
9177         | Pathname _ | Device _ | Dev_or_Path _ | String _
9178         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9179         | StringList n | DeviceList n ->
9180             pr "  free (%s);\n" n
9181       ) (snd style);
9182
9183       pr "  if (r == %s) {\n" error_code;
9184       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9185       pr "    return NULL;\n";
9186       pr "  }\n";
9187       pr "\n";
9188
9189       (match fst style with
9190        | RErr ->
9191            pr "  Py_INCREF (Py_None);\n";
9192            pr "  py_r = Py_None;\n"
9193        | RInt _
9194        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9195        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9196        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9197        | RConstOptString _ ->
9198            pr "  if (r)\n";
9199            pr "    py_r = PyString_FromString (r);\n";
9200            pr "  else {\n";
9201            pr "    Py_INCREF (Py_None);\n";
9202            pr "    py_r = Py_None;\n";
9203            pr "  }\n"
9204        | RString _ ->
9205            pr "  py_r = PyString_FromString (r);\n";
9206            pr "  free (r);\n"
9207        | RStringList _ ->
9208            pr "  py_r = put_string_list (r);\n";
9209            pr "  free_strings (r);\n"
9210        | RStruct (_, typ) ->
9211            pr "  py_r = put_%s (r);\n" typ;
9212            pr "  guestfs_free_%s (r);\n" typ
9213        | RStructList (_, typ) ->
9214            pr "  py_r = put_%s_list (r);\n" typ;
9215            pr "  guestfs_free_%s_list (r);\n" typ
9216        | RHashtable n ->
9217            pr "  py_r = put_table (r);\n";
9218            pr "  free_strings (r);\n"
9219        | RBufferOut _ ->
9220            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9221            pr "  free (r);\n"
9222       );
9223
9224       pr "  return py_r;\n";
9225       pr "}\n";
9226       pr "\n"
9227   ) all_functions;
9228
9229   (* Table of functions. *)
9230   pr "static PyMethodDef methods[] = {\n";
9231   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9232   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9233   List.iter (
9234     fun (name, _, _, _, _, _, _) ->
9235       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9236         name name
9237   ) all_functions;
9238   pr "  { NULL, NULL, 0, NULL }\n";
9239   pr "};\n";
9240   pr "\n";
9241
9242   (* Init function. *)
9243   pr "\
9244 void
9245 initlibguestfsmod (void)
9246 {
9247   static int initialized = 0;
9248
9249   if (initialized) return;
9250   Py_InitModule ((char *) \"libguestfsmod\", methods);
9251   initialized = 1;
9252 }
9253 "
9254
9255 (* Generate Python module. *)
9256 and generate_python_py () =
9257   generate_header HashStyle LGPLv2plus;
9258
9259   pr "\
9260 u\"\"\"Python bindings for libguestfs
9261
9262 import guestfs
9263 g = guestfs.GuestFS ()
9264 g.add_drive (\"guest.img\")
9265 g.launch ()
9266 parts = g.list_partitions ()
9267
9268 The guestfs module provides a Python binding to the libguestfs API
9269 for examining and modifying virtual machine disk images.
9270
9271 Amongst the things this is good for: making batch configuration
9272 changes to guests, getting disk used/free statistics (see also:
9273 virt-df), migrating between virtualization systems (see also:
9274 virt-p2v), performing partial backups, performing partial guest
9275 clones, cloning guests and changing registry/UUID/hostname info, and
9276 much else besides.
9277
9278 Libguestfs uses Linux kernel and qemu code, and can access any type of
9279 guest filesystem that Linux and qemu can, including but not limited
9280 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9281 schemes, qcow, qcow2, vmdk.
9282
9283 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9284 LVs, what filesystem is in each LV, etc.).  It can also run commands
9285 in the context of the guest.  Also you can access filesystems over
9286 FUSE.
9287
9288 Errors which happen while using the API are turned into Python
9289 RuntimeError exceptions.
9290
9291 To create a guestfs handle you usually have to perform the following
9292 sequence of calls:
9293
9294 # Create the handle, call add_drive at least once, and possibly
9295 # several times if the guest has multiple block devices:
9296 g = guestfs.GuestFS ()
9297 g.add_drive (\"guest.img\")
9298
9299 # Launch the qemu subprocess and wait for it to become ready:
9300 g.launch ()
9301
9302 # Now you can issue commands, for example:
9303 logvols = g.lvs ()
9304
9305 \"\"\"
9306
9307 import libguestfsmod
9308
9309 class GuestFS:
9310     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9311
9312     def __init__ (self):
9313         \"\"\"Create a new libguestfs handle.\"\"\"
9314         self._o = libguestfsmod.create ()
9315
9316     def __del__ (self):
9317         libguestfsmod.close (self._o)
9318
9319 ";
9320
9321   List.iter (
9322     fun (name, style, _, flags, _, _, longdesc) ->
9323       pr "    def %s " name;
9324       generate_py_call_args ~handle:"self" (snd style);
9325       pr ":\n";
9326
9327       if not (List.mem NotInDocs flags) then (
9328         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9329         let doc =
9330           match fst style with
9331           | RErr | RInt _ | RInt64 _ | RBool _
9332           | RConstOptString _ | RConstString _
9333           | RString _ | RBufferOut _ -> doc
9334           | RStringList _ ->
9335               doc ^ "\n\nThis function returns a list of strings."
9336           | RStruct (_, typ) ->
9337               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9338           | RStructList (_, typ) ->
9339               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9340           | RHashtable _ ->
9341               doc ^ "\n\nThis function returns a dictionary." in
9342         let doc =
9343           if List.mem ProtocolLimitWarning flags then
9344             doc ^ "\n\n" ^ protocol_limit_warning
9345           else doc in
9346         let doc =
9347           if List.mem DangerWillRobinson flags then
9348             doc ^ "\n\n" ^ danger_will_robinson
9349           else doc in
9350         let doc =
9351           match deprecation_notice flags with
9352           | None -> doc
9353           | Some txt -> doc ^ "\n\n" ^ txt in
9354         let doc = pod2text ~width:60 name doc in
9355         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9356         let doc = String.concat "\n        " doc in
9357         pr "        u\"\"\"%s\"\"\"\n" doc;
9358       );
9359       pr "        return libguestfsmod.%s " name;
9360       generate_py_call_args ~handle:"self._o" (snd style);
9361       pr "\n";
9362       pr "\n";
9363   ) all_functions
9364
9365 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9366 and generate_py_call_args ~handle args =
9367   pr "(%s" handle;
9368   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9369   pr ")"
9370
9371 (* Useful if you need the longdesc POD text as plain text.  Returns a
9372  * list of lines.
9373  *
9374  * Because this is very slow (the slowest part of autogeneration),
9375  * we memoize the results.
9376  *)
9377 and pod2text ~width name longdesc =
9378   let key = width, name, longdesc in
9379   try Hashtbl.find pod2text_memo key
9380   with Not_found ->
9381     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9382     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9383     close_out chan;
9384     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9385     let chan = open_process_in cmd in
9386     let lines = ref [] in
9387     let rec loop i =
9388       let line = input_line chan in
9389       if i = 1 then             (* discard the first line of output *)
9390         loop (i+1)
9391       else (
9392         let line = triml line in
9393         lines := line :: !lines;
9394         loop (i+1)
9395       ) in
9396     let lines = try loop 1 with End_of_file -> List.rev !lines in
9397     unlink filename;
9398     (match close_process_in chan with
9399      | WEXITED 0 -> ()
9400      | WEXITED i ->
9401          failwithf "pod2text: process exited with non-zero status (%d)" i
9402      | WSIGNALED i | WSTOPPED i ->
9403          failwithf "pod2text: process signalled or stopped by signal %d" i
9404     );
9405     Hashtbl.add pod2text_memo key lines;
9406     pod2text_memo_updated ();
9407     lines
9408
9409 (* Generate ruby bindings. *)
9410 and generate_ruby_c () =
9411   generate_header CStyle LGPLv2plus;
9412
9413   pr "\
9414 #include <stdio.h>
9415 #include <stdlib.h>
9416
9417 #include <ruby.h>
9418
9419 #include \"guestfs.h\"
9420
9421 #include \"extconf.h\"
9422
9423 /* For Ruby < 1.9 */
9424 #ifndef RARRAY_LEN
9425 #define RARRAY_LEN(r) (RARRAY((r))->len)
9426 #endif
9427
9428 static VALUE m_guestfs;                 /* guestfs module */
9429 static VALUE c_guestfs;                 /* guestfs_h handle */
9430 static VALUE e_Error;                   /* used for all errors */
9431
9432 static void ruby_guestfs_free (void *p)
9433 {
9434   if (!p) return;
9435   guestfs_close ((guestfs_h *) p);
9436 }
9437
9438 static VALUE ruby_guestfs_create (VALUE m)
9439 {
9440   guestfs_h *g;
9441
9442   g = guestfs_create ();
9443   if (!g)
9444     rb_raise (e_Error, \"failed to create guestfs handle\");
9445
9446   /* Don't print error messages to stderr by default. */
9447   guestfs_set_error_handler (g, NULL, NULL);
9448
9449   /* Wrap it, and make sure the close function is called when the
9450    * handle goes away.
9451    */
9452   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9453 }
9454
9455 static VALUE ruby_guestfs_close (VALUE gv)
9456 {
9457   guestfs_h *g;
9458   Data_Get_Struct (gv, guestfs_h, g);
9459
9460   ruby_guestfs_free (g);
9461   DATA_PTR (gv) = NULL;
9462
9463   return Qnil;
9464 }
9465
9466 ";
9467
9468   List.iter (
9469     fun (name, style, _, _, _, _, _) ->
9470       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9471       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9472       pr ")\n";
9473       pr "{\n";
9474       pr "  guestfs_h *g;\n";
9475       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9476       pr "  if (!g)\n";
9477       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9478         name;
9479       pr "\n";
9480
9481       List.iter (
9482         function
9483         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9484             pr "  Check_Type (%sv, T_STRING);\n" n;
9485             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9486             pr "  if (!%s)\n" n;
9487             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9488             pr "              \"%s\", \"%s\");\n" n name
9489         | OptString n ->
9490             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9491         | StringList n | DeviceList n ->
9492             pr "  char **%s;\n" n;
9493             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9494             pr "  {\n";
9495             pr "    int i, len;\n";
9496             pr "    len = RARRAY_LEN (%sv);\n" n;
9497             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9498               n;
9499             pr "    for (i = 0; i < len; ++i) {\n";
9500             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9501             pr "      %s[i] = StringValueCStr (v);\n" n;
9502             pr "    }\n";
9503             pr "    %s[len] = NULL;\n" n;
9504             pr "  }\n";
9505         | Bool n ->
9506             pr "  int %s = RTEST (%sv);\n" n n
9507         | Int n ->
9508             pr "  int %s = NUM2INT (%sv);\n" n n
9509         | Int64 n ->
9510             pr "  long long %s = NUM2LL (%sv);\n" n n
9511       ) (snd style);
9512       pr "\n";
9513
9514       let error_code =
9515         match fst style with
9516         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9517         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9518         | RConstString _ | RConstOptString _ ->
9519             pr "  const char *r;\n"; "NULL"
9520         | RString _ -> pr "  char *r;\n"; "NULL"
9521         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9522         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9523         | RStructList (_, typ) ->
9524             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9525         | RBufferOut _ ->
9526             pr "  char *r;\n";
9527             pr "  size_t size;\n";
9528             "NULL" in
9529       pr "\n";
9530
9531       pr "  r = guestfs_%s " name;
9532       generate_c_call_args ~handle:"g" style;
9533       pr ";\n";
9534
9535       List.iter (
9536         function
9537         | Pathname _ | Device _ | Dev_or_Path _ | String _
9538         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9539         | StringList n | DeviceList n ->
9540             pr "  free (%s);\n" n
9541       ) (snd style);
9542
9543       pr "  if (r == %s)\n" error_code;
9544       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9545       pr "\n";
9546
9547       (match fst style with
9548        | RErr ->
9549            pr "  return Qnil;\n"
9550        | RInt _ | RBool _ ->
9551            pr "  return INT2NUM (r);\n"
9552        | RInt64 _ ->
9553            pr "  return ULL2NUM (r);\n"
9554        | RConstString _ ->
9555            pr "  return rb_str_new2 (r);\n";
9556        | RConstOptString _ ->
9557            pr "  if (r)\n";
9558            pr "    return rb_str_new2 (r);\n";
9559            pr "  else\n";
9560            pr "    return Qnil;\n";
9561        | RString _ ->
9562            pr "  VALUE rv = rb_str_new2 (r);\n";
9563            pr "  free (r);\n";
9564            pr "  return rv;\n";
9565        | RStringList _ ->
9566            pr "  int i, len = 0;\n";
9567            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9568            pr "  VALUE rv = rb_ary_new2 (len);\n";
9569            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9570            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9571            pr "    free (r[i]);\n";
9572            pr "  }\n";
9573            pr "  free (r);\n";
9574            pr "  return rv;\n"
9575        | RStruct (_, typ) ->
9576            let cols = cols_of_struct typ in
9577            generate_ruby_struct_code typ cols
9578        | RStructList (_, typ) ->
9579            let cols = cols_of_struct typ in
9580            generate_ruby_struct_list_code typ cols
9581        | RHashtable _ ->
9582            pr "  VALUE rv = rb_hash_new ();\n";
9583            pr "  int i;\n";
9584            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9585            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9586            pr "    free (r[i]);\n";
9587            pr "    free (r[i+1]);\n";
9588            pr "  }\n";
9589            pr "  free (r);\n";
9590            pr "  return rv;\n"
9591        | RBufferOut _ ->
9592            pr "  VALUE rv = rb_str_new (r, size);\n";
9593            pr "  free (r);\n";
9594            pr "  return rv;\n";
9595       );
9596
9597       pr "}\n";
9598       pr "\n"
9599   ) all_functions;
9600
9601   pr "\
9602 /* Initialize the module. */
9603 void Init__guestfs ()
9604 {
9605   m_guestfs = rb_define_module (\"Guestfs\");
9606   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9607   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9608
9609   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9610   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9611
9612 ";
9613   (* Define the rest of the methods. *)
9614   List.iter (
9615     fun (name, style, _, _, _, _, _) ->
9616       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9617       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9618   ) all_functions;
9619
9620   pr "}\n"
9621
9622 (* Ruby code to return a struct. *)
9623 and generate_ruby_struct_code typ cols =
9624   pr "  VALUE rv = rb_hash_new ();\n";
9625   List.iter (
9626     function
9627     | name, FString ->
9628         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9629     | name, FBuffer ->
9630         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9631     | name, FUUID ->
9632         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9633     | name, (FBytes|FUInt64) ->
9634         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9635     | name, FInt64 ->
9636         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9637     | name, FUInt32 ->
9638         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9639     | name, FInt32 ->
9640         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9641     | name, FOptPercent ->
9642         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9643     | name, FChar -> (* XXX wrong? *)
9644         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9645   ) cols;
9646   pr "  guestfs_free_%s (r);\n" typ;
9647   pr "  return rv;\n"
9648
9649 (* Ruby code to return a struct list. *)
9650 and generate_ruby_struct_list_code typ cols =
9651   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9652   pr "  int i;\n";
9653   pr "  for (i = 0; i < r->len; ++i) {\n";
9654   pr "    VALUE hv = rb_hash_new ();\n";
9655   List.iter (
9656     function
9657     | name, FString ->
9658         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9659     | name, FBuffer ->
9660         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
9661     | name, FUUID ->
9662         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9663     | name, (FBytes|FUInt64) ->
9664         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9665     | name, FInt64 ->
9666         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9667     | name, FUInt32 ->
9668         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9669     | name, FInt32 ->
9670         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9671     | name, FOptPercent ->
9672         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9673     | name, FChar -> (* XXX wrong? *)
9674         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9675   ) cols;
9676   pr "    rb_ary_push (rv, hv);\n";
9677   pr "  }\n";
9678   pr "  guestfs_free_%s_list (r);\n" typ;
9679   pr "  return rv;\n"
9680
9681 (* Generate Java bindings GuestFS.java file. *)
9682 and generate_java_java () =
9683   generate_header CStyle LGPLv2plus;
9684
9685   pr "\
9686 package com.redhat.et.libguestfs;
9687
9688 import java.util.HashMap;
9689 import com.redhat.et.libguestfs.LibGuestFSException;
9690 import com.redhat.et.libguestfs.PV;
9691 import com.redhat.et.libguestfs.VG;
9692 import com.redhat.et.libguestfs.LV;
9693 import com.redhat.et.libguestfs.Stat;
9694 import com.redhat.et.libguestfs.StatVFS;
9695 import com.redhat.et.libguestfs.IntBool;
9696 import com.redhat.et.libguestfs.Dirent;
9697
9698 /**
9699  * The GuestFS object is a libguestfs handle.
9700  *
9701  * @author rjones
9702  */
9703 public class GuestFS {
9704   // Load the native code.
9705   static {
9706     System.loadLibrary (\"guestfs_jni\");
9707   }
9708
9709   /**
9710    * The native guestfs_h pointer.
9711    */
9712   long g;
9713
9714   /**
9715    * Create a libguestfs handle.
9716    *
9717    * @throws LibGuestFSException
9718    */
9719   public GuestFS () throws LibGuestFSException
9720   {
9721     g = _create ();
9722   }
9723   private native long _create () throws LibGuestFSException;
9724
9725   /**
9726    * Close a libguestfs handle.
9727    *
9728    * You can also leave handles to be collected by the garbage
9729    * collector, but this method ensures that the resources used
9730    * by the handle are freed up immediately.  If you call any
9731    * other methods after closing the handle, you will get an
9732    * exception.
9733    *
9734    * @throws LibGuestFSException
9735    */
9736   public void close () throws LibGuestFSException
9737   {
9738     if (g != 0)
9739       _close (g);
9740     g = 0;
9741   }
9742   private native void _close (long g) throws LibGuestFSException;
9743
9744   public void finalize () throws LibGuestFSException
9745   {
9746     close ();
9747   }
9748
9749 ";
9750
9751   List.iter (
9752     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9753       if not (List.mem NotInDocs flags); then (
9754         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9755         let doc =
9756           if List.mem ProtocolLimitWarning flags then
9757             doc ^ "\n\n" ^ protocol_limit_warning
9758           else doc in
9759         let doc =
9760           if List.mem DangerWillRobinson flags then
9761             doc ^ "\n\n" ^ danger_will_robinson
9762           else doc in
9763         let doc =
9764           match deprecation_notice flags with
9765           | None -> doc
9766           | Some txt -> doc ^ "\n\n" ^ txt in
9767         let doc = pod2text ~width:60 name doc in
9768         let doc = List.map (            (* RHBZ#501883 *)
9769           function
9770           | "" -> "<p>"
9771           | nonempty -> nonempty
9772         ) doc in
9773         let doc = String.concat "\n   * " doc in
9774
9775         pr "  /**\n";
9776         pr "   * %s\n" shortdesc;
9777         pr "   * <p>\n";
9778         pr "   * %s\n" doc;
9779         pr "   * @throws LibGuestFSException\n";
9780         pr "   */\n";
9781         pr "  ";
9782       );
9783       generate_java_prototype ~public:true ~semicolon:false name style;
9784       pr "\n";
9785       pr "  {\n";
9786       pr "    if (g == 0)\n";
9787       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9788         name;
9789       pr "    ";
9790       if fst style <> RErr then pr "return ";
9791       pr "_%s " name;
9792       generate_java_call_args ~handle:"g" (snd style);
9793       pr ";\n";
9794       pr "  }\n";
9795       pr "  ";
9796       generate_java_prototype ~privat:true ~native:true name style;
9797       pr "\n";
9798       pr "\n";
9799   ) all_functions;
9800
9801   pr "}\n"
9802
9803 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9804 and generate_java_call_args ~handle args =
9805   pr "(%s" handle;
9806   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9807   pr ")"
9808
9809 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9810     ?(semicolon=true) name style =
9811   if privat then pr "private ";
9812   if public then pr "public ";
9813   if native then pr "native ";
9814
9815   (* return type *)
9816   (match fst style with
9817    | RErr -> pr "void ";
9818    | RInt _ -> pr "int ";
9819    | RInt64 _ -> pr "long ";
9820    | RBool _ -> pr "boolean ";
9821    | RConstString _ | RConstOptString _ | RString _
9822    | RBufferOut _ -> pr "String ";
9823    | RStringList _ -> pr "String[] ";
9824    | RStruct (_, typ) ->
9825        let name = java_name_of_struct typ in
9826        pr "%s " name;
9827    | RStructList (_, typ) ->
9828        let name = java_name_of_struct typ in
9829        pr "%s[] " name;
9830    | RHashtable _ -> pr "HashMap<String,String> ";
9831   );
9832
9833   if native then pr "_%s " name else pr "%s " name;
9834   pr "(";
9835   let needs_comma = ref false in
9836   if native then (
9837     pr "long g";
9838     needs_comma := true
9839   );
9840
9841   (* args *)
9842   List.iter (
9843     fun arg ->
9844       if !needs_comma then pr ", ";
9845       needs_comma := true;
9846
9847       match arg with
9848       | Pathname n
9849       | Device n | Dev_or_Path n
9850       | String n
9851       | OptString n
9852       | FileIn n
9853       | FileOut n ->
9854           pr "String %s" n
9855       | StringList n | DeviceList n ->
9856           pr "String[] %s" n
9857       | Bool n ->
9858           pr "boolean %s" n
9859       | Int n ->
9860           pr "int %s" n
9861       | Int64 n ->
9862           pr "long %s" n
9863   ) (snd style);
9864
9865   pr ")\n";
9866   pr "    throws LibGuestFSException";
9867   if semicolon then pr ";"
9868
9869 and generate_java_struct jtyp cols () =
9870   generate_header CStyle LGPLv2plus;
9871
9872   pr "\
9873 package com.redhat.et.libguestfs;
9874
9875 /**
9876  * Libguestfs %s structure.
9877  *
9878  * @author rjones
9879  * @see GuestFS
9880  */
9881 public class %s {
9882 " jtyp jtyp;
9883
9884   List.iter (
9885     function
9886     | name, FString
9887     | name, FUUID
9888     | name, FBuffer -> pr "  public String %s;\n" name
9889     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9890     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9891     | name, FChar -> pr "  public char %s;\n" name
9892     | name, FOptPercent ->
9893         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9894         pr "  public float %s;\n" name
9895   ) cols;
9896
9897   pr "}\n"
9898
9899 and generate_java_c () =
9900   generate_header CStyle LGPLv2plus;
9901
9902   pr "\
9903 #include <stdio.h>
9904 #include <stdlib.h>
9905 #include <string.h>
9906
9907 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9908 #include \"guestfs.h\"
9909
9910 /* Note that this function returns.  The exception is not thrown
9911  * until after the wrapper function returns.
9912  */
9913 static void
9914 throw_exception (JNIEnv *env, const char *msg)
9915 {
9916   jclass cl;
9917   cl = (*env)->FindClass (env,
9918                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9919   (*env)->ThrowNew (env, cl, msg);
9920 }
9921
9922 JNIEXPORT jlong JNICALL
9923 Java_com_redhat_et_libguestfs_GuestFS__1create
9924   (JNIEnv *env, jobject obj)
9925 {
9926   guestfs_h *g;
9927
9928   g = guestfs_create ();
9929   if (g == NULL) {
9930     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9931     return 0;
9932   }
9933   guestfs_set_error_handler (g, NULL, NULL);
9934   return (jlong) (long) g;
9935 }
9936
9937 JNIEXPORT void JNICALL
9938 Java_com_redhat_et_libguestfs_GuestFS__1close
9939   (JNIEnv *env, jobject obj, jlong jg)
9940 {
9941   guestfs_h *g = (guestfs_h *) (long) jg;
9942   guestfs_close (g);
9943 }
9944
9945 ";
9946
9947   List.iter (
9948     fun (name, style, _, _, _, _, _) ->
9949       pr "JNIEXPORT ";
9950       (match fst style with
9951        | RErr -> pr "void ";
9952        | RInt _ -> pr "jint ";
9953        | RInt64 _ -> pr "jlong ";
9954        | RBool _ -> pr "jboolean ";
9955        | RConstString _ | RConstOptString _ | RString _
9956        | RBufferOut _ -> pr "jstring ";
9957        | RStruct _ | RHashtable _ ->
9958            pr "jobject ";
9959        | RStringList _ | RStructList _ ->
9960            pr "jobjectArray ";
9961       );
9962       pr "JNICALL\n";
9963       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9964       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9965       pr "\n";
9966       pr "  (JNIEnv *env, jobject obj, jlong jg";
9967       List.iter (
9968         function
9969         | Pathname n
9970         | Device n | Dev_or_Path n
9971         | String n
9972         | OptString n
9973         | FileIn n
9974         | FileOut n ->
9975             pr ", jstring j%s" n
9976         | StringList n | DeviceList n ->
9977             pr ", jobjectArray j%s" n
9978         | Bool n ->
9979             pr ", jboolean j%s" n
9980         | Int n ->
9981             pr ", jint j%s" n
9982         | Int64 n ->
9983             pr ", jlong j%s" n
9984       ) (snd style);
9985       pr ")\n";
9986       pr "{\n";
9987       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9988       let error_code, no_ret =
9989         match fst style with
9990         | RErr -> pr "  int r;\n"; "-1", ""
9991         | RBool _
9992         | RInt _ -> pr "  int r;\n"; "-1", "0"
9993         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9994         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9995         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9996         | RString _ ->
9997             pr "  jstring jr;\n";
9998             pr "  char *r;\n"; "NULL", "NULL"
9999         | RStringList _ ->
10000             pr "  jobjectArray jr;\n";
10001             pr "  int r_len;\n";
10002             pr "  jclass cl;\n";
10003             pr "  jstring jstr;\n";
10004             pr "  char **r;\n"; "NULL", "NULL"
10005         | RStruct (_, typ) ->
10006             pr "  jobject jr;\n";
10007             pr "  jclass cl;\n";
10008             pr "  jfieldID fl;\n";
10009             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10010         | RStructList (_, typ) ->
10011             pr "  jobjectArray jr;\n";
10012             pr "  jclass cl;\n";
10013             pr "  jfieldID fl;\n";
10014             pr "  jobject jfl;\n";
10015             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10016         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10017         | RBufferOut _ ->
10018             pr "  jstring jr;\n";
10019             pr "  char *r;\n";
10020             pr "  size_t size;\n";
10021             "NULL", "NULL" in
10022       List.iter (
10023         function
10024         | Pathname n
10025         | Device n | Dev_or_Path n
10026         | String n
10027         | OptString n
10028         | FileIn n
10029         | FileOut n ->
10030             pr "  const char *%s;\n" n
10031         | StringList n | DeviceList n ->
10032             pr "  int %s_len;\n" n;
10033             pr "  const char **%s;\n" n
10034         | Bool n
10035         | Int n ->
10036             pr "  int %s;\n" n
10037         | Int64 n ->
10038             pr "  int64_t %s;\n" n
10039       ) (snd style);
10040
10041       let needs_i =
10042         (match fst style with
10043          | RStringList _ | RStructList _ -> true
10044          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10045          | RConstOptString _
10046          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10047           List.exists (function
10048                        | StringList _ -> true
10049                        | DeviceList _ -> true
10050                        | _ -> false) (snd style) in
10051       if needs_i then
10052         pr "  int i;\n";
10053
10054       pr "\n";
10055
10056       (* Get the parameters. *)
10057       List.iter (
10058         function
10059         | Pathname n
10060         | Device n | Dev_or_Path n
10061         | String n
10062         | FileIn n
10063         | FileOut n ->
10064             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10065         | OptString n ->
10066             (* This is completely undocumented, but Java null becomes
10067              * a NULL parameter.
10068              *)
10069             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10070         | StringList n | DeviceList n ->
10071             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10072             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10073             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10074             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10075               n;
10076             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10077             pr "  }\n";
10078             pr "  %s[%s_len] = NULL;\n" n n;
10079         | Bool n
10080         | Int n
10081         | Int64 n ->
10082             pr "  %s = j%s;\n" n n
10083       ) (snd style);
10084
10085       (* Make the call. *)
10086       pr "  r = guestfs_%s " name;
10087       generate_c_call_args ~handle:"g" style;
10088       pr ";\n";
10089
10090       (* Release the parameters. *)
10091       List.iter (
10092         function
10093         | Pathname n
10094         | Device n | Dev_or_Path n
10095         | String n
10096         | FileIn n
10097         | FileOut n ->
10098             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10099         | OptString n ->
10100             pr "  if (j%s)\n" n;
10101             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10102         | StringList n | DeviceList n ->
10103             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10104             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10105               n;
10106             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10107             pr "  }\n";
10108             pr "  free (%s);\n" n
10109         | Bool n
10110         | Int n
10111         | Int64 n -> ()
10112       ) (snd style);
10113
10114       (* Check for errors. *)
10115       pr "  if (r == %s) {\n" error_code;
10116       pr "    throw_exception (env, guestfs_last_error (g));\n";
10117       pr "    return %s;\n" no_ret;
10118       pr "  }\n";
10119
10120       (* Return value. *)
10121       (match fst style with
10122        | RErr -> ()
10123        | RInt _ -> pr "  return (jint) r;\n"
10124        | RBool _ -> pr "  return (jboolean) r;\n"
10125        | RInt64 _ -> pr "  return (jlong) r;\n"
10126        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10127        | RConstOptString _ ->
10128            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10129        | RString _ ->
10130            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10131            pr "  free (r);\n";
10132            pr "  return jr;\n"
10133        | RStringList _ ->
10134            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10135            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10136            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10137            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10138            pr "  for (i = 0; i < r_len; ++i) {\n";
10139            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10140            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10141            pr "    free (r[i]);\n";
10142            pr "  }\n";
10143            pr "  free (r);\n";
10144            pr "  return jr;\n"
10145        | RStruct (_, typ) ->
10146            let jtyp = java_name_of_struct typ in
10147            let cols = cols_of_struct typ in
10148            generate_java_struct_return typ jtyp cols
10149        | RStructList (_, typ) ->
10150            let jtyp = java_name_of_struct typ in
10151            let cols = cols_of_struct typ in
10152            generate_java_struct_list_return typ jtyp cols
10153        | RHashtable _ ->
10154            (* XXX *)
10155            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10156            pr "  return NULL;\n"
10157        | RBufferOut _ ->
10158            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10159            pr "  free (r);\n";
10160            pr "  return jr;\n"
10161       );
10162
10163       pr "}\n";
10164       pr "\n"
10165   ) all_functions
10166
10167 and generate_java_struct_return typ jtyp cols =
10168   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10169   pr "  jr = (*env)->AllocObject (env, cl);\n";
10170   List.iter (
10171     function
10172     | name, FString ->
10173         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10174         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10175     | name, FUUID ->
10176         pr "  {\n";
10177         pr "    char s[33];\n";
10178         pr "    memcpy (s, r->%s, 32);\n" name;
10179         pr "    s[32] = 0;\n";
10180         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10181         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10182         pr "  }\n";
10183     | name, FBuffer ->
10184         pr "  {\n";
10185         pr "    int len = r->%s_len;\n" name;
10186         pr "    char s[len+1];\n";
10187         pr "    memcpy (s, r->%s, len);\n" name;
10188         pr "    s[len] = 0;\n";
10189         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10190         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10191         pr "  }\n";
10192     | name, (FBytes|FUInt64|FInt64) ->
10193         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10194         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10195     | name, (FUInt32|FInt32) ->
10196         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10197         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10198     | name, FOptPercent ->
10199         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10200         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10201     | name, FChar ->
10202         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10203         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10204   ) cols;
10205   pr "  free (r);\n";
10206   pr "  return jr;\n"
10207
10208 and generate_java_struct_list_return typ jtyp cols =
10209   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10210   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10211   pr "  for (i = 0; i < r->len; ++i) {\n";
10212   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10213   List.iter (
10214     function
10215     | name, FString ->
10216         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10217         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10218     | name, FUUID ->
10219         pr "    {\n";
10220         pr "      char s[33];\n";
10221         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10222         pr "      s[32] = 0;\n";
10223         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10224         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10225         pr "    }\n";
10226     | name, FBuffer ->
10227         pr "    {\n";
10228         pr "      int len = r->val[i].%s_len;\n" name;
10229         pr "      char s[len+1];\n";
10230         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10231         pr "      s[len] = 0;\n";
10232         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10233         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10234         pr "    }\n";
10235     | name, (FBytes|FUInt64|FInt64) ->
10236         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10237         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10238     | name, (FUInt32|FInt32) ->
10239         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10240         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10241     | name, FOptPercent ->
10242         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10243         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10244     | name, FChar ->
10245         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10246         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10247   ) cols;
10248   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10249   pr "  }\n";
10250   pr "  guestfs_free_%s_list (r);\n" typ;
10251   pr "  return jr;\n"
10252
10253 and generate_java_makefile_inc () =
10254   generate_header HashStyle GPLv2plus;
10255
10256   pr "java_built_sources = \\\n";
10257   List.iter (
10258     fun (typ, jtyp) ->
10259         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10260   ) java_structs;
10261   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10262
10263 and generate_haskell_hs () =
10264   generate_header HaskellStyle LGPLv2plus;
10265
10266   (* XXX We only know how to generate partial FFI for Haskell
10267    * at the moment.  Please help out!
10268    *)
10269   let can_generate style =
10270     match style with
10271     | RErr, _
10272     | RInt _, _
10273     | RInt64 _, _ -> true
10274     | RBool _, _
10275     | RConstString _, _
10276     | RConstOptString _, _
10277     | RString _, _
10278     | RStringList _, _
10279     | RStruct _, _
10280     | RStructList _, _
10281     | RHashtable _, _
10282     | RBufferOut _, _ -> false in
10283
10284   pr "\
10285 {-# INCLUDE <guestfs.h> #-}
10286 {-# LANGUAGE ForeignFunctionInterface #-}
10287
10288 module Guestfs (
10289   create";
10290
10291   (* List out the names of the actions we want to export. *)
10292   List.iter (
10293     fun (name, style, _, _, _, _, _) ->
10294       if can_generate style then pr ",\n  %s" name
10295   ) all_functions;
10296
10297   pr "
10298   ) where
10299
10300 -- Unfortunately some symbols duplicate ones already present
10301 -- in Prelude.  We don't know which, so we hard-code a list
10302 -- here.
10303 import Prelude hiding (truncate)
10304
10305 import Foreign
10306 import Foreign.C
10307 import Foreign.C.Types
10308 import IO
10309 import Control.Exception
10310 import Data.Typeable
10311
10312 data GuestfsS = GuestfsS            -- represents the opaque C struct
10313 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10314 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10315
10316 -- XXX define properly later XXX
10317 data PV = PV
10318 data VG = VG
10319 data LV = LV
10320 data IntBool = IntBool
10321 data Stat = Stat
10322 data StatVFS = StatVFS
10323 data Hashtable = Hashtable
10324
10325 foreign import ccall unsafe \"guestfs_create\" c_create
10326   :: IO GuestfsP
10327 foreign import ccall unsafe \"&guestfs_close\" c_close
10328   :: FunPtr (GuestfsP -> IO ())
10329 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10330   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10331
10332 create :: IO GuestfsH
10333 create = do
10334   p <- c_create
10335   c_set_error_handler p nullPtr nullPtr
10336   h <- newForeignPtr c_close p
10337   return h
10338
10339 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10340   :: GuestfsP -> IO CString
10341
10342 -- last_error :: GuestfsH -> IO (Maybe String)
10343 -- last_error h = do
10344 --   str <- withForeignPtr h (\\p -> c_last_error p)
10345 --   maybePeek peekCString str
10346
10347 last_error :: GuestfsH -> IO (String)
10348 last_error h = do
10349   str <- withForeignPtr h (\\p -> c_last_error p)
10350   if (str == nullPtr)
10351     then return \"no error\"
10352     else peekCString str
10353
10354 ";
10355
10356   (* Generate wrappers for each foreign function. *)
10357   List.iter (
10358     fun (name, style, _, _, _, _, _) ->
10359       if can_generate style then (
10360         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10361         pr "  :: ";
10362         generate_haskell_prototype ~handle:"GuestfsP" style;
10363         pr "\n";
10364         pr "\n";
10365         pr "%s :: " name;
10366         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10367         pr "\n";
10368         pr "%s %s = do\n" name
10369           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10370         pr "  r <- ";
10371         (* Convert pointer arguments using with* functions. *)
10372         List.iter (
10373           function
10374           | FileIn n
10375           | FileOut n
10376           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10377           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10378           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10379           | Bool _ | Int _ | Int64 _ -> ()
10380         ) (snd style);
10381         (* Convert integer arguments. *)
10382         let args =
10383           List.map (
10384             function
10385             | Bool n -> sprintf "(fromBool %s)" n
10386             | Int n -> sprintf "(fromIntegral %s)" n
10387             | Int64 n -> sprintf "(fromIntegral %s)" n
10388             | FileIn n | FileOut n
10389             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10390           ) (snd style) in
10391         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10392           (String.concat " " ("p" :: args));
10393         (match fst style with
10394          | RErr | RInt _ | RInt64 _ | RBool _ ->
10395              pr "  if (r == -1)\n";
10396              pr "    then do\n";
10397              pr "      err <- last_error h\n";
10398              pr "      fail err\n";
10399          | RConstString _ | RConstOptString _ | RString _
10400          | RStringList _ | RStruct _
10401          | RStructList _ | RHashtable _ | RBufferOut _ ->
10402              pr "  if (r == nullPtr)\n";
10403              pr "    then do\n";
10404              pr "      err <- last_error h\n";
10405              pr "      fail err\n";
10406         );
10407         (match fst style with
10408          | RErr ->
10409              pr "    else return ()\n"
10410          | RInt _ ->
10411              pr "    else return (fromIntegral r)\n"
10412          | RInt64 _ ->
10413              pr "    else return (fromIntegral r)\n"
10414          | RBool _ ->
10415              pr "    else return (toBool r)\n"
10416          | RConstString _
10417          | RConstOptString _
10418          | RString _
10419          | RStringList _
10420          | RStruct _
10421          | RStructList _
10422          | RHashtable _
10423          | RBufferOut _ ->
10424              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10425         );
10426         pr "\n";
10427       )
10428   ) all_functions
10429
10430 and generate_haskell_prototype ~handle ?(hs = false) style =
10431   pr "%s -> " handle;
10432   let string = if hs then "String" else "CString" in
10433   let int = if hs then "Int" else "CInt" in
10434   let bool = if hs then "Bool" else "CInt" in
10435   let int64 = if hs then "Integer" else "Int64" in
10436   List.iter (
10437     fun arg ->
10438       (match arg with
10439        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10440        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10441        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10442        | Bool _ -> pr "%s" bool
10443        | Int _ -> pr "%s" int
10444        | Int64 _ -> pr "%s" int
10445        | FileIn _ -> pr "%s" string
10446        | FileOut _ -> pr "%s" string
10447       );
10448       pr " -> ";
10449   ) (snd style);
10450   pr "IO (";
10451   (match fst style with
10452    | RErr -> if not hs then pr "CInt"
10453    | RInt _ -> pr "%s" int
10454    | RInt64 _ -> pr "%s" int64
10455    | RBool _ -> pr "%s" bool
10456    | RConstString _ -> pr "%s" string
10457    | RConstOptString _ -> pr "Maybe %s" string
10458    | RString _ -> pr "%s" string
10459    | RStringList _ -> pr "[%s]" string
10460    | RStruct (_, typ) ->
10461        let name = java_name_of_struct typ in
10462        pr "%s" name
10463    | RStructList (_, typ) ->
10464        let name = java_name_of_struct typ in
10465        pr "[%s]" name
10466    | RHashtable _ -> pr "Hashtable"
10467    | RBufferOut _ -> pr "%s" string
10468   );
10469   pr ")"
10470
10471 and generate_csharp () =
10472   generate_header CPlusPlusStyle LGPLv2plus;
10473
10474   (* XXX Make this configurable by the C# assembly users. *)
10475   let library = "libguestfs.so.0" in
10476
10477   pr "\
10478 // These C# bindings are highly experimental at present.
10479 //
10480 // Firstly they only work on Linux (ie. Mono).  In order to get them
10481 // to work on Windows (ie. .Net) you would need to port the library
10482 // itself to Windows first.
10483 //
10484 // The second issue is that some calls are known to be incorrect and
10485 // can cause Mono to segfault.  Particularly: calls which pass or
10486 // return string[], or return any structure value.  This is because
10487 // we haven't worked out the correct way to do this from C#.
10488 //
10489 // The third issue is that when compiling you get a lot of warnings.
10490 // We are not sure whether the warnings are important or not.
10491 //
10492 // Fourthly we do not routinely build or test these bindings as part
10493 // of the make && make check cycle, which means that regressions might
10494 // go unnoticed.
10495 //
10496 // Suggestions and patches are welcome.
10497
10498 // To compile:
10499 //
10500 // gmcs Libguestfs.cs
10501 // mono Libguestfs.exe
10502 //
10503 // (You'll probably want to add a Test class / static main function
10504 // otherwise this won't do anything useful).
10505
10506 using System;
10507 using System.IO;
10508 using System.Runtime.InteropServices;
10509 using System.Runtime.Serialization;
10510 using System.Collections;
10511
10512 namespace Guestfs
10513 {
10514   class Error : System.ApplicationException
10515   {
10516     public Error (string message) : base (message) {}
10517     protected Error (SerializationInfo info, StreamingContext context) {}
10518   }
10519
10520   class Guestfs
10521   {
10522     IntPtr _handle;
10523
10524     [DllImport (\"%s\")]
10525     static extern IntPtr guestfs_create ();
10526
10527     public Guestfs ()
10528     {
10529       _handle = guestfs_create ();
10530       if (_handle == IntPtr.Zero)
10531         throw new Error (\"could not create guestfs handle\");
10532     }
10533
10534     [DllImport (\"%s\")]
10535     static extern void guestfs_close (IntPtr h);
10536
10537     ~Guestfs ()
10538     {
10539       guestfs_close (_handle);
10540     }
10541
10542     [DllImport (\"%s\")]
10543     static extern string guestfs_last_error (IntPtr h);
10544
10545 " library library library;
10546
10547   (* Generate C# structure bindings.  We prefix struct names with
10548    * underscore because C# cannot have conflicting struct names and
10549    * method names (eg. "class stat" and "stat").
10550    *)
10551   List.iter (
10552     fun (typ, cols) ->
10553       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10554       pr "    public class _%s {\n" typ;
10555       List.iter (
10556         function
10557         | name, FChar -> pr "      char %s;\n" name
10558         | name, FString -> pr "      string %s;\n" name
10559         | name, FBuffer ->
10560             pr "      uint %s_len;\n" name;
10561             pr "      string %s;\n" name
10562         | name, FUUID ->
10563             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10564             pr "      string %s;\n" name
10565         | name, FUInt32 -> pr "      uint %s;\n" name
10566         | name, FInt32 -> pr "      int %s;\n" name
10567         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10568         | name, FInt64 -> pr "      long %s;\n" name
10569         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10570       ) cols;
10571       pr "    }\n";
10572       pr "\n"
10573   ) structs;
10574
10575   (* Generate C# function bindings. *)
10576   List.iter (
10577     fun (name, style, _, _, _, shortdesc, _) ->
10578       let rec csharp_return_type () =
10579         match fst style with
10580         | RErr -> "void"
10581         | RBool n -> "bool"
10582         | RInt n -> "int"
10583         | RInt64 n -> "long"
10584         | RConstString n
10585         | RConstOptString n
10586         | RString n
10587         | RBufferOut n -> "string"
10588         | RStruct (_,n) -> "_" ^ n
10589         | RHashtable n -> "Hashtable"
10590         | RStringList n -> "string[]"
10591         | RStructList (_,n) -> sprintf "_%s[]" n
10592
10593       and c_return_type () =
10594         match fst style with
10595         | RErr
10596         | RBool _
10597         | RInt _ -> "int"
10598         | RInt64 _ -> "long"
10599         | RConstString _
10600         | RConstOptString _
10601         | RString _
10602         | RBufferOut _ -> "string"
10603         | RStruct (_,n) -> "_" ^ n
10604         | RHashtable _
10605         | RStringList _ -> "string[]"
10606         | RStructList (_,n) -> sprintf "_%s[]" n
10607
10608       and c_error_comparison () =
10609         match fst style with
10610         | RErr
10611         | RBool _
10612         | RInt _
10613         | RInt64 _ -> "== -1"
10614         | RConstString _
10615         | RConstOptString _
10616         | RString _
10617         | RBufferOut _
10618         | RStruct (_,_)
10619         | RHashtable _
10620         | RStringList _
10621         | RStructList (_,_) -> "== null"
10622
10623       and generate_extern_prototype () =
10624         pr "    static extern %s guestfs_%s (IntPtr h"
10625           (c_return_type ()) name;
10626         List.iter (
10627           function
10628           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10629           | FileIn n | FileOut n ->
10630               pr ", [In] string %s" n
10631           | StringList n | DeviceList n ->
10632               pr ", [In] string[] %s" n
10633           | Bool n ->
10634               pr ", bool %s" n
10635           | Int n ->
10636               pr ", int %s" n
10637           | Int64 n ->
10638               pr ", long %s" n
10639         ) (snd style);
10640         pr ");\n"
10641
10642       and generate_public_prototype () =
10643         pr "    public %s %s (" (csharp_return_type ()) name;
10644         let comma = ref false in
10645         let next () =
10646           if !comma then pr ", ";
10647           comma := true
10648         in
10649         List.iter (
10650           function
10651           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10652           | FileIn n | FileOut n ->
10653               next (); pr "string %s" n
10654           | StringList n | DeviceList n ->
10655               next (); pr "string[] %s" n
10656           | Bool n ->
10657               next (); pr "bool %s" n
10658           | Int n ->
10659               next (); pr "int %s" n
10660           | Int64 n ->
10661               next (); pr "long %s" n
10662         ) (snd style);
10663         pr ")\n"
10664
10665       and generate_call () =
10666         pr "guestfs_%s (_handle" name;
10667         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10668         pr ");\n";
10669       in
10670
10671       pr "    [DllImport (\"%s\")]\n" library;
10672       generate_extern_prototype ();
10673       pr "\n";
10674       pr "    /// <summary>\n";
10675       pr "    /// %s\n" shortdesc;
10676       pr "    /// </summary>\n";
10677       generate_public_prototype ();
10678       pr "    {\n";
10679       pr "      %s r;\n" (c_return_type ());
10680       pr "      r = ";
10681       generate_call ();
10682       pr "      if (r %s)\n" (c_error_comparison ());
10683       pr "        throw new Error (guestfs_last_error (_handle));\n";
10684       (match fst style with
10685        | RErr -> ()
10686        | RBool _ ->
10687            pr "      return r != 0 ? true : false;\n"
10688        | RHashtable _ ->
10689            pr "      Hashtable rr = new Hashtable ();\n";
10690            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10691            pr "        rr.Add (r[i], r[i+1]);\n";
10692            pr "      return rr;\n"
10693        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10694        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10695        | RStructList _ ->
10696            pr "      return r;\n"
10697       );
10698       pr "    }\n";
10699       pr "\n";
10700   ) all_functions_sorted;
10701
10702   pr "  }
10703 }
10704 "
10705
10706 and generate_bindtests () =
10707   generate_header CStyle LGPLv2plus;
10708
10709   pr "\
10710 #include <stdio.h>
10711 #include <stdlib.h>
10712 #include <inttypes.h>
10713 #include <string.h>
10714
10715 #include \"guestfs.h\"
10716 #include \"guestfs-internal.h\"
10717 #include \"guestfs-internal-actions.h\"
10718 #include \"guestfs_protocol.h\"
10719
10720 #define error guestfs_error
10721 #define safe_calloc guestfs_safe_calloc
10722 #define safe_malloc guestfs_safe_malloc
10723
10724 static void
10725 print_strings (char *const *argv)
10726 {
10727   int argc;
10728
10729   printf (\"[\");
10730   for (argc = 0; argv[argc] != NULL; ++argc) {
10731     if (argc > 0) printf (\", \");
10732     printf (\"\\\"%%s\\\"\", argv[argc]);
10733   }
10734   printf (\"]\\n\");
10735 }
10736
10737 /* The test0 function prints its parameters to stdout. */
10738 ";
10739
10740   let test0, tests =
10741     match test_functions with
10742     | [] -> assert false
10743     | test0 :: tests -> test0, tests in
10744
10745   let () =
10746     let (name, style, _, _, _, _, _) = test0 in
10747     generate_prototype ~extern:false ~semicolon:false ~newline:true
10748       ~handle:"g" ~prefix:"guestfs__" name style;
10749     pr "{\n";
10750     List.iter (
10751       function
10752       | Pathname n
10753       | Device n | Dev_or_Path n
10754       | String n
10755       | FileIn n
10756       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10757       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10758       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10759       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10760       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10761       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10762     ) (snd style);
10763     pr "  /* Java changes stdout line buffering so we need this: */\n";
10764     pr "  fflush (stdout);\n";
10765     pr "  return 0;\n";
10766     pr "}\n";
10767     pr "\n" in
10768
10769   List.iter (
10770     fun (name, style, _, _, _, _, _) ->
10771       if String.sub name (String.length name - 3) 3 <> "err" then (
10772         pr "/* Test normal return. */\n";
10773         generate_prototype ~extern:false ~semicolon:false ~newline:true
10774           ~handle:"g" ~prefix:"guestfs__" name style;
10775         pr "{\n";
10776         (match fst style with
10777          | RErr ->
10778              pr "  return 0;\n"
10779          | RInt _ ->
10780              pr "  int r;\n";
10781              pr "  sscanf (val, \"%%d\", &r);\n";
10782              pr "  return r;\n"
10783          | RInt64 _ ->
10784              pr "  int64_t r;\n";
10785              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10786              pr "  return r;\n"
10787          | RBool _ ->
10788              pr "  return STREQ (val, \"true\");\n"
10789          | RConstString _
10790          | RConstOptString _ ->
10791              (* Can't return the input string here.  Return a static
10792               * string so we ensure we get a segfault if the caller
10793               * tries to free it.
10794               *)
10795              pr "  return \"static string\";\n"
10796          | RString _ ->
10797              pr "  return strdup (val);\n"
10798          | RStringList _ ->
10799              pr "  char **strs;\n";
10800              pr "  int n, i;\n";
10801              pr "  sscanf (val, \"%%d\", &n);\n";
10802              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10803              pr "  for (i = 0; i < n; ++i) {\n";
10804              pr "    strs[i] = safe_malloc (g, 16);\n";
10805              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10806              pr "  }\n";
10807              pr "  strs[n] = NULL;\n";
10808              pr "  return strs;\n"
10809          | RStruct (_, typ) ->
10810              pr "  struct guestfs_%s *r;\n" typ;
10811              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10812              pr "  return r;\n"
10813          | RStructList (_, typ) ->
10814              pr "  struct guestfs_%s_list *r;\n" typ;
10815              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10816              pr "  sscanf (val, \"%%d\", &r->len);\n";
10817              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10818              pr "  return r;\n"
10819          | RHashtable _ ->
10820              pr "  char **strs;\n";
10821              pr "  int n, i;\n";
10822              pr "  sscanf (val, \"%%d\", &n);\n";
10823              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10824              pr "  for (i = 0; i < n; ++i) {\n";
10825              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10826              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10827              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10828              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10829              pr "  }\n";
10830              pr "  strs[n*2] = NULL;\n";
10831              pr "  return strs;\n"
10832          | RBufferOut _ ->
10833              pr "  return strdup (val);\n"
10834         );
10835         pr "}\n";
10836         pr "\n"
10837       ) else (
10838         pr "/* Test error return. */\n";
10839         generate_prototype ~extern:false ~semicolon:false ~newline:true
10840           ~handle:"g" ~prefix:"guestfs__" name style;
10841         pr "{\n";
10842         pr "  error (g, \"error\");\n";
10843         (match fst style with
10844          | RErr | RInt _ | RInt64 _ | RBool _ ->
10845              pr "  return -1;\n"
10846          | RConstString _ | RConstOptString _
10847          | RString _ | RStringList _ | RStruct _
10848          | RStructList _
10849          | RHashtable _
10850          | RBufferOut _ ->
10851              pr "  return NULL;\n"
10852         );
10853         pr "}\n";
10854         pr "\n"
10855       )
10856   ) tests
10857
10858 and generate_ocaml_bindtests () =
10859   generate_header OCamlStyle GPLv2plus;
10860
10861   pr "\
10862 let () =
10863   let g = Guestfs.create () in
10864 ";
10865
10866   let mkargs args =
10867     String.concat " " (
10868       List.map (
10869         function
10870         | CallString s -> "\"" ^ s ^ "\""
10871         | CallOptString None -> "None"
10872         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10873         | CallStringList xs ->
10874             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10875         | CallInt i when i >= 0 -> string_of_int i
10876         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10877         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10878         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10879         | CallBool b -> string_of_bool b
10880       ) args
10881     )
10882   in
10883
10884   generate_lang_bindtests (
10885     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10886   );
10887
10888   pr "print_endline \"EOF\"\n"
10889
10890 and generate_perl_bindtests () =
10891   pr "#!/usr/bin/perl -w\n";
10892   generate_header HashStyle GPLv2plus;
10893
10894   pr "\
10895 use strict;
10896
10897 use Sys::Guestfs;
10898
10899 my $g = Sys::Guestfs->new ();
10900 ";
10901
10902   let mkargs args =
10903     String.concat ", " (
10904       List.map (
10905         function
10906         | CallString s -> "\"" ^ s ^ "\""
10907         | CallOptString None -> "undef"
10908         | CallOptString (Some s) -> sprintf "\"%s\"" s
10909         | CallStringList xs ->
10910             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10911         | CallInt i -> string_of_int i
10912         | CallInt64 i -> Int64.to_string i
10913         | CallBool b -> if b then "1" else "0"
10914       ) args
10915     )
10916   in
10917
10918   generate_lang_bindtests (
10919     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10920   );
10921
10922   pr "print \"EOF\\n\"\n"
10923
10924 and generate_python_bindtests () =
10925   generate_header HashStyle GPLv2plus;
10926
10927   pr "\
10928 import guestfs
10929
10930 g = guestfs.GuestFS ()
10931 ";
10932
10933   let mkargs args =
10934     String.concat ", " (
10935       List.map (
10936         function
10937         | CallString s -> "\"" ^ s ^ "\""
10938         | CallOptString None -> "None"
10939         | CallOptString (Some s) -> sprintf "\"%s\"" s
10940         | CallStringList xs ->
10941             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10942         | CallInt i -> string_of_int i
10943         | CallInt64 i -> Int64.to_string i
10944         | CallBool b -> if b then "1" else "0"
10945       ) args
10946     )
10947   in
10948
10949   generate_lang_bindtests (
10950     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10951   );
10952
10953   pr "print \"EOF\"\n"
10954
10955 and generate_ruby_bindtests () =
10956   generate_header HashStyle GPLv2plus;
10957
10958   pr "\
10959 require 'guestfs'
10960
10961 g = Guestfs::create()
10962 ";
10963
10964   let mkargs args =
10965     String.concat ", " (
10966       List.map (
10967         function
10968         | CallString s -> "\"" ^ s ^ "\""
10969         | CallOptString None -> "nil"
10970         | CallOptString (Some s) -> sprintf "\"%s\"" s
10971         | CallStringList xs ->
10972             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10973         | CallInt i -> string_of_int i
10974         | CallInt64 i -> Int64.to_string i
10975         | CallBool b -> string_of_bool b
10976       ) args
10977     )
10978   in
10979
10980   generate_lang_bindtests (
10981     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10982   );
10983
10984   pr "print \"EOF\\n\"\n"
10985
10986 and generate_java_bindtests () =
10987   generate_header CStyle GPLv2plus;
10988
10989   pr "\
10990 import com.redhat.et.libguestfs.*;
10991
10992 public class Bindtests {
10993     public static void main (String[] argv)
10994     {
10995         try {
10996             GuestFS g = new GuestFS ();
10997 ";
10998
10999   let mkargs args =
11000     String.concat ", " (
11001       List.map (
11002         function
11003         | CallString s -> "\"" ^ s ^ "\""
11004         | CallOptString None -> "null"
11005         | CallOptString (Some s) -> sprintf "\"%s\"" s
11006         | CallStringList xs ->
11007             "new String[]{" ^
11008               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11009         | CallInt i -> string_of_int i
11010         | CallInt64 i -> Int64.to_string i
11011         | CallBool b -> string_of_bool b
11012       ) args
11013     )
11014   in
11015
11016   generate_lang_bindtests (
11017     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11018   );
11019
11020   pr "
11021             System.out.println (\"EOF\");
11022         }
11023         catch (Exception exn) {
11024             System.err.println (exn);
11025             System.exit (1);
11026         }
11027     }
11028 }
11029 "
11030
11031 and generate_haskell_bindtests () =
11032   generate_header HaskellStyle GPLv2plus;
11033
11034   pr "\
11035 module Bindtests where
11036 import qualified Guestfs
11037
11038 main = do
11039   g <- Guestfs.create
11040 ";
11041
11042   let mkargs args =
11043     String.concat " " (
11044       List.map (
11045         function
11046         | CallString s -> "\"" ^ s ^ "\""
11047         | CallOptString None -> "Nothing"
11048         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11049         | CallStringList xs ->
11050             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11051         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11052         | CallInt i -> string_of_int i
11053         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11054         | CallInt64 i -> Int64.to_string i
11055         | CallBool true -> "True"
11056         | CallBool false -> "False"
11057       ) args
11058     )
11059   in
11060
11061   generate_lang_bindtests (
11062     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11063   );
11064
11065   pr "  putStrLn \"EOF\"\n"
11066
11067 (* Language-independent bindings tests - we do it this way to
11068  * ensure there is parity in testing bindings across all languages.
11069  *)
11070 and generate_lang_bindtests call =
11071   call "test0" [CallString "abc"; CallOptString (Some "def");
11072                 CallStringList []; CallBool false;
11073                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11074   call "test0" [CallString "abc"; CallOptString None;
11075                 CallStringList []; CallBool false;
11076                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11077   call "test0" [CallString ""; CallOptString (Some "def");
11078                 CallStringList []; CallBool false;
11079                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11080   call "test0" [CallString ""; CallOptString (Some "");
11081                 CallStringList []; CallBool false;
11082                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11083   call "test0" [CallString "abc"; CallOptString (Some "def");
11084                 CallStringList ["1"]; CallBool false;
11085                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11086   call "test0" [CallString "abc"; CallOptString (Some "def");
11087                 CallStringList ["1"; "2"]; CallBool false;
11088                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11089   call "test0" [CallString "abc"; CallOptString (Some "def");
11090                 CallStringList ["1"]; CallBool true;
11091                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11092   call "test0" [CallString "abc"; CallOptString (Some "def");
11093                 CallStringList ["1"]; CallBool false;
11094                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11095   call "test0" [CallString "abc"; CallOptString (Some "def");
11096                 CallStringList ["1"]; CallBool false;
11097                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11098   call "test0" [CallString "abc"; CallOptString (Some "def");
11099                 CallStringList ["1"]; CallBool false;
11100                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11101   call "test0" [CallString "abc"; CallOptString (Some "def");
11102                 CallStringList ["1"]; CallBool false;
11103                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11104   call "test0" [CallString "abc"; CallOptString (Some "def");
11105                 CallStringList ["1"]; CallBool false;
11106                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11107   call "test0" [CallString "abc"; CallOptString (Some "def");
11108                 CallStringList ["1"]; CallBool false;
11109                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11110
11111 (* XXX Add here tests of the return and error functions. *)
11112
11113 (* Code to generator bindings for virt-inspector.  Currently only
11114  * implemented for OCaml code (for virt-p2v 2.0).
11115  *)
11116 let rng_input = "inspector/virt-inspector.rng"
11117
11118 (* Read the input file and parse it into internal structures.  This is
11119  * by no means a complete RELAX NG parser, but is just enough to be
11120  * able to parse the specific input file.
11121  *)
11122 type rng =
11123   | Element of string * rng list        (* <element name=name/> *)
11124   | Attribute of string * rng list        (* <attribute name=name/> *)
11125   | Interleave of rng list                (* <interleave/> *)
11126   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11127   | OneOrMore of rng                        (* <oneOrMore/> *)
11128   | Optional of rng                        (* <optional/> *)
11129   | Choice of string list                (* <choice><value/>*</choice> *)
11130   | Value of string                        (* <value>str</value> *)
11131   | Text                                (* <text/> *)
11132
11133 let rec string_of_rng = function
11134   | Element (name, xs) ->
11135       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11136   | Attribute (name, xs) ->
11137       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11138   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11139   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11140   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11141   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11142   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11143   | Value value -> "Value \"" ^ value ^ "\""
11144   | Text -> "Text"
11145
11146 and string_of_rng_list xs =
11147   String.concat ", " (List.map string_of_rng xs)
11148
11149 let rec parse_rng ?defines context = function
11150   | [] -> []
11151   | Xml.Element ("element", ["name", name], children) :: rest ->
11152       Element (name, parse_rng ?defines context children)
11153       :: parse_rng ?defines context rest
11154   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11155       Attribute (name, parse_rng ?defines context children)
11156       :: parse_rng ?defines context rest
11157   | Xml.Element ("interleave", [], children) :: rest ->
11158       Interleave (parse_rng ?defines context children)
11159       :: parse_rng ?defines context rest
11160   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11161       let rng = parse_rng ?defines context [child] in
11162       (match rng with
11163        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11164        | _ ->
11165            failwithf "%s: <zeroOrMore> contains more than one child element"
11166              context
11167       )
11168   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11169       let rng = parse_rng ?defines context [child] in
11170       (match rng with
11171        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11172        | _ ->
11173            failwithf "%s: <oneOrMore> contains more than one child element"
11174              context
11175       )
11176   | Xml.Element ("optional", [], [child]) :: rest ->
11177       let rng = parse_rng ?defines context [child] in
11178       (match rng with
11179        | [child] -> Optional child :: parse_rng ?defines context rest
11180        | _ ->
11181            failwithf "%s: <optional> contains more than one child element"
11182              context
11183       )
11184   | Xml.Element ("choice", [], children) :: rest ->
11185       let values = List.map (
11186         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11187         | _ ->
11188             failwithf "%s: can't handle anything except <value> in <choice>"
11189               context
11190       ) children in
11191       Choice values
11192       :: parse_rng ?defines context rest
11193   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11194       Value value :: parse_rng ?defines context rest
11195   | Xml.Element ("text", [], []) :: rest ->
11196       Text :: parse_rng ?defines context rest
11197   | Xml.Element ("ref", ["name", name], []) :: rest ->
11198       (* Look up the reference.  Because of limitations in this parser,
11199        * we can't handle arbitrarily nested <ref> yet.  You can only
11200        * use <ref> from inside <start>.
11201        *)
11202       (match defines with
11203        | None ->
11204            failwithf "%s: contains <ref>, but no refs are defined yet" context
11205        | Some map ->
11206            let rng = StringMap.find name map in
11207            rng @ parse_rng ?defines context rest
11208       )
11209   | x :: _ ->
11210       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11211
11212 let grammar =
11213   let xml = Xml.parse_file rng_input in
11214   match xml with
11215   | Xml.Element ("grammar", _,
11216                  Xml.Element ("start", _, gram) :: defines) ->
11217       (* The <define/> elements are referenced in the <start> section,
11218        * so build a map of those first.
11219        *)
11220       let defines = List.fold_left (
11221         fun map ->
11222           function Xml.Element ("define", ["name", name], defn) ->
11223             StringMap.add name defn map
11224           | _ ->
11225               failwithf "%s: expected <define name=name/>" rng_input
11226       ) StringMap.empty defines in
11227       let defines = StringMap.mapi parse_rng defines in
11228
11229       (* Parse the <start> clause, passing the defines. *)
11230       parse_rng ~defines "<start>" gram
11231   | _ ->
11232       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11233         rng_input
11234
11235 let name_of_field = function
11236   | Element (name, _) | Attribute (name, _)
11237   | ZeroOrMore (Element (name, _))
11238   | OneOrMore (Element (name, _))
11239   | Optional (Element (name, _)) -> name
11240   | Optional (Attribute (name, _)) -> name
11241   | Text -> (* an unnamed field in an element *)
11242       "data"
11243   | rng ->
11244       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11245
11246 (* At the moment this function only generates OCaml types.  However we
11247  * should parameterize it later so it can generate types/structs in a
11248  * variety of languages.
11249  *)
11250 let generate_types xs =
11251   (* A simple type is one that can be printed out directly, eg.
11252    * "string option".  A complex type is one which has a name and has
11253    * to be defined via another toplevel definition, eg. a struct.
11254    *
11255    * generate_type generates code for either simple or complex types.
11256    * In the simple case, it returns the string ("string option").  In
11257    * the complex case, it returns the name ("mountpoint").  In the
11258    * complex case it has to print out the definition before returning,
11259    * so it should only be called when we are at the beginning of a
11260    * new line (BOL context).
11261    *)
11262   let rec generate_type = function
11263     | Text ->                                (* string *)
11264         "string", true
11265     | Choice values ->                        (* [`val1|`val2|...] *)
11266         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11267     | ZeroOrMore rng ->                        (* <rng> list *)
11268         let t, is_simple = generate_type rng in
11269         t ^ " list (* 0 or more *)", is_simple
11270     | OneOrMore rng ->                        (* <rng> list *)
11271         let t, is_simple = generate_type rng in
11272         t ^ " list (* 1 or more *)", is_simple
11273                                         (* virt-inspector hack: bool *)
11274     | Optional (Attribute (name, [Value "1"])) ->
11275         "bool", true
11276     | Optional rng ->                        (* <rng> list *)
11277         let t, is_simple = generate_type rng in
11278         t ^ " option", is_simple
11279                                         (* type name = { fields ... } *)
11280     | Element (name, fields) when is_attrs_interleave fields ->
11281         generate_type_struct name (get_attrs_interleave fields)
11282     | Element (name, [field])                (* type name = field *)
11283     | Attribute (name, [field]) ->
11284         let t, is_simple = generate_type field in
11285         if is_simple then (t, true)
11286         else (
11287           pr "type %s = %s\n" name t;
11288           name, false
11289         )
11290     | Element (name, fields) ->              (* type name = { fields ... } *)
11291         generate_type_struct name fields
11292     | rng ->
11293         failwithf "generate_type failed at: %s" (string_of_rng rng)
11294
11295   and is_attrs_interleave = function
11296     | [Interleave _] -> true
11297     | Attribute _ :: fields -> is_attrs_interleave fields
11298     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11299     | _ -> false
11300
11301   and get_attrs_interleave = function
11302     | [Interleave fields] -> fields
11303     | ((Attribute _) as field) :: fields
11304     | ((Optional (Attribute _)) as field) :: fields ->
11305         field :: get_attrs_interleave fields
11306     | _ -> assert false
11307
11308   and generate_types xs =
11309     List.iter (fun x -> ignore (generate_type x)) xs
11310
11311   and generate_type_struct name fields =
11312     (* Calculate the types of the fields first.  We have to do this
11313      * before printing anything so we are still in BOL context.
11314      *)
11315     let types = List.map fst (List.map generate_type fields) in
11316
11317     (* Special case of a struct containing just a string and another
11318      * field.  Turn it into an assoc list.
11319      *)
11320     match types with
11321     | ["string"; other] ->
11322         let fname1, fname2 =
11323           match fields with
11324           | [f1; f2] -> name_of_field f1, name_of_field f2
11325           | _ -> assert false in
11326         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11327         name, false
11328
11329     | types ->
11330         pr "type %s = {\n" name;
11331         List.iter (
11332           fun (field, ftype) ->
11333             let fname = name_of_field field in
11334             pr "  %s_%s : %s;\n" name fname ftype
11335         ) (List.combine fields types);
11336         pr "}\n";
11337         (* Return the name of this type, and
11338          * false because it's not a simple type.
11339          *)
11340         name, false
11341   in
11342
11343   generate_types xs
11344
11345 let generate_parsers xs =
11346   (* As for generate_type above, generate_parser makes a parser for
11347    * some type, and returns the name of the parser it has generated.
11348    * Because it (may) need to print something, it should always be
11349    * called in BOL context.
11350    *)
11351   let rec generate_parser = function
11352     | Text ->                                (* string *)
11353         "string_child_or_empty"
11354     | Choice values ->                        (* [`val1|`val2|...] *)
11355         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11356           (String.concat "|"
11357              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11358     | ZeroOrMore rng ->                        (* <rng> list *)
11359         let pa = generate_parser rng in
11360         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11361     | OneOrMore rng ->                        (* <rng> list *)
11362         let pa = generate_parser rng in
11363         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11364                                         (* virt-inspector hack: bool *)
11365     | Optional (Attribute (name, [Value "1"])) ->
11366         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11367     | Optional rng ->                        (* <rng> list *)
11368         let pa = generate_parser rng in
11369         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11370                                         (* type name = { fields ... } *)
11371     | Element (name, fields) when is_attrs_interleave fields ->
11372         generate_parser_struct name (get_attrs_interleave fields)
11373     | Element (name, [field]) ->        (* type name = field *)
11374         let pa = generate_parser field in
11375         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11376         pr "let %s =\n" parser_name;
11377         pr "  %s\n" pa;
11378         pr "let parse_%s = %s\n" name parser_name;
11379         parser_name
11380     | Attribute (name, [field]) ->
11381         let pa = generate_parser field in
11382         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11383         pr "let %s =\n" parser_name;
11384         pr "  %s\n" pa;
11385         pr "let parse_%s = %s\n" name parser_name;
11386         parser_name
11387     | Element (name, fields) ->              (* type name = { fields ... } *)
11388         generate_parser_struct name ([], fields)
11389     | rng ->
11390         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11391
11392   and is_attrs_interleave = function
11393     | [Interleave _] -> true
11394     | Attribute _ :: fields -> is_attrs_interleave fields
11395     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11396     | _ -> false
11397
11398   and get_attrs_interleave = function
11399     | [Interleave fields] -> [], fields
11400     | ((Attribute _) as field) :: fields
11401     | ((Optional (Attribute _)) as field) :: fields ->
11402         let attrs, interleaves = get_attrs_interleave fields in
11403         (field :: attrs), interleaves
11404     | _ -> assert false
11405
11406   and generate_parsers xs =
11407     List.iter (fun x -> ignore (generate_parser x)) xs
11408
11409   and generate_parser_struct name (attrs, interleaves) =
11410     (* Generate parsers for the fields first.  We have to do this
11411      * before printing anything so we are still in BOL context.
11412      *)
11413     let fields = attrs @ interleaves in
11414     let pas = List.map generate_parser fields in
11415
11416     (* Generate an intermediate tuple from all the fields first.
11417      * If the type is just a string + another field, then we will
11418      * return this directly, otherwise it is turned into a record.
11419      *
11420      * RELAX NG note: This code treats <interleave> and plain lists of
11421      * fields the same.  In other words, it doesn't bother enforcing
11422      * any ordering of fields in the XML.
11423      *)
11424     pr "let parse_%s x =\n" name;
11425     pr "  let t = (\n    ";
11426     let comma = ref false in
11427     List.iter (
11428       fun x ->
11429         if !comma then pr ",\n    ";
11430         comma := true;
11431         match x with
11432         | Optional (Attribute (fname, [field])), pa ->
11433             pr "%s x" pa
11434         | Optional (Element (fname, [field])), pa ->
11435             pr "%s (optional_child %S x)" pa fname
11436         | Attribute (fname, [Text]), _ ->
11437             pr "attribute %S x" fname
11438         | (ZeroOrMore _ | OneOrMore _), pa ->
11439             pr "%s x" pa
11440         | Text, pa ->
11441             pr "%s x" pa
11442         | (field, pa) ->
11443             let fname = name_of_field field in
11444             pr "%s (child %S x)" pa fname
11445     ) (List.combine fields pas);
11446     pr "\n  ) in\n";
11447
11448     (match fields with
11449      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11450          pr "  t\n"
11451
11452      | _ ->
11453          pr "  (Obj.magic t : %s)\n" name
11454 (*
11455          List.iter (
11456            function
11457            | (Optional (Attribute (fname, [field])), pa) ->
11458                pr "  %s_%s =\n" name fname;
11459                pr "    %s x;\n" pa
11460            | (Optional (Element (fname, [field])), pa) ->
11461                pr "  %s_%s =\n" name fname;
11462                pr "    (let x = optional_child %S x in\n" fname;
11463                pr "     %s x);\n" pa
11464            | (field, pa) ->
11465                let fname = name_of_field field in
11466                pr "  %s_%s =\n" name fname;
11467                pr "    (let x = child %S x in\n" fname;
11468                pr "     %s x);\n" pa
11469          ) (List.combine fields pas);
11470          pr "}\n"
11471 *)
11472     );
11473     sprintf "parse_%s" name
11474   in
11475
11476   generate_parsers xs
11477
11478 (* Generate ocaml/guestfs_inspector.mli. *)
11479 let generate_ocaml_inspector_mli () =
11480   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11481
11482   pr "\
11483 (** This is an OCaml language binding to the external [virt-inspector]
11484     program.
11485
11486     For more information, please read the man page [virt-inspector(1)].
11487 *)
11488
11489 ";
11490
11491   generate_types grammar;
11492   pr "(** The nested information returned from the {!inspect} function. *)\n";
11493   pr "\n";
11494
11495   pr "\
11496 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11497 (** To inspect a libvirt domain called [name], pass a singleton
11498     list: [inspect [name]].  When using libvirt only, you may
11499     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11500
11501     To inspect a disk image or images, pass a list of the filenames
11502     of the disk images: [inspect filenames]
11503
11504     This function inspects the given guest or disk images and
11505     returns a list of operating system(s) found and a large amount
11506     of information about them.  In the vast majority of cases,
11507     a virtual machine only contains a single operating system.
11508
11509     If the optional [~xml] parameter is given, then this function
11510     skips running the external virt-inspector program and just
11511     parses the given XML directly (which is expected to be XML
11512     produced from a previous run of virt-inspector).  The list of
11513     names and connect URI are ignored in this case.
11514
11515     This function can throw a wide variety of exceptions, for example
11516     if the external virt-inspector program cannot be found, or if
11517     it doesn't generate valid XML.
11518 *)
11519 "
11520
11521 (* Generate ocaml/guestfs_inspector.ml. *)
11522 let generate_ocaml_inspector_ml () =
11523   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11524
11525   pr "open Unix\n";
11526   pr "\n";
11527
11528   generate_types grammar;
11529   pr "\n";
11530
11531   pr "\
11532 (* Misc functions which are used by the parser code below. *)
11533 let first_child = function
11534   | Xml.Element (_, _, c::_) -> c
11535   | Xml.Element (name, _, []) ->
11536       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11537   | Xml.PCData str ->
11538       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11539
11540 let string_child_or_empty = function
11541   | Xml.Element (_, _, [Xml.PCData s]) -> s
11542   | Xml.Element (_, _, []) -> \"\"
11543   | Xml.Element (x, _, _) ->
11544       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11545                 x ^ \" instead\")
11546   | Xml.PCData str ->
11547       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11548
11549 let optional_child name xml =
11550   let children = Xml.children xml in
11551   try
11552     Some (List.find (function
11553                      | Xml.Element (n, _, _) when n = name -> true
11554                      | _ -> false) children)
11555   with
11556     Not_found -> None
11557
11558 let child name xml =
11559   match optional_child name xml with
11560   | Some c -> c
11561   | None ->
11562       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11563
11564 let attribute name xml =
11565   try Xml.attrib xml name
11566   with Xml.No_attribute _ ->
11567     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11568
11569 ";
11570
11571   generate_parsers grammar;
11572   pr "\n";
11573
11574   pr "\
11575 (* Run external virt-inspector, then use parser to parse the XML. *)
11576 let inspect ?connect ?xml names =
11577   let xml =
11578     match xml with
11579     | None ->
11580         if names = [] then invalid_arg \"inspect: no names given\";
11581         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11582           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11583           names in
11584         let cmd = List.map Filename.quote cmd in
11585         let cmd = String.concat \" \" cmd in
11586         let chan = open_process_in cmd in
11587         let xml = Xml.parse_in chan in
11588         (match close_process_in chan with
11589          | WEXITED 0 -> ()
11590          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11591          | WSIGNALED i | WSTOPPED i ->
11592              failwith (\"external virt-inspector command died or stopped on sig \" ^
11593                        string_of_int i)
11594         );
11595         xml
11596     | Some doc ->
11597         Xml.parse_string doc in
11598   parse_operatingsystems xml
11599 "
11600
11601 (* This is used to generate the src/MAX_PROC_NR file which
11602  * contains the maximum procedure number, a surrogate for the
11603  * ABI version number.  See src/Makefile.am for the details.
11604  *)
11605 and generate_max_proc_nr () =
11606   let proc_nrs = List.map (
11607     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11608   ) daemon_functions in
11609
11610   let max_proc_nr = List.fold_left max 0 proc_nrs in
11611
11612   pr "%d\n" max_proc_nr
11613
11614 let output_to filename k =
11615   let filename_new = filename ^ ".new" in
11616   chan := open_out filename_new;
11617   k ();
11618   close_out !chan;
11619   chan := Pervasives.stdout;
11620
11621   (* Is the new file different from the current file? *)
11622   if Sys.file_exists filename && files_equal filename filename_new then
11623     unlink filename_new                 (* same, so skip it *)
11624   else (
11625     (* different, overwrite old one *)
11626     (try chmod filename 0o644 with Unix_error _ -> ());
11627     rename filename_new filename;
11628     chmod filename 0o444;
11629     printf "written %s\n%!" filename;
11630   )
11631
11632 let perror msg = function
11633   | Unix_error (err, _, _) ->
11634       eprintf "%s: %s\n" msg (error_message err)
11635   | exn ->
11636       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11637
11638 (* Main program. *)
11639 let () =
11640   let lock_fd =
11641     try openfile "HACKING" [O_RDWR] 0
11642     with
11643     | Unix_error (ENOENT, _, _) ->
11644         eprintf "\
11645 You are probably running this from the wrong directory.
11646 Run it from the top source directory using the command
11647   src/generator.ml
11648 ";
11649         exit 1
11650     | exn ->
11651         perror "open: HACKING" exn;
11652         exit 1 in
11653
11654   (* Acquire a lock so parallel builds won't try to run the generator
11655    * twice at the same time.  Subsequent builds will wait for the first
11656    * one to finish.  Note the lock is released implicitly when the
11657    * program exits.
11658    *)
11659   (try lockf lock_fd F_LOCK 1
11660    with exn ->
11661      perror "lock: HACKING" exn;
11662      exit 1);
11663
11664   check_functions ();
11665
11666   output_to "src/guestfs_protocol.x" generate_xdr;
11667   output_to "src/guestfs-structs.h" generate_structs_h;
11668   output_to "src/guestfs-actions.h" generate_actions_h;
11669   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11670   output_to "src/guestfs-actions.c" generate_client_actions;
11671   output_to "src/guestfs-bindtests.c" generate_bindtests;
11672   output_to "src/guestfs-structs.pod" generate_structs_pod;
11673   output_to "src/guestfs-actions.pod" generate_actions_pod;
11674   output_to "src/guestfs-availability.pod" generate_availability_pod;
11675   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11676   output_to "src/libguestfs.syms" generate_linker_script;
11677   output_to "daemon/actions.h" generate_daemon_actions_h;
11678   output_to "daemon/stubs.c" generate_daemon_actions;
11679   output_to "daemon/names.c" generate_daemon_names;
11680   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11681   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11682   output_to "capitests/tests.c" generate_tests;
11683   output_to "fish/cmds.c" generate_fish_cmds;
11684   output_to "fish/completion.c" generate_fish_completion;
11685   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11686   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11687   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11688   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11689   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11690   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11691   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11692   output_to "perl/Guestfs.xs" generate_perl_xs;
11693   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11694   output_to "perl/bindtests.pl" generate_perl_bindtests;
11695   output_to "python/guestfs-py.c" generate_python_c;
11696   output_to "python/guestfs.py" generate_python_py;
11697   output_to "python/bindtests.py" generate_python_bindtests;
11698   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11699   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11700   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11701
11702   List.iter (
11703     fun (typ, jtyp) ->
11704       let cols = cols_of_struct typ in
11705       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11706       output_to filename (generate_java_struct jtyp cols);
11707   ) java_structs;
11708
11709   output_to "java/Makefile.inc" generate_java_makefile_inc;
11710   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11711   output_to "java/Bindtests.java" generate_java_bindtests;
11712   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11713   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11714   output_to "csharp/Libguestfs.cs" generate_csharp;
11715
11716   (* Always generate this file last, and unconditionally.  It's used
11717    * by the Makefile to know when we must re-run the generator.
11718    *)
11719   let chan = open_out "src/stamp-generator" in
11720   fprintf chan "1\n";
11721   close_out chan;
11722
11723   printf "generated %d lines of code\n" !lines