9112a4843571cbac8325c30ec03276f47e986e51
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | FishOutput of fish_output_t (* how to display output in guestfish *)
186   | NotInFish             (* do not export via guestfish *)
187   | NotInDocs             (* do not add this function to documentation *)
188   | DeprecatedBy of string (* function is deprecated, use .. instead *)
189   | Optional of string    (* function is part of an optional group *)
190
191 and fish_output_t =
192   | FishOutputOctal       (* for int return, print in octal *)
193   | FishOutputHexadecimal (* for int return, print in hex *)
194
195 (* You can supply zero or as many tests as you want per API call.
196  *
197  * Note that the test environment has 3 block devices, of size 500MB,
198  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
199  * a fourth ISO block device with some known files on it (/dev/sdd).
200  *
201  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
202  * Number of cylinders was 63 for IDE emulated disks with precisely
203  * the same size.  How exactly this is calculated is a mystery.
204  *
205  * The ISO block device (/dev/sdd) comes from images/test.iso.
206  *
207  * To be able to run the tests in a reasonable amount of time,
208  * the virtual machine and block devices are reused between tests.
209  * So don't try testing kill_subprocess :-x
210  *
211  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
212  *
213  * Don't assume anything about the previous contents of the block
214  * devices.  Use 'Init*' to create some initial scenarios.
215  *
216  * You can add a prerequisite clause to any individual test.  This
217  * is a run-time check, which, if it fails, causes the test to be
218  * skipped.  Useful if testing a command which might not work on
219  * all variations of libguestfs builds.  A test that has prerequisite
220  * of 'Always' is run unconditionally.
221  *
222  * In addition, packagers can skip individual tests by setting the
223  * environment variables:     eg:
224  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
225  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
226  *)
227 type tests = (test_init * test_prereq * test) list
228 and test =
229     (* Run the command sequence and just expect nothing to fail. *)
230   | TestRun of seq
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the string.
234      *)
235   | TestOutput of seq * string
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of strings.
239      *)
240   | TestOutputList of seq * string list
241
242     (* Run the command sequence and expect the output of the final
243      * command to be the list of block devices (could be either
244      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
245      * character of each string).
246      *)
247   | TestOutputListOfDevices of seq * string list
248
249     (* Run the command sequence and expect the output of the final
250      * command to be the integer.
251      *)
252   | TestOutputInt of seq * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be <op> <int>, eg. ">=", "1".
256      *)
257   | TestOutputIntOp of seq * string * int
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a true value (!= 0 or != NULL).
261      *)
262   | TestOutputTrue of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a false value (== 0 or == NULL, but not an error).
266      *)
267   | TestOutputFalse of seq
268
269     (* Run the command sequence and expect the output of the final
270      * command to be a list of the given length (but don't care about
271      * content).
272      *)
273   | TestOutputLength of seq * int
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a buffer (RBufferOut), ie. string + size.
277      *)
278   | TestOutputBuffer of seq * string
279
280     (* Run the command sequence and expect the output of the final
281      * command to be a structure.
282      *)
283   | TestOutputStruct of seq * test_field_compare list
284
285     (* Run the command sequence and expect the final command (only)
286      * to fail.
287      *)
288   | TestLastFail of seq
289
290 and test_field_compare =
291   | CompareWithInt of string * int
292   | CompareWithIntOp of string * string * int
293   | CompareWithString of string * string
294   | CompareFieldsIntEq of string * string
295   | CompareFieldsStrEq of string * string
296
297 (* Test prerequisites. *)
298 and test_prereq =
299     (* Test always runs. *)
300   | Always
301
302     (* Test is currently disabled - eg. it fails, or it tests some
303      * unimplemented feature.
304      *)
305   | Disabled
306
307     (* 'string' is some C code (a function body) that should return
308      * true or false.  The test will run if the code returns true.
309      *)
310   | If of string
311
312     (* As for 'If' but the test runs _unless_ the code returns true. *)
313   | Unless of string
314
315 (* Some initial scenarios for testing. *)
316 and test_init =
317     (* Do nothing, block devices could contain random stuff including
318      * LVM PVs, and some filesystems might be mounted.  This is usually
319      * a bad idea.
320      *)
321   | InitNone
322
323     (* Block devices are empty and no filesystems are mounted. *)
324   | InitEmpty
325
326     (* /dev/sda contains a single partition /dev/sda1, with random
327      * content.  /dev/sdb and /dev/sdc may have random content.
328      * No LVM.
329      *)
330   | InitPartition
331
332     (* /dev/sda contains a single partition /dev/sda1, which is formatted
333      * as ext2, empty [except for lost+found] and mounted on /.
334      * /dev/sdb and /dev/sdc may have random content.
335      * No LVM.
336      *)
337   | InitBasicFS
338
339     (* /dev/sda:
340      *   /dev/sda1 (is a PV):
341      *     /dev/VG/LV (size 8MB):
342      *       formatted as ext2, empty [except for lost+found], mounted on /
343      * /dev/sdb and /dev/sdc may have random content.
344      *)
345   | InitBasicFSonLVM
346
347     (* /dev/sdd (the ISO, see images/ directory in source)
348      * is mounted on /
349      *)
350   | InitISOFS
351
352 (* Sequence of commands for testing. *)
353 and seq = cmd list
354 and cmd = string list
355
356 (* Note about long descriptions: When referring to another
357  * action, use the format C<guestfs_other> (ie. the full name of
358  * the C function).  This will be replaced as appropriate in other
359  * language bindings.
360  *
361  * Apart from that, long descriptions are just perldoc paragraphs.
362  *)
363
364 (* Generate a random UUID (used in tests). *)
365 let uuidgen () =
366   let chan = open_process_in "uuidgen" in
367   let uuid = input_line chan in
368   (match close_process_in chan with
369    | WEXITED 0 -> ()
370    | WEXITED _ ->
371        failwith "uuidgen: process exited with non-zero status"
372    | WSIGNALED _ | WSTOPPED _ ->
373        failwith "uuidgen: process signalled or stopped by signal"
374   );
375   uuid
376
377 (* These test functions are used in the language binding tests. *)
378
379 let test_all_args = [
380   String "str";
381   OptString "optstr";
382   StringList "strlist";
383   Bool "b";
384   Int "integer";
385   Int64 "integer64";
386   FileIn "filein";
387   FileOut "fileout";
388 ]
389
390 let test_all_rets = [
391   (* except for RErr, which is tested thoroughly elsewhere *)
392   "test0rint",         RInt "valout";
393   "test0rint64",       RInt64 "valout";
394   "test0rbool",        RBool "valout";
395   "test0rconststring", RConstString "valout";
396   "test0rconstoptstring", RConstOptString "valout";
397   "test0rstring",      RString "valout";
398   "test0rstringlist",  RStringList "valout";
399   "test0rstruct",      RStruct ("valout", "lvm_pv");
400   "test0rstructlist",  RStructList ("valout", "lvm_pv");
401   "test0rhashtable",   RHashtable "valout";
402 ]
403
404 let test_functions = [
405   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
406    [],
407    "internal test function - do not use",
408    "\
409 This is an internal test function which is used to test whether
410 the automatically generated bindings can handle every possible
411 parameter type correctly.
412
413 It echos the contents of each parameter to stdout.
414
415 You probably don't want to call this function.");
416 ] @ List.flatten (
417   List.map (
418     fun (name, ret) ->
419       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
420         [],
421         "internal test function - do not use",
422         "\
423 This is an internal test function which is used to test whether
424 the automatically generated bindings can handle every possible
425 return type correctly.
426
427 It converts string C<val> to the return type.
428
429 You probably don't want to call this function.");
430        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
431         [],
432         "internal test function - do not use",
433         "\
434 This is an internal test function which is used to test whether
435 the automatically generated bindings can handle every possible
436 return type correctly.
437
438 This function always returns an error.
439
440 You probably don't want to call this function.")]
441   ) test_all_rets
442 )
443
444 (* non_daemon_functions are any functions which don't get processed
445  * in the daemon, eg. functions for setting and getting local
446  * configuration values.
447  *)
448
449 let non_daemon_functions = test_functions @ [
450   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
451    [],
452    "launch the qemu subprocess",
453    "\
454 Internally libguestfs is implemented by running a virtual machine
455 using L<qemu(1)>.
456
457 You should call this after configuring the handle
458 (eg. adding drives) but before performing any actions.");
459
460   ("wait_ready", (RErr, []), -1, [NotInFish],
461    [],
462    "wait until the qemu subprocess launches (no op)",
463    "\
464 This function is a no op.
465
466 In versions of the API E<lt> 1.0.71 you had to call this function
467 just after calling C<guestfs_launch> to wait for the launch
468 to complete.  However this is no longer necessary because
469 C<guestfs_launch> now does the waiting.
470
471 If you see any calls to this function in code then you can just
472 remove them, unless you want to retain compatibility with older
473 versions of the API.");
474
475   ("kill_subprocess", (RErr, []), -1, [],
476    [],
477    "kill the qemu subprocess",
478    "\
479 This kills the qemu subprocess.  You should never need to call this.");
480
481   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
482    [],
483    "add an image to examine or modify",
484    "\
485 This function adds a virtual machine disk image C<filename> to the
486 guest.  The first time you call this function, the disk appears as IDE
487 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
488 so on.
489
490 You don't necessarily need to be root when using libguestfs.  However
491 you obviously do need sufficient permissions to access the filename
492 for whatever operations you want to perform (ie. read access if you
493 just want to read the image or write access if you want to modify the
494 image).
495
496 This is equivalent to the qemu parameter
497 C<-drive file=filename,cache=off,if=...>.
498
499 C<cache=off> is omitted in cases where it is not supported by
500 the underlying filesystem.
501
502 C<if=...> is set at compile time by the configuration option
503 C<./configure --with-drive-if=...>.  In the rare case where you
504 might need to change this at run time, use C<guestfs_add_drive_with_if>
505 or C<guestfs_add_drive_ro_with_if>.
506
507 Note that this call checks for the existence of C<filename>.  This
508 stops you from specifying other types of drive which are supported
509 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
510 the general C<guestfs_config> call instead.");
511
512   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
513    [],
514    "add a CD-ROM disk image to examine",
515    "\
516 This function adds a virtual CD-ROM disk image to the guest.
517
518 This is equivalent to the qemu parameter C<-cdrom filename>.
519
520 Notes:
521
522 =over 4
523
524 =item *
525
526 This call checks for the existence of C<filename>.  This
527 stops you from specifying other types of drive which are supported
528 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
529 the general C<guestfs_config> call instead.
530
531 =item *
532
533 If you just want to add an ISO file (often you use this as an
534 efficient way to transfer large files into the guest), then you
535 should probably use C<guestfs_add_drive_ro> instead.
536
537 =back");
538
539   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
540    [],
541    "add a drive in snapshot mode (read-only)",
542    "\
543 This adds a drive in snapshot mode, making it effectively
544 read-only.
545
546 Note that writes to the device are allowed, and will be seen for
547 the duration of the guestfs handle, but they are written
548 to a temporary file which is discarded as soon as the guestfs
549 handle is closed.  We don't currently have any method to enable
550 changes to be committed, although qemu can support this.
551
552 This is equivalent to the qemu parameter
553 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
554
555 C<if=...> is set at compile time by the configuration option
556 C<./configure --with-drive-if=...>.  In the rare case where you
557 might need to change this at run time, use C<guestfs_add_drive_with_if>
558 or C<guestfs_add_drive_ro_with_if>.
559
560 C<readonly=on> is only added where qemu supports this option.
561
562 Note that this call checks for the existence of C<filename>.  This
563 stops you from specifying other types of drive which are supported
564 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
565 the general C<guestfs_config> call instead.");
566
567   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
568    [],
569    "add qemu parameters",
570    "\
571 This can be used to add arbitrary qemu command line parameters
572 of the form C<-param value>.  Actually it's not quite arbitrary - we
573 prevent you from setting some parameters which would interfere with
574 parameters that we use.
575
576 The first character of C<param> string must be a C<-> (dash).
577
578 C<value> can be NULL.");
579
580   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
581    [],
582    "set the qemu binary",
583    "\
584 Set the qemu binary that we will use.
585
586 The default is chosen when the library was compiled by the
587 configure script.
588
589 You can also override this by setting the C<LIBGUESTFS_QEMU>
590 environment variable.
591
592 Setting C<qemu> to C<NULL> restores the default qemu binary.
593
594 Note that you should call this function as early as possible
595 after creating the handle.  This is because some pre-launch
596 operations depend on testing qemu features (by running C<qemu -help>).
597 If the qemu binary changes, we don't retest features, and
598 so you might see inconsistent results.  Using the environment
599 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
600 the qemu binary at the same time as the handle is created.");
601
602   ("get_qemu", (RConstString "qemu", []), -1, [],
603    [InitNone, Always, TestRun (
604       [["get_qemu"]])],
605    "get the qemu binary",
606    "\
607 Return the current qemu binary.
608
609 This is always non-NULL.  If it wasn't set already, then this will
610 return the default qemu binary name.");
611
612   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
613    [],
614    "set the search path",
615    "\
616 Set the path that libguestfs searches for kernel and initrd.img.
617
618 The default is C<$libdir/guestfs> unless overridden by setting
619 C<LIBGUESTFS_PATH> environment variable.
620
621 Setting C<path> to C<NULL> restores the default path.");
622
623   ("get_path", (RConstString "path", []), -1, [],
624    [InitNone, Always, TestRun (
625       [["get_path"]])],
626    "get the search path",
627    "\
628 Return the current search path.
629
630 This is always non-NULL.  If it wasn't set already, then this will
631 return the default path.");
632
633   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
634    [],
635    "add options to kernel command line",
636    "\
637 This function is used to add additional options to the
638 guest kernel command line.
639
640 The default is C<NULL> unless overridden by setting
641 C<LIBGUESTFS_APPEND> environment variable.
642
643 Setting C<append> to C<NULL> means I<no> additional options
644 are passed (libguestfs always adds a few of its own).");
645
646   ("get_append", (RConstOptString "append", []), -1, [],
647    (* This cannot be tested with the current framework.  The
648     * function can return NULL in normal operations, which the
649     * test framework interprets as an error.
650     *)
651    [],
652    "get the additional kernel options",
653    "\
654 Return the additional kernel options which are added to the
655 guest kernel command line.
656
657 If C<NULL> then no options are added.");
658
659   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
660    [],
661    "set autosync mode",
662    "\
663 If C<autosync> is true, this enables autosync.  Libguestfs will make a
664 best effort attempt to run C<guestfs_umount_all> followed by
665 C<guestfs_sync> when the handle is closed
666 (also if the program exits without closing handles).
667
668 This is disabled by default (except in guestfish where it is
669 enabled by default).");
670
671   ("get_autosync", (RBool "autosync", []), -1, [],
672    [InitNone, Always, TestRun (
673       [["get_autosync"]])],
674    "get autosync mode",
675    "\
676 Get the autosync flag.");
677
678   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
679    [],
680    "set verbose mode",
681    "\
682 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
683
684 Verbose messages are disabled unless the environment variable
685 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
686
687   ("get_verbose", (RBool "verbose", []), -1, [],
688    [],
689    "get verbose mode",
690    "\
691 This returns the verbose messages flag.");
692
693   ("is_ready", (RBool "ready", []), -1, [],
694    [InitNone, Always, TestOutputTrue (
695       [["is_ready"]])],
696    "is ready to accept commands",
697    "\
698 This returns true iff this handle is ready to accept commands
699 (in the C<READY> state).
700
701 For more information on states, see L<guestfs(3)>.");
702
703   ("is_config", (RBool "config", []), -1, [],
704    [InitNone, Always, TestOutputFalse (
705       [["is_config"]])],
706    "is in configuration state",
707    "\
708 This returns true iff this handle is being configured
709 (in the C<CONFIG> state).
710
711 For more information on states, see L<guestfs(3)>.");
712
713   ("is_launching", (RBool "launching", []), -1, [],
714    [InitNone, Always, TestOutputFalse (
715       [["is_launching"]])],
716    "is launching subprocess",
717    "\
718 This returns true iff this handle is launching the subprocess
719 (in the C<LAUNCHING> state).
720
721 For more information on states, see L<guestfs(3)>.");
722
723   ("is_busy", (RBool "busy", []), -1, [],
724    [InitNone, Always, TestOutputFalse (
725       [["is_busy"]])],
726    "is busy processing a command",
727    "\
728 This returns true iff this handle is busy processing a command
729 (in the C<BUSY> state).
730
731 For more information on states, see L<guestfs(3)>.");
732
733   ("get_state", (RInt "state", []), -1, [],
734    [],
735    "get the current state",
736    "\
737 This returns the current state as an opaque integer.  This is
738 only useful for printing debug and internal error messages.
739
740 For more information on states, see L<guestfs(3)>.");
741
742   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
743    [InitNone, Always, TestOutputInt (
744       [["set_memsize"; "500"];
745        ["get_memsize"]], 500)],
746    "set memory allocated to the qemu subprocess",
747    "\
748 This sets the memory size in megabytes allocated to the
749 qemu subprocess.  This only has any effect if called before
750 C<guestfs_launch>.
751
752 You can also change this by setting the environment
753 variable C<LIBGUESTFS_MEMSIZE> before the handle is
754 created.
755
756 For more information on the architecture of libguestfs,
757 see L<guestfs(3)>.");
758
759   ("get_memsize", (RInt "memsize", []), -1, [],
760    [InitNone, Always, TestOutputIntOp (
761       [["get_memsize"]], ">=", 256)],
762    "get memory allocated to the qemu subprocess",
763    "\
764 This gets the memory size in megabytes allocated to the
765 qemu subprocess.
766
767 If C<guestfs_set_memsize> was not called
768 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
769 then this returns the compiled-in default value for memsize.
770
771 For more information on the architecture of libguestfs,
772 see L<guestfs(3)>.");
773
774   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
775    [InitNone, Always, TestOutputIntOp (
776       [["get_pid"]], ">=", 1)],
777    "get PID of qemu subprocess",
778    "\
779 Return the process ID of the qemu subprocess.  If there is no
780 qemu subprocess, then this will return an error.
781
782 This is an internal call used for debugging and testing.");
783
784   ("version", (RStruct ("version", "version"), []), -1, [],
785    [InitNone, Always, TestOutputStruct (
786       [["version"]], [CompareWithInt ("major", 1)])],
787    "get the library version number",
788    "\
789 Return the libguestfs version number that the program is linked
790 against.
791
792 Note that because of dynamic linking this is not necessarily
793 the version of libguestfs that you compiled against.  You can
794 compile the program, and then at runtime dynamically link
795 against a completely different C<libguestfs.so> library.
796
797 This call was added in version C<1.0.58>.  In previous
798 versions of libguestfs there was no way to get the version
799 number.  From C code you can use ELF weak linking tricks to find out if
800 this symbol exists (if it doesn't, then it's an earlier version).
801
802 The call returns a structure with four elements.  The first
803 three (C<major>, C<minor> and C<release>) are numbers and
804 correspond to the usual version triplet.  The fourth element
805 (C<extra>) is a string and is normally empty, but may be
806 used for distro-specific information.
807
808 To construct the original version string:
809 C<$major.$minor.$release$extra>
810
811 I<Note:> Don't use this call to test for availability
812 of features.  Distro backports makes this unreliable.  Use
813 C<guestfs_available> instead.");
814
815   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
816    [InitNone, Always, TestOutputTrue (
817       [["set_selinux"; "true"];
818        ["get_selinux"]])],
819    "set SELinux enabled or disabled at appliance boot",
820    "\
821 This sets the selinux flag that is passed to the appliance
822 at boot time.  The default is C<selinux=0> (disabled).
823
824 Note that if SELinux is enabled, it is always in
825 Permissive mode (C<enforcing=0>).
826
827 For more information on the architecture of libguestfs,
828 see L<guestfs(3)>.");
829
830   ("get_selinux", (RBool "selinux", []), -1, [],
831    [],
832    "get SELinux enabled flag",
833    "\
834 This returns the current setting of the selinux flag which
835 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
836
837 For more information on the architecture of libguestfs,
838 see L<guestfs(3)>.");
839
840   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
841    [InitNone, Always, TestOutputFalse (
842       [["set_trace"; "false"];
843        ["get_trace"]])],
844    "enable or disable command traces",
845    "\
846 If the command trace flag is set to 1, then commands are
847 printed on stdout before they are executed in a format
848 which is very similar to the one used by guestfish.  In
849 other words, you can run a program with this enabled, and
850 you will get out a script which you can feed to guestfish
851 to perform the same set of actions.
852
853 If you want to trace C API calls into libguestfs (and
854 other libraries) then possibly a better way is to use
855 the external ltrace(1) command.
856
857 Command traces are disabled unless the environment variable
858 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
859
860   ("get_trace", (RBool "trace", []), -1, [],
861    [],
862    "get command trace enabled flag",
863    "\
864 Return the command trace flag.");
865
866   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
867    [InitNone, Always, TestOutputFalse (
868       [["set_direct"; "false"];
869        ["get_direct"]])],
870    "enable or disable direct appliance mode",
871    "\
872 If the direct appliance mode flag is enabled, then stdin and
873 stdout are passed directly through to the appliance once it
874 is launched.
875
876 One consequence of this is that log messages aren't caught
877 by the library and handled by C<guestfs_set_log_message_callback>,
878 but go straight to stdout.
879
880 You probably don't want to use this unless you know what you
881 are doing.
882
883 The default is disabled.");
884
885   ("get_direct", (RBool "direct", []), -1, [],
886    [],
887    "get direct appliance mode flag",
888    "\
889 Return the direct appliance mode flag.");
890
891   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
892    [InitNone, Always, TestOutputTrue (
893       [["set_recovery_proc"; "true"];
894        ["get_recovery_proc"]])],
895    "enable or disable the recovery process",
896    "\
897 If this is called with the parameter C<false> then
898 C<guestfs_launch> does not create a recovery process.  The
899 purpose of the recovery process is to stop runaway qemu
900 processes in the case where the main program aborts abruptly.
901
902 This only has any effect if called before C<guestfs_launch>,
903 and the default is true.
904
905 About the only time when you would want to disable this is
906 if the main process will fork itself into the background
907 (\"daemonize\" itself).  In this case the recovery process
908 thinks that the main program has disappeared and so kills
909 qemu, which is not very helpful.");
910
911   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
912    [],
913    "get recovery process enabled flag",
914    "\
915 Return the recovery process enabled flag.");
916
917   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
918    [],
919    "add a drive specifying the QEMU block emulation to use",
920    "\
921 This is the same as C<guestfs_add_drive> but it allows you
922 to specify the QEMU interface emulation to use at run time.");
923
924   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
925    [],
926    "add a drive read-only specifying the QEMU block emulation to use",
927    "\
928 This is the same as C<guestfs_add_drive_ro> but it allows you
929 to specify the QEMU interface emulation to use at run time.");
930
931 ]
932
933 (* daemon_functions are any functions which cause some action
934  * to take place in the daemon.
935  *)
936
937 let daemon_functions = [
938   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
939    [InitEmpty, Always, TestOutput (
940       [["part_disk"; "/dev/sda"; "mbr"];
941        ["mkfs"; "ext2"; "/dev/sda1"];
942        ["mount"; "/dev/sda1"; "/"];
943        ["write_file"; "/new"; "new file contents"; "0"];
944        ["cat"; "/new"]], "new file contents")],
945    "mount a guest disk at a position in the filesystem",
946    "\
947 Mount a guest disk at a position in the filesystem.  Block devices
948 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
949 the guest.  If those block devices contain partitions, they will have
950 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
951 names can be used.
952
953 The rules are the same as for L<mount(2)>:  A filesystem must
954 first be mounted on C</> before others can be mounted.  Other
955 filesystems can only be mounted on directories which already
956 exist.
957
958 The mounted filesystem is writable, if we have sufficient permissions
959 on the underlying device.
960
961 B<Important note:>
962 When you use this call, the filesystem options C<sync> and C<noatime>
963 are set implicitly.  This was originally done because we thought it
964 would improve reliability, but it turns out that I<-o sync> has a
965 very large negative performance impact and negligible effect on
966 reliability.  Therefore we recommend that you avoid using
967 C<guestfs_mount> in any code that needs performance, and instead
968 use C<guestfs_mount_options> (use an empty string for the first
969 parameter if you don't want any options).");
970
971   ("sync", (RErr, []), 2, [],
972    [ InitEmpty, Always, TestRun [["sync"]]],
973    "sync disks, writes are flushed through to the disk image",
974    "\
975 This syncs the disk, so that any writes are flushed through to the
976 underlying disk image.
977
978 You should always call this if you have modified a disk image, before
979 closing the handle.");
980
981   ("touch", (RErr, [Pathname "path"]), 3, [],
982    [InitBasicFS, Always, TestOutputTrue (
983       [["touch"; "/new"];
984        ["exists"; "/new"]])],
985    "update file timestamps or create a new file",
986    "\
987 Touch acts like the L<touch(1)> command.  It can be used to
988 update the timestamps on a file, or, if the file does not exist,
989 to create a new zero-length file.");
990
991   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
992    [InitISOFS, Always, TestOutput (
993       [["cat"; "/known-2"]], "abcdef\n")],
994    "list the contents of a file",
995    "\
996 Return the contents of the file named C<path>.
997
998 Note that this function cannot correctly handle binary files
999 (specifically, files containing C<\\0> character which is treated
1000 as end of string).  For those you need to use the C<guestfs_read_file>
1001 or C<guestfs_download> functions which have a more complex interface.");
1002
1003   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1004    [], (* XXX Tricky to test because it depends on the exact format
1005         * of the 'ls -l' command, which changes between F10 and F11.
1006         *)
1007    "list the files in a directory (long format)",
1008    "\
1009 List the files in C<directory> (relative to the root directory,
1010 there is no cwd) in the format of 'ls -la'.
1011
1012 This command is mostly useful for interactive sessions.  It
1013 is I<not> intended that you try to parse the output string.");
1014
1015   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1016    [InitBasicFS, Always, TestOutputList (
1017       [["touch"; "/new"];
1018        ["touch"; "/newer"];
1019        ["touch"; "/newest"];
1020        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1021    "list the files in a directory",
1022    "\
1023 List the files in C<directory> (relative to the root directory,
1024 there is no cwd).  The '.' and '..' entries are not returned, but
1025 hidden files are shown.
1026
1027 This command is mostly useful for interactive sessions.  Programs
1028 should probably use C<guestfs_readdir> instead.");
1029
1030   ("list_devices", (RStringList "devices", []), 7, [],
1031    [InitEmpty, Always, TestOutputListOfDevices (
1032       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1033    "list the block devices",
1034    "\
1035 List all the block devices.
1036
1037 The full block device names are returned, eg. C</dev/sda>");
1038
1039   ("list_partitions", (RStringList "partitions", []), 8, [],
1040    [InitBasicFS, Always, TestOutputListOfDevices (
1041       [["list_partitions"]], ["/dev/sda1"]);
1042     InitEmpty, Always, TestOutputListOfDevices (
1043       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1044        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1045    "list the partitions",
1046    "\
1047 List all the partitions detected on all block devices.
1048
1049 The full partition device names are returned, eg. C</dev/sda1>
1050
1051 This does not return logical volumes.  For that you will need to
1052 call C<guestfs_lvs>.");
1053
1054   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1055    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1056       [["pvs"]], ["/dev/sda1"]);
1057     InitEmpty, Always, TestOutputListOfDevices (
1058       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1059        ["pvcreate"; "/dev/sda1"];
1060        ["pvcreate"; "/dev/sda2"];
1061        ["pvcreate"; "/dev/sda3"];
1062        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1063    "list the LVM physical volumes (PVs)",
1064    "\
1065 List all the physical volumes detected.  This is the equivalent
1066 of the L<pvs(8)> command.
1067
1068 This returns a list of just the device names that contain
1069 PVs (eg. C</dev/sda2>).
1070
1071 See also C<guestfs_pvs_full>.");
1072
1073   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1074    [InitBasicFSonLVM, Always, TestOutputList (
1075       [["vgs"]], ["VG"]);
1076     InitEmpty, Always, TestOutputList (
1077       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1078        ["pvcreate"; "/dev/sda1"];
1079        ["pvcreate"; "/dev/sda2"];
1080        ["pvcreate"; "/dev/sda3"];
1081        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1082        ["vgcreate"; "VG2"; "/dev/sda3"];
1083        ["vgs"]], ["VG1"; "VG2"])],
1084    "list the LVM volume groups (VGs)",
1085    "\
1086 List all the volumes groups detected.  This is the equivalent
1087 of the L<vgs(8)> command.
1088
1089 This returns a list of just the volume group names that were
1090 detected (eg. C<VolGroup00>).
1091
1092 See also C<guestfs_vgs_full>.");
1093
1094   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1095    [InitBasicFSonLVM, Always, TestOutputList (
1096       [["lvs"]], ["/dev/VG/LV"]);
1097     InitEmpty, Always, TestOutputList (
1098       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1099        ["pvcreate"; "/dev/sda1"];
1100        ["pvcreate"; "/dev/sda2"];
1101        ["pvcreate"; "/dev/sda3"];
1102        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1103        ["vgcreate"; "VG2"; "/dev/sda3"];
1104        ["lvcreate"; "LV1"; "VG1"; "50"];
1105        ["lvcreate"; "LV2"; "VG1"; "50"];
1106        ["lvcreate"; "LV3"; "VG2"; "50"];
1107        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1108    "list the LVM logical volumes (LVs)",
1109    "\
1110 List all the logical volumes detected.  This is the equivalent
1111 of the L<lvs(8)> command.
1112
1113 This returns a list of the logical volume device names
1114 (eg. C</dev/VolGroup00/LogVol00>).
1115
1116 See also C<guestfs_lvs_full>.");
1117
1118   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1119    [], (* XXX how to test? *)
1120    "list the LVM physical volumes (PVs)",
1121    "\
1122 List all the physical volumes detected.  This is the equivalent
1123 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1124
1125   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM volume groups (VGs)",
1128    "\
1129 List all the volumes groups detected.  This is the equivalent
1130 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1133    [], (* XXX how to test? *)
1134    "list the LVM logical volumes (LVs)",
1135    "\
1136 List all the logical volumes detected.  This is the equivalent
1137 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1138
1139   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1140    [InitISOFS, Always, TestOutputList (
1141       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1142     InitISOFS, Always, TestOutputList (
1143       [["read_lines"; "/empty"]], [])],
1144    "read file as lines",
1145    "\
1146 Return the contents of the file named C<path>.
1147
1148 The file contents are returned as a list of lines.  Trailing
1149 C<LF> and C<CRLF> character sequences are I<not> returned.
1150
1151 Note that this function cannot correctly handle binary files
1152 (specifically, files containing C<\\0> character which is treated
1153 as end of line).  For those you need to use the C<guestfs_read_file>
1154 function which has a more complex interface.");
1155
1156   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1157    [], (* XXX Augeas code needs tests. *)
1158    "create a new Augeas handle",
1159    "\
1160 Create a new Augeas handle for editing configuration files.
1161 If there was any previous Augeas handle associated with this
1162 guestfs session, then it is closed.
1163
1164 You must call this before using any other C<guestfs_aug_*>
1165 commands.
1166
1167 C<root> is the filesystem root.  C<root> must not be NULL,
1168 use C</> instead.
1169
1170 The flags are the same as the flags defined in
1171 E<lt>augeas.hE<gt>, the logical I<or> of the following
1172 integers:
1173
1174 =over 4
1175
1176 =item C<AUG_SAVE_BACKUP> = 1
1177
1178 Keep the original file with a C<.augsave> extension.
1179
1180 =item C<AUG_SAVE_NEWFILE> = 2
1181
1182 Save changes into a file with extension C<.augnew>, and
1183 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1184
1185 =item C<AUG_TYPE_CHECK> = 4
1186
1187 Typecheck lenses (can be expensive).
1188
1189 =item C<AUG_NO_STDINC> = 8
1190
1191 Do not use standard load path for modules.
1192
1193 =item C<AUG_SAVE_NOOP> = 16
1194
1195 Make save a no-op, just record what would have been changed.
1196
1197 =item C<AUG_NO_LOAD> = 32
1198
1199 Do not load the tree in C<guestfs_aug_init>.
1200
1201 =back
1202
1203 To close the handle, you can call C<guestfs_aug_close>.
1204
1205 To find out more about Augeas, see L<http://augeas.net/>.");
1206
1207   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1208    [], (* XXX Augeas code needs tests. *)
1209    "close the current Augeas handle",
1210    "\
1211 Close the current Augeas handle and free up any resources
1212 used by it.  After calling this, you have to call
1213 C<guestfs_aug_init> again before you can use any other
1214 Augeas functions.");
1215
1216   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1217    [], (* XXX Augeas code needs tests. *)
1218    "define an Augeas variable",
1219    "\
1220 Defines an Augeas variable C<name> whose value is the result
1221 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1222 undefined.
1223
1224 On success this returns the number of nodes in C<expr>, or
1225 C<0> if C<expr> evaluates to something which is not a nodeset.");
1226
1227   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1228    [], (* XXX Augeas code needs tests. *)
1229    "define an Augeas node",
1230    "\
1231 Defines a variable C<name> whose value is the result of
1232 evaluating C<expr>.
1233
1234 If C<expr> evaluates to an empty nodeset, a node is created,
1235 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1236 C<name> will be the nodeset containing that single node.
1237
1238 On success this returns a pair containing the
1239 number of nodes in the nodeset, and a boolean flag
1240 if a node was created.");
1241
1242   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "look up the value of an Augeas path",
1245    "\
1246 Look up the value associated with C<path>.  If C<path>
1247 matches exactly one node, the C<value> is returned.");
1248
1249   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1250    [], (* XXX Augeas code needs tests. *)
1251    "set Augeas path to value",
1252    "\
1253 Set the value associated with C<path> to C<val>.
1254
1255 In the Augeas API, it is possible to clear a node by setting
1256 the value to NULL.  Due to an oversight in the libguestfs API
1257 you cannot do that with this call.  Instead you must use the
1258 C<guestfs_aug_clear> call.");
1259
1260   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1261    [], (* XXX Augeas code needs tests. *)
1262    "insert a sibling Augeas node",
1263    "\
1264 Create a new sibling C<label> for C<path>, inserting it into
1265 the tree before or after C<path> (depending on the boolean
1266 flag C<before>).
1267
1268 C<path> must match exactly one existing node in the tree, and
1269 C<label> must be a label, ie. not contain C</>, C<*> or end
1270 with a bracketed index C<[N]>.");
1271
1272   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1273    [], (* XXX Augeas code needs tests. *)
1274    "remove an Augeas path",
1275    "\
1276 Remove C<path> and all of its children.
1277
1278 On success this returns the number of entries which were removed.");
1279
1280   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1281    [], (* XXX Augeas code needs tests. *)
1282    "move Augeas node",
1283    "\
1284 Move the node C<src> to C<dest>.  C<src> must match exactly
1285 one node.  C<dest> is overwritten if it exists.");
1286
1287   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "return Augeas nodes which match augpath",
1290    "\
1291 Returns a list of paths which match the path expression C<path>.
1292 The returned paths are sufficiently qualified so that they match
1293 exactly one node in the current tree.");
1294
1295   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1296    [], (* XXX Augeas code needs tests. *)
1297    "write all pending Augeas changes to disk",
1298    "\
1299 This writes all pending changes to disk.
1300
1301 The flags which were passed to C<guestfs_aug_init> affect exactly
1302 how files are saved.");
1303
1304   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1305    [], (* XXX Augeas code needs tests. *)
1306    "load files into the tree",
1307    "\
1308 Load files into the tree.
1309
1310 See C<aug_load> in the Augeas documentation for the full gory
1311 details.");
1312
1313   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1314    [], (* XXX Augeas code needs tests. *)
1315    "list Augeas nodes under augpath",
1316    "\
1317 This is just a shortcut for listing C<guestfs_aug_match>
1318 C<path/*> and sorting the resulting nodes into alphabetical order.");
1319
1320   ("rm", (RErr, [Pathname "path"]), 29, [],
1321    [InitBasicFS, Always, TestRun
1322       [["touch"; "/new"];
1323        ["rm"; "/new"]];
1324     InitBasicFS, Always, TestLastFail
1325       [["rm"; "/new"]];
1326     InitBasicFS, Always, TestLastFail
1327       [["mkdir"; "/new"];
1328        ["rm"; "/new"]]],
1329    "remove a file",
1330    "\
1331 Remove the single file C<path>.");
1332
1333   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1334    [InitBasicFS, Always, TestRun
1335       [["mkdir"; "/new"];
1336        ["rmdir"; "/new"]];
1337     InitBasicFS, Always, TestLastFail
1338       [["rmdir"; "/new"]];
1339     InitBasicFS, Always, TestLastFail
1340       [["touch"; "/new"];
1341        ["rmdir"; "/new"]]],
1342    "remove a directory",
1343    "\
1344 Remove the single directory C<path>.");
1345
1346   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1347    [InitBasicFS, Always, TestOutputFalse
1348       [["mkdir"; "/new"];
1349        ["mkdir"; "/new/foo"];
1350        ["touch"; "/new/foo/bar"];
1351        ["rm_rf"; "/new"];
1352        ["exists"; "/new"]]],
1353    "remove a file or directory recursively",
1354    "\
1355 Remove the file or directory C<path>, recursively removing the
1356 contents if its a directory.  This is like the C<rm -rf> shell
1357 command.");
1358
1359   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1360    [InitBasicFS, Always, TestOutputTrue
1361       [["mkdir"; "/new"];
1362        ["is_dir"; "/new"]];
1363     InitBasicFS, Always, TestLastFail
1364       [["mkdir"; "/new/foo/bar"]]],
1365    "create a directory",
1366    "\
1367 Create a directory named C<path>.");
1368
1369   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1370    [InitBasicFS, Always, TestOutputTrue
1371       [["mkdir_p"; "/new/foo/bar"];
1372        ["is_dir"; "/new/foo/bar"]];
1373     InitBasicFS, Always, TestOutputTrue
1374       [["mkdir_p"; "/new/foo/bar"];
1375        ["is_dir"; "/new/foo"]];
1376     InitBasicFS, Always, TestOutputTrue
1377       [["mkdir_p"; "/new/foo/bar"];
1378        ["is_dir"; "/new"]];
1379     (* Regression tests for RHBZ#503133: *)
1380     InitBasicFS, Always, TestRun
1381       [["mkdir"; "/new"];
1382        ["mkdir_p"; "/new"]];
1383     InitBasicFS, Always, TestLastFail
1384       [["touch"; "/new"];
1385        ["mkdir_p"; "/new"]]],
1386    "create a directory and parents",
1387    "\
1388 Create a directory named C<path>, creating any parent directories
1389 as necessary.  This is like the C<mkdir -p> shell command.");
1390
1391   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1392    [], (* XXX Need stat command to test *)
1393    "change file mode",
1394    "\
1395 Change the mode (permissions) of C<path> to C<mode>.  Only
1396 numeric modes are supported.
1397
1398 I<Note>: When using this command from guestfish, C<mode>
1399 by default would be decimal, unless you prefix it with
1400 C<0> to get octal, ie. use C<0700> not C<700>.
1401
1402 The mode actually set is affected by the umask.");
1403
1404   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1405    [], (* XXX Need stat command to test *)
1406    "change file owner and group",
1407    "\
1408 Change the file owner to C<owner> and group to C<group>.
1409
1410 Only numeric uid and gid are supported.  If you want to use
1411 names, you will need to locate and parse the password file
1412 yourself (Augeas support makes this relatively easy).");
1413
1414   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1415    [InitISOFS, Always, TestOutputTrue (
1416       [["exists"; "/empty"]]);
1417     InitISOFS, Always, TestOutputTrue (
1418       [["exists"; "/directory"]])],
1419    "test if file or directory exists",
1420    "\
1421 This returns C<true> if and only if there is a file, directory
1422 (or anything) with the given C<path> name.
1423
1424 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1425
1426   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1427    [InitISOFS, Always, TestOutputTrue (
1428       [["is_file"; "/known-1"]]);
1429     InitISOFS, Always, TestOutputFalse (
1430       [["is_file"; "/directory"]])],
1431    "test if file exists",
1432    "\
1433 This returns C<true> if and only if there is a file
1434 with the given C<path> name.  Note that it returns false for
1435 other objects like directories.
1436
1437 See also C<guestfs_stat>.");
1438
1439   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1440    [InitISOFS, Always, TestOutputFalse (
1441       [["is_dir"; "/known-3"]]);
1442     InitISOFS, Always, TestOutputTrue (
1443       [["is_dir"; "/directory"]])],
1444    "test if file exists",
1445    "\
1446 This returns C<true> if and only if there is a directory
1447 with the given C<path> name.  Note that it returns false for
1448 other objects like files.
1449
1450 See also C<guestfs_stat>.");
1451
1452   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1453    [InitEmpty, Always, TestOutputListOfDevices (
1454       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1455        ["pvcreate"; "/dev/sda1"];
1456        ["pvcreate"; "/dev/sda2"];
1457        ["pvcreate"; "/dev/sda3"];
1458        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1459    "create an LVM physical volume",
1460    "\
1461 This creates an LVM physical volume on the named C<device>,
1462 where C<device> should usually be a partition name such
1463 as C</dev/sda1>.");
1464
1465   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1466    [InitEmpty, Always, TestOutputList (
1467       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1468        ["pvcreate"; "/dev/sda1"];
1469        ["pvcreate"; "/dev/sda2"];
1470        ["pvcreate"; "/dev/sda3"];
1471        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1472        ["vgcreate"; "VG2"; "/dev/sda3"];
1473        ["vgs"]], ["VG1"; "VG2"])],
1474    "create an LVM volume group",
1475    "\
1476 This creates an LVM volume group called C<volgroup>
1477 from the non-empty list of physical volumes C<physvols>.");
1478
1479   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1480    [InitEmpty, Always, TestOutputList (
1481       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1482        ["pvcreate"; "/dev/sda1"];
1483        ["pvcreate"; "/dev/sda2"];
1484        ["pvcreate"; "/dev/sda3"];
1485        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1486        ["vgcreate"; "VG2"; "/dev/sda3"];
1487        ["lvcreate"; "LV1"; "VG1"; "50"];
1488        ["lvcreate"; "LV2"; "VG1"; "50"];
1489        ["lvcreate"; "LV3"; "VG2"; "50"];
1490        ["lvcreate"; "LV4"; "VG2"; "50"];
1491        ["lvcreate"; "LV5"; "VG2"; "50"];
1492        ["lvs"]],
1493       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1494        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1495    "create an LVM logical volume",
1496    "\
1497 This creates an LVM logical volume called C<logvol>
1498 on the volume group C<volgroup>, with C<size> megabytes.");
1499
1500   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1501    [InitEmpty, Always, TestOutput (
1502       [["part_disk"; "/dev/sda"; "mbr"];
1503        ["mkfs"; "ext2"; "/dev/sda1"];
1504        ["mount_options"; ""; "/dev/sda1"; "/"];
1505        ["write_file"; "/new"; "new file contents"; "0"];
1506        ["cat"; "/new"]], "new file contents")],
1507    "make a filesystem",
1508    "\
1509 This creates a filesystem on C<device> (usually a partition
1510 or LVM logical volume).  The filesystem type is C<fstype>, for
1511 example C<ext3>.");
1512
1513   ("sfdisk", (RErr, [Device "device";
1514                      Int "cyls"; Int "heads"; Int "sectors";
1515                      StringList "lines"]), 43, [DangerWillRobinson],
1516    [],
1517    "create partitions on a block device",
1518    "\
1519 This is a direct interface to the L<sfdisk(8)> program for creating
1520 partitions on block devices.
1521
1522 C<device> should be a block device, for example C</dev/sda>.
1523
1524 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1525 and sectors on the device, which are passed directly to sfdisk as
1526 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1527 of these, then the corresponding parameter is omitted.  Usually for
1528 'large' disks, you can just pass C<0> for these, but for small
1529 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1530 out the right geometry and you will need to tell it.
1531
1532 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1533 information refer to the L<sfdisk(8)> manpage.
1534
1535 To create a single partition occupying the whole disk, you would
1536 pass C<lines> as a single element list, when the single element being
1537 the string C<,> (comma).
1538
1539 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1540 C<guestfs_part_init>");
1541
1542   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1543    [InitBasicFS, Always, TestOutput (
1544       [["write_file"; "/new"; "new file contents"; "0"];
1545        ["cat"; "/new"]], "new file contents");
1546     InitBasicFS, Always, TestOutput (
1547       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1548        ["cat"; "/new"]], "\nnew file contents\n");
1549     InitBasicFS, Always, TestOutput (
1550       [["write_file"; "/new"; "\n\n"; "0"];
1551        ["cat"; "/new"]], "\n\n");
1552     InitBasicFS, Always, TestOutput (
1553       [["write_file"; "/new"; ""; "0"];
1554        ["cat"; "/new"]], "");
1555     InitBasicFS, Always, TestOutput (
1556       [["write_file"; "/new"; "\n\n\n"; "0"];
1557        ["cat"; "/new"]], "\n\n\n");
1558     InitBasicFS, Always, TestOutput (
1559       [["write_file"; "/new"; "\n"; "0"];
1560        ["cat"; "/new"]], "\n")],
1561    "create a file",
1562    "\
1563 This call creates a file called C<path>.  The contents of the
1564 file is the string C<content> (which can contain any 8 bit data),
1565 with length C<size>.
1566
1567 As a special case, if C<size> is C<0>
1568 then the length is calculated using C<strlen> (so in this case
1569 the content cannot contain embedded ASCII NULs).
1570
1571 I<NB.> Owing to a bug, writing content containing ASCII NUL
1572 characters does I<not> work, even if the length is specified.
1573 We hope to resolve this bug in a future version.  In the meantime
1574 use C<guestfs_upload>.");
1575
1576   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1577    [InitEmpty, Always, TestOutputListOfDevices (
1578       [["part_disk"; "/dev/sda"; "mbr"];
1579        ["mkfs"; "ext2"; "/dev/sda1"];
1580        ["mount_options"; ""; "/dev/sda1"; "/"];
1581        ["mounts"]], ["/dev/sda1"]);
1582     InitEmpty, Always, TestOutputList (
1583       [["part_disk"; "/dev/sda"; "mbr"];
1584        ["mkfs"; "ext2"; "/dev/sda1"];
1585        ["mount_options"; ""; "/dev/sda1"; "/"];
1586        ["umount"; "/"];
1587        ["mounts"]], [])],
1588    "unmount a filesystem",
1589    "\
1590 This unmounts the given filesystem.  The filesystem may be
1591 specified either by its mountpoint (path) or the device which
1592 contains the filesystem.");
1593
1594   ("mounts", (RStringList "devices", []), 46, [],
1595    [InitBasicFS, Always, TestOutputListOfDevices (
1596       [["mounts"]], ["/dev/sda1"])],
1597    "show mounted filesystems",
1598    "\
1599 This returns the list of currently mounted filesystems.  It returns
1600 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1601
1602 Some internal mounts are not shown.
1603
1604 See also: C<guestfs_mountpoints>");
1605
1606   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1607    [InitBasicFS, Always, TestOutputList (
1608       [["umount_all"];
1609        ["mounts"]], []);
1610     (* check that umount_all can unmount nested mounts correctly: *)
1611     InitEmpty, Always, TestOutputList (
1612       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1613        ["mkfs"; "ext2"; "/dev/sda1"];
1614        ["mkfs"; "ext2"; "/dev/sda2"];
1615        ["mkfs"; "ext2"; "/dev/sda3"];
1616        ["mount_options"; ""; "/dev/sda1"; "/"];
1617        ["mkdir"; "/mp1"];
1618        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1619        ["mkdir"; "/mp1/mp2"];
1620        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1621        ["mkdir"; "/mp1/mp2/mp3"];
1622        ["umount_all"];
1623        ["mounts"]], [])],
1624    "unmount all filesystems",
1625    "\
1626 This unmounts all mounted filesystems.
1627
1628 Some internal mounts are not unmounted by this call.");
1629
1630   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1631    [],
1632    "remove all LVM LVs, VGs and PVs",
1633    "\
1634 This command removes all LVM logical volumes, volume groups
1635 and physical volumes.");
1636
1637   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1638    [InitISOFS, Always, TestOutput (
1639       [["file"; "/empty"]], "empty");
1640     InitISOFS, Always, TestOutput (
1641       [["file"; "/known-1"]], "ASCII text");
1642     InitISOFS, Always, TestLastFail (
1643       [["file"; "/notexists"]])],
1644    "determine file type",
1645    "\
1646 This call uses the standard L<file(1)> command to determine
1647 the type or contents of the file.  This also works on devices,
1648 for example to find out whether a partition contains a filesystem.
1649
1650 This call will also transparently look inside various types
1651 of compressed file.
1652
1653 The exact command which runs is C<file -zbsL path>.  Note in
1654 particular that the filename is not prepended to the output
1655 (the C<-b> option).");
1656
1657   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1658    [InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 1"]], "Result1");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 2"]], "Result2\n");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 3"]], "\nResult3");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 4"]], "\nResult4\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 5"]], "\nResult5\n\n");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1682     InitBasicFS, Always, TestOutput (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command 7"]], "");
1686     InitBasicFS, Always, TestOutput (
1687       [["upload"; "test-command"; "/test-command"];
1688        ["chmod"; "0o755"; "/test-command"];
1689        ["command"; "/test-command 8"]], "\n");
1690     InitBasicFS, Always, TestOutput (
1691       [["upload"; "test-command"; "/test-command"];
1692        ["chmod"; "0o755"; "/test-command"];
1693        ["command"; "/test-command 9"]], "\n\n");
1694     InitBasicFS, Always, TestOutput (
1695       [["upload"; "test-command"; "/test-command"];
1696        ["chmod"; "0o755"; "/test-command"];
1697        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1698     InitBasicFS, Always, TestOutput (
1699       [["upload"; "test-command"; "/test-command"];
1700        ["chmod"; "0o755"; "/test-command"];
1701        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1702     InitBasicFS, Always, TestLastFail (
1703       [["upload"; "test-command"; "/test-command"];
1704        ["chmod"; "0o755"; "/test-command"];
1705        ["command"; "/test-command"]])],
1706    "run a command from the guest filesystem",
1707    "\
1708 This call runs a command from the guest filesystem.  The
1709 filesystem must be mounted, and must contain a compatible
1710 operating system (ie. something Linux, with the same
1711 or compatible processor architecture).
1712
1713 The single parameter is an argv-style list of arguments.
1714 The first element is the name of the program to run.
1715 Subsequent elements are parameters.  The list must be
1716 non-empty (ie. must contain a program name).  Note that
1717 the command runs directly, and is I<not> invoked via
1718 the shell (see C<guestfs_sh>).
1719
1720 The return value is anything printed to I<stdout> by
1721 the command.
1722
1723 If the command returns a non-zero exit status, then
1724 this function returns an error message.  The error message
1725 string is the content of I<stderr> from the command.
1726
1727 The C<$PATH> environment variable will contain at least
1728 C</usr/bin> and C</bin>.  If you require a program from
1729 another location, you should provide the full path in the
1730 first parameter.
1731
1732 Shared libraries and data files required by the program
1733 must be available on filesystems which are mounted in the
1734 correct places.  It is the caller's responsibility to ensure
1735 all filesystems that are needed are mounted at the right
1736 locations.");
1737
1738   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1739    [InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 1"]], ["Result1"]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 2"]], ["Result2"]);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1763     InitBasicFS, Always, TestOutputList (
1764       [["upload"; "test-command"; "/test-command"];
1765        ["chmod"; "0o755"; "/test-command"];
1766        ["command_lines"; "/test-command 7"]], []);
1767     InitBasicFS, Always, TestOutputList (
1768       [["upload"; "test-command"; "/test-command"];
1769        ["chmod"; "0o755"; "/test-command"];
1770        ["command_lines"; "/test-command 8"]], [""]);
1771     InitBasicFS, Always, TestOutputList (
1772       [["upload"; "test-command"; "/test-command"];
1773        ["chmod"; "0o755"; "/test-command"];
1774        ["command_lines"; "/test-command 9"]], ["";""]);
1775     InitBasicFS, Always, TestOutputList (
1776       [["upload"; "test-command"; "/test-command"];
1777        ["chmod"; "0o755"; "/test-command"];
1778        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1779     InitBasicFS, Always, TestOutputList (
1780       [["upload"; "test-command"; "/test-command"];
1781        ["chmod"; "0o755"; "/test-command"];
1782        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1783    "run a command, returning lines",
1784    "\
1785 This is the same as C<guestfs_command>, but splits the
1786 result into a list of lines.
1787
1788 See also: C<guestfs_sh_lines>");
1789
1790   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1791    [InitISOFS, Always, TestOutputStruct (
1792       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1793    "get file information",
1794    "\
1795 Returns file information for the given C<path>.
1796
1797 This is the same as the C<stat(2)> system call.");
1798
1799   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1800    [InitISOFS, Always, TestOutputStruct (
1801       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1802    "get file information for a symbolic link",
1803    "\
1804 Returns file information for the given C<path>.
1805
1806 This is the same as C<guestfs_stat> except that if C<path>
1807 is a symbolic link, then the link is stat-ed, not the file it
1808 refers to.
1809
1810 This is the same as the C<lstat(2)> system call.");
1811
1812   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1813    [InitISOFS, Always, TestOutputStruct (
1814       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1815    "get file system statistics",
1816    "\
1817 Returns file system statistics for any mounted file system.
1818 C<path> should be a file or directory in the mounted file system
1819 (typically it is the mount point itself, but it doesn't need to be).
1820
1821 This is the same as the C<statvfs(2)> system call.");
1822
1823   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1824    [], (* XXX test *)
1825    "get ext2/ext3/ext4 superblock details",
1826    "\
1827 This returns the contents of the ext2, ext3 or ext4 filesystem
1828 superblock on C<device>.
1829
1830 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1831 manpage for more details.  The list of fields returned isn't
1832 clearly defined, and depends on both the version of C<tune2fs>
1833 that libguestfs was built against, and the filesystem itself.");
1834
1835   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1836    [InitEmpty, Always, TestOutputTrue (
1837       [["blockdev_setro"; "/dev/sda"];
1838        ["blockdev_getro"; "/dev/sda"]])],
1839    "set block device to read-only",
1840    "\
1841 Sets the block device named C<device> to read-only.
1842
1843 This uses the L<blockdev(8)> command.");
1844
1845   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1846    [InitEmpty, Always, TestOutputFalse (
1847       [["blockdev_setrw"; "/dev/sda"];
1848        ["blockdev_getro"; "/dev/sda"]])],
1849    "set block device to read-write",
1850    "\
1851 Sets the block device named C<device> to read-write.
1852
1853 This uses the L<blockdev(8)> command.");
1854
1855   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1856    [InitEmpty, Always, TestOutputTrue (
1857       [["blockdev_setro"; "/dev/sda"];
1858        ["blockdev_getro"; "/dev/sda"]])],
1859    "is block device set to read-only",
1860    "\
1861 Returns a boolean indicating if the block device is read-only
1862 (true if read-only, false if not).
1863
1864 This uses the L<blockdev(8)> command.");
1865
1866   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1867    [InitEmpty, Always, TestOutputInt (
1868       [["blockdev_getss"; "/dev/sda"]], 512)],
1869    "get sectorsize of block device",
1870    "\
1871 This returns the size of sectors on a block device.
1872 Usually 512, but can be larger for modern devices.
1873
1874 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1875 for that).
1876
1877 This uses the L<blockdev(8)> command.");
1878
1879   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1880    [InitEmpty, Always, TestOutputInt (
1881       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1882    "get blocksize of block device",
1883    "\
1884 This returns the block size of a device.
1885
1886 (Note this is different from both I<size in blocks> and
1887 I<filesystem block size>).
1888
1889 This uses the L<blockdev(8)> command.");
1890
1891   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1892    [], (* XXX test *)
1893    "set blocksize of block device",
1894    "\
1895 This sets the block size of a device.
1896
1897 (Note this is different from both I<size in blocks> and
1898 I<filesystem block size>).
1899
1900 This uses the L<blockdev(8)> command.");
1901
1902   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1903    [InitEmpty, Always, TestOutputInt (
1904       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1905    "get total size of device in 512-byte sectors",
1906    "\
1907 This returns the size of the device in units of 512-byte sectors
1908 (even if the sectorsize isn't 512 bytes ... weird).
1909
1910 See also C<guestfs_blockdev_getss> for the real sector size of
1911 the device, and C<guestfs_blockdev_getsize64> for the more
1912 useful I<size in bytes>.
1913
1914 This uses the L<blockdev(8)> command.");
1915
1916   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1917    [InitEmpty, Always, TestOutputInt (
1918       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1919    "get total size of device in bytes",
1920    "\
1921 This returns the size of the device in bytes.
1922
1923 See also C<guestfs_blockdev_getsz>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1928    [InitEmpty, Always, TestRun
1929       [["blockdev_flushbufs"; "/dev/sda"]]],
1930    "flush device buffers",
1931    "\
1932 This tells the kernel to flush internal buffers associated
1933 with C<device>.
1934
1935 This uses the L<blockdev(8)> command.");
1936
1937   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1938    [InitEmpty, Always, TestRun
1939       [["blockdev_rereadpt"; "/dev/sda"]]],
1940    "reread partition table",
1941    "\
1942 Reread the partition table on C<device>.
1943
1944 This uses the L<blockdev(8)> command.");
1945
1946   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1947    [InitBasicFS, Always, TestOutput (
1948       (* Pick a file from cwd which isn't likely to change. *)
1949       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1950        ["checksum"; "md5"; "/COPYING.LIB"]],
1951       Digest.to_hex (Digest.file "COPYING.LIB"))],
1952    "upload a file from the local machine",
1953    "\
1954 Upload local file C<filename> to C<remotefilename> on the
1955 filesystem.
1956
1957 C<filename> can also be a named pipe.
1958
1959 See also C<guestfs_download>.");
1960
1961   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1962    [InitBasicFS, Always, TestOutput (
1963       (* Pick a file from cwd which isn't likely to change. *)
1964       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1965        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1966        ["upload"; "testdownload.tmp"; "/upload"];
1967        ["checksum"; "md5"; "/upload"]],
1968       Digest.to_hex (Digest.file "COPYING.LIB"))],
1969    "download a file to the local machine",
1970    "\
1971 Download file C<remotefilename> and save it as C<filename>
1972 on the local machine.
1973
1974 C<filename> can also be a named pipe.
1975
1976 See also C<guestfs_upload>, C<guestfs_cat>.");
1977
1978   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1979    [InitISOFS, Always, TestOutput (
1980       [["checksum"; "crc"; "/known-3"]], "2891671662");
1981     InitISOFS, Always, TestLastFail (
1982       [["checksum"; "crc"; "/notexists"]]);
1983     InitISOFS, Always, TestOutput (
1984       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1985     InitISOFS, Always, TestOutput (
1986       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1987     InitISOFS, Always, TestOutput (
1988       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1989     InitISOFS, Always, TestOutput (
1990       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1991     InitISOFS, Always, TestOutput (
1992       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1993     InitISOFS, Always, TestOutput (
1994       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1995     (* Test for RHBZ#579608, absolute symbolic links. *)
1996     InitISOFS, Always, TestOutput (
1997       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1998    "compute MD5, SHAx or CRC checksum of file",
1999    "\
2000 This call computes the MD5, SHAx or CRC checksum of the
2001 file named C<path>.
2002
2003 The type of checksum to compute is given by the C<csumtype>
2004 parameter which must have one of the following values:
2005
2006 =over 4
2007
2008 =item C<crc>
2009
2010 Compute the cyclic redundancy check (CRC) specified by POSIX
2011 for the C<cksum> command.
2012
2013 =item C<md5>
2014
2015 Compute the MD5 hash (using the C<md5sum> program).
2016
2017 =item C<sha1>
2018
2019 Compute the SHA1 hash (using the C<sha1sum> program).
2020
2021 =item C<sha224>
2022
2023 Compute the SHA224 hash (using the C<sha224sum> program).
2024
2025 =item C<sha256>
2026
2027 Compute the SHA256 hash (using the C<sha256sum> program).
2028
2029 =item C<sha384>
2030
2031 Compute the SHA384 hash (using the C<sha384sum> program).
2032
2033 =item C<sha512>
2034
2035 Compute the SHA512 hash (using the C<sha512sum> program).
2036
2037 =back
2038
2039 The checksum is returned as a printable string.
2040
2041 To get the checksum for a device, use C<guestfs_checksum_device>.
2042
2043 To get the checksums for many files, use C<guestfs_checksums_out>.");
2044
2045   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2046    [InitBasicFS, Always, TestOutput (
2047       [["tar_in"; "../images/helloworld.tar"; "/"];
2048        ["cat"; "/hello"]], "hello\n")],
2049    "unpack tarfile to directory",
2050    "\
2051 This command uploads and unpacks local file C<tarfile> (an
2052 I<uncompressed> tar file) into C<directory>.
2053
2054 To upload a compressed tarball, use C<guestfs_tgz_in>
2055 or C<guestfs_txz_in>.");
2056
2057   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2058    [],
2059    "pack directory into tarfile",
2060    "\
2061 This command packs the contents of C<directory> and downloads
2062 it to local file C<tarfile>.
2063
2064 To download a compressed tarball, use C<guestfs_tgz_out>
2065 or C<guestfs_txz_out>.");
2066
2067   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2068    [InitBasicFS, Always, TestOutput (
2069       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2070        ["cat"; "/hello"]], "hello\n")],
2071    "unpack compressed tarball to directory",
2072    "\
2073 This command uploads and unpacks local file C<tarball> (a
2074 I<gzip compressed> tar file) into C<directory>.
2075
2076 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2077
2078   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2079    [],
2080    "pack directory into compressed tarball",
2081    "\
2082 This command packs the contents of C<directory> and downloads
2083 it to local file C<tarball>.
2084
2085 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2086
2087   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2088    [InitBasicFS, Always, TestLastFail (
2089       [["umount"; "/"];
2090        ["mount_ro"; "/dev/sda1"; "/"];
2091        ["touch"; "/new"]]);
2092     InitBasicFS, Always, TestOutput (
2093       [["write_file"; "/new"; "data"; "0"];
2094        ["umount"; "/"];
2095        ["mount_ro"; "/dev/sda1"; "/"];
2096        ["cat"; "/new"]], "data")],
2097    "mount a guest disk, read-only",
2098    "\
2099 This is the same as the C<guestfs_mount> command, but it
2100 mounts the filesystem with the read-only (I<-o ro>) flag.");
2101
2102   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2103    [],
2104    "mount a guest disk with mount options",
2105    "\
2106 This is the same as the C<guestfs_mount> command, but it
2107 allows you to set the mount options as for the
2108 L<mount(8)> I<-o> flag.
2109
2110 If the C<options> parameter is an empty string, then
2111 no options are passed (all options default to whatever
2112 the filesystem uses).");
2113
2114   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2115    [],
2116    "mount a guest disk with mount options and vfstype",
2117    "\
2118 This is the same as the C<guestfs_mount> command, but it
2119 allows you to set both the mount options and the vfstype
2120 as for the L<mount(8)> I<-o> and I<-t> flags.");
2121
2122   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2123    [],
2124    "debugging and internals",
2125    "\
2126 The C<guestfs_debug> command exposes some internals of
2127 C<guestfsd> (the guestfs daemon) that runs inside the
2128 qemu subprocess.
2129
2130 There is no comprehensive help for this command.  You have
2131 to look at the file C<daemon/debug.c> in the libguestfs source
2132 to find out what you can do.");
2133
2134   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2135    [InitEmpty, Always, TestOutputList (
2136       [["part_disk"; "/dev/sda"; "mbr"];
2137        ["pvcreate"; "/dev/sda1"];
2138        ["vgcreate"; "VG"; "/dev/sda1"];
2139        ["lvcreate"; "LV1"; "VG"; "50"];
2140        ["lvcreate"; "LV2"; "VG"; "50"];
2141        ["lvremove"; "/dev/VG/LV1"];
2142        ["lvs"]], ["/dev/VG/LV2"]);
2143     InitEmpty, Always, TestOutputList (
2144       [["part_disk"; "/dev/sda"; "mbr"];
2145        ["pvcreate"; "/dev/sda1"];
2146        ["vgcreate"; "VG"; "/dev/sda1"];
2147        ["lvcreate"; "LV1"; "VG"; "50"];
2148        ["lvcreate"; "LV2"; "VG"; "50"];
2149        ["lvremove"; "/dev/VG"];
2150        ["lvs"]], []);
2151     InitEmpty, Always, TestOutputList (
2152       [["part_disk"; "/dev/sda"; "mbr"];
2153        ["pvcreate"; "/dev/sda1"];
2154        ["vgcreate"; "VG"; "/dev/sda1"];
2155        ["lvcreate"; "LV1"; "VG"; "50"];
2156        ["lvcreate"; "LV2"; "VG"; "50"];
2157        ["lvremove"; "/dev/VG"];
2158        ["vgs"]], ["VG"])],
2159    "remove an LVM logical volume",
2160    "\
2161 Remove an LVM logical volume C<device>, where C<device> is
2162 the path to the LV, such as C</dev/VG/LV>.
2163
2164 You can also remove all LVs in a volume group by specifying
2165 the VG name, C</dev/VG>.");
2166
2167   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2168    [InitEmpty, Always, TestOutputList (
2169       [["part_disk"; "/dev/sda"; "mbr"];
2170        ["pvcreate"; "/dev/sda1"];
2171        ["vgcreate"; "VG"; "/dev/sda1"];
2172        ["lvcreate"; "LV1"; "VG"; "50"];
2173        ["lvcreate"; "LV2"; "VG"; "50"];
2174        ["vgremove"; "VG"];
2175        ["lvs"]], []);
2176     InitEmpty, Always, TestOutputList (
2177       [["part_disk"; "/dev/sda"; "mbr"];
2178        ["pvcreate"; "/dev/sda1"];
2179        ["vgcreate"; "VG"; "/dev/sda1"];
2180        ["lvcreate"; "LV1"; "VG"; "50"];
2181        ["lvcreate"; "LV2"; "VG"; "50"];
2182        ["vgremove"; "VG"];
2183        ["vgs"]], [])],
2184    "remove an LVM volume group",
2185    "\
2186 Remove an LVM volume group C<vgname>, (for example C<VG>).
2187
2188 This also forcibly removes all logical volumes in the volume
2189 group (if any).");
2190
2191   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2192    [InitEmpty, Always, TestOutputListOfDevices (
2193       [["part_disk"; "/dev/sda"; "mbr"];
2194        ["pvcreate"; "/dev/sda1"];
2195        ["vgcreate"; "VG"; "/dev/sda1"];
2196        ["lvcreate"; "LV1"; "VG"; "50"];
2197        ["lvcreate"; "LV2"; "VG"; "50"];
2198        ["vgremove"; "VG"];
2199        ["pvremove"; "/dev/sda1"];
2200        ["lvs"]], []);
2201     InitEmpty, Always, TestOutputListOfDevices (
2202       [["part_disk"; "/dev/sda"; "mbr"];
2203        ["pvcreate"; "/dev/sda1"];
2204        ["vgcreate"; "VG"; "/dev/sda1"];
2205        ["lvcreate"; "LV1"; "VG"; "50"];
2206        ["lvcreate"; "LV2"; "VG"; "50"];
2207        ["vgremove"; "VG"];
2208        ["pvremove"; "/dev/sda1"];
2209        ["vgs"]], []);
2210     InitEmpty, Always, TestOutputListOfDevices (
2211       [["part_disk"; "/dev/sda"; "mbr"];
2212        ["pvcreate"; "/dev/sda1"];
2213        ["vgcreate"; "VG"; "/dev/sda1"];
2214        ["lvcreate"; "LV1"; "VG"; "50"];
2215        ["lvcreate"; "LV2"; "VG"; "50"];
2216        ["vgremove"; "VG"];
2217        ["pvremove"; "/dev/sda1"];
2218        ["pvs"]], [])],
2219    "remove an LVM physical volume",
2220    "\
2221 This wipes a physical volume C<device> so that LVM will no longer
2222 recognise it.
2223
2224 The implementation uses the C<pvremove> command which refuses to
2225 wipe physical volumes that contain any volume groups, so you have
2226 to remove those first.");
2227
2228   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2229    [InitBasicFS, Always, TestOutput (
2230       [["set_e2label"; "/dev/sda1"; "testlabel"];
2231        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2232    "set the ext2/3/4 filesystem label",
2233    "\
2234 This sets the ext2/3/4 filesystem label of the filesystem on
2235 C<device> to C<label>.  Filesystem labels are limited to
2236 16 characters.
2237
2238 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2239 to return the existing label on a filesystem.");
2240
2241   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2242    [],
2243    "get the ext2/3/4 filesystem label",
2244    "\
2245 This returns the ext2/3/4 filesystem label of the filesystem on
2246 C<device>.");
2247
2248   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2249    (let uuid = uuidgen () in
2250     [InitBasicFS, Always, TestOutput (
2251        [["set_e2uuid"; "/dev/sda1"; uuid];
2252         ["get_e2uuid"; "/dev/sda1"]], uuid);
2253      InitBasicFS, Always, TestOutput (
2254        [["set_e2uuid"; "/dev/sda1"; "clear"];
2255         ["get_e2uuid"; "/dev/sda1"]], "");
2256      (* We can't predict what UUIDs will be, so just check the commands run. *)
2257      InitBasicFS, Always, TestRun (
2258        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2259      InitBasicFS, Always, TestRun (
2260        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2261    "set the ext2/3/4 filesystem UUID",
2262    "\
2263 This sets the ext2/3/4 filesystem UUID of the filesystem on
2264 C<device> to C<uuid>.  The format of the UUID and alternatives
2265 such as C<clear>, C<random> and C<time> are described in the
2266 L<tune2fs(8)> manpage.
2267
2268 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2269 to return the existing UUID of a filesystem.");
2270
2271   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2272    [],
2273    "get the ext2/3/4 filesystem UUID",
2274    "\
2275 This returns the ext2/3/4 filesystem UUID of the filesystem on
2276 C<device>.");
2277
2278   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2279    [InitBasicFS, Always, TestOutputInt (
2280       [["umount"; "/dev/sda1"];
2281        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2282     InitBasicFS, Always, TestOutputInt (
2283       [["umount"; "/dev/sda1"];
2284        ["zero"; "/dev/sda1"];
2285        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2286    "run the filesystem checker",
2287    "\
2288 This runs the filesystem checker (fsck) on C<device> which
2289 should have filesystem type C<fstype>.
2290
2291 The returned integer is the status.  See L<fsck(8)> for the
2292 list of status codes from C<fsck>.
2293
2294 Notes:
2295
2296 =over 4
2297
2298 =item *
2299
2300 Multiple status codes can be summed together.
2301
2302 =item *
2303
2304 A non-zero return code can mean \"success\", for example if
2305 errors have been corrected on the filesystem.
2306
2307 =item *
2308
2309 Checking or repairing NTFS volumes is not supported
2310 (by linux-ntfs).
2311
2312 =back
2313
2314 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2315
2316   ("zero", (RErr, [Device "device"]), 85, [],
2317    [InitBasicFS, Always, TestOutput (
2318       [["umount"; "/dev/sda1"];
2319        ["zero"; "/dev/sda1"];
2320        ["file"; "/dev/sda1"]], "data")],
2321    "write zeroes to the device",
2322    "\
2323 This command writes zeroes over the first few blocks of C<device>.
2324
2325 How many blocks are zeroed isn't specified (but it's I<not> enough
2326 to securely wipe the device).  It should be sufficient to remove
2327 any partition tables, filesystem superblocks and so on.
2328
2329 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2330
2331   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2332    (* Test disabled because grub-install incompatible with virtio-blk driver.
2333     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2334     *)
2335    [InitBasicFS, Disabled, TestOutputTrue (
2336       [["grub_install"; "/"; "/dev/sda1"];
2337        ["is_dir"; "/boot"]])],
2338    "install GRUB",
2339    "\
2340 This command installs GRUB (the Grand Unified Bootloader) on
2341 C<device>, with the root directory being C<root>.");
2342
2343   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2344    [InitBasicFS, Always, TestOutput (
2345       [["write_file"; "/old"; "file content"; "0"];
2346        ["cp"; "/old"; "/new"];
2347        ["cat"; "/new"]], "file content");
2348     InitBasicFS, Always, TestOutputTrue (
2349       [["write_file"; "/old"; "file content"; "0"];
2350        ["cp"; "/old"; "/new"];
2351        ["is_file"; "/old"]]);
2352     InitBasicFS, Always, TestOutput (
2353       [["write_file"; "/old"; "file content"; "0"];
2354        ["mkdir"; "/dir"];
2355        ["cp"; "/old"; "/dir/new"];
2356        ["cat"; "/dir/new"]], "file content")],
2357    "copy a file",
2358    "\
2359 This copies a file from C<src> to C<dest> where C<dest> is
2360 either a destination filename or destination directory.");
2361
2362   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2363    [InitBasicFS, Always, TestOutput (
2364       [["mkdir"; "/olddir"];
2365        ["mkdir"; "/newdir"];
2366        ["write_file"; "/olddir/file"; "file content"; "0"];
2367        ["cp_a"; "/olddir"; "/newdir"];
2368        ["cat"; "/newdir/olddir/file"]], "file content")],
2369    "copy a file or directory recursively",
2370    "\
2371 This copies a file or directory from C<src> to C<dest>
2372 recursively using the C<cp -a> command.");
2373
2374   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2375    [InitBasicFS, Always, TestOutput (
2376       [["write_file"; "/old"; "file content"; "0"];
2377        ["mv"; "/old"; "/new"];
2378        ["cat"; "/new"]], "file content");
2379     InitBasicFS, Always, TestOutputFalse (
2380       [["write_file"; "/old"; "file content"; "0"];
2381        ["mv"; "/old"; "/new"];
2382        ["is_file"; "/old"]])],
2383    "move a file",
2384    "\
2385 This moves a file from C<src> to C<dest> where C<dest> is
2386 either a destination filename or destination directory.");
2387
2388   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2389    [InitEmpty, Always, TestRun (
2390       [["drop_caches"; "3"]])],
2391    "drop kernel page cache, dentries and inodes",
2392    "\
2393 This instructs the guest kernel to drop its page cache,
2394 and/or dentries and inode caches.  The parameter C<whattodrop>
2395 tells the kernel what precisely to drop, see
2396 L<http://linux-mm.org/Drop_Caches>
2397
2398 Setting C<whattodrop> to 3 should drop everything.
2399
2400 This automatically calls L<sync(2)> before the operation,
2401 so that the maximum guest memory is freed.");
2402
2403   ("dmesg", (RString "kmsgs", []), 91, [],
2404    [InitEmpty, Always, TestRun (
2405       [["dmesg"]])],
2406    "return kernel messages",
2407    "\
2408 This returns the kernel messages (C<dmesg> output) from
2409 the guest kernel.  This is sometimes useful for extended
2410 debugging of problems.
2411
2412 Another way to get the same information is to enable
2413 verbose messages with C<guestfs_set_verbose> or by setting
2414 the environment variable C<LIBGUESTFS_DEBUG=1> before
2415 running the program.");
2416
2417   ("ping_daemon", (RErr, []), 92, [],
2418    [InitEmpty, Always, TestRun (
2419       [["ping_daemon"]])],
2420    "ping the guest daemon",
2421    "\
2422 This is a test probe into the guestfs daemon running inside
2423 the qemu subprocess.  Calling this function checks that the
2424 daemon responds to the ping message, without affecting the daemon
2425 or attached block device(s) in any other way.");
2426
2427   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2428    [InitBasicFS, Always, TestOutputTrue (
2429       [["write_file"; "/file1"; "contents of a file"; "0"];
2430        ["cp"; "/file1"; "/file2"];
2431        ["equal"; "/file1"; "/file2"]]);
2432     InitBasicFS, Always, TestOutputFalse (
2433       [["write_file"; "/file1"; "contents of a file"; "0"];
2434        ["write_file"; "/file2"; "contents of another file"; "0"];
2435        ["equal"; "/file1"; "/file2"]]);
2436     InitBasicFS, Always, TestLastFail (
2437       [["equal"; "/file1"; "/file2"]])],
2438    "test if two files have equal contents",
2439    "\
2440 This compares the two files C<file1> and C<file2> and returns
2441 true if their content is exactly equal, or false otherwise.
2442
2443 The external L<cmp(1)> program is used for the comparison.");
2444
2445   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2446    [InitISOFS, Always, TestOutputList (
2447       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2448     InitISOFS, Always, TestOutputList (
2449       [["strings"; "/empty"]], [])],
2450    "print the printable strings in a file",
2451    "\
2452 This runs the L<strings(1)> command on a file and returns
2453 the list of printable strings found.");
2454
2455   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2456    [InitISOFS, Always, TestOutputList (
2457       [["strings_e"; "b"; "/known-5"]], []);
2458     InitBasicFS, Disabled, TestOutputList (
2459       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2460        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2461    "print the printable strings in a file",
2462    "\
2463 This is like the C<guestfs_strings> command, but allows you to
2464 specify the encoding.
2465
2466 See the L<strings(1)> manpage for the full list of encodings.
2467
2468 Commonly useful encodings are C<l> (lower case L) which will
2469 show strings inside Windows/x86 files.
2470
2471 The returned strings are transcoded to UTF-8.");
2472
2473   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2474    [InitISOFS, Always, TestOutput (
2475       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2476     (* Test for RHBZ#501888c2 regression which caused large hexdump
2477      * commands to segfault.
2478      *)
2479     InitISOFS, Always, TestRun (
2480       [["hexdump"; "/100krandom"]]);
2481     (* Test for RHBZ#579608, absolute symbolic links. *)
2482     InitISOFS, Always, TestRun (
2483       [["hexdump"; "/abssymlink"]])],
2484    "dump a file in hexadecimal",
2485    "\
2486 This runs C<hexdump -C> on the given C<path>.  The result is
2487 the human-readable, canonical hex dump of the file.");
2488
2489   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2490    [InitNone, Always, TestOutput (
2491       [["part_disk"; "/dev/sda"; "mbr"];
2492        ["mkfs"; "ext3"; "/dev/sda1"];
2493        ["mount_options"; ""; "/dev/sda1"; "/"];
2494        ["write_file"; "/new"; "test file"; "0"];
2495        ["umount"; "/dev/sda1"];
2496        ["zerofree"; "/dev/sda1"];
2497        ["mount_options"; ""; "/dev/sda1"; "/"];
2498        ["cat"; "/new"]], "test file")],
2499    "zero unused inodes and disk blocks on ext2/3 filesystem",
2500    "\
2501 This runs the I<zerofree> program on C<device>.  This program
2502 claims to zero unused inodes and disk blocks on an ext2/3
2503 filesystem, thus making it possible to compress the filesystem
2504 more effectively.
2505
2506 You should B<not> run this program if the filesystem is
2507 mounted.
2508
2509 It is possible that using this program can damage the filesystem
2510 or data on the filesystem.");
2511
2512   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2513    [],
2514    "resize an LVM physical volume",
2515    "\
2516 This resizes (expands or shrinks) an existing LVM physical
2517 volume to match the new size of the underlying device.");
2518
2519   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2520                        Int "cyls"; Int "heads"; Int "sectors";
2521                        String "line"]), 99, [DangerWillRobinson],
2522    [],
2523    "modify a single partition on a block device",
2524    "\
2525 This runs L<sfdisk(8)> option to modify just the single
2526 partition C<n> (note: C<n> counts from 1).
2527
2528 For other parameters, see C<guestfs_sfdisk>.  You should usually
2529 pass C<0> for the cyls/heads/sectors parameters.
2530
2531 See also: C<guestfs_part_add>");
2532
2533   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2534    [],
2535    "display the partition table",
2536    "\
2537 This displays the partition table on C<device>, in the
2538 human-readable output of the L<sfdisk(8)> command.  It is
2539 not intended to be parsed.
2540
2541 See also: C<guestfs_part_list>");
2542
2543   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2544    [],
2545    "display the kernel geometry",
2546    "\
2547 This displays the kernel's idea of the geometry of C<device>.
2548
2549 The result is in human-readable format, and not designed to
2550 be parsed.");
2551
2552   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2553    [],
2554    "display the disk geometry from the partition table",
2555    "\
2556 This displays the disk geometry of C<device> read from the
2557 partition table.  Especially in the case where the underlying
2558 block device has been resized, this can be different from the
2559 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2560
2561 The result is in human-readable format, and not designed to
2562 be parsed.");
2563
2564   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2565    [],
2566    "activate or deactivate all volume groups",
2567    "\
2568 This command activates or (if C<activate> is false) deactivates
2569 all logical volumes in all volume groups.
2570 If activated, then they are made known to the
2571 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2572 then those devices disappear.
2573
2574 This command is the same as running C<vgchange -a y|n>");
2575
2576   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2577    [],
2578    "activate or deactivate some volume groups",
2579    "\
2580 This command activates or (if C<activate> is false) deactivates
2581 all logical volumes in the listed volume groups C<volgroups>.
2582 If activated, then they are made known to the
2583 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2584 then those devices disappear.
2585
2586 This command is the same as running C<vgchange -a y|n volgroups...>
2587
2588 Note that if C<volgroups> is an empty list then B<all> volume groups
2589 are activated or deactivated.");
2590
2591   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2592    [InitNone, Always, TestOutput (
2593       [["part_disk"; "/dev/sda"; "mbr"];
2594        ["pvcreate"; "/dev/sda1"];
2595        ["vgcreate"; "VG"; "/dev/sda1"];
2596        ["lvcreate"; "LV"; "VG"; "10"];
2597        ["mkfs"; "ext2"; "/dev/VG/LV"];
2598        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2599        ["write_file"; "/new"; "test content"; "0"];
2600        ["umount"; "/"];
2601        ["lvresize"; "/dev/VG/LV"; "20"];
2602        ["e2fsck_f"; "/dev/VG/LV"];
2603        ["resize2fs"; "/dev/VG/LV"];
2604        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2605        ["cat"; "/new"]], "test content");
2606     InitNone, Always, TestRun (
2607       (* Make an LV smaller to test RHBZ#587484. *)
2608       [["part_disk"; "/dev/sda"; "mbr"];
2609        ["pvcreate"; "/dev/sda1"];
2610        ["vgcreate"; "VG"; "/dev/sda1"];
2611        ["lvcreate"; "LV"; "VG"; "20"];
2612        ["lvresize"; "/dev/VG/LV"; "10"]])],
2613    "resize an LVM logical volume",
2614    "\
2615 This resizes (expands or shrinks) an existing LVM logical
2616 volume to C<mbytes>.  When reducing, data in the reduced part
2617 is lost.");
2618
2619   ("resize2fs", (RErr, [Device "device"]), 106, [],
2620    [], (* lvresize tests this *)
2621    "resize an ext2/ext3 filesystem",
2622    "\
2623 This resizes an ext2 or ext3 filesystem to match the size of
2624 the underlying device.
2625
2626 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2627 on the C<device> before calling this command.  For unknown reasons
2628 C<resize2fs> sometimes gives an error about this and sometimes not.
2629 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2630 calling this function.");
2631
2632   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2633    [InitBasicFS, Always, TestOutputList (
2634       [["find"; "/"]], ["lost+found"]);
2635     InitBasicFS, Always, TestOutputList (
2636       [["touch"; "/a"];
2637        ["mkdir"; "/b"];
2638        ["touch"; "/b/c"];
2639        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2640     InitBasicFS, Always, TestOutputList (
2641       [["mkdir_p"; "/a/b/c"];
2642        ["touch"; "/a/b/c/d"];
2643        ["find"; "/a/b/"]], ["c"; "c/d"])],
2644    "find all files and directories",
2645    "\
2646 This command lists out all files and directories, recursively,
2647 starting at C<directory>.  It is essentially equivalent to
2648 running the shell command C<find directory -print> but some
2649 post-processing happens on the output, described below.
2650
2651 This returns a list of strings I<without any prefix>.  Thus
2652 if the directory structure was:
2653
2654  /tmp/a
2655  /tmp/b
2656  /tmp/c/d
2657
2658 then the returned list from C<guestfs_find> C</tmp> would be
2659 4 elements:
2660
2661  a
2662  b
2663  c
2664  c/d
2665
2666 If C<directory> is not a directory, then this command returns
2667 an error.
2668
2669 The returned list is sorted.
2670
2671 See also C<guestfs_find0>.");
2672
2673   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2674    [], (* lvresize tests this *)
2675    "check an ext2/ext3 filesystem",
2676    "\
2677 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2678 filesystem checker on C<device>, noninteractively (C<-p>),
2679 even if the filesystem appears to be clean (C<-f>).
2680
2681 This command is only needed because of C<guestfs_resize2fs>
2682 (q.v.).  Normally you should use C<guestfs_fsck>.");
2683
2684   ("sleep", (RErr, [Int "secs"]), 109, [],
2685    [InitNone, Always, TestRun (
2686       [["sleep"; "1"]])],
2687    "sleep for some seconds",
2688    "\
2689 Sleep for C<secs> seconds.");
2690
2691   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2692    [InitNone, Always, TestOutputInt (
2693       [["part_disk"; "/dev/sda"; "mbr"];
2694        ["mkfs"; "ntfs"; "/dev/sda1"];
2695        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2696     InitNone, Always, TestOutputInt (
2697       [["part_disk"; "/dev/sda"; "mbr"];
2698        ["mkfs"; "ext2"; "/dev/sda1"];
2699        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2700    "probe NTFS volume",
2701    "\
2702 This command runs the L<ntfs-3g.probe(8)> command which probes
2703 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2704 be mounted read-write, and some cannot be mounted at all).
2705
2706 C<rw> is a boolean flag.  Set it to true if you want to test
2707 if the volume can be mounted read-write.  Set it to false if
2708 you want to test if the volume can be mounted read-only.
2709
2710 The return value is an integer which C<0> if the operation
2711 would succeed, or some non-zero value documented in the
2712 L<ntfs-3g.probe(8)> manual page.");
2713
2714   ("sh", (RString "output", [String "command"]), 111, [],
2715    [], (* XXX needs tests *)
2716    "run a command via the shell",
2717    "\
2718 This call runs a command from the guest filesystem via the
2719 guest's C</bin/sh>.
2720
2721 This is like C<guestfs_command>, but passes the command to:
2722
2723  /bin/sh -c \"command\"
2724
2725 Depending on the guest's shell, this usually results in
2726 wildcards being expanded, shell expressions being interpolated
2727 and so on.
2728
2729 All the provisos about C<guestfs_command> apply to this call.");
2730
2731   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2732    [], (* XXX needs tests *)
2733    "run a command via the shell returning lines",
2734    "\
2735 This is the same as C<guestfs_sh>, but splits the result
2736 into a list of lines.
2737
2738 See also: C<guestfs_command_lines>");
2739
2740   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2741    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2742     * code in stubs.c, since all valid glob patterns must start with "/".
2743     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2744     *)
2745    [InitBasicFS, Always, TestOutputList (
2746       [["mkdir_p"; "/a/b/c"];
2747        ["touch"; "/a/b/c/d"];
2748        ["touch"; "/a/b/c/e"];
2749        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2750     InitBasicFS, Always, TestOutputList (
2751       [["mkdir_p"; "/a/b/c"];
2752        ["touch"; "/a/b/c/d"];
2753        ["touch"; "/a/b/c/e"];
2754        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2755     InitBasicFS, Always, TestOutputList (
2756       [["mkdir_p"; "/a/b/c"];
2757        ["touch"; "/a/b/c/d"];
2758        ["touch"; "/a/b/c/e"];
2759        ["glob_expand"; "/a/*/x/*"]], [])],
2760    "expand a wildcard path",
2761    "\
2762 This command searches for all the pathnames matching
2763 C<pattern> according to the wildcard expansion rules
2764 used by the shell.
2765
2766 If no paths match, then this returns an empty list
2767 (note: not an error).
2768
2769 It is just a wrapper around the C L<glob(3)> function
2770 with flags C<GLOB_MARK|GLOB_BRACE>.
2771 See that manual page for more details.");
2772
2773   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2774    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2775       [["scrub_device"; "/dev/sdc"]])],
2776    "scrub (securely wipe) a device",
2777    "\
2778 This command writes patterns over C<device> to make data retrieval
2779 more difficult.
2780
2781 It is an interface to the L<scrub(1)> program.  See that
2782 manual page for more details.");
2783
2784   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2785    [InitBasicFS, Always, TestRun (
2786       [["write_file"; "/file"; "content"; "0"];
2787        ["scrub_file"; "/file"]])],
2788    "scrub (securely wipe) a file",
2789    "\
2790 This command writes patterns over a file to make data retrieval
2791 more difficult.
2792
2793 The file is I<removed> after scrubbing.
2794
2795 It is an interface to the L<scrub(1)> program.  See that
2796 manual page for more details.");
2797
2798   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2799    [], (* XXX needs testing *)
2800    "scrub (securely wipe) free space",
2801    "\
2802 This command creates the directory C<dir> and then fills it
2803 with files until the filesystem is full, and scrubs the files
2804 as for C<guestfs_scrub_file>, and deletes them.
2805 The intention is to scrub any free space on the partition
2806 containing C<dir>.
2807
2808 It is an interface to the L<scrub(1)> program.  See that
2809 manual page for more details.");
2810
2811   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2812    [InitBasicFS, Always, TestRun (
2813       [["mkdir"; "/tmp"];
2814        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2815    "create a temporary directory",
2816    "\
2817 This command creates a temporary directory.  The
2818 C<template> parameter should be a full pathname for the
2819 temporary directory name with the final six characters being
2820 \"XXXXXX\".
2821
2822 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2823 the second one being suitable for Windows filesystems.
2824
2825 The name of the temporary directory that was created
2826 is returned.
2827
2828 The temporary directory is created with mode 0700
2829 and is owned by root.
2830
2831 The caller is responsible for deleting the temporary
2832 directory and its contents after use.
2833
2834 See also: L<mkdtemp(3)>");
2835
2836   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2837    [InitISOFS, Always, TestOutputInt (
2838       [["wc_l"; "/10klines"]], 10000)],
2839    "count lines in a file",
2840    "\
2841 This command counts the lines in a file, using the
2842 C<wc -l> external command.");
2843
2844   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2845    [InitISOFS, Always, TestOutputInt (
2846       [["wc_w"; "/10klines"]], 10000)],
2847    "count words in a file",
2848    "\
2849 This command counts the words in a file, using the
2850 C<wc -w> external command.");
2851
2852   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2853    [InitISOFS, Always, TestOutputInt (
2854       [["wc_c"; "/100kallspaces"]], 102400)],
2855    "count characters in a file",
2856    "\
2857 This command counts the characters in a file, using the
2858 C<wc -c> external command.");
2859
2860   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2861    [InitISOFS, Always, TestOutputList (
2862       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2863    "return first 10 lines of a file",
2864    "\
2865 This command returns up to the first 10 lines of a file as
2866 a list of strings.");
2867
2868   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2869    [InitISOFS, Always, TestOutputList (
2870       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2871     InitISOFS, Always, TestOutputList (
2872       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2873     InitISOFS, Always, TestOutputList (
2874       [["head_n"; "0"; "/10klines"]], [])],
2875    "return first N lines of a file",
2876    "\
2877 If the parameter C<nrlines> is a positive number, this returns the first
2878 C<nrlines> lines of the file C<path>.
2879
2880 If the parameter C<nrlines> is a negative number, this returns lines
2881 from the file C<path>, excluding the last C<nrlines> lines.
2882
2883 If the parameter C<nrlines> is zero, this returns an empty list.");
2884
2885   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2886    [InitISOFS, Always, TestOutputList (
2887       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2888    "return last 10 lines of a file",
2889    "\
2890 This command returns up to the last 10 lines of a file as
2891 a list of strings.");
2892
2893   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2894    [InitISOFS, Always, TestOutputList (
2895       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2896     InitISOFS, Always, TestOutputList (
2897       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2898     InitISOFS, Always, TestOutputList (
2899       [["tail_n"; "0"; "/10klines"]], [])],
2900    "return last N lines of a file",
2901    "\
2902 If the parameter C<nrlines> is a positive number, this returns the last
2903 C<nrlines> lines of the file C<path>.
2904
2905 If the parameter C<nrlines> is a negative number, this returns lines
2906 from the file C<path>, starting with the C<-nrlines>th line.
2907
2908 If the parameter C<nrlines> is zero, this returns an empty list.");
2909
2910   ("df", (RString "output", []), 125, [],
2911    [], (* XXX Tricky to test because it depends on the exact format
2912         * of the 'df' command and other imponderables.
2913         *)
2914    "report file system disk space usage",
2915    "\
2916 This command runs the C<df> command to report disk space used.
2917
2918 This command is mostly useful for interactive sessions.  It
2919 is I<not> intended that you try to parse the output string.
2920 Use C<statvfs> from programs.");
2921
2922   ("df_h", (RString "output", []), 126, [],
2923    [], (* XXX Tricky to test because it depends on the exact format
2924         * of the 'df' command and other imponderables.
2925         *)
2926    "report file system disk space usage (human readable)",
2927    "\
2928 This command runs the C<df -h> command to report disk space used
2929 in human-readable format.
2930
2931 This command is mostly useful for interactive sessions.  It
2932 is I<not> intended that you try to parse the output string.
2933 Use C<statvfs> from programs.");
2934
2935   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2936    [InitISOFS, Always, TestOutputInt (
2937       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2938    "estimate file space usage",
2939    "\
2940 This command runs the C<du -s> command to estimate file space
2941 usage for C<path>.
2942
2943 C<path> can be a file or a directory.  If C<path> is a directory
2944 then the estimate includes the contents of the directory and all
2945 subdirectories (recursively).
2946
2947 The result is the estimated size in I<kilobytes>
2948 (ie. units of 1024 bytes).");
2949
2950   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2951    [InitISOFS, Always, TestOutputList (
2952       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2953    "list files in an initrd",
2954    "\
2955 This command lists out files contained in an initrd.
2956
2957 The files are listed without any initial C</> character.  The
2958 files are listed in the order they appear (not necessarily
2959 alphabetical).  Directory names are listed as separate items.
2960
2961 Old Linux kernels (2.4 and earlier) used a compressed ext2
2962 filesystem as initrd.  We I<only> support the newer initramfs
2963 format (compressed cpio files).");
2964
2965   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2966    [],
2967    "mount a file using the loop device",
2968    "\
2969 This command lets you mount C<file> (a filesystem image
2970 in a file) on a mount point.  It is entirely equivalent to
2971 the command C<mount -o loop file mountpoint>.");
2972
2973   ("mkswap", (RErr, [Device "device"]), 130, [],
2974    [InitEmpty, Always, TestRun (
2975       [["part_disk"; "/dev/sda"; "mbr"];
2976        ["mkswap"; "/dev/sda1"]])],
2977    "create a swap partition",
2978    "\
2979 Create a swap partition on C<device>.");
2980
2981   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2982    [InitEmpty, Always, TestRun (
2983       [["part_disk"; "/dev/sda"; "mbr"];
2984        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2985    "create a swap partition with a label",
2986    "\
2987 Create a swap partition on C<device> with label C<label>.
2988
2989 Note that you cannot attach a swap label to a block device
2990 (eg. C</dev/sda>), just to a partition.  This appears to be
2991 a limitation of the kernel or swap tools.");
2992
2993   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2994    (let uuid = uuidgen () in
2995     [InitEmpty, Always, TestRun (
2996        [["part_disk"; "/dev/sda"; "mbr"];
2997         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2998    "create a swap partition with an explicit UUID",
2999    "\
3000 Create a swap partition on C<device> with UUID C<uuid>.");
3001
3002   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3003    [InitBasicFS, Always, TestOutputStruct (
3004       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3005        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3006        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3007     InitBasicFS, Always, TestOutputStruct (
3008       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3009        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3010    "make block, character or FIFO devices",
3011    "\
3012 This call creates block or character special devices, or
3013 named pipes (FIFOs).
3014
3015 The C<mode> parameter should be the mode, using the standard
3016 constants.  C<devmajor> and C<devminor> are the
3017 device major and minor numbers, only used when creating block
3018 and character special devices.
3019
3020 Note that, just like L<mknod(2)>, the mode must be bitwise
3021 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3022 just creates a regular file).  These constants are
3023 available in the standard Linux header files, or you can use
3024 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3025 which are wrappers around this command which bitwise OR
3026 in the appropriate constant for you.
3027
3028 The mode actually set is affected by the umask.");
3029
3030   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3031    [InitBasicFS, Always, TestOutputStruct (
3032       [["mkfifo"; "0o777"; "/node"];
3033        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3034    "make FIFO (named pipe)",
3035    "\
3036 This call creates a FIFO (named pipe) called C<path> with
3037 mode C<mode>.  It is just a convenient wrapper around
3038 C<guestfs_mknod>.
3039
3040 The mode actually set is affected by the umask.");
3041
3042   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3043    [InitBasicFS, Always, TestOutputStruct (
3044       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3045        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3046    "make block device node",
3047    "\
3048 This call creates a block device node called C<path> with
3049 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3050 It is just a convenient wrapper around C<guestfs_mknod>.
3051
3052 The mode actually set is affected by the umask.");
3053
3054   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3055    [InitBasicFS, Always, TestOutputStruct (
3056       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3057        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3058    "make char device node",
3059    "\
3060 This call creates a char device node called C<path> with
3061 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3062 It is just a convenient wrapper around C<guestfs_mknod>.
3063
3064 The mode actually set is affected by the umask.");
3065
3066   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3067    [InitEmpty, Always, TestOutputInt (
3068       [["umask"; "0o22"]], 0o22)],
3069    "set file mode creation mask (umask)",
3070    "\
3071 This function sets the mask used for creating new files and
3072 device nodes to C<mask & 0777>.
3073
3074 Typical umask values would be C<022> which creates new files
3075 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3076 C<002> which creates new files with permissions like
3077 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3078
3079 The default umask is C<022>.  This is important because it
3080 means that directories and device nodes will be created with
3081 C<0644> or C<0755> mode even if you specify C<0777>.
3082
3083 See also C<guestfs_get_umask>,
3084 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3085
3086 This call returns the previous umask.");
3087
3088   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3089    [],
3090    "read directories entries",
3091    "\
3092 This returns the list of directory entries in directory C<dir>.
3093
3094 All entries in the directory are returned, including C<.> and
3095 C<..>.  The entries are I<not> sorted, but returned in the same
3096 order as the underlying filesystem.
3097
3098 Also this call returns basic file type information about each
3099 file.  The C<ftyp> field will contain one of the following characters:
3100
3101 =over 4
3102
3103 =item 'b'
3104
3105 Block special
3106
3107 =item 'c'
3108
3109 Char special
3110
3111 =item 'd'
3112
3113 Directory
3114
3115 =item 'f'
3116
3117 FIFO (named pipe)
3118
3119 =item 'l'
3120
3121 Symbolic link
3122
3123 =item 'r'
3124
3125 Regular file
3126
3127 =item 's'
3128
3129 Socket
3130
3131 =item 'u'
3132
3133 Unknown file type
3134
3135 =item '?'
3136
3137 The L<readdir(3)> returned a C<d_type> field with an
3138 unexpected value
3139
3140 =back
3141
3142 This function is primarily intended for use by programs.  To
3143 get a simple list of names, use C<guestfs_ls>.  To get a printable
3144 directory for human consumption, use C<guestfs_ll>.");
3145
3146   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3147    [],
3148    "create partitions on a block device",
3149    "\
3150 This is a simplified interface to the C<guestfs_sfdisk>
3151 command, where partition sizes are specified in megabytes
3152 only (rounded to the nearest cylinder) and you don't need
3153 to specify the cyls, heads and sectors parameters which
3154 were rarely if ever used anyway.
3155
3156 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3157 and C<guestfs_part_disk>");
3158
3159   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3160    [],
3161    "determine file type inside a compressed file",
3162    "\
3163 This command runs C<file> after first decompressing C<path>
3164 using C<method>.
3165
3166 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3167
3168 Since 1.0.63, use C<guestfs_file> instead which can now
3169 process compressed files.");
3170
3171   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3172    [],
3173    "list extended attributes of a file or directory",
3174    "\
3175 This call lists the extended attributes of the file or directory
3176 C<path>.
3177
3178 At the system call level, this is a combination of the
3179 L<listxattr(2)> and L<getxattr(2)> calls.
3180
3181 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3182
3183   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3184    [],
3185    "list extended attributes of a file or directory",
3186    "\
3187 This is the same as C<guestfs_getxattrs>, but if C<path>
3188 is a symbolic link, then it returns the extended attributes
3189 of the link itself.");
3190
3191   ("setxattr", (RErr, [String "xattr";
3192                        String "val"; Int "vallen"; (* will be BufferIn *)
3193                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3194    [],
3195    "set extended attribute of a file or directory",
3196    "\
3197 This call sets the extended attribute named C<xattr>
3198 of the file C<path> to the value C<val> (of length C<vallen>).
3199 The value is arbitrary 8 bit data.
3200
3201 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3202
3203   ("lsetxattr", (RErr, [String "xattr";
3204                         String "val"; Int "vallen"; (* will be BufferIn *)
3205                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3206    [],
3207    "set extended attribute of a file or directory",
3208    "\
3209 This is the same as C<guestfs_setxattr>, but if C<path>
3210 is a symbolic link, then it sets an extended attribute
3211 of the link itself.");
3212
3213   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3214    [],
3215    "remove extended attribute of a file or directory",
3216    "\
3217 This call removes the extended attribute named C<xattr>
3218 of the file C<path>.
3219
3220 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3221
3222   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3223    [],
3224    "remove extended attribute of a file or directory",
3225    "\
3226 This is the same as C<guestfs_removexattr>, but if C<path>
3227 is a symbolic link, then it removes an extended attribute
3228 of the link itself.");
3229
3230   ("mountpoints", (RHashtable "mps", []), 147, [],
3231    [],
3232    "show mountpoints",
3233    "\
3234 This call is similar to C<guestfs_mounts>.  That call returns
3235 a list of devices.  This one returns a hash table (map) of
3236 device name to directory where the device is mounted.");
3237
3238   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3239    (* This is a special case: while you would expect a parameter
3240     * of type "Pathname", that doesn't work, because it implies
3241     * NEED_ROOT in the generated calling code in stubs.c, and
3242     * this function cannot use NEED_ROOT.
3243     *)
3244    [],
3245    "create a mountpoint",
3246    "\
3247 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3248 specialized calls that can be used to create extra mountpoints
3249 before mounting the first filesystem.
3250
3251 These calls are I<only> necessary in some very limited circumstances,
3252 mainly the case where you want to mount a mix of unrelated and/or
3253 read-only filesystems together.
3254
3255 For example, live CDs often contain a \"Russian doll\" nest of
3256 filesystems, an ISO outer layer, with a squashfs image inside, with
3257 an ext2/3 image inside that.  You can unpack this as follows
3258 in guestfish:
3259
3260  add-ro Fedora-11-i686-Live.iso
3261  run
3262  mkmountpoint /cd
3263  mkmountpoint /squash
3264  mkmountpoint /ext3
3265  mount /dev/sda /cd
3266  mount-loop /cd/LiveOS/squashfs.img /squash
3267  mount-loop /squash/LiveOS/ext3fs.img /ext3
3268
3269 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3270
3271   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3272    [],
3273    "remove a mountpoint",
3274    "\
3275 This calls removes a mountpoint that was previously created
3276 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3277 for full details.");
3278
3279   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3280    [InitISOFS, Always, TestOutputBuffer (
3281       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3282    "read a file",
3283    "\
3284 This calls returns the contents of the file C<path> as a
3285 buffer.
3286
3287 Unlike C<guestfs_cat>, this function can correctly
3288 handle files that contain embedded ASCII NUL characters.
3289 However unlike C<guestfs_download>, this function is limited
3290 in the total size of file that can be handled.");
3291
3292   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3293    [InitISOFS, Always, TestOutputList (
3294       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3295     InitISOFS, Always, TestOutputList (
3296       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3297    "return lines matching a pattern",
3298    "\
3299 This calls the external C<grep> program and returns the
3300 matching lines.");
3301
3302   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3303    [InitISOFS, Always, TestOutputList (
3304       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3305    "return lines matching a pattern",
3306    "\
3307 This calls the external C<egrep> program and returns the
3308 matching lines.");
3309
3310   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3311    [InitISOFS, Always, TestOutputList (
3312       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3313    "return lines matching a pattern",
3314    "\
3315 This calls the external C<fgrep> program and returns the
3316 matching lines.");
3317
3318   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3319    [InitISOFS, Always, TestOutputList (
3320       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3321    "return lines matching a pattern",
3322    "\
3323 This calls the external C<grep -i> program and returns the
3324 matching lines.");
3325
3326   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3327    [InitISOFS, Always, TestOutputList (
3328       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3329    "return lines matching a pattern",
3330    "\
3331 This calls the external C<egrep -i> program and returns the
3332 matching lines.");
3333
3334   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3335    [InitISOFS, Always, TestOutputList (
3336       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3337    "return lines matching a pattern",
3338    "\
3339 This calls the external C<fgrep -i> program and returns the
3340 matching lines.");
3341
3342   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3343    [InitISOFS, Always, TestOutputList (
3344       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3345    "return lines matching a pattern",
3346    "\
3347 This calls the external C<zgrep> program and returns the
3348 matching lines.");
3349
3350   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3351    [InitISOFS, Always, TestOutputList (
3352       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3353    "return lines matching a pattern",
3354    "\
3355 This calls the external C<zegrep> program and returns the
3356 matching lines.");
3357
3358   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3359    [InitISOFS, Always, TestOutputList (
3360       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3361    "return lines matching a pattern",
3362    "\
3363 This calls the external C<zfgrep> program and returns the
3364 matching lines.");
3365
3366   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3367    [InitISOFS, Always, TestOutputList (
3368       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3369    "return lines matching a pattern",
3370    "\
3371 This calls the external C<zgrep -i> program and returns the
3372 matching lines.");
3373
3374   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3375    [InitISOFS, Always, TestOutputList (
3376       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3377    "return lines matching a pattern",
3378    "\
3379 This calls the external C<zegrep -i> program and returns the
3380 matching lines.");
3381
3382   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3383    [InitISOFS, Always, TestOutputList (
3384       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3385    "return lines matching a pattern",
3386    "\
3387 This calls the external C<zfgrep -i> program and returns the
3388 matching lines.");
3389
3390   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3391    [InitISOFS, Always, TestOutput (
3392       [["realpath"; "/../directory"]], "/directory")],
3393    "canonicalized absolute pathname",
3394    "\
3395 Return the canonicalized absolute pathname of C<path>.  The
3396 returned path has no C<.>, C<..> or symbolic link path elements.");
3397
3398   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3399    [InitBasicFS, Always, TestOutputStruct (
3400       [["touch"; "/a"];
3401        ["ln"; "/a"; "/b"];
3402        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3403    "create a hard link",
3404    "\
3405 This command creates a hard link using the C<ln> command.");
3406
3407   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3408    [InitBasicFS, Always, TestOutputStruct (
3409       [["touch"; "/a"];
3410        ["touch"; "/b"];
3411        ["ln_f"; "/a"; "/b"];
3412        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3413    "create a hard link",
3414    "\
3415 This command creates a hard link using the C<ln -f> command.
3416 The C<-f> option removes the link (C<linkname>) if it exists already.");
3417
3418   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3419    [InitBasicFS, Always, TestOutputStruct (
3420       [["touch"; "/a"];
3421        ["ln_s"; "a"; "/b"];
3422        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3423    "create a symbolic link",
3424    "\
3425 This command creates a symbolic link using the C<ln -s> command.");
3426
3427   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3428    [InitBasicFS, Always, TestOutput (
3429       [["mkdir_p"; "/a/b"];
3430        ["touch"; "/a/b/c"];
3431        ["ln_sf"; "../d"; "/a/b/c"];
3432        ["readlink"; "/a/b/c"]], "../d")],
3433    "create a symbolic link",
3434    "\
3435 This command creates a symbolic link using the C<ln -sf> command,
3436 The C<-f> option removes the link (C<linkname>) if it exists already.");
3437
3438   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3439    [] (* XXX tested above *),
3440    "read the target of a symbolic link",
3441    "\
3442 This command reads the target of a symbolic link.");
3443
3444   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3445    [InitBasicFS, Always, TestOutputStruct (
3446       [["fallocate"; "/a"; "1000000"];
3447        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3448    "preallocate a file in the guest filesystem",
3449    "\
3450 This command preallocates a file (containing zero bytes) named
3451 C<path> of size C<len> bytes.  If the file exists already, it
3452 is overwritten.
3453
3454 Do not confuse this with the guestfish-specific
3455 C<alloc> command which allocates a file in the host and
3456 attaches it as a device.");
3457
3458   ("swapon_device", (RErr, [Device "device"]), 170, [],
3459    [InitPartition, Always, TestRun (
3460       [["mkswap"; "/dev/sda1"];
3461        ["swapon_device"; "/dev/sda1"];
3462        ["swapoff_device"; "/dev/sda1"]])],
3463    "enable swap on device",
3464    "\
3465 This command enables the libguestfs appliance to use the
3466 swap device or partition named C<device>.  The increased
3467 memory is made available for all commands, for example
3468 those run using C<guestfs_command> or C<guestfs_sh>.
3469
3470 Note that you should not swap to existing guest swap
3471 partitions unless you know what you are doing.  They may
3472 contain hibernation information, or other information that
3473 the guest doesn't want you to trash.  You also risk leaking
3474 information about the host to the guest this way.  Instead,
3475 attach a new host device to the guest and swap on that.");
3476
3477   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3478    [], (* XXX tested by swapon_device *)
3479    "disable swap on device",
3480    "\
3481 This command disables the libguestfs appliance swap
3482 device or partition named C<device>.
3483 See C<guestfs_swapon_device>.");
3484
3485   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3486    [InitBasicFS, Always, TestRun (
3487       [["fallocate"; "/swap"; "8388608"];
3488        ["mkswap_file"; "/swap"];
3489        ["swapon_file"; "/swap"];
3490        ["swapoff_file"; "/swap"]])],
3491    "enable swap on file",
3492    "\
3493 This command enables swap to a file.
3494 See C<guestfs_swapon_device> for other notes.");
3495
3496   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3497    [], (* XXX tested by swapon_file *)
3498    "disable swap on file",
3499    "\
3500 This command disables the libguestfs appliance swap on file.");
3501
3502   ("swapon_label", (RErr, [String "label"]), 174, [],
3503    [InitEmpty, Always, TestRun (
3504       [["part_disk"; "/dev/sdb"; "mbr"];
3505        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3506        ["swapon_label"; "swapit"];
3507        ["swapoff_label"; "swapit"];
3508        ["zero"; "/dev/sdb"];
3509        ["blockdev_rereadpt"; "/dev/sdb"]])],
3510    "enable swap on labeled swap partition",
3511    "\
3512 This command enables swap to a labeled swap partition.
3513 See C<guestfs_swapon_device> for other notes.");
3514
3515   ("swapoff_label", (RErr, [String "label"]), 175, [],
3516    [], (* XXX tested by swapon_label *)
3517    "disable swap on labeled swap partition",
3518    "\
3519 This command disables the libguestfs appliance swap on
3520 labeled swap partition.");
3521
3522   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3523    (let uuid = uuidgen () in
3524     [InitEmpty, Always, TestRun (
3525        [["mkswap_U"; uuid; "/dev/sdb"];
3526         ["swapon_uuid"; uuid];
3527         ["swapoff_uuid"; uuid]])]),
3528    "enable swap on swap partition by UUID",
3529    "\
3530 This command enables swap to a swap partition with the given UUID.
3531 See C<guestfs_swapon_device> for other notes.");
3532
3533   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3534    [], (* XXX tested by swapon_uuid *)
3535    "disable swap on swap partition by UUID",
3536    "\
3537 This command disables the libguestfs appliance swap partition
3538 with the given UUID.");
3539
3540   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3541    [InitBasicFS, Always, TestRun (
3542       [["fallocate"; "/swap"; "8388608"];
3543        ["mkswap_file"; "/swap"]])],
3544    "create a swap file",
3545    "\
3546 Create a swap file.
3547
3548 This command just writes a swap file signature to an existing
3549 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3550
3551   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3552    [InitISOFS, Always, TestRun (
3553       [["inotify_init"; "0"]])],
3554    "create an inotify handle",
3555    "\
3556 This command creates a new inotify handle.
3557 The inotify subsystem can be used to notify events which happen to
3558 objects in the guest filesystem.
3559
3560 C<maxevents> is the maximum number of events which will be
3561 queued up between calls to C<guestfs_inotify_read> or
3562 C<guestfs_inotify_files>.
3563 If this is passed as C<0>, then the kernel (or previously set)
3564 default is used.  For Linux 2.6.29 the default was 16384 events.
3565 Beyond this limit, the kernel throws away events, but records
3566 the fact that it threw them away by setting a flag
3567 C<IN_Q_OVERFLOW> in the returned structure list (see
3568 C<guestfs_inotify_read>).
3569
3570 Before any events are generated, you have to add some
3571 watches to the internal watch list.  See:
3572 C<guestfs_inotify_add_watch>,
3573 C<guestfs_inotify_rm_watch> and
3574 C<guestfs_inotify_watch_all>.
3575
3576 Queued up events should be read periodically by calling
3577 C<guestfs_inotify_read>
3578 (or C<guestfs_inotify_files> which is just a helpful
3579 wrapper around C<guestfs_inotify_read>).  If you don't
3580 read the events out often enough then you risk the internal
3581 queue overflowing.
3582
3583 The handle should be closed after use by calling
3584 C<guestfs_inotify_close>.  This also removes any
3585 watches automatically.
3586
3587 See also L<inotify(7)> for an overview of the inotify interface
3588 as exposed by the Linux kernel, which is roughly what we expose
3589 via libguestfs.  Note that there is one global inotify handle
3590 per libguestfs instance.");
3591
3592   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3593    [InitBasicFS, Always, TestOutputList (
3594       [["inotify_init"; "0"];
3595        ["inotify_add_watch"; "/"; "1073741823"];
3596        ["touch"; "/a"];
3597        ["touch"; "/b"];
3598        ["inotify_files"]], ["a"; "b"])],
3599    "add an inotify watch",
3600    "\
3601 Watch C<path> for the events listed in C<mask>.
3602
3603 Note that if C<path> is a directory then events within that
3604 directory are watched, but this does I<not> happen recursively
3605 (in subdirectories).
3606
3607 Note for non-C or non-Linux callers: the inotify events are
3608 defined by the Linux kernel ABI and are listed in
3609 C</usr/include/sys/inotify.h>.");
3610
3611   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3612    [],
3613    "remove an inotify watch",
3614    "\
3615 Remove a previously defined inotify watch.
3616 See C<guestfs_inotify_add_watch>.");
3617
3618   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3619    [],
3620    "return list of inotify events",
3621    "\
3622 Return the complete queue of events that have happened
3623 since the previous read call.
3624
3625 If no events have happened, this returns an empty list.
3626
3627 I<Note>: In order to make sure that all events have been
3628 read, you must call this function repeatedly until it
3629 returns an empty list.  The reason is that the call will
3630 read events up to the maximum appliance-to-host message
3631 size and leave remaining events in the queue.");
3632
3633   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3634    [],
3635    "return list of watched files that had events",
3636    "\
3637 This function is a helpful wrapper around C<guestfs_inotify_read>
3638 which just returns a list of pathnames of objects that were
3639 touched.  The returned pathnames are sorted and deduplicated.");
3640
3641   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3642    [],
3643    "close the inotify handle",
3644    "\
3645 This closes the inotify handle which was previously
3646 opened by inotify_init.  It removes all watches, throws
3647 away any pending events, and deallocates all resources.");
3648
3649   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3650    [],
3651    "set SELinux security context",
3652    "\
3653 This sets the SELinux security context of the daemon
3654 to the string C<context>.
3655
3656 See the documentation about SELINUX in L<guestfs(3)>.");
3657
3658   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3659    [],
3660    "get SELinux security context",
3661    "\
3662 This gets the SELinux security context of the daemon.
3663
3664 See the documentation about SELINUX in L<guestfs(3)>,
3665 and C<guestfs_setcon>");
3666
3667   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3668    [InitEmpty, Always, TestOutput (
3669       [["part_disk"; "/dev/sda"; "mbr"];
3670        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3671        ["mount_options"; ""; "/dev/sda1"; "/"];
3672        ["write_file"; "/new"; "new file contents"; "0"];
3673        ["cat"; "/new"]], "new file contents")],
3674    "make a filesystem with block size",
3675    "\
3676 This call is similar to C<guestfs_mkfs>, but it allows you to
3677 control the block size of the resulting filesystem.  Supported
3678 block sizes depend on the filesystem type, but typically they
3679 are C<1024>, C<2048> or C<4096> only.");
3680
3681   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3682    [InitEmpty, Always, TestOutput (
3683       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3684        ["mke2journal"; "4096"; "/dev/sda1"];
3685        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3686        ["mount_options"; ""; "/dev/sda2"; "/"];
3687        ["write_file"; "/new"; "new file contents"; "0"];
3688        ["cat"; "/new"]], "new file contents")],
3689    "make ext2/3/4 external journal",
3690    "\
3691 This creates an ext2 external journal on C<device>.  It is equivalent
3692 to the command:
3693
3694  mke2fs -O journal_dev -b blocksize device");
3695
3696   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3697    [InitEmpty, Always, TestOutput (
3698       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3699        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3700        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3701        ["mount_options"; ""; "/dev/sda2"; "/"];
3702        ["write_file"; "/new"; "new file contents"; "0"];
3703        ["cat"; "/new"]], "new file contents")],
3704    "make ext2/3/4 external journal with label",
3705    "\
3706 This creates an ext2 external journal on C<device> with label C<label>.");
3707
3708   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3709    (let uuid = uuidgen () in
3710     [InitEmpty, Always, TestOutput (
3711        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3712         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3713         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3714         ["mount_options"; ""; "/dev/sda2"; "/"];
3715         ["write_file"; "/new"; "new file contents"; "0"];
3716         ["cat"; "/new"]], "new file contents")]),
3717    "make ext2/3/4 external journal with UUID",
3718    "\
3719 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3720
3721   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3722    [],
3723    "make ext2/3/4 filesystem with external journal",
3724    "\
3725 This creates an ext2/3/4 filesystem on C<device> with
3726 an external journal on C<journal>.  It is equivalent
3727 to the command:
3728
3729  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3730
3731 See also C<guestfs_mke2journal>.");
3732
3733   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3734    [],
3735    "make ext2/3/4 filesystem with external journal",
3736    "\
3737 This creates an ext2/3/4 filesystem on C<device> with
3738 an external journal on the journal labeled C<label>.
3739
3740 See also C<guestfs_mke2journal_L>.");
3741
3742   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3743    [],
3744    "make ext2/3/4 filesystem with external journal",
3745    "\
3746 This creates an ext2/3/4 filesystem on C<device> with
3747 an external journal on the journal with UUID C<uuid>.
3748
3749 See also C<guestfs_mke2journal_U>.");
3750
3751   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3752    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3753    "load a kernel module",
3754    "\
3755 This loads a kernel module in the appliance.
3756
3757 The kernel module must have been whitelisted when libguestfs
3758 was built (see C<appliance/kmod.whitelist.in> in the source).");
3759
3760   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3761    [InitNone, Always, TestOutput (
3762       [["echo_daemon"; "This is a test"]], "This is a test"
3763     )],
3764    "echo arguments back to the client",
3765    "\
3766 This command concatenate the list of C<words> passed with single spaces between
3767 them and returns the resulting string.
3768
3769 You can use this command to test the connection through to the daemon.
3770
3771 See also C<guestfs_ping_daemon>.");
3772
3773   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3774    [], (* There is a regression test for this. *)
3775    "find all files and directories, returning NUL-separated list",
3776    "\
3777 This command lists out all files and directories, recursively,
3778 starting at C<directory>, placing the resulting list in the
3779 external file called C<files>.
3780
3781 This command works the same way as C<guestfs_find> with the
3782 following exceptions:
3783
3784 =over 4
3785
3786 =item *
3787
3788 The resulting list is written to an external file.
3789
3790 =item *
3791
3792 Items (filenames) in the result are separated
3793 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3794
3795 =item *
3796
3797 This command is not limited in the number of names that it
3798 can return.
3799
3800 =item *
3801
3802 The result list is not sorted.
3803
3804 =back");
3805
3806   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3807    [InitISOFS, Always, TestOutput (
3808       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3809     InitISOFS, Always, TestOutput (
3810       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3811     InitISOFS, Always, TestOutput (
3812       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3813     InitISOFS, Always, TestLastFail (
3814       [["case_sensitive_path"; "/Known-1/"]]);
3815     InitBasicFS, Always, TestOutput (
3816       [["mkdir"; "/a"];
3817        ["mkdir"; "/a/bbb"];
3818        ["touch"; "/a/bbb/c"];
3819        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3820     InitBasicFS, Always, TestOutput (
3821       [["mkdir"; "/a"];
3822        ["mkdir"; "/a/bbb"];
3823        ["touch"; "/a/bbb/c"];
3824        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3825     InitBasicFS, Always, TestLastFail (
3826       [["mkdir"; "/a"];
3827        ["mkdir"; "/a/bbb"];
3828        ["touch"; "/a/bbb/c"];
3829        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3830    "return true path on case-insensitive filesystem",
3831    "\
3832 This can be used to resolve case insensitive paths on
3833 a filesystem which is case sensitive.  The use case is
3834 to resolve paths which you have read from Windows configuration
3835 files or the Windows Registry, to the true path.
3836
3837 The command handles a peculiarity of the Linux ntfs-3g
3838 filesystem driver (and probably others), which is that although
3839 the underlying filesystem is case-insensitive, the driver
3840 exports the filesystem to Linux as case-sensitive.
3841
3842 One consequence of this is that special directories such
3843 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3844 (or other things) depending on the precise details of how
3845 they were created.  In Windows itself this would not be
3846 a problem.
3847
3848 Bug or feature?  You decide:
3849 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3850
3851 This function resolves the true case of each element in the
3852 path and returns the case-sensitive path.
3853
3854 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3855 might return C<\"/WINDOWS/system32\"> (the exact return value
3856 would depend on details of how the directories were originally
3857 created under Windows).
3858
3859 I<Note>:
3860 This function does not handle drive names, backslashes etc.
3861
3862 See also C<guestfs_realpath>.");
3863
3864   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3865    [InitBasicFS, Always, TestOutput (
3866       [["vfs_type"; "/dev/sda1"]], "ext2")],
3867    "get the Linux VFS type corresponding to a mounted device",
3868    "\
3869 This command gets the block device type corresponding to
3870 a mounted device called C<device>.
3871
3872 Usually the result is the name of the Linux VFS module that
3873 is used to mount this device (probably determined automatically
3874 if you used the C<guestfs_mount> call).");
3875
3876   ("truncate", (RErr, [Pathname "path"]), 199, [],
3877    [InitBasicFS, Always, TestOutputStruct (
3878       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3879        ["truncate"; "/test"];
3880        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3881    "truncate a file to zero size",
3882    "\
3883 This command truncates C<path> to a zero-length file.  The
3884 file must exist already.");
3885
3886   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3887    [InitBasicFS, Always, TestOutputStruct (
3888       [["touch"; "/test"];
3889        ["truncate_size"; "/test"; "1000"];
3890        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3891    "truncate a file to a particular size",
3892    "\
3893 This command truncates C<path> to size C<size> bytes.  The file
3894 must exist already.  If the file is smaller than C<size> then
3895 the file is extended to the required size with null bytes.");
3896
3897   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3898    [InitBasicFS, Always, TestOutputStruct (
3899       [["touch"; "/test"];
3900        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3901        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3902    "set timestamp of a file with nanosecond precision",
3903    "\
3904 This command sets the timestamps of a file with nanosecond
3905 precision.
3906
3907 C<atsecs, atnsecs> are the last access time (atime) in secs and
3908 nanoseconds from the epoch.
3909
3910 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3911 secs and nanoseconds from the epoch.
3912
3913 If the C<*nsecs> field contains the special value C<-1> then
3914 the corresponding timestamp is set to the current time.  (The
3915 C<*secs> field is ignored in this case).
3916
3917 If the C<*nsecs> field contains the special value C<-2> then
3918 the corresponding timestamp is left unchanged.  (The
3919 C<*secs> field is ignored in this case).");
3920
3921   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3922    [InitBasicFS, Always, TestOutputStruct (
3923       [["mkdir_mode"; "/test"; "0o111"];
3924        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3925    "create a directory with a particular mode",
3926    "\
3927 This command creates a directory, setting the initial permissions
3928 of the directory to C<mode>.
3929
3930 For common Linux filesystems, the actual mode which is set will
3931 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3932 interpret the mode in other ways.
3933
3934 See also C<guestfs_mkdir>, C<guestfs_umask>");
3935
3936   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3937    [], (* XXX *)
3938    "change file owner and group",
3939    "\
3940 Change the file owner to C<owner> and group to C<group>.
3941 This is like C<guestfs_chown> but if C<path> is a symlink then
3942 the link itself is changed, not the target.
3943
3944 Only numeric uid and gid are supported.  If you want to use
3945 names, you will need to locate and parse the password file
3946 yourself (Augeas support makes this relatively easy).");
3947
3948   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3949    [], (* XXX *)
3950    "lstat on multiple files",
3951    "\
3952 This call allows you to perform the C<guestfs_lstat> operation
3953 on multiple files, where all files are in the directory C<path>.
3954 C<names> is the list of files from this directory.
3955
3956 On return you get a list of stat structs, with a one-to-one
3957 correspondence to the C<names> list.  If any name did not exist
3958 or could not be lstat'd, then the C<ino> field of that structure
3959 is set to C<-1>.
3960
3961 This call is intended for programs that want to efficiently
3962 list a directory contents without making many round-trips.
3963 See also C<guestfs_lxattrlist> for a similarly efficient call
3964 for getting extended attributes.  Very long directory listings
3965 might cause the protocol message size to be exceeded, causing
3966 this call to fail.  The caller must split up such requests
3967 into smaller groups of names.");
3968
3969   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3970    [], (* XXX *)
3971    "lgetxattr on multiple files",
3972    "\
3973 This call allows you to get the extended attributes
3974 of multiple files, where all files are in the directory C<path>.
3975 C<names> is the list of files from this directory.
3976
3977 On return you get a flat list of xattr structs which must be
3978 interpreted sequentially.  The first xattr struct always has a zero-length
3979 C<attrname>.  C<attrval> in this struct is zero-length
3980 to indicate there was an error doing C<lgetxattr> for this
3981 file, I<or> is a C string which is a decimal number
3982 (the number of following attributes for this file, which could
3983 be C<\"0\">).  Then after the first xattr struct are the
3984 zero or more attributes for the first named file.
3985 This repeats for the second and subsequent files.
3986
3987 This call is intended for programs that want to efficiently
3988 list a directory contents without making many round-trips.
3989 See also C<guestfs_lstatlist> for a similarly efficient call
3990 for getting standard stats.  Very long directory listings
3991 might cause the protocol message size to be exceeded, causing
3992 this call to fail.  The caller must split up such requests
3993 into smaller groups of names.");
3994
3995   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3996    [], (* XXX *)
3997    "readlink on multiple files",
3998    "\
3999 This call allows you to do a C<readlink> operation
4000 on multiple files, where all files are in the directory C<path>.
4001 C<names> is the list of files from this directory.
4002
4003 On return you get a list of strings, with a one-to-one
4004 correspondence to the C<names> list.  Each string is the
4005 value of the symbol link.
4006
4007 If the C<readlink(2)> operation fails on any name, then
4008 the corresponding result string is the empty string C<\"\">.
4009 However the whole operation is completed even if there
4010 were C<readlink(2)> errors, and so you can call this
4011 function with names where you don't know if they are
4012 symbolic links already (albeit slightly less efficient).
4013
4014 This call is intended for programs that want to efficiently
4015 list a directory contents without making many round-trips.
4016 Very long directory listings might cause the protocol
4017 message size to be exceeded, causing
4018 this call to fail.  The caller must split up such requests
4019 into smaller groups of names.");
4020
4021   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4022    [InitISOFS, Always, TestOutputBuffer (
4023       [["pread"; "/known-4"; "1"; "3"]], "\n");
4024     InitISOFS, Always, TestOutputBuffer (
4025       [["pread"; "/empty"; "0"; "100"]], "")],
4026    "read part of a file",
4027    "\
4028 This command lets you read part of a file.  It reads C<count>
4029 bytes of the file, starting at C<offset>, from file C<path>.
4030
4031 This may read fewer bytes than requested.  For further details
4032 see the L<pread(2)> system call.");
4033
4034   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4035    [InitEmpty, Always, TestRun (
4036       [["part_init"; "/dev/sda"; "gpt"]])],
4037    "create an empty partition table",
4038    "\
4039 This creates an empty partition table on C<device> of one of the
4040 partition types listed below.  Usually C<parttype> should be
4041 either C<msdos> or C<gpt> (for large disks).
4042
4043 Initially there are no partitions.  Following this, you should
4044 call C<guestfs_part_add> for each partition required.
4045
4046 Possible values for C<parttype> are:
4047
4048 =over 4
4049
4050 =item B<efi> | B<gpt>
4051
4052 Intel EFI / GPT partition table.
4053
4054 This is recommended for >= 2 TB partitions that will be accessed
4055 from Linux and Intel-based Mac OS X.  It also has limited backwards
4056 compatibility with the C<mbr> format.
4057
4058 =item B<mbr> | B<msdos>
4059
4060 The standard PC \"Master Boot Record\" (MBR) format used
4061 by MS-DOS and Windows.  This partition type will B<only> work
4062 for device sizes up to 2 TB.  For large disks we recommend
4063 using C<gpt>.
4064
4065 =back
4066
4067 Other partition table types that may work but are not
4068 supported include:
4069
4070 =over 4
4071
4072 =item B<aix>
4073
4074 AIX disk labels.
4075
4076 =item B<amiga> | B<rdb>
4077
4078 Amiga \"Rigid Disk Block\" format.
4079
4080 =item B<bsd>
4081
4082 BSD disk labels.
4083
4084 =item B<dasd>
4085
4086 DASD, used on IBM mainframes.
4087
4088 =item B<dvh>
4089
4090 MIPS/SGI volumes.
4091
4092 =item B<mac>
4093
4094 Old Mac partition format.  Modern Macs use C<gpt>.
4095
4096 =item B<pc98>
4097
4098 NEC PC-98 format, common in Japan apparently.
4099
4100 =item B<sun>
4101
4102 Sun disk labels.
4103
4104 =back");
4105
4106   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4107    [InitEmpty, Always, TestRun (
4108       [["part_init"; "/dev/sda"; "mbr"];
4109        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4110     InitEmpty, Always, TestRun (
4111       [["part_init"; "/dev/sda"; "gpt"];
4112        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4113        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4114     InitEmpty, Always, TestRun (
4115       [["part_init"; "/dev/sda"; "mbr"];
4116        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4117        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4118        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4119        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4120    "add a partition to the device",
4121    "\
4122 This command adds a partition to C<device>.  If there is no partition
4123 table on the device, call C<guestfs_part_init> first.
4124
4125 The C<prlogex> parameter is the type of partition.  Normally you
4126 should pass C<p> or C<primary> here, but MBR partition tables also
4127 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4128 types.
4129
4130 C<startsect> and C<endsect> are the start and end of the partition
4131 in I<sectors>.  C<endsect> may be negative, which means it counts
4132 backwards from the end of the disk (C<-1> is the last sector).
4133
4134 Creating a partition which covers the whole disk is not so easy.
4135 Use C<guestfs_part_disk> to do that.");
4136
4137   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4138    [InitEmpty, Always, TestRun (
4139       [["part_disk"; "/dev/sda"; "mbr"]]);
4140     InitEmpty, Always, TestRun (
4141       [["part_disk"; "/dev/sda"; "gpt"]])],
4142    "partition whole disk with a single primary partition",
4143    "\
4144 This command is simply a combination of C<guestfs_part_init>
4145 followed by C<guestfs_part_add> to create a single primary partition
4146 covering the whole disk.
4147
4148 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4149 but other possible values are described in C<guestfs_part_init>.");
4150
4151   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4152    [InitEmpty, Always, TestRun (
4153       [["part_disk"; "/dev/sda"; "mbr"];
4154        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4155    "make a partition bootable",
4156    "\
4157 This sets the bootable flag on partition numbered C<partnum> on
4158 device C<device>.  Note that partitions are numbered from 1.
4159
4160 The bootable flag is used by some operating systems (notably
4161 Windows) to determine which partition to boot from.  It is by
4162 no means universally recognized.");
4163
4164   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4165    [InitEmpty, Always, TestRun (
4166       [["part_disk"; "/dev/sda"; "gpt"];
4167        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4168    "set partition name",
4169    "\
4170 This sets the partition name on partition numbered C<partnum> on
4171 device C<device>.  Note that partitions are numbered from 1.
4172
4173 The partition name can only be set on certain types of partition
4174 table.  This works on C<gpt> but not on C<mbr> partitions.");
4175
4176   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4177    [], (* XXX Add a regression test for this. *)
4178    "list partitions on a device",
4179    "\
4180 This command parses the partition table on C<device> and
4181 returns the list of partitions found.
4182
4183 The fields in the returned structure are:
4184
4185 =over 4
4186
4187 =item B<part_num>
4188
4189 Partition number, counting from 1.
4190
4191 =item B<part_start>
4192
4193 Start of the partition I<in bytes>.  To get sectors you have to
4194 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4195
4196 =item B<part_end>
4197
4198 End of the partition in bytes.
4199
4200 =item B<part_size>
4201
4202 Size of the partition in bytes.
4203
4204 =back");
4205
4206   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4207    [InitEmpty, Always, TestOutput (
4208       [["part_disk"; "/dev/sda"; "gpt"];
4209        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4210    "get the partition table type",
4211    "\
4212 This command examines the partition table on C<device> and
4213 returns the partition table type (format) being used.
4214
4215 Common return values include: C<msdos> (a DOS/Windows style MBR
4216 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4217 values are possible, although unusual.  See C<guestfs_part_init>
4218 for a full list.");
4219
4220   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4221    [InitBasicFS, Always, TestOutputBuffer (
4222       [["fill"; "0x63"; "10"; "/test"];
4223        ["read_file"; "/test"]], "cccccccccc")],
4224    "fill a file with octets",
4225    "\
4226 This command creates a new file called C<path>.  The initial
4227 content of the file is C<len> octets of C<c>, where C<c>
4228 must be a number in the range C<[0..255]>.
4229
4230 To fill a file with zero bytes (sparsely), it is
4231 much more efficient to use C<guestfs_truncate_size>.");
4232
4233   ("available", (RErr, [StringList "groups"]), 216, [],
4234    [InitNone, Always, TestRun [["available"; ""]]],
4235    "test availability of some parts of the API",
4236    "\
4237 This command is used to check the availability of some
4238 groups of functionality in the appliance, which not all builds of
4239 the libguestfs appliance will be able to provide.
4240
4241 The libguestfs groups, and the functions that those
4242 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4243
4244 The argument C<groups> is a list of group names, eg:
4245 C<[\"inotify\", \"augeas\"]> would check for the availability of
4246 the Linux inotify functions and Augeas (configuration file
4247 editing) functions.
4248
4249 The command returns no error if I<all> requested groups are available.
4250
4251 It fails with an error if one or more of the requested
4252 groups is unavailable in the appliance.
4253
4254 If an unknown group name is included in the
4255 list of groups then an error is always returned.
4256
4257 I<Notes:>
4258
4259 =over 4
4260
4261 =item *
4262
4263 You must call C<guestfs_launch> before calling this function.
4264
4265 The reason is because we don't know what groups are
4266 supported by the appliance/daemon until it is running and can
4267 be queried.
4268
4269 =item *
4270
4271 If a group of functions is available, this does not necessarily
4272 mean that they will work.  You still have to check for errors
4273 when calling individual API functions even if they are
4274 available.
4275
4276 =item *
4277
4278 It is usually the job of distro packagers to build
4279 complete functionality into the libguestfs appliance.
4280 Upstream libguestfs, if built from source with all
4281 requirements satisfied, will support everything.
4282
4283 =item *
4284
4285 This call was added in version C<1.0.80>.  In previous
4286 versions of libguestfs all you could do would be to speculatively
4287 execute a command to find out if the daemon implemented it.
4288 See also C<guestfs_version>.
4289
4290 =back");
4291
4292   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4293    [InitBasicFS, Always, TestOutputBuffer (
4294       [["write_file"; "/src"; "hello, world"; "0"];
4295        ["dd"; "/src"; "/dest"];
4296        ["read_file"; "/dest"]], "hello, world")],
4297    "copy from source to destination using dd",
4298    "\
4299 This command copies from one source device or file C<src>
4300 to another destination device or file C<dest>.  Normally you
4301 would use this to copy to or from a device or partition, for
4302 example to duplicate a filesystem.
4303
4304 If the destination is a device, it must be as large or larger
4305 than the source file or device, otherwise the copy will fail.
4306 This command cannot do partial copies (see C<guestfs_copy_size>).");
4307
4308   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4309    [InitBasicFS, Always, TestOutputInt (
4310       [["write_file"; "/file"; "hello, world"; "0"];
4311        ["filesize"; "/file"]], 12)],
4312    "return the size of the file in bytes",
4313    "\
4314 This command returns the size of C<file> in bytes.
4315
4316 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4317 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4318 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4319
4320   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4321    [InitBasicFSonLVM, Always, TestOutputList (
4322       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4323        ["lvs"]], ["/dev/VG/LV2"])],
4324    "rename an LVM logical volume",
4325    "\
4326 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4327
4328   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4329    [InitBasicFSonLVM, Always, TestOutputList (
4330       [["umount"; "/"];
4331        ["vg_activate"; "false"; "VG"];
4332        ["vgrename"; "VG"; "VG2"];
4333        ["vg_activate"; "true"; "VG2"];
4334        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4335        ["vgs"]], ["VG2"])],
4336    "rename an LVM volume group",
4337    "\
4338 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4339
4340   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4341    [InitISOFS, Always, TestOutputBuffer (
4342       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4343    "list the contents of a single file in an initrd",
4344    "\
4345 This command unpacks the file C<filename> from the initrd file
4346 called C<initrdpath>.  The filename must be given I<without> the
4347 initial C</> character.
4348
4349 For example, in guestfish you could use the following command
4350 to examine the boot script (usually called C</init>)
4351 contained in a Linux initrd or initramfs image:
4352
4353  initrd-cat /boot/initrd-<version>.img init
4354
4355 See also C<guestfs_initrd_list>.");
4356
4357   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4358    [],
4359    "get the UUID of a physical volume",
4360    "\
4361 This command returns the UUID of the LVM PV C<device>.");
4362
4363   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4364    [],
4365    "get the UUID of a volume group",
4366    "\
4367 This command returns the UUID of the LVM VG named C<vgname>.");
4368
4369   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4370    [],
4371    "get the UUID of a logical volume",
4372    "\
4373 This command returns the UUID of the LVM LV C<device>.");
4374
4375   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4376    [],
4377    "get the PV UUIDs containing the volume group",
4378    "\
4379 Given a VG called C<vgname>, this returns the UUIDs of all
4380 the physical volumes that this volume group resides on.
4381
4382 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4383 calls to associate physical volumes and volume groups.
4384
4385 See also C<guestfs_vglvuuids>.");
4386
4387   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4388    [],
4389    "get the LV UUIDs of all LVs in the volume group",
4390    "\
4391 Given a VG called C<vgname>, this returns the UUIDs of all
4392 the logical volumes created in this volume group.
4393
4394 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4395 calls to associate logical volumes and volume groups.
4396
4397 See also C<guestfs_vgpvuuids>.");
4398
4399   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4400    [InitBasicFS, Always, TestOutputBuffer (
4401       [["write_file"; "/src"; "hello, world"; "0"];
4402        ["copy_size"; "/src"; "/dest"; "5"];
4403        ["read_file"; "/dest"]], "hello")],
4404    "copy size bytes from source to destination using dd",
4405    "\
4406 This command copies exactly C<size> bytes from one source device
4407 or file C<src> to another destination device or file C<dest>.
4408
4409 Note this will fail if the source is too short or if the destination
4410 is not large enough.");
4411
4412   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4413    [InitBasicFSonLVM, Always, TestRun (
4414       [["zero_device"; "/dev/VG/LV"]])],
4415    "write zeroes to an entire device",
4416    "\
4417 This command writes zeroes over the entire C<device>.  Compare
4418 with C<guestfs_zero> which just zeroes the first few blocks of
4419 a device.");
4420
4421   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4422    [InitBasicFS, Always, TestOutput (
4423       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4424        ["cat"; "/hello"]], "hello\n")],
4425    "unpack compressed tarball to directory",
4426    "\
4427 This command uploads and unpacks local file C<tarball> (an
4428 I<xz compressed> tar file) into C<directory>.");
4429
4430   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4431    [],
4432    "pack directory into compressed tarball",
4433    "\
4434 This command packs the contents of C<directory> and downloads
4435 it to local file C<tarball> (as an xz compressed tar archive).");
4436
4437   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4438    [],
4439    "resize an NTFS filesystem",
4440    "\
4441 This command resizes an NTFS filesystem, expanding or
4442 shrinking it to the size of the underlying device.
4443 See also L<ntfsresize(8)>.");
4444
4445   ("vgscan", (RErr, []), 232, [],
4446    [InitEmpty, Always, TestRun (
4447       [["vgscan"]])],
4448    "rescan for LVM physical volumes, volume groups and logical volumes",
4449    "\
4450 This rescans all block devices and rebuilds the list of LVM
4451 physical volumes, volume groups and logical volumes.");
4452
4453   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4454    [InitEmpty, Always, TestRun (
4455       [["part_init"; "/dev/sda"; "mbr"];
4456        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4457        ["part_del"; "/dev/sda"; "1"]])],
4458    "delete a partition",
4459    "\
4460 This command deletes the partition numbered C<partnum> on C<device>.
4461
4462 Note that in the case of MBR partitioning, deleting an
4463 extended partition also deletes any logical partitions
4464 it contains.");
4465
4466   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4467    [InitEmpty, Always, TestOutputTrue (
4468       [["part_init"; "/dev/sda"; "mbr"];
4469        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4470        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4471        ["part_get_bootable"; "/dev/sda"; "1"]])],
4472    "return true if a partition is bootable",
4473    "\
4474 This command returns true if the partition C<partnum> on
4475 C<device> has the bootable flag set.
4476
4477 See also C<guestfs_part_set_bootable>.");
4478
4479   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4480    [InitEmpty, Always, TestOutputInt (
4481       [["part_init"; "/dev/sda"; "mbr"];
4482        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4483        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4484        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4485    "get the MBR type byte (ID byte) from a partition",
4486    "\
4487 Returns the MBR type byte (also known as the ID byte) from
4488 the numbered partition C<partnum>.
4489
4490 Note that only MBR (old DOS-style) partitions have type bytes.
4491 You will get undefined results for other partition table
4492 types (see C<guestfs_part_get_parttype>).");
4493
4494   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4495    [], (* tested by part_get_mbr_id *)
4496    "set the MBR type byte (ID byte) of a partition",
4497    "\
4498 Sets the MBR type byte (also known as the ID byte) of
4499 the numbered partition C<partnum> to C<idbyte>.  Note
4500 that the type bytes quoted in most documentation are
4501 in fact hexadecimal numbers, but usually documented
4502 without any leading \"0x\" which might be confusing.
4503
4504 Note that only MBR (old DOS-style) partitions have type bytes.
4505 You will get undefined results for other partition table
4506 types (see C<guestfs_part_get_parttype>).");
4507
4508   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4509    [InitISOFS, Always, TestOutput (
4510       [["checksum_device"; "md5"; "/dev/sdd"]],
4511       (Digest.to_hex (Digest.file "images/test.iso")))],
4512    "compute MD5, SHAx or CRC checksum of the contents of a device",
4513    "\
4514 This call computes the MD5, SHAx or CRC checksum of the
4515 contents of the device named C<device>.  For the types of
4516 checksums supported see the C<guestfs_checksum> command.");
4517
4518   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4519    [InitNone, Always, TestRun (
4520       [["part_disk"; "/dev/sda"; "mbr"];
4521        ["pvcreate"; "/dev/sda1"];
4522        ["vgcreate"; "VG"; "/dev/sda1"];
4523        ["lvcreate"; "LV"; "VG"; "10"];
4524        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4525    "expand an LV to fill free space",
4526    "\
4527 This expands an existing logical volume C<lv> so that it fills
4528 C<pc>% of the remaining free space in the volume group.  Commonly
4529 you would call this with pc = 100 which expands the logical volume
4530 as much as possible, using all remaining free space in the volume
4531 group.");
4532
4533   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4534    [], (* XXX Augeas code needs tests. *)
4535    "clear Augeas path",
4536    "\
4537 Set the value associated with C<path> to C<NULL>.  This
4538 is the same as the L<augtool(1)> C<clear> command.");
4539
4540   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4541    [InitEmpty, Always, TestOutputInt (
4542       [["get_umask"]], 0o22)],
4543    "get the current umask",
4544    "\
4545 Return the current umask.  By default the umask is C<022>
4546 unless it has been set by calling C<guestfs_umask>.");
4547
4548   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4549    [],
4550    "upload a file to the appliance (internal use only)",
4551    "\
4552 The C<guestfs_debug_upload> command uploads a file to
4553 the libguestfs appliance.
4554
4555 There is no comprehensive help for this command.  You have
4556 to look at the file C<daemon/debug.c> in the libguestfs source
4557 to find out what it is for.");
4558
4559   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4560    [InitBasicFS, Always, TestOutput (
4561       [["base64_in"; "../images/hello.b64"; "/hello"];
4562        ["cat"; "/hello"]], "hello\n")],
4563    "upload base64-encoded data to file",
4564    "\
4565 This command uploads base64-encoded data from C<base64file>
4566 to C<filename>.");
4567
4568   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4569    [],
4570    "download file and encode as base64",
4571    "\
4572 This command downloads the contents of C<filename>, writing
4573 it out to local file C<base64file> encoded as base64.");
4574
4575   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4576    [],
4577    "compute MD5, SHAx or CRC checksum of files in a directory",
4578    "\
4579 This command computes the checksums of all regular files in
4580 C<directory> and then emits a list of those checksums to
4581 the local output file C<sumsfile>.
4582
4583 This can be used for verifying the integrity of a virtual
4584 machine.  However to be properly secure you should pay
4585 attention to the output of the checksum command (it uses
4586 the ones from GNU coreutils).  In particular when the
4587 filename is not printable, coreutils uses a special
4588 backslash syntax.  For more information, see the GNU
4589 coreutils info file.");
4590
4591 ]
4592
4593 let all_functions = non_daemon_functions @ daemon_functions
4594
4595 (* In some places we want the functions to be displayed sorted
4596  * alphabetically, so this is useful:
4597  *)
4598 let all_functions_sorted =
4599   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4600                compare n1 n2) all_functions
4601
4602 (* Field types for structures. *)
4603 type field =
4604   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4605   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4606   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4607   | FUInt32
4608   | FInt32
4609   | FUInt64
4610   | FInt64
4611   | FBytes                      (* Any int measure that counts bytes. *)
4612   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4613   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4614
4615 (* Because we generate extra parsing code for LVM command line tools,
4616  * we have to pull out the LVM columns separately here.
4617  *)
4618 let lvm_pv_cols = [
4619   "pv_name", FString;
4620   "pv_uuid", FUUID;
4621   "pv_fmt", FString;
4622   "pv_size", FBytes;
4623   "dev_size", FBytes;
4624   "pv_free", FBytes;
4625   "pv_used", FBytes;
4626   "pv_attr", FString (* XXX *);
4627   "pv_pe_count", FInt64;
4628   "pv_pe_alloc_count", FInt64;
4629   "pv_tags", FString;
4630   "pe_start", FBytes;
4631   "pv_mda_count", FInt64;
4632   "pv_mda_free", FBytes;
4633   (* Not in Fedora 10:
4634      "pv_mda_size", FBytes;
4635   *)
4636 ]
4637 let lvm_vg_cols = [
4638   "vg_name", FString;
4639   "vg_uuid", FUUID;
4640   "vg_fmt", FString;
4641   "vg_attr", FString (* XXX *);
4642   "vg_size", FBytes;
4643   "vg_free", FBytes;
4644   "vg_sysid", FString;
4645   "vg_extent_size", FBytes;
4646   "vg_extent_count", FInt64;
4647   "vg_free_count", FInt64;
4648   "max_lv", FInt64;
4649   "max_pv", FInt64;
4650   "pv_count", FInt64;
4651   "lv_count", FInt64;
4652   "snap_count", FInt64;
4653   "vg_seqno", FInt64;
4654   "vg_tags", FString;
4655   "vg_mda_count", FInt64;
4656   "vg_mda_free", FBytes;
4657   (* Not in Fedora 10:
4658      "vg_mda_size", FBytes;
4659   *)
4660 ]
4661 let lvm_lv_cols = [
4662   "lv_name", FString;
4663   "lv_uuid", FUUID;
4664   "lv_attr", FString (* XXX *);
4665   "lv_major", FInt64;
4666   "lv_minor", FInt64;
4667   "lv_kernel_major", FInt64;
4668   "lv_kernel_minor", FInt64;
4669   "lv_size", FBytes;
4670   "seg_count", FInt64;
4671   "origin", FString;
4672   "snap_percent", FOptPercent;
4673   "copy_percent", FOptPercent;
4674   "move_pv", FString;
4675   "lv_tags", FString;
4676   "mirror_log", FString;
4677   "modules", FString;
4678 ]
4679
4680 (* Names and fields in all structures (in RStruct and RStructList)
4681  * that we support.
4682  *)
4683 let structs = [
4684   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4685    * not use this struct in any new code.
4686    *)
4687   "int_bool", [
4688     "i", FInt32;                (* for historical compatibility *)
4689     "b", FInt32;                (* for historical compatibility *)
4690   ];
4691
4692   (* LVM PVs, VGs, LVs. *)
4693   "lvm_pv", lvm_pv_cols;
4694   "lvm_vg", lvm_vg_cols;
4695   "lvm_lv", lvm_lv_cols;
4696
4697   (* Column names and types from stat structures.
4698    * NB. Can't use things like 'st_atime' because glibc header files
4699    * define some of these as macros.  Ugh.
4700    *)
4701   "stat", [
4702     "dev", FInt64;
4703     "ino", FInt64;
4704     "mode", FInt64;
4705     "nlink", FInt64;
4706     "uid", FInt64;
4707     "gid", FInt64;
4708     "rdev", FInt64;
4709     "size", FInt64;
4710     "blksize", FInt64;
4711     "blocks", FInt64;
4712     "atime", FInt64;
4713     "mtime", FInt64;
4714     "ctime", FInt64;
4715   ];
4716   "statvfs", [
4717     "bsize", FInt64;
4718     "frsize", FInt64;
4719     "blocks", FInt64;
4720     "bfree", FInt64;
4721     "bavail", FInt64;
4722     "files", FInt64;
4723     "ffree", FInt64;
4724     "favail", FInt64;
4725     "fsid", FInt64;
4726     "flag", FInt64;
4727     "namemax", FInt64;
4728   ];
4729
4730   (* Column names in dirent structure. *)
4731   "dirent", [
4732     "ino", FInt64;
4733     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4734     "ftyp", FChar;
4735     "name", FString;
4736   ];
4737
4738   (* Version numbers. *)
4739   "version", [
4740     "major", FInt64;
4741     "minor", FInt64;
4742     "release", FInt64;
4743     "extra", FString;
4744   ];
4745
4746   (* Extended attribute. *)
4747   "xattr", [
4748     "attrname", FString;
4749     "attrval", FBuffer;
4750   ];
4751
4752   (* Inotify events. *)
4753   "inotify_event", [
4754     "in_wd", FInt64;
4755     "in_mask", FUInt32;
4756     "in_cookie", FUInt32;
4757     "in_name", FString;
4758   ];
4759
4760   (* Partition table entry. *)
4761   "partition", [
4762     "part_num", FInt32;
4763     "part_start", FBytes;
4764     "part_end", FBytes;
4765     "part_size", FBytes;
4766   ];
4767 ] (* end of structs *)
4768
4769 (* Ugh, Java has to be different ..
4770  * These names are also used by the Haskell bindings.
4771  *)
4772 let java_structs = [
4773   "int_bool", "IntBool";
4774   "lvm_pv", "PV";
4775   "lvm_vg", "VG";
4776   "lvm_lv", "LV";
4777   "stat", "Stat";
4778   "statvfs", "StatVFS";
4779   "dirent", "Dirent";
4780   "version", "Version";
4781   "xattr", "XAttr";
4782   "inotify_event", "INotifyEvent";
4783   "partition", "Partition";
4784 ]
4785
4786 (* What structs are actually returned. *)
4787 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4788
4789 (* Returns a list of RStruct/RStructList structs that are returned
4790  * by any function.  Each element of returned list is a pair:
4791  *
4792  * (structname, RStructOnly)
4793  *    == there exists function which returns RStruct (_, structname)
4794  * (structname, RStructListOnly)
4795  *    == there exists function which returns RStructList (_, structname)
4796  * (structname, RStructAndList)
4797  *    == there are functions returning both RStruct (_, structname)
4798  *                                      and RStructList (_, structname)
4799  *)
4800 let rstructs_used_by functions =
4801   (* ||| is a "logical OR" for rstructs_used_t *)
4802   let (|||) a b =
4803     match a, b with
4804     | RStructAndList, _
4805     | _, RStructAndList -> RStructAndList
4806     | RStructOnly, RStructListOnly
4807     | RStructListOnly, RStructOnly -> RStructAndList
4808     | RStructOnly, RStructOnly -> RStructOnly
4809     | RStructListOnly, RStructListOnly -> RStructListOnly
4810   in
4811
4812   let h = Hashtbl.create 13 in
4813
4814   (* if elem->oldv exists, update entry using ||| operator,
4815    * else just add elem->newv to the hash
4816    *)
4817   let update elem newv =
4818     try  let oldv = Hashtbl.find h elem in
4819          Hashtbl.replace h elem (newv ||| oldv)
4820     with Not_found -> Hashtbl.add h elem newv
4821   in
4822
4823   List.iter (
4824     fun (_, style, _, _, _, _, _) ->
4825       match fst style with
4826       | RStruct (_, structname) -> update structname RStructOnly
4827       | RStructList (_, structname) -> update structname RStructListOnly
4828       | _ -> ()
4829   ) functions;
4830
4831   (* return key->values as a list of (key,value) *)
4832   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4833
4834 (* Used for testing language bindings. *)
4835 type callt =
4836   | CallString of string
4837   | CallOptString of string option
4838   | CallStringList of string list
4839   | CallInt of int
4840   | CallInt64 of int64
4841   | CallBool of bool
4842
4843 (* Used to memoize the result of pod2text. *)
4844 let pod2text_memo_filename = "src/.pod2text.data"
4845 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4846   try
4847     let chan = open_in pod2text_memo_filename in
4848     let v = input_value chan in
4849     close_in chan;
4850     v
4851   with
4852     _ -> Hashtbl.create 13
4853 let pod2text_memo_updated () =
4854   let chan = open_out pod2text_memo_filename in
4855   output_value chan pod2text_memo;
4856   close_out chan
4857
4858 (* Useful functions.
4859  * Note we don't want to use any external OCaml libraries which
4860  * makes this a bit harder than it should be.
4861  *)
4862 module StringMap = Map.Make (String)
4863
4864 let failwithf fs = ksprintf failwith fs
4865
4866 let unique = let i = ref 0 in fun () -> incr i; !i
4867
4868 let replace_char s c1 c2 =
4869   let s2 = String.copy s in
4870   let r = ref false in
4871   for i = 0 to String.length s2 - 1 do
4872     if String.unsafe_get s2 i = c1 then (
4873       String.unsafe_set s2 i c2;
4874       r := true
4875     )
4876   done;
4877   if not !r then s else s2
4878
4879 let isspace c =
4880   c = ' '
4881   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4882
4883 let triml ?(test = isspace) str =
4884   let i = ref 0 in
4885   let n = ref (String.length str) in
4886   while !n > 0 && test str.[!i]; do
4887     decr n;
4888     incr i
4889   done;
4890   if !i = 0 then str
4891   else String.sub str !i !n
4892
4893 let trimr ?(test = isspace) str =
4894   let n = ref (String.length str) in
4895   while !n > 0 && test str.[!n-1]; do
4896     decr n
4897   done;
4898   if !n = String.length str then str
4899   else String.sub str 0 !n
4900
4901 let trim ?(test = isspace) str =
4902   trimr ~test (triml ~test str)
4903
4904 let rec find s sub =
4905   let len = String.length s in
4906   let sublen = String.length sub in
4907   let rec loop i =
4908     if i <= len-sublen then (
4909       let rec loop2 j =
4910         if j < sublen then (
4911           if s.[i+j] = sub.[j] then loop2 (j+1)
4912           else -1
4913         ) else
4914           i (* found *)
4915       in
4916       let r = loop2 0 in
4917       if r = -1 then loop (i+1) else r
4918     ) else
4919       -1 (* not found *)
4920   in
4921   loop 0
4922
4923 let rec replace_str s s1 s2 =
4924   let len = String.length s in
4925   let sublen = String.length s1 in
4926   let i = find s s1 in
4927   if i = -1 then s
4928   else (
4929     let s' = String.sub s 0 i in
4930     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4931     s' ^ s2 ^ replace_str s'' s1 s2
4932   )
4933
4934 let rec string_split sep str =
4935   let len = String.length str in
4936   let seplen = String.length sep in
4937   let i = find str sep in
4938   if i = -1 then [str]
4939   else (
4940     let s' = String.sub str 0 i in
4941     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4942     s' :: string_split sep s''
4943   )
4944
4945 let files_equal n1 n2 =
4946   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4947   match Sys.command cmd with
4948   | 0 -> true
4949   | 1 -> false
4950   | i -> failwithf "%s: failed with error code %d" cmd i
4951
4952 let rec filter_map f = function
4953   | [] -> []
4954   | x :: xs ->
4955       match f x with
4956       | Some y -> y :: filter_map f xs
4957       | None -> filter_map f xs
4958
4959 let rec find_map f = function
4960   | [] -> raise Not_found
4961   | x :: xs ->
4962       match f x with
4963       | Some y -> y
4964       | None -> find_map f xs
4965
4966 let iteri f xs =
4967   let rec loop i = function
4968     | [] -> ()
4969     | x :: xs -> f i x; loop (i+1) xs
4970   in
4971   loop 0 xs
4972
4973 let mapi f xs =
4974   let rec loop i = function
4975     | [] -> []
4976     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4977   in
4978   loop 0 xs
4979
4980 let count_chars c str =
4981   let count = ref 0 in
4982   for i = 0 to String.length str - 1 do
4983     if c = String.unsafe_get str i then incr count
4984   done;
4985   !count
4986
4987 let name_of_argt = function
4988   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4989   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4990   | FileIn n | FileOut n -> n
4991
4992 let java_name_of_struct typ =
4993   try List.assoc typ java_structs
4994   with Not_found ->
4995     failwithf
4996       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4997
4998 let cols_of_struct typ =
4999   try List.assoc typ structs
5000   with Not_found ->
5001     failwithf "cols_of_struct: unknown struct %s" typ
5002
5003 let seq_of_test = function
5004   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5005   | TestOutputListOfDevices (s, _)
5006   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5007   | TestOutputTrue s | TestOutputFalse s
5008   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5009   | TestOutputStruct (s, _)
5010   | TestLastFail s -> s
5011
5012 (* Handling for function flags. *)
5013 let protocol_limit_warning =
5014   "Because of the message protocol, there is a transfer limit
5015 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5016
5017 let danger_will_robinson =
5018   "B<This command is dangerous.  Without careful use you
5019 can easily destroy all your data>."
5020
5021 let deprecation_notice flags =
5022   try
5023     let alt =
5024       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5025     let txt =
5026       sprintf "This function is deprecated.
5027 In new code, use the C<%s> call instead.
5028
5029 Deprecated functions will not be removed from the API, but the
5030 fact that they are deprecated indicates that there are problems
5031 with correct use of these functions." alt in
5032     Some txt
5033   with
5034     Not_found -> None
5035
5036 (* Create list of optional groups. *)
5037 let optgroups =
5038   let h = Hashtbl.create 13 in
5039   List.iter (
5040     fun (name, _, _, flags, _, _, _) ->
5041       List.iter (
5042         function
5043         | Optional group ->
5044             let names = try Hashtbl.find h group with Not_found -> [] in
5045             Hashtbl.replace h group (name :: names)
5046         | _ -> ()
5047       ) flags
5048   ) daemon_functions;
5049   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5050   let groups =
5051     List.map (
5052       fun group -> group, List.sort compare (Hashtbl.find h group)
5053     ) groups in
5054   List.sort (fun x y -> compare (fst x) (fst y)) groups
5055
5056 (* Check function names etc. for consistency. *)
5057 let check_functions () =
5058   let contains_uppercase str =
5059     let len = String.length str in
5060     let rec loop i =
5061       if i >= len then false
5062       else (
5063         let c = str.[i] in
5064         if c >= 'A' && c <= 'Z' then true
5065         else loop (i+1)
5066       )
5067     in
5068     loop 0
5069   in
5070
5071   (* Check function names. *)
5072   List.iter (
5073     fun (name, _, _, _, _, _, _) ->
5074       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5075         failwithf "function name %s does not need 'guestfs' prefix" name;
5076       if name = "" then
5077         failwithf "function name is empty";
5078       if name.[0] < 'a' || name.[0] > 'z' then
5079         failwithf "function name %s must start with lowercase a-z" name;
5080       if String.contains name '-' then
5081         failwithf "function name %s should not contain '-', use '_' instead."
5082           name
5083   ) all_functions;
5084
5085   (* Check function parameter/return names. *)
5086   List.iter (
5087     fun (name, style, _, _, _, _, _) ->
5088       let check_arg_ret_name n =
5089         if contains_uppercase n then
5090           failwithf "%s param/ret %s should not contain uppercase chars"
5091             name n;
5092         if String.contains n '-' || String.contains n '_' then
5093           failwithf "%s param/ret %s should not contain '-' or '_'"
5094             name n;
5095         if n = "value" then
5096           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;
5097         if n = "int" || n = "char" || n = "short" || n = "long" then
5098           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5099         if n = "i" || n = "n" then
5100           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5101         if n = "argv" || n = "args" then
5102           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5103
5104         (* List Haskell, OCaml and C keywords here.
5105          * http://www.haskell.org/haskellwiki/Keywords
5106          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5107          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5108          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5109          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5110          * Omitting _-containing words, since they're handled above.
5111          * Omitting the OCaml reserved word, "val", is ok,
5112          * and saves us from renaming several parameters.
5113          *)
5114         let reserved = [
5115           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5116           "char"; "class"; "const"; "constraint"; "continue"; "data";
5117           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5118           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5119           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5120           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5121           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5122           "interface";
5123           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5124           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5125           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5126           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5127           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5128           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5129           "volatile"; "when"; "where"; "while";
5130           ] in
5131         if List.mem n reserved then
5132           failwithf "%s has param/ret using reserved word %s" name n;
5133       in
5134
5135       (match fst style with
5136        | RErr -> ()
5137        | RInt n | RInt64 n | RBool n
5138        | RConstString n | RConstOptString n | RString n
5139        | RStringList n | RStruct (n, _) | RStructList (n, _)
5140        | RHashtable n | RBufferOut n ->
5141            check_arg_ret_name n
5142       );
5143       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5144   ) all_functions;
5145
5146   (* Check short descriptions. *)
5147   List.iter (
5148     fun (name, _, _, _, _, shortdesc, _) ->
5149       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5150         failwithf "short description of %s should begin with lowercase." name;
5151       let c = shortdesc.[String.length shortdesc-1] in
5152       if c = '\n' || c = '.' then
5153         failwithf "short description of %s should not end with . or \\n." name
5154   ) all_functions;
5155
5156   (* Check long descriptions. *)
5157   List.iter (
5158     fun (name, _, _, _, _, _, longdesc) ->
5159       if longdesc.[String.length longdesc-1] = '\n' then
5160         failwithf "long description of %s should not end with \\n." name
5161   ) all_functions;
5162
5163   (* Check proc_nrs. *)
5164   List.iter (
5165     fun (name, _, proc_nr, _, _, _, _) ->
5166       if proc_nr <= 0 then
5167         failwithf "daemon function %s should have proc_nr > 0" name
5168   ) daemon_functions;
5169
5170   List.iter (
5171     fun (name, _, proc_nr, _, _, _, _) ->
5172       if proc_nr <> -1 then
5173         failwithf "non-daemon function %s should have proc_nr -1" name
5174   ) non_daemon_functions;
5175
5176   let proc_nrs =
5177     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5178       daemon_functions in
5179   let proc_nrs =
5180     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5181   let rec loop = function
5182     | [] -> ()
5183     | [_] -> ()
5184     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5185         loop rest
5186     | (name1,nr1) :: (name2,nr2) :: _ ->
5187         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5188           name1 name2 nr1 nr2
5189   in
5190   loop proc_nrs;
5191
5192   (* Check tests. *)
5193   List.iter (
5194     function
5195       (* Ignore functions that have no tests.  We generate a
5196        * warning when the user does 'make check' instead.
5197        *)
5198     | name, _, _, _, [], _, _ -> ()
5199     | name, _, _, _, tests, _, _ ->
5200         let funcs =
5201           List.map (
5202             fun (_, _, test) ->
5203               match seq_of_test test with
5204               | [] ->
5205                   failwithf "%s has a test containing an empty sequence" name
5206               | cmds -> List.map List.hd cmds
5207           ) tests in
5208         let funcs = List.flatten funcs in
5209
5210         let tested = List.mem name funcs in
5211
5212         if not tested then
5213           failwithf "function %s has tests but does not test itself" name
5214   ) all_functions
5215
5216 (* 'pr' prints to the current output file. *)
5217 let chan = ref Pervasives.stdout
5218 let lines = ref 0
5219 let pr fs =
5220   ksprintf
5221     (fun str ->
5222        let i = count_chars '\n' str in
5223        lines := !lines + i;
5224        output_string !chan str
5225     ) fs
5226
5227 let copyright_years =
5228   let this_year = 1900 + (localtime (time ())).tm_year in
5229   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5230
5231 (* Generate a header block in a number of standard styles. *)
5232 type comment_style =
5233     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5234 type license = GPLv2plus | LGPLv2plus
5235
5236 let generate_header ?(extra_inputs = []) comment license =
5237   let inputs = "src/generator.ml" :: extra_inputs in
5238   let c = match comment with
5239     | CStyle ->         pr "/* "; " *"
5240     | CPlusPlusStyle -> pr "// "; "//"
5241     | HashStyle ->      pr "# ";  "#"
5242     | OCamlStyle ->     pr "(* "; " *"
5243     | HaskellStyle ->   pr "{- "; "  " in
5244   pr "libguestfs generated file\n";
5245   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5246   List.iter (pr "%s   %s\n" c) inputs;
5247   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5248   pr "%s\n" c;
5249   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5250   pr "%s\n" c;
5251   (match license with
5252    | GPLv2plus ->
5253        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5254        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5255        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5256        pr "%s (at your option) any later version.\n" c;
5257        pr "%s\n" c;
5258        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5259        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5260        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5261        pr "%s GNU General Public License for more details.\n" c;
5262        pr "%s\n" c;
5263        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5264        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5265        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5266
5267    | LGPLv2plus ->
5268        pr "%s This library is free software; you can redistribute it and/or\n" c;
5269        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5270        pr "%s License as published by the Free Software Foundation; either\n" c;
5271        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5272        pr "%s\n" c;
5273        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5274        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5275        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5276        pr "%s Lesser General Public License for more details.\n" c;
5277        pr "%s\n" c;
5278        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5279        pr "%s License along with this library; if not, write to the Free Software\n" c;
5280        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5281   );
5282   (match comment with
5283    | CStyle -> pr " */\n"
5284    | CPlusPlusStyle
5285    | HashStyle -> ()
5286    | OCamlStyle -> pr " *)\n"
5287    | HaskellStyle -> pr "-}\n"
5288   );
5289   pr "\n"
5290
5291 (* Start of main code generation functions below this line. *)
5292
5293 (* Generate the pod documentation for the C API. *)
5294 let rec generate_actions_pod () =
5295   List.iter (
5296     fun (shortname, style, _, flags, _, _, longdesc) ->
5297       if not (List.mem NotInDocs flags) then (
5298         let name = "guestfs_" ^ shortname in
5299         pr "=head2 %s\n\n" name;
5300         pr " ";
5301         generate_prototype ~extern:false ~handle:"g" name style;
5302         pr "\n\n";
5303         pr "%s\n\n" longdesc;
5304         (match fst style with
5305          | RErr ->
5306              pr "This function returns 0 on success or -1 on error.\n\n"
5307          | RInt _ ->
5308              pr "On error this function returns -1.\n\n"
5309          | RInt64 _ ->
5310              pr "On error this function returns -1.\n\n"
5311          | RBool _ ->
5312              pr "This function returns a C truth value on success or -1 on error.\n\n"
5313          | RConstString _ ->
5314              pr "This function returns a string, or NULL on error.
5315 The string is owned by the guest handle and must I<not> be freed.\n\n"
5316          | RConstOptString _ ->
5317              pr "This function returns a string which may be NULL.
5318 There is way to return an error from this function.
5319 The string is owned by the guest handle and must I<not> be freed.\n\n"
5320          | RString _ ->
5321              pr "This function returns a string, or NULL on error.
5322 I<The caller must free the returned string after use>.\n\n"
5323          | RStringList _ ->
5324              pr "This function returns a NULL-terminated array of strings
5325 (like L<environ(3)>), or NULL if there was an error.
5326 I<The caller must free the strings and the array after use>.\n\n"
5327          | RStruct (_, typ) ->
5328              pr "This function returns a C<struct guestfs_%s *>,
5329 or NULL if there was an error.
5330 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5331          | RStructList (_, typ) ->
5332              pr "This function returns a C<struct guestfs_%s_list *>
5333 (see E<lt>guestfs-structs.hE<gt>),
5334 or NULL if there was an error.
5335 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5336          | RHashtable _ ->
5337              pr "This function returns a NULL-terminated array of
5338 strings, or NULL if there was an error.
5339 The array of strings will always have length C<2n+1>, where
5340 C<n> keys and values alternate, followed by the trailing NULL entry.
5341 I<The caller must free the strings and the array after use>.\n\n"
5342          | RBufferOut _ ->
5343              pr "This function returns a buffer, or NULL on error.
5344 The size of the returned buffer is written to C<*size_r>.
5345 I<The caller must free the returned buffer after use>.\n\n"
5346         );
5347         if List.mem ProtocolLimitWarning flags then
5348           pr "%s\n\n" protocol_limit_warning;
5349         if List.mem DangerWillRobinson flags then
5350           pr "%s\n\n" danger_will_robinson;
5351         match deprecation_notice flags with
5352         | None -> ()
5353         | Some txt -> pr "%s\n\n" txt
5354       )
5355   ) all_functions_sorted
5356
5357 and generate_structs_pod () =
5358   (* Structs documentation. *)
5359   List.iter (
5360     fun (typ, cols) ->
5361       pr "=head2 guestfs_%s\n" typ;
5362       pr "\n";
5363       pr " struct guestfs_%s {\n" typ;
5364       List.iter (
5365         function
5366         | name, FChar -> pr "   char %s;\n" name
5367         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5368         | name, FInt32 -> pr "   int32_t %s;\n" name
5369         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5370         | name, FInt64 -> pr "   int64_t %s;\n" name
5371         | name, FString -> pr "   char *%s;\n" name
5372         | name, FBuffer ->
5373             pr "   /* The next two fields describe a byte array. */\n";
5374             pr "   uint32_t %s_len;\n" name;
5375             pr "   char *%s;\n" name
5376         | name, FUUID ->
5377             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5378             pr "   char %s[32];\n" name
5379         | name, FOptPercent ->
5380             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5381             pr "   float %s;\n" name
5382       ) cols;
5383       pr " };\n";
5384       pr " \n";
5385       pr " struct guestfs_%s_list {\n" typ;
5386       pr "   uint32_t len; /* Number of elements in list. */\n";
5387       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5388       pr " };\n";
5389       pr " \n";
5390       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5391       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5392         typ typ;
5393       pr "\n"
5394   ) structs
5395
5396 and generate_availability_pod () =
5397   (* Availability documentation. *)
5398   pr "=over 4\n";
5399   pr "\n";
5400   List.iter (
5401     fun (group, functions) ->
5402       pr "=item B<%s>\n" group;
5403       pr "\n";
5404       pr "The following functions:\n";
5405       List.iter (pr "L</guestfs_%s>\n") functions;
5406       pr "\n"
5407   ) optgroups;
5408   pr "=back\n";
5409   pr "\n"
5410
5411 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5412  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5413  *
5414  * We have to use an underscore instead of a dash because otherwise
5415  * rpcgen generates incorrect code.
5416  *
5417  * This header is NOT exported to clients, but see also generate_structs_h.
5418  *)
5419 and generate_xdr () =
5420   generate_header CStyle LGPLv2plus;
5421
5422   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5423   pr "typedef string str<>;\n";
5424   pr "\n";
5425
5426   (* Internal structures. *)
5427   List.iter (
5428     function
5429     | typ, cols ->
5430         pr "struct guestfs_int_%s {\n" typ;
5431         List.iter (function
5432                    | name, FChar -> pr "  char %s;\n" name
5433                    | name, FString -> pr "  string %s<>;\n" name
5434                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5435                    | name, FUUID -> pr "  opaque %s[32];\n" name
5436                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5437                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5438                    | name, FOptPercent -> pr "  float %s;\n" name
5439                   ) cols;
5440         pr "};\n";
5441         pr "\n";
5442         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5443         pr "\n";
5444   ) structs;
5445
5446   List.iter (
5447     fun (shortname, style, _, _, _, _, _) ->
5448       let name = "guestfs_" ^ shortname in
5449
5450       (match snd style with
5451        | [] -> ()
5452        | args ->
5453            pr "struct %s_args {\n" name;
5454            List.iter (
5455              function
5456              | Pathname n | Device n | Dev_or_Path n | String n ->
5457                  pr "  string %s<>;\n" n
5458              | OptString n -> pr "  str *%s;\n" n
5459              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5460              | Bool n -> pr "  bool %s;\n" n
5461              | Int n -> pr "  int %s;\n" n
5462              | Int64 n -> pr "  hyper %s;\n" n
5463              | FileIn _ | FileOut _ -> ()
5464            ) args;
5465            pr "};\n\n"
5466       );
5467       (match fst style with
5468        | RErr -> ()
5469        | RInt n ->
5470            pr "struct %s_ret {\n" name;
5471            pr "  int %s;\n" n;
5472            pr "};\n\n"
5473        | RInt64 n ->
5474            pr "struct %s_ret {\n" name;
5475            pr "  hyper %s;\n" n;
5476            pr "};\n\n"
5477        | RBool n ->
5478            pr "struct %s_ret {\n" name;
5479            pr "  bool %s;\n" n;
5480            pr "};\n\n"
5481        | RConstString _ | RConstOptString _ ->
5482            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5483        | RString n ->
5484            pr "struct %s_ret {\n" name;
5485            pr "  string %s<>;\n" n;
5486            pr "};\n\n"
5487        | RStringList n ->
5488            pr "struct %s_ret {\n" name;
5489            pr "  str %s<>;\n" n;
5490            pr "};\n\n"
5491        | RStruct (n, typ) ->
5492            pr "struct %s_ret {\n" name;
5493            pr "  guestfs_int_%s %s;\n" typ n;
5494            pr "};\n\n"
5495        | RStructList (n, typ) ->
5496            pr "struct %s_ret {\n" name;
5497            pr "  guestfs_int_%s_list %s;\n" typ n;
5498            pr "};\n\n"
5499        | RHashtable n ->
5500            pr "struct %s_ret {\n" name;
5501            pr "  str %s<>;\n" n;
5502            pr "};\n\n"
5503        | RBufferOut n ->
5504            pr "struct %s_ret {\n" name;
5505            pr "  opaque %s<>;\n" n;
5506            pr "};\n\n"
5507       );
5508   ) daemon_functions;
5509
5510   (* Table of procedure numbers. *)
5511   pr "enum guestfs_procedure {\n";
5512   List.iter (
5513     fun (shortname, _, proc_nr, _, _, _, _) ->
5514       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5515   ) daemon_functions;
5516   pr "  GUESTFS_PROC_NR_PROCS\n";
5517   pr "};\n";
5518   pr "\n";
5519
5520   (* Having to choose a maximum message size is annoying for several
5521    * reasons (it limits what we can do in the API), but it (a) makes
5522    * the protocol a lot simpler, and (b) provides a bound on the size
5523    * of the daemon which operates in limited memory space.
5524    *)
5525   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5526   pr "\n";
5527
5528   (* Message header, etc. *)
5529   pr "\
5530 /* The communication protocol is now documented in the guestfs(3)
5531  * manpage.
5532  */
5533
5534 const GUESTFS_PROGRAM = 0x2000F5F5;
5535 const GUESTFS_PROTOCOL_VERSION = 1;
5536
5537 /* These constants must be larger than any possible message length. */
5538 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5539 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5540
5541 enum guestfs_message_direction {
5542   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5543   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5544 };
5545
5546 enum guestfs_message_status {
5547   GUESTFS_STATUS_OK = 0,
5548   GUESTFS_STATUS_ERROR = 1
5549 };
5550
5551 const GUESTFS_ERROR_LEN = 256;
5552
5553 struct guestfs_message_error {
5554   string error_message<GUESTFS_ERROR_LEN>;
5555 };
5556
5557 struct guestfs_message_header {
5558   unsigned prog;                     /* GUESTFS_PROGRAM */
5559   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5560   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5561   guestfs_message_direction direction;
5562   unsigned serial;                   /* message serial number */
5563   guestfs_message_status status;
5564 };
5565
5566 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5567
5568 struct guestfs_chunk {
5569   int cancel;                        /* if non-zero, transfer is cancelled */
5570   /* data size is 0 bytes if the transfer has finished successfully */
5571   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5572 };
5573 "
5574
5575 (* Generate the guestfs-structs.h file. *)
5576 and generate_structs_h () =
5577   generate_header CStyle LGPLv2plus;
5578
5579   (* This is a public exported header file containing various
5580    * structures.  The structures are carefully written to have
5581    * exactly the same in-memory format as the XDR structures that
5582    * we use on the wire to the daemon.  The reason for creating
5583    * copies of these structures here is just so we don't have to
5584    * export the whole of guestfs_protocol.h (which includes much
5585    * unrelated and XDR-dependent stuff that we don't want to be
5586    * public, or required by clients).
5587    *
5588    * To reiterate, we will pass these structures to and from the
5589    * client with a simple assignment or memcpy, so the format
5590    * must be identical to what rpcgen / the RFC defines.
5591    *)
5592
5593   (* Public structures. *)
5594   List.iter (
5595     fun (typ, cols) ->
5596       pr "struct guestfs_%s {\n" typ;
5597       List.iter (
5598         function
5599         | name, FChar -> pr "  char %s;\n" name
5600         | name, FString -> pr "  char *%s;\n" name
5601         | name, FBuffer ->
5602             pr "  uint32_t %s_len;\n" name;
5603             pr "  char *%s;\n" name
5604         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5605         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5606         | name, FInt32 -> pr "  int32_t %s;\n" name
5607         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5608         | name, FInt64 -> pr "  int64_t %s;\n" name
5609         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5610       ) cols;
5611       pr "};\n";
5612       pr "\n";
5613       pr "struct guestfs_%s_list {\n" typ;
5614       pr "  uint32_t len;\n";
5615       pr "  struct guestfs_%s *val;\n" typ;
5616       pr "};\n";
5617       pr "\n";
5618       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5619       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5620       pr "\n"
5621   ) structs
5622
5623 (* Generate the guestfs-actions.h file. *)
5624 and generate_actions_h () =
5625   generate_header CStyle LGPLv2plus;
5626   List.iter (
5627     fun (shortname, style, _, _, _, _, _) ->
5628       let name = "guestfs_" ^ shortname in
5629       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5630         name style
5631   ) all_functions
5632
5633 (* Generate the guestfs-internal-actions.h file. *)
5634 and generate_internal_actions_h () =
5635   generate_header CStyle LGPLv2plus;
5636   List.iter (
5637     fun (shortname, style, _, _, _, _, _) ->
5638       let name = "guestfs__" ^ shortname in
5639       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5640         name style
5641   ) non_daemon_functions
5642
5643 (* Generate the client-side dispatch stubs. *)
5644 and generate_client_actions () =
5645   generate_header CStyle LGPLv2plus;
5646
5647   pr "\
5648 #include <stdio.h>
5649 #include <stdlib.h>
5650 #include <stdint.h>
5651 #include <string.h>
5652 #include <inttypes.h>
5653
5654 #include \"guestfs.h\"
5655 #include \"guestfs-internal.h\"
5656 #include \"guestfs-internal-actions.h\"
5657 #include \"guestfs_protocol.h\"
5658
5659 #define error guestfs_error
5660 //#define perrorf guestfs_perrorf
5661 #define safe_malloc guestfs_safe_malloc
5662 #define safe_realloc guestfs_safe_realloc
5663 //#define safe_strdup guestfs_safe_strdup
5664 #define safe_memdup guestfs_safe_memdup
5665
5666 /* Check the return message from a call for validity. */
5667 static int
5668 check_reply_header (guestfs_h *g,
5669                     const struct guestfs_message_header *hdr,
5670                     unsigned int proc_nr, unsigned int serial)
5671 {
5672   if (hdr->prog != GUESTFS_PROGRAM) {
5673     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5674     return -1;
5675   }
5676   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5677     error (g, \"wrong protocol version (%%d/%%d)\",
5678            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5679     return -1;
5680   }
5681   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5682     error (g, \"unexpected message direction (%%d/%%d)\",
5683            hdr->direction, GUESTFS_DIRECTION_REPLY);
5684     return -1;
5685   }
5686   if (hdr->proc != proc_nr) {
5687     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5688     return -1;
5689   }
5690   if (hdr->serial != serial) {
5691     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5692     return -1;
5693   }
5694
5695   return 0;
5696 }
5697
5698 /* Check we are in the right state to run a high-level action. */
5699 static int
5700 check_state (guestfs_h *g, const char *caller)
5701 {
5702   if (!guestfs__is_ready (g)) {
5703     if (guestfs__is_config (g) || guestfs__is_launching (g))
5704       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5705         caller);
5706     else
5707       error (g, \"%%s called from the wrong state, %%d != READY\",
5708         caller, guestfs__get_state (g));
5709     return -1;
5710   }
5711   return 0;
5712 }
5713
5714 ";
5715
5716   (* Generate code to generate guestfish call traces. *)
5717   let trace_call shortname style =
5718     pr "  if (guestfs__get_trace (g)) {\n";
5719
5720     let needs_i =
5721       List.exists (function
5722                    | StringList _ | DeviceList _ -> true
5723                    | _ -> false) (snd style) in
5724     if needs_i then (
5725       pr "    int i;\n";
5726       pr "\n"
5727     );
5728
5729     pr "    printf (\"%s\");\n" shortname;
5730     List.iter (
5731       function
5732       | String n                        (* strings *)
5733       | Device n
5734       | Pathname n
5735       | Dev_or_Path n
5736       | FileIn n
5737       | FileOut n ->
5738           (* guestfish doesn't support string escaping, so neither do we *)
5739           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5740       | OptString n ->                  (* string option *)
5741           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5742           pr "    else printf (\" null\");\n"
5743       | StringList n
5744       | DeviceList n ->                 (* string list *)
5745           pr "    putchar (' ');\n";
5746           pr "    putchar ('\"');\n";
5747           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5748           pr "      if (i > 0) putchar (' ');\n";
5749           pr "      fputs (%s[i], stdout);\n" n;
5750           pr "    }\n";
5751           pr "    putchar ('\"');\n";
5752       | Bool n ->                       (* boolean *)
5753           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5754       | Int n ->                        (* int *)
5755           pr "    printf (\" %%d\", %s);\n" n
5756       | Int64 n ->
5757           pr "    printf (\" %%\" PRIi64, %s);\n" n
5758     ) (snd style);
5759     pr "    putchar ('\\n');\n";
5760     pr "  }\n";
5761     pr "\n";
5762   in
5763
5764   (* For non-daemon functions, generate a wrapper around each function. *)
5765   List.iter (
5766     fun (shortname, style, _, _, _, _, _) ->
5767       let name = "guestfs_" ^ shortname in
5768
5769       generate_prototype ~extern:false ~semicolon:false ~newline:true
5770         ~handle:"g" name style;
5771       pr "{\n";
5772       trace_call shortname style;
5773       pr "  return guestfs__%s " shortname;
5774       generate_c_call_args ~handle:"g" style;
5775       pr ";\n";
5776       pr "}\n";
5777       pr "\n"
5778   ) non_daemon_functions;
5779
5780   (* Client-side stubs for each function. *)
5781   List.iter (
5782     fun (shortname, style, _, _, _, _, _) ->
5783       let name = "guestfs_" ^ shortname in
5784
5785       (* Generate the action stub. *)
5786       generate_prototype ~extern:false ~semicolon:false ~newline:true
5787         ~handle:"g" name style;
5788
5789       let error_code =
5790         match fst style with
5791         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5792         | RConstString _ | RConstOptString _ ->
5793             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5794         | RString _ | RStringList _
5795         | RStruct _ | RStructList _
5796         | RHashtable _ | RBufferOut _ ->
5797             "NULL" in
5798
5799       pr "{\n";
5800
5801       (match snd style with
5802        | [] -> ()
5803        | _ -> pr "  struct %s_args args;\n" name
5804       );
5805
5806       pr "  guestfs_message_header hdr;\n";
5807       pr "  guestfs_message_error err;\n";
5808       let has_ret =
5809         match fst style with
5810         | RErr -> false
5811         | RConstString _ | RConstOptString _ ->
5812             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5813         | RInt _ | RInt64 _
5814         | RBool _ | RString _ | RStringList _
5815         | RStruct _ | RStructList _
5816         | RHashtable _ | RBufferOut _ ->
5817             pr "  struct %s_ret ret;\n" name;
5818             true in
5819
5820       pr "  int serial;\n";
5821       pr "  int r;\n";
5822       pr "\n";
5823       trace_call shortname style;
5824       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5825         shortname error_code;
5826       pr "  guestfs___set_busy (g);\n";
5827       pr "\n";
5828
5829       (* Send the main header and arguments. *)
5830       (match snd style with
5831        | [] ->
5832            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5833              (String.uppercase shortname)
5834        | args ->
5835            List.iter (
5836              function
5837              | Pathname n | Device n | Dev_or_Path n | String n ->
5838                  pr "  args.%s = (char *) %s;\n" n n
5839              | OptString n ->
5840                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5841              | StringList n | DeviceList n ->
5842                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5843                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5844              | Bool n ->
5845                  pr "  args.%s = %s;\n" n n
5846              | Int n ->
5847                  pr "  args.%s = %s;\n" n n
5848              | Int64 n ->
5849                  pr "  args.%s = %s;\n" n n
5850              | FileIn _ | FileOut _ -> ()
5851            ) args;
5852            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5853              (String.uppercase shortname);
5854            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5855              name;
5856       );
5857       pr "  if (serial == -1) {\n";
5858       pr "    guestfs___end_busy (g);\n";
5859       pr "    return %s;\n" error_code;
5860       pr "  }\n";
5861       pr "\n";
5862
5863       (* Send any additional files (FileIn) requested. *)
5864       let need_read_reply_label = ref false in
5865       List.iter (
5866         function
5867         | FileIn n ->
5868             pr "  r = guestfs___send_file (g, %s);\n" n;
5869             pr "  if (r == -1) {\n";
5870             pr "    guestfs___end_busy (g);\n";
5871             pr "    return %s;\n" error_code;
5872             pr "  }\n";
5873             pr "  if (r == -2) /* daemon cancelled */\n";
5874             pr "    goto read_reply;\n";
5875             need_read_reply_label := true;
5876             pr "\n";
5877         | _ -> ()
5878       ) (snd style);
5879
5880       (* Wait for the reply from the remote end. *)
5881       if !need_read_reply_label then pr " read_reply:\n";
5882       pr "  memset (&hdr, 0, sizeof hdr);\n";
5883       pr "  memset (&err, 0, sizeof err);\n";
5884       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5885       pr "\n";
5886       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5887       if not has_ret then
5888         pr "NULL, NULL"
5889       else
5890         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5891       pr ");\n";
5892
5893       pr "  if (r == -1) {\n";
5894       pr "    guestfs___end_busy (g);\n";
5895       pr "    return %s;\n" error_code;
5896       pr "  }\n";
5897       pr "\n";
5898
5899       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5900         (String.uppercase shortname);
5901       pr "    guestfs___end_busy (g);\n";
5902       pr "    return %s;\n" error_code;
5903       pr "  }\n";
5904       pr "\n";
5905
5906       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5907       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5908       pr "    free (err.error_message);\n";
5909       pr "    guestfs___end_busy (g);\n";
5910       pr "    return %s;\n" error_code;
5911       pr "  }\n";
5912       pr "\n";
5913
5914       (* Expecting to receive further files (FileOut)? *)
5915       List.iter (
5916         function
5917         | FileOut n ->
5918             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5919             pr "    guestfs___end_busy (g);\n";
5920             pr "    return %s;\n" error_code;
5921             pr "  }\n";
5922             pr "\n";
5923         | _ -> ()
5924       ) (snd style);
5925
5926       pr "  guestfs___end_busy (g);\n";
5927
5928       (match fst style with
5929        | RErr -> pr "  return 0;\n"
5930        | RInt n | RInt64 n | RBool n ->
5931            pr "  return ret.%s;\n" n
5932        | RConstString _ | RConstOptString _ ->
5933            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5934        | RString n ->
5935            pr "  return ret.%s; /* caller will free */\n" n
5936        | RStringList n | RHashtable n ->
5937            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5938            pr "  ret.%s.%s_val =\n" n n;
5939            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5940            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5941              n n;
5942            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5943            pr "  return ret.%s.%s_val;\n" n n
5944        | RStruct (n, _) ->
5945            pr "  /* caller will free this */\n";
5946            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5947        | RStructList (n, _) ->
5948            pr "  /* caller will free this */\n";
5949            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5950        | RBufferOut n ->
5951            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5952            pr "   * _val might be NULL here.  To make the API saner for\n";
5953            pr "   * callers, we turn this case into a unique pointer (using\n";
5954            pr "   * malloc(1)).\n";
5955            pr "   */\n";
5956            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5957            pr "    *size_r = ret.%s.%s_len;\n" n n;
5958            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5959            pr "  } else {\n";
5960            pr "    free (ret.%s.%s_val);\n" n n;
5961            pr "    char *p = safe_malloc (g, 1);\n";
5962            pr "    *size_r = ret.%s.%s_len;\n" n n;
5963            pr "    return p;\n";
5964            pr "  }\n";
5965       );
5966
5967       pr "}\n\n"
5968   ) daemon_functions;
5969
5970   (* Functions to free structures. *)
5971   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5972   pr " * structure format is identical to the XDR format.  See note in\n";
5973   pr " * generator.ml.\n";
5974   pr " */\n";
5975   pr "\n";
5976
5977   List.iter (
5978     fun (typ, _) ->
5979       pr "void\n";
5980       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5981       pr "{\n";
5982       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5983       pr "  free (x);\n";
5984       pr "}\n";
5985       pr "\n";
5986
5987       pr "void\n";
5988       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5989       pr "{\n";
5990       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5991       pr "  free (x);\n";
5992       pr "}\n";
5993       pr "\n";
5994
5995   ) structs;
5996
5997 (* Generate daemon/actions.h. *)
5998 and generate_daemon_actions_h () =
5999   generate_header CStyle GPLv2plus;
6000
6001   pr "#include \"../src/guestfs_protocol.h\"\n";
6002   pr "\n";
6003
6004   List.iter (
6005     fun (name, style, _, _, _, _, _) ->
6006       generate_prototype
6007         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6008         name style;
6009   ) daemon_functions
6010
6011 (* Generate the linker script which controls the visibility of
6012  * symbols in the public ABI and ensures no other symbols get
6013  * exported accidentally.
6014  *)
6015 and generate_linker_script () =
6016   generate_header HashStyle GPLv2plus;
6017
6018   let globals = [
6019     "guestfs_create";
6020     "guestfs_close";
6021     "guestfs_get_error_handler";
6022     "guestfs_get_out_of_memory_handler";
6023     "guestfs_last_error";
6024     "guestfs_set_error_handler";
6025     "guestfs_set_launch_done_callback";
6026     "guestfs_set_log_message_callback";
6027     "guestfs_set_out_of_memory_handler";
6028     "guestfs_set_subprocess_quit_callback";
6029
6030     (* Unofficial parts of the API: the bindings code use these
6031      * functions, so it is useful to export them.
6032      *)
6033     "guestfs_safe_calloc";
6034     "guestfs_safe_malloc";
6035   ] in
6036   let functions =
6037     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6038       all_functions in
6039   let structs =
6040     List.concat (
6041       List.map (fun (typ, _) ->
6042                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6043         structs
6044     ) in
6045   let globals = List.sort compare (globals @ functions @ structs) in
6046
6047   pr "{\n";
6048   pr "    global:\n";
6049   List.iter (pr "        %s;\n") globals;
6050   pr "\n";
6051
6052   pr "    local:\n";
6053   pr "        *;\n";
6054   pr "};\n"
6055
6056 (* Generate the server-side stubs. *)
6057 and generate_daemon_actions () =
6058   generate_header CStyle GPLv2plus;
6059
6060   pr "#include <config.h>\n";
6061   pr "\n";
6062   pr "#include <stdio.h>\n";
6063   pr "#include <stdlib.h>\n";
6064   pr "#include <string.h>\n";
6065   pr "#include <inttypes.h>\n";
6066   pr "#include <rpc/types.h>\n";
6067   pr "#include <rpc/xdr.h>\n";
6068   pr "\n";
6069   pr "#include \"daemon.h\"\n";
6070   pr "#include \"c-ctype.h\"\n";
6071   pr "#include \"../src/guestfs_protocol.h\"\n";
6072   pr "#include \"actions.h\"\n";
6073   pr "\n";
6074
6075   List.iter (
6076     fun (name, style, _, _, _, _, _) ->
6077       (* Generate server-side stubs. *)
6078       pr "static void %s_stub (XDR *xdr_in)\n" name;
6079       pr "{\n";
6080       let error_code =
6081         match fst style with
6082         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6083         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6084         | RBool _ -> pr "  int r;\n"; "-1"
6085         | RConstString _ | RConstOptString _ ->
6086             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6087         | RString _ -> pr "  char *r;\n"; "NULL"
6088         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6089         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6090         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6091         | RBufferOut _ ->
6092             pr "  size_t size = 1;\n";
6093             pr "  char *r;\n";
6094             "NULL" in
6095
6096       (match snd style with
6097        | [] -> ()
6098        | args ->
6099            pr "  struct guestfs_%s_args args;\n" name;
6100            List.iter (
6101              function
6102              | Device n | Dev_or_Path n
6103              | Pathname n
6104              | String n -> ()
6105              | OptString n -> pr "  char *%s;\n" n
6106              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6107              | Bool n -> pr "  int %s;\n" n
6108              | Int n -> pr "  int %s;\n" n
6109              | Int64 n -> pr "  int64_t %s;\n" n
6110              | FileIn _ | FileOut _ -> ()
6111            ) args
6112       );
6113       pr "\n";
6114
6115       let is_filein =
6116         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6117
6118       (match snd style with
6119        | [] -> ()
6120        | args ->
6121            pr "  memset (&args, 0, sizeof args);\n";
6122            pr "\n";
6123            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6124            if is_filein then
6125              pr "    cancel_receive ();\n";
6126            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6127            pr "    goto done;\n";
6128            pr "  }\n";
6129            let pr_args n =
6130              pr "  char *%s = args.%s;\n" n n
6131            in
6132            let pr_list_handling_code n =
6133              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6134              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6135              pr "  if (%s == NULL) {\n" n;
6136              if is_filein then
6137                pr "    cancel_receive ();\n";
6138              pr "    reply_with_perror (\"realloc\");\n";
6139              pr "    goto done;\n";
6140              pr "  }\n";
6141              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6142              pr "  args.%s.%s_val = %s;\n" n n n;
6143            in
6144            List.iter (
6145              function
6146              | Pathname n ->
6147                  pr_args n;
6148                  pr "  ABS_PATH (%s, %s, goto done);\n"
6149                    n (if is_filein then "cancel_receive ()" else "");
6150              | Device n ->
6151                  pr_args n;
6152                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6153                    n (if is_filein then "cancel_receive ()" else "");
6154              | Dev_or_Path n ->
6155                  pr_args n;
6156                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6157                    n (if is_filein then "cancel_receive ()" else "");
6158              | String n -> pr_args n
6159              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6160              | StringList n ->
6161                  pr_list_handling_code n;
6162              | DeviceList n ->
6163                  pr_list_handling_code n;
6164                  pr "  /* Ensure that each is a device,\n";
6165                  pr "   * and perform device name translation. */\n";
6166                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6167                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6168                    (if is_filein then "cancel_receive ()" else "");
6169                  pr "  }\n";
6170              | Bool n -> pr "  %s = args.%s;\n" n n
6171              | Int n -> pr "  %s = args.%s;\n" n n
6172              | Int64 n -> pr "  %s = args.%s;\n" n n
6173              | FileIn _ | FileOut _ -> ()
6174            ) args;
6175            pr "\n"
6176       );
6177
6178
6179       (* this is used at least for do_equal *)
6180       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6181         (* Emit NEED_ROOT just once, even when there are two or
6182            more Pathname args *)
6183         pr "  NEED_ROOT (%s, goto done);\n"
6184           (if is_filein then "cancel_receive ()" else "");
6185       );
6186
6187       (* Don't want to call the impl with any FileIn or FileOut
6188        * parameters, since these go "outside" the RPC protocol.
6189        *)
6190       let args' =
6191         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6192           (snd style) in
6193       pr "  r = do_%s " name;
6194       generate_c_call_args (fst style, args');
6195       pr ";\n";
6196
6197       (match fst style with
6198        | RErr | RInt _ | RInt64 _ | RBool _
6199        | RConstString _ | RConstOptString _
6200        | RString _ | RStringList _ | RHashtable _
6201        | RStruct (_, _) | RStructList (_, _) ->
6202            pr "  if (r == %s)\n" error_code;
6203            pr "    /* do_%s has already called reply_with_error */\n" name;
6204            pr "    goto done;\n";
6205            pr "\n"
6206        | RBufferOut _ ->
6207            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6208            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6209            pr "   */\n";
6210            pr "  if (size == 1 && r == %s)\n" error_code;
6211            pr "    /* do_%s has already called reply_with_error */\n" name;
6212            pr "    goto done;\n";
6213            pr "\n"
6214       );
6215
6216       (* If there are any FileOut parameters, then the impl must
6217        * send its own reply.
6218        *)
6219       let no_reply =
6220         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6221       if no_reply then
6222         pr "  /* do_%s has already sent a reply */\n" name
6223       else (
6224         match fst style with
6225         | RErr -> pr "  reply (NULL, NULL);\n"
6226         | RInt n | RInt64 n | RBool n ->
6227             pr "  struct guestfs_%s_ret ret;\n" name;
6228             pr "  ret.%s = r;\n" n;
6229             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6230               name
6231         | RConstString _ | RConstOptString _ ->
6232             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6233         | RString n ->
6234             pr "  struct guestfs_%s_ret ret;\n" name;
6235             pr "  ret.%s = r;\n" n;
6236             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6237               name;
6238             pr "  free (r);\n"
6239         | RStringList n | RHashtable n ->
6240             pr "  struct guestfs_%s_ret ret;\n" name;
6241             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6242             pr "  ret.%s.%s_val = r;\n" n n;
6243             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6244               name;
6245             pr "  free_strings (r);\n"
6246         | RStruct (n, _) ->
6247             pr "  struct guestfs_%s_ret ret;\n" name;
6248             pr "  ret.%s = *r;\n" n;
6249             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6250               name;
6251             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6252               name
6253         | RStructList (n, _) ->
6254             pr "  struct guestfs_%s_ret ret;\n" name;
6255             pr "  ret.%s = *r;\n" n;
6256             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6257               name;
6258             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6259               name
6260         | RBufferOut n ->
6261             pr "  struct guestfs_%s_ret ret;\n" name;
6262             pr "  ret.%s.%s_val = r;\n" n n;
6263             pr "  ret.%s.%s_len = size;\n" n n;
6264             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6265               name;
6266             pr "  free (r);\n"
6267       );
6268
6269       (* Free the args. *)
6270       pr "done:\n";
6271       (match snd style with
6272        | [] -> ()
6273        | _ ->
6274            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6275              name
6276       );
6277       pr "  return;\n";
6278       pr "}\n\n";
6279   ) daemon_functions;
6280
6281   (* Dispatch function. *)
6282   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6283   pr "{\n";
6284   pr "  switch (proc_nr) {\n";
6285
6286   List.iter (
6287     fun (name, style, _, _, _, _, _) ->
6288       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6289       pr "      %s_stub (xdr_in);\n" name;
6290       pr "      break;\n"
6291   ) daemon_functions;
6292
6293   pr "    default:\n";
6294   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";
6295   pr "  }\n";
6296   pr "}\n";
6297   pr "\n";
6298
6299   (* LVM columns and tokenization functions. *)
6300   (* XXX This generates crap code.  We should rethink how we
6301    * do this parsing.
6302    *)
6303   List.iter (
6304     function
6305     | typ, cols ->
6306         pr "static const char *lvm_%s_cols = \"%s\";\n"
6307           typ (String.concat "," (List.map fst cols));
6308         pr "\n";
6309
6310         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6311         pr "{\n";
6312         pr "  char *tok, *p, *next;\n";
6313         pr "  int i, j;\n";
6314         pr "\n";
6315         (*
6316           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6317           pr "\n";
6318         *)
6319         pr "  if (!str) {\n";
6320         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6321         pr "    return -1;\n";
6322         pr "  }\n";
6323         pr "  if (!*str || c_isspace (*str)) {\n";
6324         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6325         pr "    return -1;\n";
6326         pr "  }\n";
6327         pr "  tok = str;\n";
6328         List.iter (
6329           fun (name, coltype) ->
6330             pr "  if (!tok) {\n";
6331             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6332             pr "    return -1;\n";
6333             pr "  }\n";
6334             pr "  p = strchrnul (tok, ',');\n";
6335             pr "  if (*p) next = p+1; else next = NULL;\n";
6336             pr "  *p = '\\0';\n";
6337             (match coltype with
6338              | FString ->
6339                  pr "  r->%s = strdup (tok);\n" name;
6340                  pr "  if (r->%s == NULL) {\n" name;
6341                  pr "    perror (\"strdup\");\n";
6342                  pr "    return -1;\n";
6343                  pr "  }\n"
6344              | FUUID ->
6345                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6346                  pr "    if (tok[j] == '\\0') {\n";
6347                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6348                  pr "      return -1;\n";
6349                  pr "    } else if (tok[j] != '-')\n";
6350                  pr "      r->%s[i++] = tok[j];\n" name;
6351                  pr "  }\n";
6352              | FBytes ->
6353                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6354                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6355                  pr "    return -1;\n";
6356                  pr "  }\n";
6357              | FInt64 ->
6358                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6359                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6360                  pr "    return -1;\n";
6361                  pr "  }\n";
6362              | FOptPercent ->
6363                  pr "  if (tok[0] == '\\0')\n";
6364                  pr "    r->%s = -1;\n" name;
6365                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6366                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6367                  pr "    return -1;\n";
6368                  pr "  }\n";
6369              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6370                  assert false (* can never be an LVM column *)
6371             );
6372             pr "  tok = next;\n";
6373         ) cols;
6374
6375         pr "  if (tok != NULL) {\n";
6376         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6377         pr "    return -1;\n";
6378         pr "  }\n";
6379         pr "  return 0;\n";
6380         pr "}\n";
6381         pr "\n";
6382
6383         pr "guestfs_int_lvm_%s_list *\n" typ;
6384         pr "parse_command_line_%ss (void)\n" typ;
6385         pr "{\n";
6386         pr "  char *out, *err;\n";
6387         pr "  char *p, *pend;\n";
6388         pr "  int r, i;\n";
6389         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6390         pr "  void *newp;\n";
6391         pr "\n";
6392         pr "  ret = malloc (sizeof *ret);\n";
6393         pr "  if (!ret) {\n";
6394         pr "    reply_with_perror (\"malloc\");\n";
6395         pr "    return NULL;\n";
6396         pr "  }\n";
6397         pr "\n";
6398         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6399         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6400         pr "\n";
6401         pr "  r = command (&out, &err,\n";
6402         pr "           \"lvm\", \"%ss\",\n" typ;
6403         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6404         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6405         pr "  if (r == -1) {\n";
6406         pr "    reply_with_error (\"%%s\", err);\n";
6407         pr "    free (out);\n";
6408         pr "    free (err);\n";
6409         pr "    free (ret);\n";
6410         pr "    return NULL;\n";
6411         pr "  }\n";
6412         pr "\n";
6413         pr "  free (err);\n";
6414         pr "\n";
6415         pr "  /* Tokenize each line of the output. */\n";
6416         pr "  p = out;\n";
6417         pr "  i = 0;\n";
6418         pr "  while (p) {\n";
6419         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6420         pr "    if (pend) {\n";
6421         pr "      *pend = '\\0';\n";
6422         pr "      pend++;\n";
6423         pr "    }\n";
6424         pr "\n";
6425         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6426         pr "      p++;\n";
6427         pr "\n";
6428         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6429         pr "      p = pend;\n";
6430         pr "      continue;\n";
6431         pr "    }\n";
6432         pr "\n";
6433         pr "    /* Allocate some space to store this next entry. */\n";
6434         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6435         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6436         pr "    if (newp == NULL) {\n";
6437         pr "      reply_with_perror (\"realloc\");\n";
6438         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6439         pr "      free (ret);\n";
6440         pr "      free (out);\n";
6441         pr "      return NULL;\n";
6442         pr "    }\n";
6443         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6444         pr "\n";
6445         pr "    /* Tokenize the next entry. */\n";
6446         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6447         pr "    if (r == -1) {\n";
6448         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6449         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6450         pr "      free (ret);\n";
6451         pr "      free (out);\n";
6452         pr "      return NULL;\n";
6453         pr "    }\n";
6454         pr "\n";
6455         pr "    ++i;\n";
6456         pr "    p = pend;\n";
6457         pr "  }\n";
6458         pr "\n";
6459         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6460         pr "\n";
6461         pr "  free (out);\n";
6462         pr "  return ret;\n";
6463         pr "}\n"
6464
6465   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6466
6467 (* Generate a list of function names, for debugging in the daemon.. *)
6468 and generate_daemon_names () =
6469   generate_header CStyle GPLv2plus;
6470
6471   pr "#include <config.h>\n";
6472   pr "\n";
6473   pr "#include \"daemon.h\"\n";
6474   pr "\n";
6475
6476   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6477   pr "const char *function_names[] = {\n";
6478   List.iter (
6479     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6480   ) daemon_functions;
6481   pr "};\n";
6482
6483 (* Generate the optional groups for the daemon to implement
6484  * guestfs_available.
6485  *)
6486 and generate_daemon_optgroups_c () =
6487   generate_header CStyle GPLv2plus;
6488
6489   pr "#include <config.h>\n";
6490   pr "\n";
6491   pr "#include \"daemon.h\"\n";
6492   pr "#include \"optgroups.h\"\n";
6493   pr "\n";
6494
6495   pr "struct optgroup optgroups[] = {\n";
6496   List.iter (
6497     fun (group, _) ->
6498       pr "  { \"%s\", optgroup_%s_available },\n" group group
6499   ) optgroups;
6500   pr "  { NULL, NULL }\n";
6501   pr "};\n"
6502
6503 and generate_daemon_optgroups_h () =
6504   generate_header CStyle GPLv2plus;
6505
6506   List.iter (
6507     fun (group, _) ->
6508       pr "extern int optgroup_%s_available (void);\n" group
6509   ) optgroups
6510
6511 (* Generate the tests. *)
6512 and generate_tests () =
6513   generate_header CStyle GPLv2plus;
6514
6515   pr "\
6516 #include <stdio.h>
6517 #include <stdlib.h>
6518 #include <string.h>
6519 #include <unistd.h>
6520 #include <sys/types.h>
6521 #include <fcntl.h>
6522
6523 #include \"guestfs.h\"
6524 #include \"guestfs-internal.h\"
6525
6526 static guestfs_h *g;
6527 static int suppress_error = 0;
6528
6529 static void print_error (guestfs_h *g, void *data, const char *msg)
6530 {
6531   if (!suppress_error)
6532     fprintf (stderr, \"%%s\\n\", msg);
6533 }
6534
6535 /* FIXME: nearly identical code appears in fish.c */
6536 static void print_strings (char *const *argv)
6537 {
6538   int argc;
6539
6540   for (argc = 0; argv[argc] != NULL; ++argc)
6541     printf (\"\\t%%s\\n\", argv[argc]);
6542 }
6543
6544 /*
6545 static void print_table (char const *const *argv)
6546 {
6547   int i;
6548
6549   for (i = 0; argv[i] != NULL; i += 2)
6550     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6551 }
6552 */
6553
6554 ";
6555
6556   (* Generate a list of commands which are not tested anywhere. *)
6557   pr "static void no_test_warnings (void)\n";
6558   pr "{\n";
6559
6560   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6561   List.iter (
6562     fun (_, _, _, _, tests, _, _) ->
6563       let tests = filter_map (
6564         function
6565         | (_, (Always|If _|Unless _), test) -> Some test
6566         | (_, Disabled, _) -> None
6567       ) tests in
6568       let seq = List.concat (List.map seq_of_test tests) in
6569       let cmds_tested = List.map List.hd seq in
6570       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6571   ) all_functions;
6572
6573   List.iter (
6574     fun (name, _, _, _, _, _, _) ->
6575       if not (Hashtbl.mem hash name) then
6576         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6577   ) all_functions;
6578
6579   pr "}\n";
6580   pr "\n";
6581
6582   (* Generate the actual tests.  Note that we generate the tests
6583    * in reverse order, deliberately, so that (in general) the
6584    * newest tests run first.  This makes it quicker and easier to
6585    * debug them.
6586    *)
6587   let test_names =
6588     List.map (
6589       fun (name, _, _, flags, tests, _, _) ->
6590         mapi (generate_one_test name flags) tests
6591     ) (List.rev all_functions) in
6592   let test_names = List.concat test_names in
6593   let nr_tests = List.length test_names in
6594
6595   pr "\
6596 int main (int argc, char *argv[])
6597 {
6598   char c = 0;
6599   unsigned long int n_failed = 0;
6600   const char *filename;
6601   int fd;
6602   int nr_tests, test_num = 0;
6603
6604   setbuf (stdout, NULL);
6605
6606   no_test_warnings ();
6607
6608   g = guestfs_create ();
6609   if (g == NULL) {
6610     printf (\"guestfs_create FAILED\\n\");
6611     exit (EXIT_FAILURE);
6612   }
6613
6614   guestfs_set_error_handler (g, print_error, NULL);
6615
6616   guestfs_set_path (g, \"../appliance\");
6617
6618   filename = \"test1.img\";
6619   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6620   if (fd == -1) {
6621     perror (filename);
6622     exit (EXIT_FAILURE);
6623   }
6624   if (lseek (fd, %d, SEEK_SET) == -1) {
6625     perror (\"lseek\");
6626     close (fd);
6627     unlink (filename);
6628     exit (EXIT_FAILURE);
6629   }
6630   if (write (fd, &c, 1) == -1) {
6631     perror (\"write\");
6632     close (fd);
6633     unlink (filename);
6634     exit (EXIT_FAILURE);
6635   }
6636   if (close (fd) == -1) {
6637     perror (filename);
6638     unlink (filename);
6639     exit (EXIT_FAILURE);
6640   }
6641   if (guestfs_add_drive (g, filename) == -1) {
6642     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6643     exit (EXIT_FAILURE);
6644   }
6645
6646   filename = \"test2.img\";
6647   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6648   if (fd == -1) {
6649     perror (filename);
6650     exit (EXIT_FAILURE);
6651   }
6652   if (lseek (fd, %d, SEEK_SET) == -1) {
6653     perror (\"lseek\");
6654     close (fd);
6655     unlink (filename);
6656     exit (EXIT_FAILURE);
6657   }
6658   if (write (fd, &c, 1) == -1) {
6659     perror (\"write\");
6660     close (fd);
6661     unlink (filename);
6662     exit (EXIT_FAILURE);
6663   }
6664   if (close (fd) == -1) {
6665     perror (filename);
6666     unlink (filename);
6667     exit (EXIT_FAILURE);
6668   }
6669   if (guestfs_add_drive (g, filename) == -1) {
6670     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6671     exit (EXIT_FAILURE);
6672   }
6673
6674   filename = \"test3.img\";
6675   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6676   if (fd == -1) {
6677     perror (filename);
6678     exit (EXIT_FAILURE);
6679   }
6680   if (lseek (fd, %d, SEEK_SET) == -1) {
6681     perror (\"lseek\");
6682     close (fd);
6683     unlink (filename);
6684     exit (EXIT_FAILURE);
6685   }
6686   if (write (fd, &c, 1) == -1) {
6687     perror (\"write\");
6688     close (fd);
6689     unlink (filename);
6690     exit (EXIT_FAILURE);
6691   }
6692   if (close (fd) == -1) {
6693     perror (filename);
6694     unlink (filename);
6695     exit (EXIT_FAILURE);
6696   }
6697   if (guestfs_add_drive (g, filename) == -1) {
6698     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6699     exit (EXIT_FAILURE);
6700   }
6701
6702   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6703     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6704     exit (EXIT_FAILURE);
6705   }
6706
6707   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6708   alarm (600);
6709
6710   if (guestfs_launch (g) == -1) {
6711     printf (\"guestfs_launch FAILED\\n\");
6712     exit (EXIT_FAILURE);
6713   }
6714
6715   /* Cancel previous alarm. */
6716   alarm (0);
6717
6718   nr_tests = %d;
6719
6720 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6721
6722   iteri (
6723     fun i test_name ->
6724       pr "  test_num++;\n";
6725       pr "  if (guestfs_get_verbose (g))\n";
6726       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6727       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6728       pr "  if (%s () == -1) {\n" test_name;
6729       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6730       pr "    n_failed++;\n";
6731       pr "  }\n";
6732   ) test_names;
6733   pr "\n";
6734
6735   pr "  guestfs_close (g);\n";
6736   pr "  unlink (\"test1.img\");\n";
6737   pr "  unlink (\"test2.img\");\n";
6738   pr "  unlink (\"test3.img\");\n";
6739   pr "\n";
6740
6741   pr "  if (n_failed > 0) {\n";
6742   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6743   pr "    exit (EXIT_FAILURE);\n";
6744   pr "  }\n";
6745   pr "\n";
6746
6747   pr "  exit (EXIT_SUCCESS);\n";
6748   pr "}\n"
6749
6750 and generate_one_test name flags i (init, prereq, test) =
6751   let test_name = sprintf "test_%s_%d" name i in
6752
6753   pr "\
6754 static int %s_skip (void)
6755 {
6756   const char *str;
6757
6758   str = getenv (\"TEST_ONLY\");
6759   if (str)
6760     return strstr (str, \"%s\") == NULL;
6761   str = getenv (\"SKIP_%s\");
6762   if (str && STREQ (str, \"1\")) return 1;
6763   str = getenv (\"SKIP_TEST_%s\");
6764   if (str && STREQ (str, \"1\")) return 1;
6765   return 0;
6766 }
6767
6768 " test_name name (String.uppercase test_name) (String.uppercase name);
6769
6770   (match prereq with
6771    | Disabled | Always -> ()
6772    | If code | Unless code ->
6773        pr "static int %s_prereq (void)\n" test_name;
6774        pr "{\n";
6775        pr "  %s\n" code;
6776        pr "}\n";
6777        pr "\n";
6778   );
6779
6780   pr "\
6781 static int %s (void)
6782 {
6783   if (%s_skip ()) {
6784     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6785     return 0;
6786   }
6787
6788 " test_name test_name test_name;
6789
6790   (* Optional functions should only be tested if the relevant
6791    * support is available in the daemon.
6792    *)
6793   List.iter (
6794     function
6795     | Optional group ->
6796         pr "  {\n";
6797         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6798         pr "    int r;\n";
6799         pr "    suppress_error = 1;\n";
6800         pr "    r = guestfs_available (g, (char **) groups);\n";
6801         pr "    suppress_error = 0;\n";
6802         pr "    if (r == -1) {\n";
6803         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6804         pr "      return 0;\n";
6805         pr "    }\n";
6806         pr "  }\n";
6807     | _ -> ()
6808   ) flags;
6809
6810   (match prereq with
6811    | Disabled ->
6812        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6813    | If _ ->
6814        pr "  if (! %s_prereq ()) {\n" test_name;
6815        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6816        pr "    return 0;\n";
6817        pr "  }\n";
6818        pr "\n";
6819        generate_one_test_body name i test_name init test;
6820    | Unless _ ->
6821        pr "  if (%s_prereq ()) {\n" test_name;
6822        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6823        pr "    return 0;\n";
6824        pr "  }\n";
6825        pr "\n";
6826        generate_one_test_body name i test_name init test;
6827    | Always ->
6828        generate_one_test_body name i test_name init test
6829   );
6830
6831   pr "  return 0;\n";
6832   pr "}\n";
6833   pr "\n";
6834   test_name
6835
6836 and generate_one_test_body name i test_name init test =
6837   (match init with
6838    | InitNone (* XXX at some point, InitNone and InitEmpty became
6839                * folded together as the same thing.  Really we should
6840                * make InitNone do nothing at all, but the tests may
6841                * need to be checked to make sure this is OK.
6842                *)
6843    | InitEmpty ->
6844        pr "  /* InitNone|InitEmpty for %s */\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    | InitPartition ->
6850        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6851        List.iter (generate_test_command_call test_name)
6852          [["blockdev_setrw"; "/dev/sda"];
6853           ["umount_all"];
6854           ["lvm_remove_all"];
6855           ["part_disk"; "/dev/sda"; "mbr"]]
6856    | InitBasicFS ->
6857        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6858        List.iter (generate_test_command_call test_name)
6859          [["blockdev_setrw"; "/dev/sda"];
6860           ["umount_all"];
6861           ["lvm_remove_all"];
6862           ["part_disk"; "/dev/sda"; "mbr"];
6863           ["mkfs"; "ext2"; "/dev/sda1"];
6864           ["mount_options"; ""; "/dev/sda1"; "/"]]
6865    | InitBasicFSonLVM ->
6866        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6867          test_name;
6868        List.iter (generate_test_command_call test_name)
6869          [["blockdev_setrw"; "/dev/sda"];
6870           ["umount_all"];
6871           ["lvm_remove_all"];
6872           ["part_disk"; "/dev/sda"; "mbr"];
6873           ["pvcreate"; "/dev/sda1"];
6874           ["vgcreate"; "VG"; "/dev/sda1"];
6875           ["lvcreate"; "LV"; "VG"; "8"];
6876           ["mkfs"; "ext2"; "/dev/VG/LV"];
6877           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6878    | InitISOFS ->
6879        pr "  /* InitISOFS for %s */\n" test_name;
6880        List.iter (generate_test_command_call test_name)
6881          [["blockdev_setrw"; "/dev/sda"];
6882           ["umount_all"];
6883           ["lvm_remove_all"];
6884           ["mount_ro"; "/dev/sdd"; "/"]]
6885   );
6886
6887   let get_seq_last = function
6888     | [] ->
6889         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6890           test_name
6891     | seq ->
6892         let seq = List.rev seq in
6893         List.rev (List.tl seq), List.hd seq
6894   in
6895
6896   match test with
6897   | TestRun seq ->
6898       pr "  /* TestRun for %s (%d) */\n" name i;
6899       List.iter (generate_test_command_call test_name) seq
6900   | TestOutput (seq, expected) ->
6901       pr "  /* TestOutput for %s (%d) */\n" name i;
6902       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6903       let seq, last = get_seq_last seq in
6904       let test () =
6905         pr "    if (STRNEQ (r, expected)) {\n";
6906         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6907         pr "      return -1;\n";
6908         pr "    }\n"
6909       in
6910       List.iter (generate_test_command_call test_name) seq;
6911       generate_test_command_call ~test test_name last
6912   | TestOutputList (seq, expected) ->
6913       pr "  /* TestOutputList for %s (%d) */\n" name i;
6914       let seq, last = get_seq_last seq in
6915       let test () =
6916         iteri (
6917           fun i str ->
6918             pr "    if (!r[%d]) {\n" i;
6919             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6920             pr "      print_strings (r);\n";
6921             pr "      return -1;\n";
6922             pr "    }\n";
6923             pr "    {\n";
6924             pr "      const char *expected = \"%s\";\n" (c_quote str);
6925             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6926             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6927             pr "        return -1;\n";
6928             pr "      }\n";
6929             pr "    }\n"
6930         ) expected;
6931         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6932         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6933           test_name;
6934         pr "      print_strings (r);\n";
6935         pr "      return -1;\n";
6936         pr "    }\n"
6937       in
6938       List.iter (generate_test_command_call test_name) seq;
6939       generate_test_command_call ~test test_name last
6940   | TestOutputListOfDevices (seq, expected) ->
6941       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6942       let seq, last = get_seq_last seq in
6943       let test () =
6944         iteri (
6945           fun i str ->
6946             pr "    if (!r[%d]) {\n" i;
6947             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6948             pr "      print_strings (r);\n";
6949             pr "      return -1;\n";
6950             pr "    }\n";
6951             pr "    {\n";
6952             pr "      const char *expected = \"%s\";\n" (c_quote str);
6953             pr "      r[%d][5] = 's';\n" i;
6954             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6955             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6956             pr "        return -1;\n";
6957             pr "      }\n";
6958             pr "    }\n"
6959         ) expected;
6960         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6961         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6962           test_name;
6963         pr "      print_strings (r);\n";
6964         pr "      return -1;\n";
6965         pr "    }\n"
6966       in
6967       List.iter (generate_test_command_call test_name) seq;
6968       generate_test_command_call ~test test_name last
6969   | TestOutputInt (seq, expected) ->
6970       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6971       let seq, last = get_seq_last seq in
6972       let test () =
6973         pr "    if (r != %d) {\n" expected;
6974         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6975           test_name expected;
6976         pr "               (int) r);\n";
6977         pr "      return -1;\n";
6978         pr "    }\n"
6979       in
6980       List.iter (generate_test_command_call test_name) seq;
6981       generate_test_command_call ~test test_name last
6982   | TestOutputIntOp (seq, op, expected) ->
6983       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6984       let seq, last = get_seq_last seq in
6985       let test () =
6986         pr "    if (! (r %s %d)) {\n" op expected;
6987         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6988           test_name op expected;
6989         pr "               (int) r);\n";
6990         pr "      return -1;\n";
6991         pr "    }\n"
6992       in
6993       List.iter (generate_test_command_call test_name) seq;
6994       generate_test_command_call ~test test_name last
6995   | TestOutputTrue seq ->
6996       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6997       let seq, last = get_seq_last seq in
6998       let test () =
6999         pr "    if (!r) {\n";
7000         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7001           test_name;
7002         pr "      return -1;\n";
7003         pr "    }\n"
7004       in
7005       List.iter (generate_test_command_call test_name) seq;
7006       generate_test_command_call ~test test_name last
7007   | TestOutputFalse seq ->
7008       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7009       let seq, last = get_seq_last seq in
7010       let test () =
7011         pr "    if (r) {\n";
7012         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7013           test_name;
7014         pr "      return -1;\n";
7015         pr "    }\n"
7016       in
7017       List.iter (generate_test_command_call test_name) seq;
7018       generate_test_command_call ~test test_name last
7019   | TestOutputLength (seq, expected) ->
7020       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7021       let seq, last = get_seq_last seq in
7022       let test () =
7023         pr "    int j;\n";
7024         pr "    for (j = 0; j < %d; ++j)\n" expected;
7025         pr "      if (r[j] == NULL) {\n";
7026         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7027           test_name;
7028         pr "        print_strings (r);\n";
7029         pr "        return -1;\n";
7030         pr "      }\n";
7031         pr "    if (r[j] != NULL) {\n";
7032         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7033           test_name;
7034         pr "      print_strings (r);\n";
7035         pr "      return -1;\n";
7036         pr "    }\n"
7037       in
7038       List.iter (generate_test_command_call test_name) seq;
7039       generate_test_command_call ~test test_name last
7040   | TestOutputBuffer (seq, expected) ->
7041       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7042       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7043       let seq, last = get_seq_last seq in
7044       let len = String.length expected in
7045       let test () =
7046         pr "    if (size != %d) {\n" len;
7047         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7048         pr "      return -1;\n";
7049         pr "    }\n";
7050         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7051         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7052         pr "      return -1;\n";
7053         pr "    }\n"
7054       in
7055       List.iter (generate_test_command_call test_name) seq;
7056       generate_test_command_call ~test test_name last
7057   | TestOutputStruct (seq, checks) ->
7058       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7059       let seq, last = get_seq_last seq in
7060       let test () =
7061         List.iter (
7062           function
7063           | CompareWithInt (field, expected) ->
7064               pr "    if (r->%s != %d) {\n" field expected;
7065               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7066                 test_name field expected;
7067               pr "               (int) r->%s);\n" field;
7068               pr "      return -1;\n";
7069               pr "    }\n"
7070           | CompareWithIntOp (field, op, expected) ->
7071               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7072               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7073                 test_name field op expected;
7074               pr "               (int) r->%s);\n" field;
7075               pr "      return -1;\n";
7076               pr "    }\n"
7077           | CompareWithString (field, expected) ->
7078               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7079               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7080                 test_name field expected;
7081               pr "               r->%s);\n" field;
7082               pr "      return -1;\n";
7083               pr "    }\n"
7084           | CompareFieldsIntEq (field1, field2) ->
7085               pr "    if (r->%s != r->%s) {\n" field1 field2;
7086               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7087                 test_name field1 field2;
7088               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7089               pr "      return -1;\n";
7090               pr "    }\n"
7091           | CompareFieldsStrEq (field1, field2) ->
7092               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7093               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7094                 test_name field1 field2;
7095               pr "               r->%s, r->%s);\n" field1 field2;
7096               pr "      return -1;\n";
7097               pr "    }\n"
7098         ) checks
7099       in
7100       List.iter (generate_test_command_call test_name) seq;
7101       generate_test_command_call ~test test_name last
7102   | TestLastFail seq ->
7103       pr "  /* TestLastFail for %s (%d) */\n" name i;
7104       let seq, last = get_seq_last seq in
7105       List.iter (generate_test_command_call test_name) seq;
7106       generate_test_command_call test_name ~expect_error:true last
7107
7108 (* Generate the code to run a command, leaving the result in 'r'.
7109  * If you expect to get an error then you should set expect_error:true.
7110  *)
7111 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7112   match cmd with
7113   | [] -> assert false
7114   | name :: args ->
7115       (* Look up the command to find out what args/ret it has. *)
7116       let style =
7117         try
7118           let _, style, _, _, _, _, _ =
7119             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7120           style
7121         with Not_found ->
7122           failwithf "%s: in test, command %s was not found" test_name name in
7123
7124       if List.length (snd style) <> List.length args then
7125         failwithf "%s: in test, wrong number of args given to %s"
7126           test_name name;
7127
7128       pr "  {\n";
7129
7130       List.iter (
7131         function
7132         | OptString n, "NULL" -> ()
7133         | Pathname n, arg
7134         | Device n, arg
7135         | Dev_or_Path n, arg
7136         | String n, arg
7137         | OptString n, arg ->
7138             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7139         | Int _, _
7140         | Int64 _, _
7141         | Bool _, _
7142         | FileIn _, _ | FileOut _, _ -> ()
7143         | StringList n, "" | DeviceList n, "" ->
7144             pr "    const char *const %s[1] = { NULL };\n" n
7145         | StringList n, arg | DeviceList n, arg ->
7146             let strs = string_split " " arg in
7147             iteri (
7148               fun i str ->
7149                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7150             ) strs;
7151             pr "    const char *const %s[] = {\n" n;
7152             iteri (
7153               fun i _ -> pr "      %s_%d,\n" n i
7154             ) strs;
7155             pr "      NULL\n";
7156             pr "    };\n";
7157       ) (List.combine (snd style) args);
7158
7159       let error_code =
7160         match fst style with
7161         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7162         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7163         | RConstString _ | RConstOptString _ ->
7164             pr "    const char *r;\n"; "NULL"
7165         | RString _ -> pr "    char *r;\n"; "NULL"
7166         | RStringList _ | RHashtable _ ->
7167             pr "    char **r;\n";
7168             pr "    int i;\n";
7169             "NULL"
7170         | RStruct (_, typ) ->
7171             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7172         | RStructList (_, typ) ->
7173             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7174         | RBufferOut _ ->
7175             pr "    char *r;\n";
7176             pr "    size_t size;\n";
7177             "NULL" in
7178
7179       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7180       pr "    r = guestfs_%s (g" name;
7181
7182       (* Generate the parameters. *)
7183       List.iter (
7184         function
7185         | OptString _, "NULL" -> pr ", NULL"
7186         | Pathname n, _
7187         | Device n, _ | Dev_or_Path n, _
7188         | String n, _
7189         | OptString n, _ ->
7190             pr ", %s" n
7191         | FileIn _, arg | FileOut _, arg ->
7192             pr ", \"%s\"" (c_quote arg)
7193         | StringList n, _ | DeviceList n, _ ->
7194             pr ", (char **) %s" n
7195         | Int _, arg ->
7196             let i =
7197               try int_of_string arg
7198               with Failure "int_of_string" ->
7199                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7200             pr ", %d" i
7201         | Int64 _, arg ->
7202             let i =
7203               try Int64.of_string arg
7204               with Failure "int_of_string" ->
7205                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7206             pr ", %Ld" i
7207         | Bool _, arg ->
7208             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7209       ) (List.combine (snd style) args);
7210
7211       (match fst style with
7212        | RBufferOut _ -> pr ", &size"
7213        | _ -> ()
7214       );
7215
7216       pr ");\n";
7217
7218       if not expect_error then
7219         pr "    if (r == %s)\n" error_code
7220       else
7221         pr "    if (r != %s)\n" error_code;
7222       pr "      return -1;\n";
7223
7224       (* Insert the test code. *)
7225       (match test with
7226        | None -> ()
7227        | Some f -> f ()
7228       );
7229
7230       (match fst style with
7231        | RErr | RInt _ | RInt64 _ | RBool _
7232        | RConstString _ | RConstOptString _ -> ()
7233        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7234        | RStringList _ | RHashtable _ ->
7235            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7236            pr "      free (r[i]);\n";
7237            pr "    free (r);\n"
7238        | RStruct (_, typ) ->
7239            pr "    guestfs_free_%s (r);\n" typ
7240        | RStructList (_, typ) ->
7241            pr "    guestfs_free_%s_list (r);\n" typ
7242       );
7243
7244       pr "  }\n"
7245
7246 and c_quote str =
7247   let str = replace_str str "\r" "\\r" in
7248   let str = replace_str str "\n" "\\n" in
7249   let str = replace_str str "\t" "\\t" in
7250   let str = replace_str str "\000" "\\0" in
7251   str
7252
7253 (* Generate a lot of different functions for guestfish. *)
7254 and generate_fish_cmds () =
7255   generate_header CStyle GPLv2plus;
7256
7257   let all_functions =
7258     List.filter (
7259       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7260     ) all_functions in
7261   let all_functions_sorted =
7262     List.filter (
7263       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7264     ) all_functions_sorted in
7265
7266   pr "#include <config.h>\n";
7267   pr "\n";
7268   pr "#include <stdio.h>\n";
7269   pr "#include <stdlib.h>\n";
7270   pr "#include <string.h>\n";
7271   pr "#include <inttypes.h>\n";
7272   pr "\n";
7273   pr "#include <guestfs.h>\n";
7274   pr "#include \"c-ctype.h\"\n";
7275   pr "#include \"full-write.h\"\n";
7276   pr "#include \"xstrtol.h\"\n";
7277   pr "#include \"fish.h\"\n";
7278   pr "\n";
7279
7280   (* list_commands function, which implements guestfish -h *)
7281   pr "void list_commands (void)\n";
7282   pr "{\n";
7283   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7284   pr "  list_builtin_commands ();\n";
7285   List.iter (
7286     fun (name, _, _, flags, _, shortdesc, _) ->
7287       let name = replace_char name '_' '-' in
7288       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7289         name shortdesc
7290   ) all_functions_sorted;
7291   pr "  printf (\"    %%s\\n\",";
7292   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7293   pr "}\n";
7294   pr "\n";
7295
7296   (* display_command function, which implements guestfish -h cmd *)
7297   pr "void display_command (const char *cmd)\n";
7298   pr "{\n";
7299   List.iter (
7300     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7301       let name2 = replace_char name '_' '-' in
7302       let alias =
7303         try find_map (function FishAlias n -> Some n | _ -> None) flags
7304         with Not_found -> name in
7305       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7306       let synopsis =
7307         match snd style with
7308         | [] -> name2
7309         | args ->
7310             sprintf "%s %s"
7311               name2 (String.concat " " (List.map name_of_argt args)) in
7312
7313       let warnings =
7314         if List.mem ProtocolLimitWarning flags then
7315           ("\n\n" ^ protocol_limit_warning)
7316         else "" in
7317
7318       (* For DangerWillRobinson commands, we should probably have
7319        * guestfish prompt before allowing you to use them (especially
7320        * in interactive mode). XXX
7321        *)
7322       let warnings =
7323         warnings ^
7324           if List.mem DangerWillRobinson flags then
7325             ("\n\n" ^ danger_will_robinson)
7326           else "" in
7327
7328       let warnings =
7329         warnings ^
7330           match deprecation_notice flags with
7331           | None -> ""
7332           | Some txt -> "\n\n" ^ txt in
7333
7334       let describe_alias =
7335         if name <> alias then
7336           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7337         else "" in
7338
7339       pr "  if (";
7340       pr "STRCASEEQ (cmd, \"%s\")" name;
7341       if name <> name2 then
7342         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7343       if name <> alias then
7344         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7345       pr ")\n";
7346       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7347         name2 shortdesc
7348         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7349          "=head1 DESCRIPTION\n\n" ^
7350          longdesc ^ warnings ^ describe_alias);
7351       pr "  else\n"
7352   ) all_functions;
7353   pr "    display_builtin_command (cmd);\n";
7354   pr "}\n";
7355   pr "\n";
7356
7357   let emit_print_list_function typ =
7358     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7359       typ typ typ;
7360     pr "{\n";
7361     pr "  unsigned int i;\n";
7362     pr "\n";
7363     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7364     pr "    printf (\"[%%d] = {\\n\", i);\n";
7365     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7366     pr "    printf (\"}\\n\");\n";
7367     pr "  }\n";
7368     pr "}\n";
7369     pr "\n";
7370   in
7371
7372   (* print_* functions *)
7373   List.iter (
7374     fun (typ, cols) ->
7375       let needs_i =
7376         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7377
7378       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7379       pr "{\n";
7380       if needs_i then (
7381         pr "  unsigned int i;\n";
7382         pr "\n"
7383       );
7384       List.iter (
7385         function
7386         | name, FString ->
7387             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7388         | name, FUUID ->
7389             pr "  printf (\"%%s%s: \", indent);\n" name;
7390             pr "  for (i = 0; i < 32; ++i)\n";
7391             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7392             pr "  printf (\"\\n\");\n"
7393         | name, FBuffer ->
7394             pr "  printf (\"%%s%s: \", indent);\n" name;
7395             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7396             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7397             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7398             pr "    else\n";
7399             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7400             pr "  printf (\"\\n\");\n"
7401         | name, (FUInt64|FBytes) ->
7402             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7403               name typ name
7404         | name, FInt64 ->
7405             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7406               name typ name
7407         | name, FUInt32 ->
7408             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7409               name typ name
7410         | name, FInt32 ->
7411             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7412               name typ name
7413         | name, FChar ->
7414             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7415               name typ name
7416         | name, FOptPercent ->
7417             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7418               typ name name typ name;
7419             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7420       ) cols;
7421       pr "}\n";
7422       pr "\n";
7423   ) structs;
7424
7425   (* Emit a print_TYPE_list function definition only if that function is used. *)
7426   List.iter (
7427     function
7428     | typ, (RStructListOnly | RStructAndList) ->
7429         (* generate the function for typ *)
7430         emit_print_list_function typ
7431     | typ, _ -> () (* empty *)
7432   ) (rstructs_used_by all_functions);
7433
7434   (* Emit a print_TYPE function definition only if that function is used. *)
7435   List.iter (
7436     function
7437     | typ, (RStructOnly | RStructAndList) ->
7438         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7439         pr "{\n";
7440         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7441         pr "}\n";
7442         pr "\n";
7443     | typ, _ -> () (* empty *)
7444   ) (rstructs_used_by all_functions);
7445
7446   (* run_<action> actions *)
7447   List.iter (
7448     fun (name, style, _, flags, _, _, _) ->
7449       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7450       pr "{\n";
7451       (match fst style with
7452        | RErr
7453        | RInt _
7454        | RBool _ -> pr "  int r;\n"
7455        | RInt64 _ -> pr "  int64_t r;\n"
7456        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7457        | RString _ -> pr "  char *r;\n"
7458        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7459        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7460        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7461        | RBufferOut _ ->
7462            pr "  char *r;\n";
7463            pr "  size_t size;\n";
7464       );
7465       List.iter (
7466         function
7467         | Device n
7468         | String n
7469         | OptString n -> pr "  const char *%s;\n" n
7470         | Pathname n
7471         | Dev_or_Path n
7472         | FileIn n
7473         | FileOut n -> pr "  char *%s;\n" n
7474         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7475         | Bool n -> pr "  int %s;\n" n
7476         | Int n -> pr "  int %s;\n" n
7477         | Int64 n -> pr "  int64_t %s;\n" n
7478       ) (snd style);
7479
7480       (* Check and convert parameters. *)
7481       let argc_expected = List.length (snd style) in
7482       pr "  if (argc != %d) {\n" argc_expected;
7483       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7484         argc_expected;
7485       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7486       pr "    return -1;\n";
7487       pr "  }\n";
7488
7489       let parse_integer fn fntyp rtyp range name i =
7490         pr "  {\n";
7491         pr "    strtol_error xerr;\n";
7492         pr "    %s r;\n" fntyp;
7493         pr "\n";
7494         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7495         pr "    if (xerr != LONGINT_OK) {\n";
7496         pr "      fprintf (stderr,\n";
7497         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7498         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7499         pr "      return -1;\n";
7500         pr "    }\n";
7501         (match range with
7502          | None -> ()
7503          | Some (min, max, comment) ->
7504              pr "    /* %s */\n" comment;
7505              pr "    if (r < %s || r > %s) {\n" min max;
7506              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7507                name;
7508              pr "      return -1;\n";
7509              pr "    }\n";
7510              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7511         );
7512         pr "    %s = r;\n" name;
7513         pr "  }\n";
7514       in
7515
7516       iteri (
7517         fun i ->
7518           function
7519           | Device name
7520           | String name ->
7521               pr "  %s = argv[%d];\n" name i
7522           | Pathname name
7523           | Dev_or_Path name ->
7524               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7525               pr "  if (%s == NULL) return -1;\n" name
7526           | OptString name ->
7527               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7528                 name i i
7529           | FileIn name ->
7530               pr "  %s = file_in (argv[%d]);\n" name i;
7531               pr "  if (%s == NULL) return -1;\n" name
7532           | FileOut name ->
7533               pr "  %s = file_out (argv[%d]);\n" name i;
7534               pr "  if (%s == NULL) return -1;\n" name
7535           | StringList name | DeviceList name ->
7536               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7537               pr "  if (%s == NULL) return -1;\n" name;
7538           | Bool name ->
7539               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7540           | Int name ->
7541               let range =
7542                 let min = "(-(2LL<<30))"
7543                 and max = "((2LL<<30)-1)"
7544                 and comment =
7545                   "The Int type in the generator is a signed 31 bit int." in
7546                 Some (min, max, comment) in
7547               parse_integer "xstrtoll" "long long" "int" range name i
7548           | Int64 name ->
7549               parse_integer "xstrtoll" "long long" "int64_t" None name i
7550       ) (snd style);
7551
7552       (* Call C API function. *)
7553       let fn =
7554         try find_map (function FishAction n -> Some n | _ -> None) flags
7555         with Not_found -> sprintf "guestfs_%s" name in
7556       pr "  r = %s " fn;
7557       generate_c_call_args ~handle:"g" style;
7558       pr ";\n";
7559
7560       List.iter (
7561         function
7562         | Device name | String name
7563         | OptString name | Bool name
7564         | Int name | Int64 name -> ()
7565         | Pathname name | Dev_or_Path name | FileOut name ->
7566             pr "  free (%s);\n" name
7567         | FileIn name ->
7568             pr "  free_file_in (%s);\n" name
7569         | StringList name | DeviceList name ->
7570             pr "  free_strings (%s);\n" name
7571       ) (snd style);
7572
7573       (* Any output flags? *)
7574       let fish_output =
7575         let flags = filter_map (
7576           function FishOutput flag -> Some flag | _ -> None
7577         ) flags in
7578         match flags with
7579         | [] -> None
7580         | [f] -> Some f
7581         | _ ->
7582             failwithf "%s: more than one FishOutput flag is not allowed" name in
7583
7584       (* Check return value for errors and display command results. *)
7585       (match fst style with
7586        | RErr -> pr "  return r;\n"
7587        | RInt _ ->
7588            pr "  if (r == -1) return -1;\n";
7589            (match fish_output with
7590             | None ->
7591                 pr "  printf (\"%%d\\n\", r);\n";
7592             | Some FishOutputOctal ->
7593                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7594             | Some FishOutputHexadecimal ->
7595                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7596            pr "  return 0;\n"
7597        | RInt64 _ ->
7598            pr "  if (r == -1) return -1;\n";
7599            (match fish_output with
7600             | None ->
7601                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7602             | Some FishOutputOctal ->
7603                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7604             | Some FishOutputHexadecimal ->
7605                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7606            pr "  return 0;\n"
7607        | RBool _ ->
7608            pr "  if (r == -1) return -1;\n";
7609            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7610            pr "  return 0;\n"
7611        | RConstString _ ->
7612            pr "  if (r == NULL) return -1;\n";
7613            pr "  printf (\"%%s\\n\", r);\n";
7614            pr "  return 0;\n"
7615        | RConstOptString _ ->
7616            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7617            pr "  return 0;\n"
7618        | RString _ ->
7619            pr "  if (r == NULL) return -1;\n";
7620            pr "  printf (\"%%s\\n\", r);\n";
7621            pr "  free (r);\n";
7622            pr "  return 0;\n"
7623        | RStringList _ ->
7624            pr "  if (r == NULL) return -1;\n";
7625            pr "  print_strings (r);\n";
7626            pr "  free_strings (r);\n";
7627            pr "  return 0;\n"
7628        | RStruct (_, typ) ->
7629            pr "  if (r == NULL) return -1;\n";
7630            pr "  print_%s (r);\n" typ;
7631            pr "  guestfs_free_%s (r);\n" typ;
7632            pr "  return 0;\n"
7633        | RStructList (_, typ) ->
7634            pr "  if (r == NULL) return -1;\n";
7635            pr "  print_%s_list (r);\n" typ;
7636            pr "  guestfs_free_%s_list (r);\n" typ;
7637            pr "  return 0;\n"
7638        | RHashtable _ ->
7639            pr "  if (r == NULL) return -1;\n";
7640            pr "  print_table (r);\n";
7641            pr "  free_strings (r);\n";
7642            pr "  return 0;\n"
7643        | RBufferOut _ ->
7644            pr "  if (r == NULL) return -1;\n";
7645            pr "  if (full_write (1, r, size) != size) {\n";
7646            pr "    perror (\"write\");\n";
7647            pr "    free (r);\n";
7648            pr "    return -1;\n";
7649            pr "  }\n";
7650            pr "  free (r);\n";
7651            pr "  return 0;\n"
7652       );
7653       pr "}\n";
7654       pr "\n"
7655   ) all_functions;
7656
7657   (* run_action function *)
7658   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7659   pr "{\n";
7660   List.iter (
7661     fun (name, _, _, flags, _, _, _) ->
7662       let name2 = replace_char name '_' '-' in
7663       let alias =
7664         try find_map (function FishAlias n -> Some n | _ -> None) flags
7665         with Not_found -> name in
7666       pr "  if (";
7667       pr "STRCASEEQ (cmd, \"%s\")" name;
7668       if name <> name2 then
7669         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7670       if name <> alias then
7671         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7672       pr ")\n";
7673       pr "    return run_%s (cmd, argc, argv);\n" name;
7674       pr "  else\n";
7675   ) all_functions;
7676   pr "    {\n";
7677   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7678   pr "      if (command_num == 1)\n";
7679   pr "        extended_help_message ();\n";
7680   pr "      return -1;\n";
7681   pr "    }\n";
7682   pr "  return 0;\n";
7683   pr "}\n";
7684   pr "\n"
7685
7686 (* Readline completion for guestfish. *)
7687 and generate_fish_completion () =
7688   generate_header CStyle GPLv2plus;
7689
7690   let all_functions =
7691     List.filter (
7692       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7693     ) all_functions in
7694
7695   pr "\
7696 #include <config.h>
7697
7698 #include <stdio.h>
7699 #include <stdlib.h>
7700 #include <string.h>
7701
7702 #ifdef HAVE_LIBREADLINE
7703 #include <readline/readline.h>
7704 #endif
7705
7706 #include \"fish.h\"
7707
7708 #ifdef HAVE_LIBREADLINE
7709
7710 static const char *const commands[] = {
7711   BUILTIN_COMMANDS_FOR_COMPLETION,
7712 ";
7713
7714   (* Get the commands, including the aliases.  They don't need to be
7715    * sorted - the generator() function just does a dumb linear search.
7716    *)
7717   let commands =
7718     List.map (
7719       fun (name, _, _, flags, _, _, _) ->
7720         let name2 = replace_char name '_' '-' in
7721         let alias =
7722           try find_map (function FishAlias n -> Some n | _ -> None) flags
7723           with Not_found -> name in
7724
7725         if name <> alias then [name2; alias] else [name2]
7726     ) all_functions in
7727   let commands = List.flatten commands in
7728
7729   List.iter (pr "  \"%s\",\n") commands;
7730
7731   pr "  NULL
7732 };
7733
7734 static char *
7735 generator (const char *text, int state)
7736 {
7737   static int index, len;
7738   const char *name;
7739
7740   if (!state) {
7741     index = 0;
7742     len = strlen (text);
7743   }
7744
7745   rl_attempted_completion_over = 1;
7746
7747   while ((name = commands[index]) != NULL) {
7748     index++;
7749     if (STRCASEEQLEN (name, text, len))
7750       return strdup (name);
7751   }
7752
7753   return NULL;
7754 }
7755
7756 #endif /* HAVE_LIBREADLINE */
7757
7758 #ifdef HAVE_RL_COMPLETION_MATCHES
7759 #define RL_COMPLETION_MATCHES rl_completion_matches
7760 #else
7761 #ifdef HAVE_COMPLETION_MATCHES
7762 #define RL_COMPLETION_MATCHES completion_matches
7763 #endif
7764 #endif /* else just fail if we don't have either symbol */
7765
7766 char **
7767 do_completion (const char *text, int start, int end)
7768 {
7769   char **matches = NULL;
7770
7771 #ifdef HAVE_LIBREADLINE
7772   rl_completion_append_character = ' ';
7773
7774   if (start == 0)
7775     matches = RL_COMPLETION_MATCHES (text, generator);
7776   else if (complete_dest_paths)
7777     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7778 #endif
7779
7780   return matches;
7781 }
7782 ";
7783
7784 (* Generate the POD documentation for guestfish. *)
7785 and generate_fish_actions_pod () =
7786   let all_functions_sorted =
7787     List.filter (
7788       fun (_, _, _, flags, _, _, _) ->
7789         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7790     ) all_functions_sorted in
7791
7792   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7793
7794   List.iter (
7795     fun (name, style, _, flags, _, _, longdesc) ->
7796       let longdesc =
7797         Str.global_substitute rex (
7798           fun s ->
7799             let sub =
7800               try Str.matched_group 1 s
7801               with Not_found ->
7802                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7803             "C<" ^ replace_char sub '_' '-' ^ ">"
7804         ) longdesc in
7805       let name = replace_char name '_' '-' in
7806       let alias =
7807         try find_map (function FishAlias n -> Some n | _ -> None) flags
7808         with Not_found -> name in
7809
7810       pr "=head2 %s" name;
7811       if name <> alias then
7812         pr " | %s" alias;
7813       pr "\n";
7814       pr "\n";
7815       pr " %s" name;
7816       List.iter (
7817         function
7818         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7819         | OptString n -> pr " %s" n
7820         | StringList n | DeviceList n -> pr " '%s ...'" n
7821         | Bool _ -> pr " true|false"
7822         | Int n -> pr " %s" n
7823         | Int64 n -> pr " %s" n
7824         | FileIn n | FileOut n -> pr " (%s|-)" n
7825       ) (snd style);
7826       pr "\n";
7827       pr "\n";
7828       pr "%s\n\n" longdesc;
7829
7830       if List.exists (function FileIn _ | FileOut _ -> true
7831                       | _ -> false) (snd style) then
7832         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7833
7834       if List.mem ProtocolLimitWarning flags then
7835         pr "%s\n\n" protocol_limit_warning;
7836
7837       if List.mem DangerWillRobinson flags then
7838         pr "%s\n\n" danger_will_robinson;
7839
7840       match deprecation_notice flags with
7841       | None -> ()
7842       | Some txt -> pr "%s\n\n" txt
7843   ) all_functions_sorted
7844
7845 (* Generate a C function prototype. *)
7846 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7847     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7848     ?(prefix = "")
7849     ?handle name style =
7850   if extern then pr "extern ";
7851   if static then pr "static ";
7852   (match fst style with
7853    | RErr -> pr "int "
7854    | RInt _ -> pr "int "
7855    | RInt64 _ -> pr "int64_t "
7856    | RBool _ -> pr "int "
7857    | RConstString _ | RConstOptString _ -> pr "const char *"
7858    | RString _ | RBufferOut _ -> pr "char *"
7859    | RStringList _ | RHashtable _ -> pr "char **"
7860    | RStruct (_, typ) ->
7861        if not in_daemon then pr "struct guestfs_%s *" typ
7862        else pr "guestfs_int_%s *" typ
7863    | RStructList (_, typ) ->
7864        if not in_daemon then pr "struct guestfs_%s_list *" typ
7865        else pr "guestfs_int_%s_list *" typ
7866   );
7867   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7868   pr "%s%s (" prefix name;
7869   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7870     pr "void"
7871   else (
7872     let comma = ref false in
7873     (match handle with
7874      | None -> ()
7875      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7876     );
7877     let next () =
7878       if !comma then (
7879         if single_line then pr ", " else pr ",\n\t\t"
7880       );
7881       comma := true
7882     in
7883     List.iter (
7884       function
7885       | Pathname n
7886       | Device n | Dev_or_Path n
7887       | String n
7888       | OptString n ->
7889           next ();
7890           pr "const char *%s" n
7891       | StringList n | DeviceList n ->
7892           next ();
7893           pr "char *const *%s" n
7894       | Bool n -> next (); pr "int %s" n
7895       | Int n -> next (); pr "int %s" n
7896       | Int64 n -> next (); pr "int64_t %s" n
7897       | FileIn n
7898       | FileOut n ->
7899           if not in_daemon then (next (); pr "const char *%s" n)
7900     ) (snd style);
7901     if is_RBufferOut then (next (); pr "size_t *size_r");
7902   );
7903   pr ")";
7904   if semicolon then pr ";";
7905   if newline then pr "\n"
7906
7907 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7908 and generate_c_call_args ?handle ?(decl = false) style =
7909   pr "(";
7910   let comma = ref false in
7911   let next () =
7912     if !comma then pr ", ";
7913     comma := true
7914   in
7915   (match handle with
7916    | None -> ()
7917    | Some handle -> pr "%s" handle; comma := true
7918   );
7919   List.iter (
7920     fun arg ->
7921       next ();
7922       pr "%s" (name_of_argt arg)
7923   ) (snd style);
7924   (* For RBufferOut calls, add implicit &size parameter. *)
7925   if not decl then (
7926     match fst style with
7927     | RBufferOut _ ->
7928         next ();
7929         pr "&size"
7930     | _ -> ()
7931   );
7932   pr ")"
7933
7934 (* Generate the OCaml bindings interface. *)
7935 and generate_ocaml_mli () =
7936   generate_header OCamlStyle LGPLv2plus;
7937
7938   pr "\
7939 (** For API documentation you should refer to the C API
7940     in the guestfs(3) manual page.  The OCaml API uses almost
7941     exactly the same calls. *)
7942
7943 type t
7944 (** A [guestfs_h] handle. *)
7945
7946 exception Error of string
7947 (** This exception is raised when there is an error. *)
7948
7949 exception Handle_closed of string
7950 (** This exception is raised if you use a {!Guestfs.t} handle
7951     after calling {!close} on it.  The string is the name of
7952     the function. *)
7953
7954 val create : unit -> t
7955 (** Create a {!Guestfs.t} handle. *)
7956
7957 val close : t -> unit
7958 (** Close the {!Guestfs.t} handle and free up all resources used
7959     by it immediately.
7960
7961     Handles are closed by the garbage collector when they become
7962     unreferenced, but callers can call this in order to provide
7963     predictable cleanup. *)
7964
7965 ";
7966   generate_ocaml_structure_decls ();
7967
7968   (* The actions. *)
7969   List.iter (
7970     fun (name, style, _, _, _, shortdesc, _) ->
7971       generate_ocaml_prototype name style;
7972       pr "(** %s *)\n" shortdesc;
7973       pr "\n"
7974   ) all_functions_sorted
7975
7976 (* Generate the OCaml bindings implementation. *)
7977 and generate_ocaml_ml () =
7978   generate_header OCamlStyle LGPLv2plus;
7979
7980   pr "\
7981 type t
7982
7983 exception Error of string
7984 exception Handle_closed of string
7985
7986 external create : unit -> t = \"ocaml_guestfs_create\"
7987 external close : t -> unit = \"ocaml_guestfs_close\"
7988
7989 (* Give the exceptions names, so they can be raised from the C code. *)
7990 let () =
7991   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7992   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7993
7994 ";
7995
7996   generate_ocaml_structure_decls ();
7997
7998   (* The actions. *)
7999   List.iter (
8000     fun (name, style, _, _, _, shortdesc, _) ->
8001       generate_ocaml_prototype ~is_external:true name style;
8002   ) all_functions_sorted
8003
8004 (* Generate the OCaml bindings C implementation. *)
8005 and generate_ocaml_c () =
8006   generate_header CStyle LGPLv2plus;
8007
8008   pr "\
8009 #include <stdio.h>
8010 #include <stdlib.h>
8011 #include <string.h>
8012
8013 #include <caml/config.h>
8014 #include <caml/alloc.h>
8015 #include <caml/callback.h>
8016 #include <caml/fail.h>
8017 #include <caml/memory.h>
8018 #include <caml/mlvalues.h>
8019 #include <caml/signals.h>
8020
8021 #include <guestfs.h>
8022
8023 #include \"guestfs_c.h\"
8024
8025 /* Copy a hashtable of string pairs into an assoc-list.  We return
8026  * the list in reverse order, but hashtables aren't supposed to be
8027  * ordered anyway.
8028  */
8029 static CAMLprim value
8030 copy_table (char * const * argv)
8031 {
8032   CAMLparam0 ();
8033   CAMLlocal5 (rv, pairv, kv, vv, cons);
8034   int i;
8035
8036   rv = Val_int (0);
8037   for (i = 0; argv[i] != NULL; i += 2) {
8038     kv = caml_copy_string (argv[i]);
8039     vv = caml_copy_string (argv[i+1]);
8040     pairv = caml_alloc (2, 0);
8041     Store_field (pairv, 0, kv);
8042     Store_field (pairv, 1, vv);
8043     cons = caml_alloc (2, 0);
8044     Store_field (cons, 1, rv);
8045     rv = cons;
8046     Store_field (cons, 0, pairv);
8047   }
8048
8049   CAMLreturn (rv);
8050 }
8051
8052 ";
8053
8054   (* Struct copy functions. *)
8055
8056   let emit_ocaml_copy_list_function typ =
8057     pr "static CAMLprim value\n";
8058     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8059     pr "{\n";
8060     pr "  CAMLparam0 ();\n";
8061     pr "  CAMLlocal2 (rv, v);\n";
8062     pr "  unsigned int i;\n";
8063     pr "\n";
8064     pr "  if (%ss->len == 0)\n" typ;
8065     pr "    CAMLreturn (Atom (0));\n";
8066     pr "  else {\n";
8067     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8068     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8069     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8070     pr "      caml_modify (&Field (rv, i), v);\n";
8071     pr "    }\n";
8072     pr "    CAMLreturn (rv);\n";
8073     pr "  }\n";
8074     pr "}\n";
8075     pr "\n";
8076   in
8077
8078   List.iter (
8079     fun (typ, cols) ->
8080       let has_optpercent_col =
8081         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8082
8083       pr "static CAMLprim value\n";
8084       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8085       pr "{\n";
8086       pr "  CAMLparam0 ();\n";
8087       if has_optpercent_col then
8088         pr "  CAMLlocal3 (rv, v, v2);\n"
8089       else
8090         pr "  CAMLlocal2 (rv, v);\n";
8091       pr "\n";
8092       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8093       iteri (
8094         fun i col ->
8095           (match col with
8096            | name, FString ->
8097                pr "  v = caml_copy_string (%s->%s);\n" typ name
8098            | name, FBuffer ->
8099                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8100                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8101                  typ name typ name
8102            | name, FUUID ->
8103                pr "  v = caml_alloc_string (32);\n";
8104                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8105            | name, (FBytes|FInt64|FUInt64) ->
8106                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8107            | name, (FInt32|FUInt32) ->
8108                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8109            | name, FOptPercent ->
8110                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8111                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8112                pr "    v = caml_alloc (1, 0);\n";
8113                pr "    Store_field (v, 0, v2);\n";
8114                pr "  } else /* None */\n";
8115                pr "    v = Val_int (0);\n";
8116            | name, FChar ->
8117                pr "  v = Val_int (%s->%s);\n" typ name
8118           );
8119           pr "  Store_field (rv, %d, v);\n" i
8120       ) cols;
8121       pr "  CAMLreturn (rv);\n";
8122       pr "}\n";
8123       pr "\n";
8124   ) structs;
8125
8126   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8127   List.iter (
8128     function
8129     | typ, (RStructListOnly | RStructAndList) ->
8130         (* generate the function for typ *)
8131         emit_ocaml_copy_list_function typ
8132     | typ, _ -> () (* empty *)
8133   ) (rstructs_used_by all_functions);
8134
8135   (* The wrappers. *)
8136   List.iter (
8137     fun (name, style, _, _, _, _, _) ->
8138       pr "/* Automatically generated wrapper for function\n";
8139       pr " * ";
8140       generate_ocaml_prototype name style;
8141       pr " */\n";
8142       pr "\n";
8143
8144       let params =
8145         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8146
8147       let needs_extra_vs =
8148         match fst style with RConstOptString _ -> true | _ -> false in
8149
8150       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8151       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8152       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8153       pr "\n";
8154
8155       pr "CAMLprim value\n";
8156       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8157       List.iter (pr ", value %s") (List.tl params);
8158       pr ")\n";
8159       pr "{\n";
8160
8161       (match params with
8162        | [p1; p2; p3; p4; p5] ->
8163            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8164        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8165            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8166            pr "  CAMLxparam%d (%s);\n"
8167              (List.length rest) (String.concat ", " rest)
8168        | ps ->
8169            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8170       );
8171       if not needs_extra_vs then
8172         pr "  CAMLlocal1 (rv);\n"
8173       else
8174         pr "  CAMLlocal3 (rv, v, v2);\n";
8175       pr "\n";
8176
8177       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8178       pr "  if (g == NULL)\n";
8179       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8180       pr "\n";
8181
8182       List.iter (
8183         function
8184         | Pathname n
8185         | Device n | Dev_or_Path n
8186         | String n
8187         | FileIn n
8188         | FileOut n ->
8189             pr "  const char *%s = String_val (%sv);\n" n n
8190         | OptString n ->
8191             pr "  const char *%s =\n" n;
8192             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8193               n n
8194         | StringList n | DeviceList n ->
8195             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8196         | Bool n ->
8197             pr "  int %s = Bool_val (%sv);\n" n n
8198         | Int n ->
8199             pr "  int %s = Int_val (%sv);\n" n n
8200         | Int64 n ->
8201             pr "  int64_t %s = Int64_val (%sv);\n" n n
8202       ) (snd style);
8203       let error_code =
8204         match fst style with
8205         | RErr -> pr "  int r;\n"; "-1"
8206         | RInt _ -> pr "  int r;\n"; "-1"
8207         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8208         | RBool _ -> pr "  int r;\n"; "-1"
8209         | RConstString _ | RConstOptString _ ->
8210             pr "  const char *r;\n"; "NULL"
8211         | RString _ -> pr "  char *r;\n"; "NULL"
8212         | RStringList _ ->
8213             pr "  int i;\n";
8214             pr "  char **r;\n";
8215             "NULL"
8216         | RStruct (_, typ) ->
8217             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8218         | RStructList (_, typ) ->
8219             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8220         | RHashtable _ ->
8221             pr "  int i;\n";
8222             pr "  char **r;\n";
8223             "NULL"
8224         | RBufferOut _ ->
8225             pr "  char *r;\n";
8226             pr "  size_t size;\n";
8227             "NULL" in
8228       pr "\n";
8229
8230       pr "  caml_enter_blocking_section ();\n";
8231       pr "  r = guestfs_%s " name;
8232       generate_c_call_args ~handle:"g" style;
8233       pr ";\n";
8234       pr "  caml_leave_blocking_section ();\n";
8235
8236       List.iter (
8237         function
8238         | StringList n | DeviceList n ->
8239             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8240         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8241         | Bool _ | Int _ | Int64 _
8242         | FileIn _ | FileOut _ -> ()
8243       ) (snd style);
8244
8245       pr "  if (r == %s)\n" error_code;
8246       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8247       pr "\n";
8248
8249       (match fst style with
8250        | RErr -> pr "  rv = Val_unit;\n"
8251        | RInt _ -> pr "  rv = Val_int (r);\n"
8252        | RInt64 _ ->
8253            pr "  rv = caml_copy_int64 (r);\n"
8254        | RBool _ -> pr "  rv = Val_bool (r);\n"
8255        | RConstString _ ->
8256            pr "  rv = caml_copy_string (r);\n"
8257        | RConstOptString _ ->
8258            pr "  if (r) { /* Some string */\n";
8259            pr "    v = caml_alloc (1, 0);\n";
8260            pr "    v2 = caml_copy_string (r);\n";
8261            pr "    Store_field (v, 0, v2);\n";
8262            pr "  } else /* None */\n";
8263            pr "    v = Val_int (0);\n";
8264        | RString _ ->
8265            pr "  rv = caml_copy_string (r);\n";
8266            pr "  free (r);\n"
8267        | RStringList _ ->
8268            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8269            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8270            pr "  free (r);\n"
8271        | RStruct (_, typ) ->
8272            pr "  rv = copy_%s (r);\n" typ;
8273            pr "  guestfs_free_%s (r);\n" typ;
8274        | RStructList (_, typ) ->
8275            pr "  rv = copy_%s_list (r);\n" typ;
8276            pr "  guestfs_free_%s_list (r);\n" typ;
8277        | RHashtable _ ->
8278            pr "  rv = copy_table (r);\n";
8279            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8280            pr "  free (r);\n";
8281        | RBufferOut _ ->
8282            pr "  rv = caml_alloc_string (size);\n";
8283            pr "  memcpy (String_val (rv), r, size);\n";
8284       );
8285
8286       pr "  CAMLreturn (rv);\n";
8287       pr "}\n";
8288       pr "\n";
8289
8290       if List.length params > 5 then (
8291         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8292         pr "CAMLprim value ";
8293         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8294         pr "CAMLprim value\n";
8295         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8296         pr "{\n";
8297         pr "  return ocaml_guestfs_%s (argv[0]" name;
8298         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8299         pr ");\n";
8300         pr "}\n";
8301         pr "\n"
8302       )
8303   ) all_functions_sorted
8304
8305 and generate_ocaml_structure_decls () =
8306   List.iter (
8307     fun (typ, cols) ->
8308       pr "type %s = {\n" typ;
8309       List.iter (
8310         function
8311         | name, FString -> pr "  %s : string;\n" name
8312         | name, FBuffer -> pr "  %s : string;\n" name
8313         | name, FUUID -> pr "  %s : string;\n" name
8314         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8315         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8316         | name, FChar -> pr "  %s : char;\n" name
8317         | name, FOptPercent -> pr "  %s : float option;\n" name
8318       ) cols;
8319       pr "}\n";
8320       pr "\n"
8321   ) structs
8322
8323 and generate_ocaml_prototype ?(is_external = false) name style =
8324   if is_external then pr "external " else pr "val ";
8325   pr "%s : t -> " name;
8326   List.iter (
8327     function
8328     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8329     | OptString _ -> pr "string option -> "
8330     | StringList _ | DeviceList _ -> pr "string array -> "
8331     | Bool _ -> pr "bool -> "
8332     | Int _ -> pr "int -> "
8333     | Int64 _ -> pr "int64 -> "
8334   ) (snd style);
8335   (match fst style with
8336    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8337    | RInt _ -> pr "int"
8338    | RInt64 _ -> pr "int64"
8339    | RBool _ -> pr "bool"
8340    | RConstString _ -> pr "string"
8341    | RConstOptString _ -> pr "string option"
8342    | RString _ | RBufferOut _ -> pr "string"
8343    | RStringList _ -> pr "string array"
8344    | RStruct (_, typ) -> pr "%s" typ
8345    | RStructList (_, typ) -> pr "%s array" typ
8346    | RHashtable _ -> pr "(string * string) list"
8347   );
8348   if is_external then (
8349     pr " = ";
8350     if List.length (snd style) + 1 > 5 then
8351       pr "\"ocaml_guestfs_%s_byte\" " name;
8352     pr "\"ocaml_guestfs_%s\"" name
8353   );
8354   pr "\n"
8355
8356 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8357 and generate_perl_xs () =
8358   generate_header CStyle LGPLv2plus;
8359
8360   pr "\
8361 #include \"EXTERN.h\"
8362 #include \"perl.h\"
8363 #include \"XSUB.h\"
8364
8365 #include <guestfs.h>
8366
8367 #ifndef PRId64
8368 #define PRId64 \"lld\"
8369 #endif
8370
8371 static SV *
8372 my_newSVll(long long val) {
8373 #ifdef USE_64_BIT_ALL
8374   return newSViv(val);
8375 #else
8376   char buf[100];
8377   int len;
8378   len = snprintf(buf, 100, \"%%\" PRId64, val);
8379   return newSVpv(buf, len);
8380 #endif
8381 }
8382
8383 #ifndef PRIu64
8384 #define PRIu64 \"llu\"
8385 #endif
8386
8387 static SV *
8388 my_newSVull(unsigned long long val) {
8389 #ifdef USE_64_BIT_ALL
8390   return newSVuv(val);
8391 #else
8392   char buf[100];
8393   int len;
8394   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8395   return newSVpv(buf, len);
8396 #endif
8397 }
8398
8399 /* http://www.perlmonks.org/?node_id=680842 */
8400 static char **
8401 XS_unpack_charPtrPtr (SV *arg) {
8402   char **ret;
8403   AV *av;
8404   I32 i;
8405
8406   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8407     croak (\"array reference expected\");
8408
8409   av = (AV *)SvRV (arg);
8410   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8411   if (!ret)
8412     croak (\"malloc failed\");
8413
8414   for (i = 0; i <= av_len (av); i++) {
8415     SV **elem = av_fetch (av, i, 0);
8416
8417     if (!elem || !*elem)
8418       croak (\"missing element in list\");
8419
8420     ret[i] = SvPV_nolen (*elem);
8421   }
8422
8423   ret[i] = NULL;
8424
8425   return ret;
8426 }
8427
8428 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8429
8430 PROTOTYPES: ENABLE
8431
8432 guestfs_h *
8433 _create ()
8434    CODE:
8435       RETVAL = guestfs_create ();
8436       if (!RETVAL)
8437         croak (\"could not create guestfs handle\");
8438       guestfs_set_error_handler (RETVAL, NULL, NULL);
8439  OUTPUT:
8440       RETVAL
8441
8442 void
8443 DESTROY (g)
8444       guestfs_h *g;
8445  PPCODE:
8446       guestfs_close (g);
8447
8448 ";
8449
8450   List.iter (
8451     fun (name, style, _, _, _, _, _) ->
8452       (match fst style with
8453        | RErr -> pr "void\n"
8454        | RInt _ -> pr "SV *\n"
8455        | RInt64 _ -> pr "SV *\n"
8456        | RBool _ -> pr "SV *\n"
8457        | RConstString _ -> pr "SV *\n"
8458        | RConstOptString _ -> pr "SV *\n"
8459        | RString _ -> pr "SV *\n"
8460        | RBufferOut _ -> pr "SV *\n"
8461        | RStringList _
8462        | RStruct _ | RStructList _
8463        | RHashtable _ ->
8464            pr "void\n" (* all lists returned implictly on the stack *)
8465       );
8466       (* Call and arguments. *)
8467       pr "%s " name;
8468       generate_c_call_args ~handle:"g" ~decl:true style;
8469       pr "\n";
8470       pr "      guestfs_h *g;\n";
8471       iteri (
8472         fun i ->
8473           function
8474           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8475               pr "      char *%s;\n" n
8476           | OptString n ->
8477               (* http://www.perlmonks.org/?node_id=554277
8478                * Note that the implicit handle argument means we have
8479                * to add 1 to the ST(x) operator.
8480                *)
8481               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8482           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8483           | Bool n -> pr "      int %s;\n" n
8484           | Int n -> pr "      int %s;\n" n
8485           | Int64 n -> pr "      int64_t %s;\n" n
8486       ) (snd style);
8487
8488       let do_cleanups () =
8489         List.iter (
8490           function
8491           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8492           | Bool _ | Int _ | Int64 _
8493           | FileIn _ | FileOut _ -> ()
8494           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8495         ) (snd style)
8496       in
8497
8498       (* Code. *)
8499       (match fst style with
8500        | RErr ->
8501            pr "PREINIT:\n";
8502            pr "      int r;\n";
8503            pr " PPCODE:\n";
8504            pr "      r = guestfs_%s " name;
8505            generate_c_call_args ~handle:"g" style;
8506            pr ";\n";
8507            do_cleanups ();
8508            pr "      if (r == -1)\n";
8509            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8510        | RInt n
8511        | RBool n ->
8512            pr "PREINIT:\n";
8513            pr "      int %s;\n" n;
8514            pr "   CODE:\n";
8515            pr "      %s = guestfs_%s " n name;
8516            generate_c_call_args ~handle:"g" style;
8517            pr ";\n";
8518            do_cleanups ();
8519            pr "      if (%s == -1)\n" n;
8520            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8521            pr "      RETVAL = newSViv (%s);\n" n;
8522            pr " OUTPUT:\n";
8523            pr "      RETVAL\n"
8524        | RInt64 n ->
8525            pr "PREINIT:\n";
8526            pr "      int64_t %s;\n" n;
8527            pr "   CODE:\n";
8528            pr "      %s = guestfs_%s " n name;
8529            generate_c_call_args ~handle:"g" style;
8530            pr ";\n";
8531            do_cleanups ();
8532            pr "      if (%s == -1)\n" n;
8533            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8534            pr "      RETVAL = my_newSVll (%s);\n" n;
8535            pr " OUTPUT:\n";
8536            pr "      RETVAL\n"
8537        | RConstString n ->
8538            pr "PREINIT:\n";
8539            pr "      const char *%s;\n" n;
8540            pr "   CODE:\n";
8541            pr "      %s = guestfs_%s " n name;
8542            generate_c_call_args ~handle:"g" style;
8543            pr ";\n";
8544            do_cleanups ();
8545            pr "      if (%s == NULL)\n" n;
8546            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8547            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8548            pr " OUTPUT:\n";
8549            pr "      RETVAL\n"
8550        | RConstOptString n ->
8551            pr "PREINIT:\n";
8552            pr "      const char *%s;\n" n;
8553            pr "   CODE:\n";
8554            pr "      %s = guestfs_%s " n name;
8555            generate_c_call_args ~handle:"g" style;
8556            pr ";\n";
8557            do_cleanups ();
8558            pr "      if (%s == NULL)\n" n;
8559            pr "        RETVAL = &PL_sv_undef;\n";
8560            pr "      else\n";
8561            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8562            pr " OUTPUT:\n";
8563            pr "      RETVAL\n"
8564        | RString n ->
8565            pr "PREINIT:\n";
8566            pr "      char *%s;\n" n;
8567            pr "   CODE:\n";
8568            pr "      %s = guestfs_%s " n name;
8569            generate_c_call_args ~handle:"g" style;
8570            pr ";\n";
8571            do_cleanups ();
8572            pr "      if (%s == NULL)\n" n;
8573            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8574            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8575            pr "      free (%s);\n" n;
8576            pr " OUTPUT:\n";
8577            pr "      RETVAL\n"
8578        | RStringList n | RHashtable n ->
8579            pr "PREINIT:\n";
8580            pr "      char **%s;\n" n;
8581            pr "      int i, n;\n";
8582            pr " PPCODE:\n";
8583            pr "      %s = guestfs_%s " n name;
8584            generate_c_call_args ~handle:"g" style;
8585            pr ";\n";
8586            do_cleanups ();
8587            pr "      if (%s == NULL)\n" n;
8588            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8589            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8590            pr "      EXTEND (SP, n);\n";
8591            pr "      for (i = 0; i < n; ++i) {\n";
8592            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8593            pr "        free (%s[i]);\n" n;
8594            pr "      }\n";
8595            pr "      free (%s);\n" n;
8596        | RStruct (n, typ) ->
8597            let cols = cols_of_struct typ in
8598            generate_perl_struct_code typ cols name style n do_cleanups
8599        | RStructList (n, typ) ->
8600            let cols = cols_of_struct typ in
8601            generate_perl_struct_list_code typ cols name style n do_cleanups
8602        | RBufferOut n ->
8603            pr "PREINIT:\n";
8604            pr "      char *%s;\n" n;
8605            pr "      size_t size;\n";
8606            pr "   CODE:\n";
8607            pr "      %s = guestfs_%s " n name;
8608            generate_c_call_args ~handle:"g" style;
8609            pr ";\n";
8610            do_cleanups ();
8611            pr "      if (%s == NULL)\n" n;
8612            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8613            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8614            pr "      free (%s);\n" n;
8615            pr " OUTPUT:\n";
8616            pr "      RETVAL\n"
8617       );
8618
8619       pr "\n"
8620   ) all_functions
8621
8622 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8623   pr "PREINIT:\n";
8624   pr "      struct guestfs_%s_list *%s;\n" typ n;
8625   pr "      int i;\n";
8626   pr "      HV *hv;\n";
8627   pr " PPCODE:\n";
8628   pr "      %s = guestfs_%s " n name;
8629   generate_c_call_args ~handle:"g" style;
8630   pr ";\n";
8631   do_cleanups ();
8632   pr "      if (%s == NULL)\n" n;
8633   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8634   pr "      EXTEND (SP, %s->len);\n" n;
8635   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8636   pr "        hv = newHV ();\n";
8637   List.iter (
8638     function
8639     | name, FString ->
8640         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8641           name (String.length name) n name
8642     | name, FUUID ->
8643         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8644           name (String.length name) n name
8645     | name, FBuffer ->
8646         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8647           name (String.length name) n name n name
8648     | name, (FBytes|FUInt64) ->
8649         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8650           name (String.length name) n name
8651     | name, FInt64 ->
8652         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8653           name (String.length name) n name
8654     | name, (FInt32|FUInt32) ->
8655         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8656           name (String.length name) n name
8657     | name, FChar ->
8658         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8659           name (String.length name) n name
8660     | name, FOptPercent ->
8661         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8662           name (String.length name) n name
8663   ) cols;
8664   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8665   pr "      }\n";
8666   pr "      guestfs_free_%s_list (%s);\n" typ n
8667
8668 and generate_perl_struct_code typ cols name style n do_cleanups =
8669   pr "PREINIT:\n";
8670   pr "      struct guestfs_%s *%s;\n" typ n;
8671   pr " PPCODE:\n";
8672   pr "      %s = guestfs_%s " n name;
8673   generate_c_call_args ~handle:"g" style;
8674   pr ";\n";
8675   do_cleanups ();
8676   pr "      if (%s == NULL)\n" n;
8677   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8678   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8679   List.iter (
8680     fun ((name, _) as col) ->
8681       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8682
8683       match col with
8684       | name, FString ->
8685           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8686             n name
8687       | name, FBuffer ->
8688           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8689             n name n name
8690       | name, FUUID ->
8691           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8692             n name
8693       | name, (FBytes|FUInt64) ->
8694           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8695             n name
8696       | name, FInt64 ->
8697           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8698             n name
8699       | name, (FInt32|FUInt32) ->
8700           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8701             n name
8702       | name, FChar ->
8703           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8704             n name
8705       | name, FOptPercent ->
8706           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8707             n name
8708   ) cols;
8709   pr "      free (%s);\n" n
8710
8711 (* Generate Sys/Guestfs.pm. *)
8712 and generate_perl_pm () =
8713   generate_header HashStyle LGPLv2plus;
8714
8715   pr "\
8716 =pod
8717
8718 =head1 NAME
8719
8720 Sys::Guestfs - Perl bindings for libguestfs
8721
8722 =head1 SYNOPSIS
8723
8724  use Sys::Guestfs;
8725
8726  my $h = Sys::Guestfs->new ();
8727  $h->add_drive ('guest.img');
8728  $h->launch ();
8729  $h->mount ('/dev/sda1', '/');
8730  $h->touch ('/hello');
8731  $h->sync ();
8732
8733 =head1 DESCRIPTION
8734
8735 The C<Sys::Guestfs> module provides a Perl XS binding to the
8736 libguestfs API for examining and modifying virtual machine
8737 disk images.
8738
8739 Amongst the things this is good for: making batch configuration
8740 changes to guests, getting disk used/free statistics (see also:
8741 virt-df), migrating between virtualization systems (see also:
8742 virt-p2v), performing partial backups, performing partial guest
8743 clones, cloning guests and changing registry/UUID/hostname info, and
8744 much else besides.
8745
8746 Libguestfs uses Linux kernel and qemu code, and can access any type of
8747 guest filesystem that Linux and qemu can, including but not limited
8748 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8749 schemes, qcow, qcow2, vmdk.
8750
8751 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8752 LVs, what filesystem is in each LV, etc.).  It can also run commands
8753 in the context of the guest.  Also you can access filesystems over
8754 FUSE.
8755
8756 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8757 functions for using libguestfs from Perl, including integration
8758 with libvirt.
8759
8760 =head1 ERRORS
8761
8762 All errors turn into calls to C<croak> (see L<Carp(3)>).
8763
8764 =head1 METHODS
8765
8766 =over 4
8767
8768 =cut
8769
8770 package Sys::Guestfs;
8771
8772 use strict;
8773 use warnings;
8774
8775 require XSLoader;
8776 XSLoader::load ('Sys::Guestfs');
8777
8778 =item $h = Sys::Guestfs->new ();
8779
8780 Create a new guestfs handle.
8781
8782 =cut
8783
8784 sub new {
8785   my $proto = shift;
8786   my $class = ref ($proto) || $proto;
8787
8788   my $self = Sys::Guestfs::_create ();
8789   bless $self, $class;
8790   return $self;
8791 }
8792
8793 ";
8794
8795   (* Actions.  We only need to print documentation for these as
8796    * they are pulled in from the XS code automatically.
8797    *)
8798   List.iter (
8799     fun (name, style, _, flags, _, _, longdesc) ->
8800       if not (List.mem NotInDocs flags) then (
8801         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8802         pr "=item ";
8803         generate_perl_prototype name style;
8804         pr "\n\n";
8805         pr "%s\n\n" longdesc;
8806         if List.mem ProtocolLimitWarning flags then
8807           pr "%s\n\n" protocol_limit_warning;
8808         if List.mem DangerWillRobinson flags then
8809           pr "%s\n\n" danger_will_robinson;
8810         match deprecation_notice flags with
8811         | None -> ()
8812         | Some txt -> pr "%s\n\n" txt
8813       )
8814   ) all_functions_sorted;
8815
8816   (* End of file. *)
8817   pr "\
8818 =cut
8819
8820 1;
8821
8822 =back
8823
8824 =head1 COPYRIGHT
8825
8826 Copyright (C) %s Red Hat Inc.
8827
8828 =head1 LICENSE
8829
8830 Please see the file COPYING.LIB for the full license.
8831
8832 =head1 SEE ALSO
8833
8834 L<guestfs(3)>,
8835 L<guestfish(1)>,
8836 L<http://libguestfs.org>,
8837 L<Sys::Guestfs::Lib(3)>.
8838
8839 =cut
8840 " copyright_years
8841
8842 and generate_perl_prototype name style =
8843   (match fst style with
8844    | RErr -> ()
8845    | RBool n
8846    | RInt n
8847    | RInt64 n
8848    | RConstString n
8849    | RConstOptString n
8850    | RString n
8851    | RBufferOut n -> pr "$%s = " n
8852    | RStruct (n,_)
8853    | RHashtable n -> pr "%%%s = " n
8854    | RStringList n
8855    | RStructList (n,_) -> pr "@%s = " n
8856   );
8857   pr "$h->%s (" name;
8858   let comma = ref false in
8859   List.iter (
8860     fun arg ->
8861       if !comma then pr ", ";
8862       comma := true;
8863       match arg with
8864       | Pathname n | Device n | Dev_or_Path n | String n
8865       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8866           pr "$%s" n
8867       | StringList n | DeviceList n ->
8868           pr "\\@%s" n
8869   ) (snd style);
8870   pr ");"
8871
8872 (* Generate Python C module. *)
8873 and generate_python_c () =
8874   generate_header CStyle LGPLv2plus;
8875
8876   pr "\
8877 #include <Python.h>
8878
8879 #include <stdio.h>
8880 #include <stdlib.h>
8881 #include <assert.h>
8882
8883 #include \"guestfs.h\"
8884
8885 typedef struct {
8886   PyObject_HEAD
8887   guestfs_h *g;
8888 } Pyguestfs_Object;
8889
8890 static guestfs_h *
8891 get_handle (PyObject *obj)
8892 {
8893   assert (obj);
8894   assert (obj != Py_None);
8895   return ((Pyguestfs_Object *) obj)->g;
8896 }
8897
8898 static PyObject *
8899 put_handle (guestfs_h *g)
8900 {
8901   assert (g);
8902   return
8903     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8904 }
8905
8906 /* This list should be freed (but not the strings) after use. */
8907 static char **
8908 get_string_list (PyObject *obj)
8909 {
8910   int i, len;
8911   char **r;
8912
8913   assert (obj);
8914
8915   if (!PyList_Check (obj)) {
8916     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8917     return NULL;
8918   }
8919
8920   len = PyList_Size (obj);
8921   r = malloc (sizeof (char *) * (len+1));
8922   if (r == NULL) {
8923     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8924     return NULL;
8925   }
8926
8927   for (i = 0; i < len; ++i)
8928     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8929   r[len] = NULL;
8930
8931   return r;
8932 }
8933
8934 static PyObject *
8935 put_string_list (char * const * const argv)
8936 {
8937   PyObject *list;
8938   int argc, i;
8939
8940   for (argc = 0; argv[argc] != NULL; ++argc)
8941     ;
8942
8943   list = PyList_New (argc);
8944   for (i = 0; i < argc; ++i)
8945     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8946
8947   return list;
8948 }
8949
8950 static PyObject *
8951 put_table (char * const * const argv)
8952 {
8953   PyObject *list, *item;
8954   int argc, i;
8955
8956   for (argc = 0; argv[argc] != NULL; ++argc)
8957     ;
8958
8959   list = PyList_New (argc >> 1);
8960   for (i = 0; i < argc; i += 2) {
8961     item = PyTuple_New (2);
8962     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8963     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8964     PyList_SetItem (list, i >> 1, item);
8965   }
8966
8967   return list;
8968 }
8969
8970 static void
8971 free_strings (char **argv)
8972 {
8973   int argc;
8974
8975   for (argc = 0; argv[argc] != NULL; ++argc)
8976     free (argv[argc]);
8977   free (argv);
8978 }
8979
8980 static PyObject *
8981 py_guestfs_create (PyObject *self, PyObject *args)
8982 {
8983   guestfs_h *g;
8984
8985   g = guestfs_create ();
8986   if (g == NULL) {
8987     PyErr_SetString (PyExc_RuntimeError,
8988                      \"guestfs.create: failed to allocate handle\");
8989     return NULL;
8990   }
8991   guestfs_set_error_handler (g, NULL, NULL);
8992   return put_handle (g);
8993 }
8994
8995 static PyObject *
8996 py_guestfs_close (PyObject *self, PyObject *args)
8997 {
8998   PyObject *py_g;
8999   guestfs_h *g;
9000
9001   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9002     return NULL;
9003   g = get_handle (py_g);
9004
9005   guestfs_close (g);
9006
9007   Py_INCREF (Py_None);
9008   return Py_None;
9009 }
9010
9011 ";
9012
9013   let emit_put_list_function typ =
9014     pr "static PyObject *\n";
9015     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9016     pr "{\n";
9017     pr "  PyObject *list;\n";
9018     pr "  int i;\n";
9019     pr "\n";
9020     pr "  list = PyList_New (%ss->len);\n" typ;
9021     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9022     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9023     pr "  return list;\n";
9024     pr "};\n";
9025     pr "\n"
9026   in
9027
9028   (* Structures, turned into Python dictionaries. *)
9029   List.iter (
9030     fun (typ, cols) ->
9031       pr "static PyObject *\n";
9032       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9033       pr "{\n";
9034       pr "  PyObject *dict;\n";
9035       pr "\n";
9036       pr "  dict = PyDict_New ();\n";
9037       List.iter (
9038         function
9039         | name, FString ->
9040             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9041             pr "                        PyString_FromString (%s->%s));\n"
9042               typ name
9043         | name, FBuffer ->
9044             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9045             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9046               typ name typ name
9047         | name, FUUID ->
9048             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9049             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9050               typ name
9051         | name, (FBytes|FUInt64) ->
9052             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9053             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9054               typ name
9055         | name, FInt64 ->
9056             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9057             pr "                        PyLong_FromLongLong (%s->%s));\n"
9058               typ name
9059         | name, FUInt32 ->
9060             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9061             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9062               typ name
9063         | name, FInt32 ->
9064             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9065             pr "                        PyLong_FromLong (%s->%s));\n"
9066               typ name
9067         | name, FOptPercent ->
9068             pr "  if (%s->%s >= 0)\n" typ name;
9069             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9070             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9071               typ name;
9072             pr "  else {\n";
9073             pr "    Py_INCREF (Py_None);\n";
9074             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9075             pr "  }\n"
9076         | name, FChar ->
9077             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9078             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9079       ) cols;
9080       pr "  return dict;\n";
9081       pr "};\n";
9082       pr "\n";
9083
9084   ) structs;
9085
9086   (* Emit a put_TYPE_list function definition only if that function is used. *)
9087   List.iter (
9088     function
9089     | typ, (RStructListOnly | RStructAndList) ->
9090         (* generate the function for typ *)
9091         emit_put_list_function typ
9092     | typ, _ -> () (* empty *)
9093   ) (rstructs_used_by all_functions);
9094
9095   (* Python wrapper functions. *)
9096   List.iter (
9097     fun (name, style, _, _, _, _, _) ->
9098       pr "static PyObject *\n";
9099       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9100       pr "{\n";
9101
9102       pr "  PyObject *py_g;\n";
9103       pr "  guestfs_h *g;\n";
9104       pr "  PyObject *py_r;\n";
9105
9106       let error_code =
9107         match fst style with
9108         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9109         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9110         | RConstString _ | RConstOptString _ ->
9111             pr "  const char *r;\n"; "NULL"
9112         | RString _ -> pr "  char *r;\n"; "NULL"
9113         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9114         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9115         | RStructList (_, typ) ->
9116             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9117         | RBufferOut _ ->
9118             pr "  char *r;\n";
9119             pr "  size_t size;\n";
9120             "NULL" in
9121
9122       List.iter (
9123         function
9124         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9125             pr "  const char *%s;\n" n
9126         | OptString n -> pr "  const char *%s;\n" n
9127         | StringList n | DeviceList n ->
9128             pr "  PyObject *py_%s;\n" n;
9129             pr "  char **%s;\n" n
9130         | Bool n -> pr "  int %s;\n" n
9131         | Int n -> pr "  int %s;\n" n
9132         | Int64 n -> pr "  long long %s;\n" n
9133       ) (snd style);
9134
9135       pr "\n";
9136
9137       (* Convert the parameters. *)
9138       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9139       List.iter (
9140         function
9141         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9142         | OptString _ -> pr "z"
9143         | StringList _ | DeviceList _ -> pr "O"
9144         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9145         | Int _ -> pr "i"
9146         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9147                              * emulate C's int/long/long long in Python?
9148                              *)
9149       ) (snd style);
9150       pr ":guestfs_%s\",\n" name;
9151       pr "                         &py_g";
9152       List.iter (
9153         function
9154         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9155         | OptString n -> pr ", &%s" n
9156         | StringList n | DeviceList n -> pr ", &py_%s" n
9157         | Bool n -> pr ", &%s" n
9158         | Int n -> pr ", &%s" n
9159         | Int64 n -> pr ", &%s" n
9160       ) (snd style);
9161
9162       pr "))\n";
9163       pr "    return NULL;\n";
9164
9165       pr "  g = get_handle (py_g);\n";
9166       List.iter (
9167         function
9168         | Pathname _ | Device _ | Dev_or_Path _ | String _
9169         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9170         | StringList n | DeviceList n ->
9171             pr "  %s = get_string_list (py_%s);\n" n n;
9172             pr "  if (!%s) return NULL;\n" n
9173       ) (snd style);
9174
9175       pr "\n";
9176
9177       pr "  r = guestfs_%s " name;
9178       generate_c_call_args ~handle:"g" style;
9179       pr ";\n";
9180
9181       List.iter (
9182         function
9183         | Pathname _ | Device _ | Dev_or_Path _ | String _
9184         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9185         | StringList n | DeviceList n ->
9186             pr "  free (%s);\n" n
9187       ) (snd style);
9188
9189       pr "  if (r == %s) {\n" error_code;
9190       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9191       pr "    return NULL;\n";
9192       pr "  }\n";
9193       pr "\n";
9194
9195       (match fst style with
9196        | RErr ->
9197            pr "  Py_INCREF (Py_None);\n";
9198            pr "  py_r = Py_None;\n"
9199        | RInt _
9200        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9201        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9202        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9203        | RConstOptString _ ->
9204            pr "  if (r)\n";
9205            pr "    py_r = PyString_FromString (r);\n";
9206            pr "  else {\n";
9207            pr "    Py_INCREF (Py_None);\n";
9208            pr "    py_r = Py_None;\n";
9209            pr "  }\n"
9210        | RString _ ->
9211            pr "  py_r = PyString_FromString (r);\n";
9212            pr "  free (r);\n"
9213        | RStringList _ ->
9214            pr "  py_r = put_string_list (r);\n";
9215            pr "  free_strings (r);\n"
9216        | RStruct (_, typ) ->
9217            pr "  py_r = put_%s (r);\n" typ;
9218            pr "  guestfs_free_%s (r);\n" typ
9219        | RStructList (_, typ) ->
9220            pr "  py_r = put_%s_list (r);\n" typ;
9221            pr "  guestfs_free_%s_list (r);\n" typ
9222        | RHashtable n ->
9223            pr "  py_r = put_table (r);\n";
9224            pr "  free_strings (r);\n"
9225        | RBufferOut _ ->
9226            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9227            pr "  free (r);\n"
9228       );
9229
9230       pr "  return py_r;\n";
9231       pr "}\n";
9232       pr "\n"
9233   ) all_functions;
9234
9235   (* Table of functions. *)
9236   pr "static PyMethodDef methods[] = {\n";
9237   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9238   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9239   List.iter (
9240     fun (name, _, _, _, _, _, _) ->
9241       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9242         name name
9243   ) all_functions;
9244   pr "  { NULL, NULL, 0, NULL }\n";
9245   pr "};\n";
9246   pr "\n";
9247
9248   (* Init function. *)
9249   pr "\
9250 void
9251 initlibguestfsmod (void)
9252 {
9253   static int initialized = 0;
9254
9255   if (initialized) return;
9256   Py_InitModule ((char *) \"libguestfsmod\", methods);
9257   initialized = 1;
9258 }
9259 "
9260
9261 (* Generate Python module. *)
9262 and generate_python_py () =
9263   generate_header HashStyle LGPLv2plus;
9264
9265   pr "\
9266 u\"\"\"Python bindings for libguestfs
9267
9268 import guestfs
9269 g = guestfs.GuestFS ()
9270 g.add_drive (\"guest.img\")
9271 g.launch ()
9272 parts = g.list_partitions ()
9273
9274 The guestfs module provides a Python binding to the libguestfs API
9275 for examining and modifying virtual machine disk images.
9276
9277 Amongst the things this is good for: making batch configuration
9278 changes to guests, getting disk used/free statistics (see also:
9279 virt-df), migrating between virtualization systems (see also:
9280 virt-p2v), performing partial backups, performing partial guest
9281 clones, cloning guests and changing registry/UUID/hostname info, and
9282 much else besides.
9283
9284 Libguestfs uses Linux kernel and qemu code, and can access any type of
9285 guest filesystem that Linux and qemu can, including but not limited
9286 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9287 schemes, qcow, qcow2, vmdk.
9288
9289 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9290 LVs, what filesystem is in each LV, etc.).  It can also run commands
9291 in the context of the guest.  Also you can access filesystems over
9292 FUSE.
9293
9294 Errors which happen while using the API are turned into Python
9295 RuntimeError exceptions.
9296
9297 To create a guestfs handle you usually have to perform the following
9298 sequence of calls:
9299
9300 # Create the handle, call add_drive at least once, and possibly
9301 # several times if the guest has multiple block devices:
9302 g = guestfs.GuestFS ()
9303 g.add_drive (\"guest.img\")
9304
9305 # Launch the qemu subprocess and wait for it to become ready:
9306 g.launch ()
9307
9308 # Now you can issue commands, for example:
9309 logvols = g.lvs ()
9310
9311 \"\"\"
9312
9313 import libguestfsmod
9314
9315 class GuestFS:
9316     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9317
9318     def __init__ (self):
9319         \"\"\"Create a new libguestfs handle.\"\"\"
9320         self._o = libguestfsmod.create ()
9321
9322     def __del__ (self):
9323         libguestfsmod.close (self._o)
9324
9325 ";
9326
9327   List.iter (
9328     fun (name, style, _, flags, _, _, longdesc) ->
9329       pr "    def %s " name;
9330       generate_py_call_args ~handle:"self" (snd style);
9331       pr ":\n";
9332
9333       if not (List.mem NotInDocs flags) then (
9334         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9335         let doc =
9336           match fst style with
9337           | RErr | RInt _ | RInt64 _ | RBool _
9338           | RConstOptString _ | RConstString _
9339           | RString _ | RBufferOut _ -> doc
9340           | RStringList _ ->
9341               doc ^ "\n\nThis function returns a list of strings."
9342           | RStruct (_, typ) ->
9343               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9344           | RStructList (_, typ) ->
9345               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9346           | RHashtable _ ->
9347               doc ^ "\n\nThis function returns a dictionary." in
9348         let doc =
9349           if List.mem ProtocolLimitWarning flags then
9350             doc ^ "\n\n" ^ protocol_limit_warning
9351           else doc in
9352         let doc =
9353           if List.mem DangerWillRobinson flags then
9354             doc ^ "\n\n" ^ danger_will_robinson
9355           else doc in
9356         let doc =
9357           match deprecation_notice flags with
9358           | None -> doc
9359           | Some txt -> doc ^ "\n\n" ^ txt in
9360         let doc = pod2text ~width:60 name doc in
9361         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9362         let doc = String.concat "\n        " doc in
9363         pr "        u\"\"\"%s\"\"\"\n" doc;
9364       );
9365       pr "        return libguestfsmod.%s " name;
9366       generate_py_call_args ~handle:"self._o" (snd style);
9367       pr "\n";
9368       pr "\n";
9369   ) all_functions
9370
9371 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9372 and generate_py_call_args ~handle args =
9373   pr "(%s" handle;
9374   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9375   pr ")"
9376
9377 (* Useful if you need the longdesc POD text as plain text.  Returns a
9378  * list of lines.
9379  *
9380  * Because this is very slow (the slowest part of autogeneration),
9381  * we memoize the results.
9382  *)
9383 and pod2text ~width name longdesc =
9384   let key = width, name, longdesc in
9385   try Hashtbl.find pod2text_memo key
9386   with Not_found ->
9387     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9388     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9389     close_out chan;
9390     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9391     let chan = open_process_in cmd in
9392     let lines = ref [] in
9393     let rec loop i =
9394       let line = input_line chan in
9395       if i = 1 then             (* discard the first line of output *)
9396         loop (i+1)
9397       else (
9398         let line = triml line in
9399         lines := line :: !lines;
9400         loop (i+1)
9401       ) in
9402     let lines = try loop 1 with End_of_file -> List.rev !lines in
9403     unlink filename;
9404     (match close_process_in chan with
9405      | WEXITED 0 -> ()
9406      | WEXITED i ->
9407          failwithf "pod2text: process exited with non-zero status (%d)" i
9408      | WSIGNALED i | WSTOPPED i ->
9409          failwithf "pod2text: process signalled or stopped by signal %d" i
9410     );
9411     Hashtbl.add pod2text_memo key lines;
9412     pod2text_memo_updated ();
9413     lines
9414
9415 (* Generate ruby bindings. *)
9416 and generate_ruby_c () =
9417   generate_header CStyle LGPLv2plus;
9418
9419   pr "\
9420 #include <stdio.h>
9421 #include <stdlib.h>
9422
9423 #include <ruby.h>
9424
9425 #include \"guestfs.h\"
9426
9427 #include \"extconf.h\"
9428
9429 /* For Ruby < 1.9 */
9430 #ifndef RARRAY_LEN
9431 #define RARRAY_LEN(r) (RARRAY((r))->len)
9432 #endif
9433
9434 static VALUE m_guestfs;                 /* guestfs module */
9435 static VALUE c_guestfs;                 /* guestfs_h handle */
9436 static VALUE e_Error;                   /* used for all errors */
9437
9438 static void ruby_guestfs_free (void *p)
9439 {
9440   if (!p) return;
9441   guestfs_close ((guestfs_h *) p);
9442 }
9443
9444 static VALUE ruby_guestfs_create (VALUE m)
9445 {
9446   guestfs_h *g;
9447
9448   g = guestfs_create ();
9449   if (!g)
9450     rb_raise (e_Error, \"failed to create guestfs handle\");
9451
9452   /* Don't print error messages to stderr by default. */
9453   guestfs_set_error_handler (g, NULL, NULL);
9454
9455   /* Wrap it, and make sure the close function is called when the
9456    * handle goes away.
9457    */
9458   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9459 }
9460
9461 static VALUE ruby_guestfs_close (VALUE gv)
9462 {
9463   guestfs_h *g;
9464   Data_Get_Struct (gv, guestfs_h, g);
9465
9466   ruby_guestfs_free (g);
9467   DATA_PTR (gv) = NULL;
9468
9469   return Qnil;
9470 }
9471
9472 ";
9473
9474   List.iter (
9475     fun (name, style, _, _, _, _, _) ->
9476       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9477       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9478       pr ")\n";
9479       pr "{\n";
9480       pr "  guestfs_h *g;\n";
9481       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9482       pr "  if (!g)\n";
9483       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9484         name;
9485       pr "\n";
9486
9487       List.iter (
9488         function
9489         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9490             pr "  Check_Type (%sv, T_STRING);\n" n;
9491             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9492             pr "  if (!%s)\n" n;
9493             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9494             pr "              \"%s\", \"%s\");\n" n name
9495         | OptString n ->
9496             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9497         | StringList n | DeviceList n ->
9498             pr "  char **%s;\n" n;
9499             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9500             pr "  {\n";
9501             pr "    int i, len;\n";
9502             pr "    len = RARRAY_LEN (%sv);\n" n;
9503             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9504               n;
9505             pr "    for (i = 0; i < len; ++i) {\n";
9506             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9507             pr "      %s[i] = StringValueCStr (v);\n" n;
9508             pr "    }\n";
9509             pr "    %s[len] = NULL;\n" n;
9510             pr "  }\n";
9511         | Bool n ->
9512             pr "  int %s = RTEST (%sv);\n" n n
9513         | Int n ->
9514             pr "  int %s = NUM2INT (%sv);\n" n n
9515         | Int64 n ->
9516             pr "  long long %s = NUM2LL (%sv);\n" n n
9517       ) (snd style);
9518       pr "\n";
9519
9520       let error_code =
9521         match fst style with
9522         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9523         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9524         | RConstString _ | RConstOptString _ ->
9525             pr "  const char *r;\n"; "NULL"
9526         | RString _ -> pr "  char *r;\n"; "NULL"
9527         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9528         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9529         | RStructList (_, typ) ->
9530             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9531         | RBufferOut _ ->
9532             pr "  char *r;\n";
9533             pr "  size_t size;\n";
9534             "NULL" in
9535       pr "\n";
9536
9537       pr "  r = guestfs_%s " name;
9538       generate_c_call_args ~handle:"g" style;
9539       pr ";\n";
9540
9541       List.iter (
9542         function
9543         | Pathname _ | Device _ | Dev_or_Path _ | String _
9544         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9545         | StringList n | DeviceList n ->
9546             pr "  free (%s);\n" n
9547       ) (snd style);
9548
9549       pr "  if (r == %s)\n" error_code;
9550       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9551       pr "\n";
9552
9553       (match fst style with
9554        | RErr ->
9555            pr "  return Qnil;\n"
9556        | RInt _ | RBool _ ->
9557            pr "  return INT2NUM (r);\n"
9558        | RInt64 _ ->
9559            pr "  return ULL2NUM (r);\n"
9560        | RConstString _ ->
9561            pr "  return rb_str_new2 (r);\n";
9562        | RConstOptString _ ->
9563            pr "  if (r)\n";
9564            pr "    return rb_str_new2 (r);\n";
9565            pr "  else\n";
9566            pr "    return Qnil;\n";
9567        | RString _ ->
9568            pr "  VALUE rv = rb_str_new2 (r);\n";
9569            pr "  free (r);\n";
9570            pr "  return rv;\n";
9571        | RStringList _ ->
9572            pr "  int i, len = 0;\n";
9573            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9574            pr "  VALUE rv = rb_ary_new2 (len);\n";
9575            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9576            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9577            pr "    free (r[i]);\n";
9578            pr "  }\n";
9579            pr "  free (r);\n";
9580            pr "  return rv;\n"
9581        | RStruct (_, typ) ->
9582            let cols = cols_of_struct typ in
9583            generate_ruby_struct_code typ cols
9584        | RStructList (_, typ) ->
9585            let cols = cols_of_struct typ in
9586            generate_ruby_struct_list_code typ cols
9587        | RHashtable _ ->
9588            pr "  VALUE rv = rb_hash_new ();\n";
9589            pr "  int i;\n";
9590            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9591            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9592            pr "    free (r[i]);\n";
9593            pr "    free (r[i+1]);\n";
9594            pr "  }\n";
9595            pr "  free (r);\n";
9596            pr "  return rv;\n"
9597        | RBufferOut _ ->
9598            pr "  VALUE rv = rb_str_new (r, size);\n";
9599            pr "  free (r);\n";
9600            pr "  return rv;\n";
9601       );
9602
9603       pr "}\n";
9604       pr "\n"
9605   ) all_functions;
9606
9607   pr "\
9608 /* Initialize the module. */
9609 void Init__guestfs ()
9610 {
9611   m_guestfs = rb_define_module (\"Guestfs\");
9612   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9613   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9614
9615   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9616   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9617
9618 ";
9619   (* Define the rest of the methods. *)
9620   List.iter (
9621     fun (name, style, _, _, _, _, _) ->
9622       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9623       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9624   ) all_functions;
9625
9626   pr "}\n"
9627
9628 (* Ruby code to return a struct. *)
9629 and generate_ruby_struct_code typ cols =
9630   pr "  VALUE rv = rb_hash_new ();\n";
9631   List.iter (
9632     function
9633     | name, FString ->
9634         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9635     | name, FBuffer ->
9636         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9637     | name, FUUID ->
9638         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9639     | name, (FBytes|FUInt64) ->
9640         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9641     | name, FInt64 ->
9642         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9643     | name, FUInt32 ->
9644         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9645     | name, FInt32 ->
9646         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9647     | name, FOptPercent ->
9648         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9649     | name, FChar -> (* XXX wrong? *)
9650         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9651   ) cols;
9652   pr "  guestfs_free_%s (r);\n" typ;
9653   pr "  return rv;\n"
9654
9655 (* Ruby code to return a struct list. *)
9656 and generate_ruby_struct_list_code typ cols =
9657   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9658   pr "  int i;\n";
9659   pr "  for (i = 0; i < r->len; ++i) {\n";
9660   pr "    VALUE hv = rb_hash_new ();\n";
9661   List.iter (
9662     function
9663     | name, FString ->
9664         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9665     | name, FBuffer ->
9666         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
9667     | name, FUUID ->
9668         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9669     | name, (FBytes|FUInt64) ->
9670         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9671     | name, FInt64 ->
9672         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9673     | name, FUInt32 ->
9674         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9675     | name, FInt32 ->
9676         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9677     | name, FOptPercent ->
9678         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9679     | name, FChar -> (* XXX wrong? *)
9680         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9681   ) cols;
9682   pr "    rb_ary_push (rv, hv);\n";
9683   pr "  }\n";
9684   pr "  guestfs_free_%s_list (r);\n" typ;
9685   pr "  return rv;\n"
9686
9687 (* Generate Java bindings GuestFS.java file. *)
9688 and generate_java_java () =
9689   generate_header CStyle LGPLv2plus;
9690
9691   pr "\
9692 package com.redhat.et.libguestfs;
9693
9694 import java.util.HashMap;
9695 import com.redhat.et.libguestfs.LibGuestFSException;
9696 import com.redhat.et.libguestfs.PV;
9697 import com.redhat.et.libguestfs.VG;
9698 import com.redhat.et.libguestfs.LV;
9699 import com.redhat.et.libguestfs.Stat;
9700 import com.redhat.et.libguestfs.StatVFS;
9701 import com.redhat.et.libguestfs.IntBool;
9702 import com.redhat.et.libguestfs.Dirent;
9703
9704 /**
9705  * The GuestFS object is a libguestfs handle.
9706  *
9707  * @author rjones
9708  */
9709 public class GuestFS {
9710   // Load the native code.
9711   static {
9712     System.loadLibrary (\"guestfs_jni\");
9713   }
9714
9715   /**
9716    * The native guestfs_h pointer.
9717    */
9718   long g;
9719
9720   /**
9721    * Create a libguestfs handle.
9722    *
9723    * @throws LibGuestFSException
9724    */
9725   public GuestFS () throws LibGuestFSException
9726   {
9727     g = _create ();
9728   }
9729   private native long _create () throws LibGuestFSException;
9730
9731   /**
9732    * Close a libguestfs handle.
9733    *
9734    * You can also leave handles to be collected by the garbage
9735    * collector, but this method ensures that the resources used
9736    * by the handle are freed up immediately.  If you call any
9737    * other methods after closing the handle, you will get an
9738    * exception.
9739    *
9740    * @throws LibGuestFSException
9741    */
9742   public void close () throws LibGuestFSException
9743   {
9744     if (g != 0)
9745       _close (g);
9746     g = 0;
9747   }
9748   private native void _close (long g) throws LibGuestFSException;
9749
9750   public void finalize () throws LibGuestFSException
9751   {
9752     close ();
9753   }
9754
9755 ";
9756
9757   List.iter (
9758     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9759       if not (List.mem NotInDocs flags); then (
9760         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9761         let doc =
9762           if List.mem ProtocolLimitWarning flags then
9763             doc ^ "\n\n" ^ protocol_limit_warning
9764           else doc in
9765         let doc =
9766           if List.mem DangerWillRobinson flags then
9767             doc ^ "\n\n" ^ danger_will_robinson
9768           else doc in
9769         let doc =
9770           match deprecation_notice flags with
9771           | None -> doc
9772           | Some txt -> doc ^ "\n\n" ^ txt in
9773         let doc = pod2text ~width:60 name doc in
9774         let doc = List.map (            (* RHBZ#501883 *)
9775           function
9776           | "" -> "<p>"
9777           | nonempty -> nonempty
9778         ) doc in
9779         let doc = String.concat "\n   * " doc in
9780
9781         pr "  /**\n";
9782         pr "   * %s\n" shortdesc;
9783         pr "   * <p>\n";
9784         pr "   * %s\n" doc;
9785         pr "   * @throws LibGuestFSException\n";
9786         pr "   */\n";
9787         pr "  ";
9788       );
9789       generate_java_prototype ~public:true ~semicolon:false name style;
9790       pr "\n";
9791       pr "  {\n";
9792       pr "    if (g == 0)\n";
9793       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9794         name;
9795       pr "    ";
9796       if fst style <> RErr then pr "return ";
9797       pr "_%s " name;
9798       generate_java_call_args ~handle:"g" (snd style);
9799       pr ";\n";
9800       pr "  }\n";
9801       pr "  ";
9802       generate_java_prototype ~privat:true ~native:true name style;
9803       pr "\n";
9804       pr "\n";
9805   ) all_functions;
9806
9807   pr "}\n"
9808
9809 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9810 and generate_java_call_args ~handle args =
9811   pr "(%s" handle;
9812   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9813   pr ")"
9814
9815 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9816     ?(semicolon=true) name style =
9817   if privat then pr "private ";
9818   if public then pr "public ";
9819   if native then pr "native ";
9820
9821   (* return type *)
9822   (match fst style with
9823    | RErr -> pr "void ";
9824    | RInt _ -> pr "int ";
9825    | RInt64 _ -> pr "long ";
9826    | RBool _ -> pr "boolean ";
9827    | RConstString _ | RConstOptString _ | RString _
9828    | RBufferOut _ -> pr "String ";
9829    | RStringList _ -> pr "String[] ";
9830    | RStruct (_, typ) ->
9831        let name = java_name_of_struct typ in
9832        pr "%s " name;
9833    | RStructList (_, typ) ->
9834        let name = java_name_of_struct typ in
9835        pr "%s[] " name;
9836    | RHashtable _ -> pr "HashMap<String,String> ";
9837   );
9838
9839   if native then pr "_%s " name else pr "%s " name;
9840   pr "(";
9841   let needs_comma = ref false in
9842   if native then (
9843     pr "long g";
9844     needs_comma := true
9845   );
9846
9847   (* args *)
9848   List.iter (
9849     fun arg ->
9850       if !needs_comma then pr ", ";
9851       needs_comma := true;
9852
9853       match arg with
9854       | Pathname n
9855       | Device n | Dev_or_Path n
9856       | String n
9857       | OptString n
9858       | FileIn n
9859       | FileOut n ->
9860           pr "String %s" n
9861       | StringList n | DeviceList n ->
9862           pr "String[] %s" n
9863       | Bool n ->
9864           pr "boolean %s" n
9865       | Int n ->
9866           pr "int %s" n
9867       | Int64 n ->
9868           pr "long %s" n
9869   ) (snd style);
9870
9871   pr ")\n";
9872   pr "    throws LibGuestFSException";
9873   if semicolon then pr ";"
9874
9875 and generate_java_struct jtyp cols () =
9876   generate_header CStyle LGPLv2plus;
9877
9878   pr "\
9879 package com.redhat.et.libguestfs;
9880
9881 /**
9882  * Libguestfs %s structure.
9883  *
9884  * @author rjones
9885  * @see GuestFS
9886  */
9887 public class %s {
9888 " jtyp jtyp;
9889
9890   List.iter (
9891     function
9892     | name, FString
9893     | name, FUUID
9894     | name, FBuffer -> pr "  public String %s;\n" name
9895     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9896     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9897     | name, FChar -> pr "  public char %s;\n" name
9898     | name, FOptPercent ->
9899         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9900         pr "  public float %s;\n" name
9901   ) cols;
9902
9903   pr "}\n"
9904
9905 and generate_java_c () =
9906   generate_header CStyle LGPLv2plus;
9907
9908   pr "\
9909 #include <stdio.h>
9910 #include <stdlib.h>
9911 #include <string.h>
9912
9913 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9914 #include \"guestfs.h\"
9915
9916 /* Note that this function returns.  The exception is not thrown
9917  * until after the wrapper function returns.
9918  */
9919 static void
9920 throw_exception (JNIEnv *env, const char *msg)
9921 {
9922   jclass cl;
9923   cl = (*env)->FindClass (env,
9924                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9925   (*env)->ThrowNew (env, cl, msg);
9926 }
9927
9928 JNIEXPORT jlong JNICALL
9929 Java_com_redhat_et_libguestfs_GuestFS__1create
9930   (JNIEnv *env, jobject obj)
9931 {
9932   guestfs_h *g;
9933
9934   g = guestfs_create ();
9935   if (g == NULL) {
9936     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9937     return 0;
9938   }
9939   guestfs_set_error_handler (g, NULL, NULL);
9940   return (jlong) (long) g;
9941 }
9942
9943 JNIEXPORT void JNICALL
9944 Java_com_redhat_et_libguestfs_GuestFS__1close
9945   (JNIEnv *env, jobject obj, jlong jg)
9946 {
9947   guestfs_h *g = (guestfs_h *) (long) jg;
9948   guestfs_close (g);
9949 }
9950
9951 ";
9952
9953   List.iter (
9954     fun (name, style, _, _, _, _, _) ->
9955       pr "JNIEXPORT ";
9956       (match fst style with
9957        | RErr -> pr "void ";
9958        | RInt _ -> pr "jint ";
9959        | RInt64 _ -> pr "jlong ";
9960        | RBool _ -> pr "jboolean ";
9961        | RConstString _ | RConstOptString _ | RString _
9962        | RBufferOut _ -> pr "jstring ";
9963        | RStruct _ | RHashtable _ ->
9964            pr "jobject ";
9965        | RStringList _ | RStructList _ ->
9966            pr "jobjectArray ";
9967       );
9968       pr "JNICALL\n";
9969       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9970       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9971       pr "\n";
9972       pr "  (JNIEnv *env, jobject obj, jlong jg";
9973       List.iter (
9974         function
9975         | Pathname n
9976         | Device n | Dev_or_Path n
9977         | String n
9978         | OptString n
9979         | FileIn n
9980         | FileOut n ->
9981             pr ", jstring j%s" n
9982         | StringList n | DeviceList n ->
9983             pr ", jobjectArray j%s" n
9984         | Bool n ->
9985             pr ", jboolean j%s" n
9986         | Int n ->
9987             pr ", jint j%s" n
9988         | Int64 n ->
9989             pr ", jlong j%s" n
9990       ) (snd style);
9991       pr ")\n";
9992       pr "{\n";
9993       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9994       let error_code, no_ret =
9995         match fst style with
9996         | RErr -> pr "  int r;\n"; "-1", ""
9997         | RBool _
9998         | RInt _ -> pr "  int r;\n"; "-1", "0"
9999         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10000         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10001         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10002         | RString _ ->
10003             pr "  jstring jr;\n";
10004             pr "  char *r;\n"; "NULL", "NULL"
10005         | RStringList _ ->
10006             pr "  jobjectArray jr;\n";
10007             pr "  int r_len;\n";
10008             pr "  jclass cl;\n";
10009             pr "  jstring jstr;\n";
10010             pr "  char **r;\n"; "NULL", "NULL"
10011         | RStruct (_, typ) ->
10012             pr "  jobject jr;\n";
10013             pr "  jclass cl;\n";
10014             pr "  jfieldID fl;\n";
10015             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10016         | RStructList (_, typ) ->
10017             pr "  jobjectArray jr;\n";
10018             pr "  jclass cl;\n";
10019             pr "  jfieldID fl;\n";
10020             pr "  jobject jfl;\n";
10021             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10022         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10023         | RBufferOut _ ->
10024             pr "  jstring jr;\n";
10025             pr "  char *r;\n";
10026             pr "  size_t size;\n";
10027             "NULL", "NULL" in
10028       List.iter (
10029         function
10030         | Pathname n
10031         | Device n | Dev_or_Path n
10032         | String n
10033         | OptString n
10034         | FileIn n
10035         | FileOut n ->
10036             pr "  const char *%s;\n" n
10037         | StringList n | DeviceList n ->
10038             pr "  int %s_len;\n" n;
10039             pr "  const char **%s;\n" n
10040         | Bool n
10041         | Int n ->
10042             pr "  int %s;\n" n
10043         | Int64 n ->
10044             pr "  int64_t %s;\n" n
10045       ) (snd style);
10046
10047       let needs_i =
10048         (match fst style with
10049          | RStringList _ | RStructList _ -> true
10050          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10051          | RConstOptString _
10052          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10053           List.exists (function
10054                        | StringList _ -> true
10055                        | DeviceList _ -> true
10056                        | _ -> false) (snd style) in
10057       if needs_i then
10058         pr "  int i;\n";
10059
10060       pr "\n";
10061
10062       (* Get the parameters. *)
10063       List.iter (
10064         function
10065         | Pathname n
10066         | Device n | Dev_or_Path n
10067         | String n
10068         | FileIn n
10069         | FileOut n ->
10070             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10071         | OptString n ->
10072             (* This is completely undocumented, but Java null becomes
10073              * a NULL parameter.
10074              *)
10075             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10076         | StringList n | DeviceList n ->
10077             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10078             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10079             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10080             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10081               n;
10082             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10083             pr "  }\n";
10084             pr "  %s[%s_len] = NULL;\n" n n;
10085         | Bool n
10086         | Int n
10087         | Int64 n ->
10088             pr "  %s = j%s;\n" n n
10089       ) (snd style);
10090
10091       (* Make the call. *)
10092       pr "  r = guestfs_%s " name;
10093       generate_c_call_args ~handle:"g" style;
10094       pr ";\n";
10095
10096       (* Release the parameters. *)
10097       List.iter (
10098         function
10099         | Pathname n
10100         | Device n | Dev_or_Path n
10101         | String n
10102         | FileIn n
10103         | FileOut n ->
10104             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10105         | OptString n ->
10106             pr "  if (j%s)\n" n;
10107             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10108         | StringList n | DeviceList n ->
10109             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10110             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10111               n;
10112             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10113             pr "  }\n";
10114             pr "  free (%s);\n" n
10115         | Bool n
10116         | Int n
10117         | Int64 n -> ()
10118       ) (snd style);
10119
10120       (* Check for errors. *)
10121       pr "  if (r == %s) {\n" error_code;
10122       pr "    throw_exception (env, guestfs_last_error (g));\n";
10123       pr "    return %s;\n" no_ret;
10124       pr "  }\n";
10125
10126       (* Return value. *)
10127       (match fst style with
10128        | RErr -> ()
10129        | RInt _ -> pr "  return (jint) r;\n"
10130        | RBool _ -> pr "  return (jboolean) r;\n"
10131        | RInt64 _ -> pr "  return (jlong) r;\n"
10132        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10133        | RConstOptString _ ->
10134            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10135        | RString _ ->
10136            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10137            pr "  free (r);\n";
10138            pr "  return jr;\n"
10139        | RStringList _ ->
10140            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10141            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10142            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10143            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10144            pr "  for (i = 0; i < r_len; ++i) {\n";
10145            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10146            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10147            pr "    free (r[i]);\n";
10148            pr "  }\n";
10149            pr "  free (r);\n";
10150            pr "  return jr;\n"
10151        | RStruct (_, typ) ->
10152            let jtyp = java_name_of_struct typ in
10153            let cols = cols_of_struct typ in
10154            generate_java_struct_return typ jtyp cols
10155        | RStructList (_, typ) ->
10156            let jtyp = java_name_of_struct typ in
10157            let cols = cols_of_struct typ in
10158            generate_java_struct_list_return typ jtyp cols
10159        | RHashtable _ ->
10160            (* XXX *)
10161            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10162            pr "  return NULL;\n"
10163        | RBufferOut _ ->
10164            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10165            pr "  free (r);\n";
10166            pr "  return jr;\n"
10167       );
10168
10169       pr "}\n";
10170       pr "\n"
10171   ) all_functions
10172
10173 and generate_java_struct_return typ jtyp cols =
10174   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10175   pr "  jr = (*env)->AllocObject (env, cl);\n";
10176   List.iter (
10177     function
10178     | name, FString ->
10179         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10180         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10181     | name, FUUID ->
10182         pr "  {\n";
10183         pr "    char s[33];\n";
10184         pr "    memcpy (s, r->%s, 32);\n" name;
10185         pr "    s[32] = 0;\n";
10186         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10187         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10188         pr "  }\n";
10189     | name, FBuffer ->
10190         pr "  {\n";
10191         pr "    int len = r->%s_len;\n" name;
10192         pr "    char s[len+1];\n";
10193         pr "    memcpy (s, r->%s, len);\n" name;
10194         pr "    s[len] = 0;\n";
10195         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10196         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10197         pr "  }\n";
10198     | name, (FBytes|FUInt64|FInt64) ->
10199         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10200         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10201     | name, (FUInt32|FInt32) ->
10202         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10203         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10204     | name, FOptPercent ->
10205         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10206         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10207     | name, FChar ->
10208         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10209         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10210   ) cols;
10211   pr "  free (r);\n";
10212   pr "  return jr;\n"
10213
10214 and generate_java_struct_list_return typ jtyp cols =
10215   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10216   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10217   pr "  for (i = 0; i < r->len; ++i) {\n";
10218   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10219   List.iter (
10220     function
10221     | name, FString ->
10222         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10223         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10224     | name, FUUID ->
10225         pr "    {\n";
10226         pr "      char s[33];\n";
10227         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10228         pr "      s[32] = 0;\n";
10229         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10230         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10231         pr "    }\n";
10232     | name, FBuffer ->
10233         pr "    {\n";
10234         pr "      int len = r->val[i].%s_len;\n" name;
10235         pr "      char s[len+1];\n";
10236         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10237         pr "      s[len] = 0;\n";
10238         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10239         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10240         pr "    }\n";
10241     | name, (FBytes|FUInt64|FInt64) ->
10242         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10243         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10244     | name, (FUInt32|FInt32) ->
10245         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10246         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10247     | name, FOptPercent ->
10248         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10249         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10250     | name, FChar ->
10251         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10252         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10253   ) cols;
10254   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10255   pr "  }\n";
10256   pr "  guestfs_free_%s_list (r);\n" typ;
10257   pr "  return jr;\n"
10258
10259 and generate_java_makefile_inc () =
10260   generate_header HashStyle GPLv2plus;
10261
10262   pr "java_built_sources = \\\n";
10263   List.iter (
10264     fun (typ, jtyp) ->
10265         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10266   ) java_structs;
10267   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10268
10269 and generate_haskell_hs () =
10270   generate_header HaskellStyle LGPLv2plus;
10271
10272   (* XXX We only know how to generate partial FFI for Haskell
10273    * at the moment.  Please help out!
10274    *)
10275   let can_generate style =
10276     match style with
10277     | RErr, _
10278     | RInt _, _
10279     | RInt64 _, _ -> true
10280     | RBool _, _
10281     | RConstString _, _
10282     | RConstOptString _, _
10283     | RString _, _
10284     | RStringList _, _
10285     | RStruct _, _
10286     | RStructList _, _
10287     | RHashtable _, _
10288     | RBufferOut _, _ -> false in
10289
10290   pr "\
10291 {-# INCLUDE <guestfs.h> #-}
10292 {-# LANGUAGE ForeignFunctionInterface #-}
10293
10294 module Guestfs (
10295   create";
10296
10297   (* List out the names of the actions we want to export. *)
10298   List.iter (
10299     fun (name, style, _, _, _, _, _) ->
10300       if can_generate style then pr ",\n  %s" name
10301   ) all_functions;
10302
10303   pr "
10304   ) where
10305
10306 -- Unfortunately some symbols duplicate ones already present
10307 -- in Prelude.  We don't know which, so we hard-code a list
10308 -- here.
10309 import Prelude hiding (truncate)
10310
10311 import Foreign
10312 import Foreign.C
10313 import Foreign.C.Types
10314 import IO
10315 import Control.Exception
10316 import Data.Typeable
10317
10318 data GuestfsS = GuestfsS            -- represents the opaque C struct
10319 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10320 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10321
10322 -- XXX define properly later XXX
10323 data PV = PV
10324 data VG = VG
10325 data LV = LV
10326 data IntBool = IntBool
10327 data Stat = Stat
10328 data StatVFS = StatVFS
10329 data Hashtable = Hashtable
10330
10331 foreign import ccall unsafe \"guestfs_create\" c_create
10332   :: IO GuestfsP
10333 foreign import ccall unsafe \"&guestfs_close\" c_close
10334   :: FunPtr (GuestfsP -> IO ())
10335 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10336   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10337
10338 create :: IO GuestfsH
10339 create = do
10340   p <- c_create
10341   c_set_error_handler p nullPtr nullPtr
10342   h <- newForeignPtr c_close p
10343   return h
10344
10345 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10346   :: GuestfsP -> IO CString
10347
10348 -- last_error :: GuestfsH -> IO (Maybe String)
10349 -- last_error h = do
10350 --   str <- withForeignPtr h (\\p -> c_last_error p)
10351 --   maybePeek peekCString str
10352
10353 last_error :: GuestfsH -> IO (String)
10354 last_error h = do
10355   str <- withForeignPtr h (\\p -> c_last_error p)
10356   if (str == nullPtr)
10357     then return \"no error\"
10358     else peekCString str
10359
10360 ";
10361
10362   (* Generate wrappers for each foreign function. *)
10363   List.iter (
10364     fun (name, style, _, _, _, _, _) ->
10365       if can_generate style then (
10366         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10367         pr "  :: ";
10368         generate_haskell_prototype ~handle:"GuestfsP" style;
10369         pr "\n";
10370         pr "\n";
10371         pr "%s :: " name;
10372         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10373         pr "\n";
10374         pr "%s %s = do\n" name
10375           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10376         pr "  r <- ";
10377         (* Convert pointer arguments using with* functions. *)
10378         List.iter (
10379           function
10380           | FileIn n
10381           | FileOut n
10382           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10383           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10384           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10385           | Bool _ | Int _ | Int64 _ -> ()
10386         ) (snd style);
10387         (* Convert integer arguments. *)
10388         let args =
10389           List.map (
10390             function
10391             | Bool n -> sprintf "(fromBool %s)" n
10392             | Int n -> sprintf "(fromIntegral %s)" n
10393             | Int64 n -> sprintf "(fromIntegral %s)" n
10394             | FileIn n | FileOut n
10395             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10396           ) (snd style) in
10397         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10398           (String.concat " " ("p" :: args));
10399         (match fst style with
10400          | RErr | RInt _ | RInt64 _ | RBool _ ->
10401              pr "  if (r == -1)\n";
10402              pr "    then do\n";
10403              pr "      err <- last_error h\n";
10404              pr "      fail err\n";
10405          | RConstString _ | RConstOptString _ | RString _
10406          | RStringList _ | RStruct _
10407          | RStructList _ | RHashtable _ | RBufferOut _ ->
10408              pr "  if (r == nullPtr)\n";
10409              pr "    then do\n";
10410              pr "      err <- last_error h\n";
10411              pr "      fail err\n";
10412         );
10413         (match fst style with
10414          | RErr ->
10415              pr "    else return ()\n"
10416          | RInt _ ->
10417              pr "    else return (fromIntegral r)\n"
10418          | RInt64 _ ->
10419              pr "    else return (fromIntegral r)\n"
10420          | RBool _ ->
10421              pr "    else return (toBool r)\n"
10422          | RConstString _
10423          | RConstOptString _
10424          | RString _
10425          | RStringList _
10426          | RStruct _
10427          | RStructList _
10428          | RHashtable _
10429          | RBufferOut _ ->
10430              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10431         );
10432         pr "\n";
10433       )
10434   ) all_functions
10435
10436 and generate_haskell_prototype ~handle ?(hs = false) style =
10437   pr "%s -> " handle;
10438   let string = if hs then "String" else "CString" in
10439   let int = if hs then "Int" else "CInt" in
10440   let bool = if hs then "Bool" else "CInt" in
10441   let int64 = if hs then "Integer" else "Int64" in
10442   List.iter (
10443     fun arg ->
10444       (match arg with
10445        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10446        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10447        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10448        | Bool _ -> pr "%s" bool
10449        | Int _ -> pr "%s" int
10450        | Int64 _ -> pr "%s" int
10451        | FileIn _ -> pr "%s" string
10452        | FileOut _ -> pr "%s" string
10453       );
10454       pr " -> ";
10455   ) (snd style);
10456   pr "IO (";
10457   (match fst style with
10458    | RErr -> if not hs then pr "CInt"
10459    | RInt _ -> pr "%s" int
10460    | RInt64 _ -> pr "%s" int64
10461    | RBool _ -> pr "%s" bool
10462    | RConstString _ -> pr "%s" string
10463    | RConstOptString _ -> pr "Maybe %s" string
10464    | RString _ -> pr "%s" string
10465    | RStringList _ -> pr "[%s]" string
10466    | RStruct (_, typ) ->
10467        let name = java_name_of_struct typ in
10468        pr "%s" name
10469    | RStructList (_, typ) ->
10470        let name = java_name_of_struct typ in
10471        pr "[%s]" name
10472    | RHashtable _ -> pr "Hashtable"
10473    | RBufferOut _ -> pr "%s" string
10474   );
10475   pr ")"
10476
10477 and generate_csharp () =
10478   generate_header CPlusPlusStyle LGPLv2plus;
10479
10480   (* XXX Make this configurable by the C# assembly users. *)
10481   let library = "libguestfs.so.0" in
10482
10483   pr "\
10484 // These C# bindings are highly experimental at present.
10485 //
10486 // Firstly they only work on Linux (ie. Mono).  In order to get them
10487 // to work on Windows (ie. .Net) you would need to port the library
10488 // itself to Windows first.
10489 //
10490 // The second issue is that some calls are known to be incorrect and
10491 // can cause Mono to segfault.  Particularly: calls which pass or
10492 // return string[], or return any structure value.  This is because
10493 // we haven't worked out the correct way to do this from C#.
10494 //
10495 // The third issue is that when compiling you get a lot of warnings.
10496 // We are not sure whether the warnings are important or not.
10497 //
10498 // Fourthly we do not routinely build or test these bindings as part
10499 // of the make && make check cycle, which means that regressions might
10500 // go unnoticed.
10501 //
10502 // Suggestions and patches are welcome.
10503
10504 // To compile:
10505 //
10506 // gmcs Libguestfs.cs
10507 // mono Libguestfs.exe
10508 //
10509 // (You'll probably want to add a Test class / static main function
10510 // otherwise this won't do anything useful).
10511
10512 using System;
10513 using System.IO;
10514 using System.Runtime.InteropServices;
10515 using System.Runtime.Serialization;
10516 using System.Collections;
10517
10518 namespace Guestfs
10519 {
10520   class Error : System.ApplicationException
10521   {
10522     public Error (string message) : base (message) {}
10523     protected Error (SerializationInfo info, StreamingContext context) {}
10524   }
10525
10526   class Guestfs
10527   {
10528     IntPtr _handle;
10529
10530     [DllImport (\"%s\")]
10531     static extern IntPtr guestfs_create ();
10532
10533     public Guestfs ()
10534     {
10535       _handle = guestfs_create ();
10536       if (_handle == IntPtr.Zero)
10537         throw new Error (\"could not create guestfs handle\");
10538     }
10539
10540     [DllImport (\"%s\")]
10541     static extern void guestfs_close (IntPtr h);
10542
10543     ~Guestfs ()
10544     {
10545       guestfs_close (_handle);
10546     }
10547
10548     [DllImport (\"%s\")]
10549     static extern string guestfs_last_error (IntPtr h);
10550
10551 " library library library;
10552
10553   (* Generate C# structure bindings.  We prefix struct names with
10554    * underscore because C# cannot have conflicting struct names and
10555    * method names (eg. "class stat" and "stat").
10556    *)
10557   List.iter (
10558     fun (typ, cols) ->
10559       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10560       pr "    public class _%s {\n" typ;
10561       List.iter (
10562         function
10563         | name, FChar -> pr "      char %s;\n" name
10564         | name, FString -> pr "      string %s;\n" name
10565         | name, FBuffer ->
10566             pr "      uint %s_len;\n" name;
10567             pr "      string %s;\n" name
10568         | name, FUUID ->
10569             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10570             pr "      string %s;\n" name
10571         | name, FUInt32 -> pr "      uint %s;\n" name
10572         | name, FInt32 -> pr "      int %s;\n" name
10573         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10574         | name, FInt64 -> pr "      long %s;\n" name
10575         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10576       ) cols;
10577       pr "    }\n";
10578       pr "\n"
10579   ) structs;
10580
10581   (* Generate C# function bindings. *)
10582   List.iter (
10583     fun (name, style, _, _, _, shortdesc, _) ->
10584       let rec csharp_return_type () =
10585         match fst style with
10586         | RErr -> "void"
10587         | RBool n -> "bool"
10588         | RInt n -> "int"
10589         | RInt64 n -> "long"
10590         | RConstString n
10591         | RConstOptString n
10592         | RString n
10593         | RBufferOut n -> "string"
10594         | RStruct (_,n) -> "_" ^ n
10595         | RHashtable n -> "Hashtable"
10596         | RStringList n -> "string[]"
10597         | RStructList (_,n) -> sprintf "_%s[]" n
10598
10599       and c_return_type () =
10600         match fst style with
10601         | RErr
10602         | RBool _
10603         | RInt _ -> "int"
10604         | RInt64 _ -> "long"
10605         | RConstString _
10606         | RConstOptString _
10607         | RString _
10608         | RBufferOut _ -> "string"
10609         | RStruct (_,n) -> "_" ^ n
10610         | RHashtable _
10611         | RStringList _ -> "string[]"
10612         | RStructList (_,n) -> sprintf "_%s[]" n
10613
10614       and c_error_comparison () =
10615         match fst style with
10616         | RErr
10617         | RBool _
10618         | RInt _
10619         | RInt64 _ -> "== -1"
10620         | RConstString _
10621         | RConstOptString _
10622         | RString _
10623         | RBufferOut _
10624         | RStruct (_,_)
10625         | RHashtable _
10626         | RStringList _
10627         | RStructList (_,_) -> "== null"
10628
10629       and generate_extern_prototype () =
10630         pr "    static extern %s guestfs_%s (IntPtr h"
10631           (c_return_type ()) name;
10632         List.iter (
10633           function
10634           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10635           | FileIn n | FileOut n ->
10636               pr ", [In] string %s" n
10637           | StringList n | DeviceList n ->
10638               pr ", [In] string[] %s" n
10639           | Bool n ->
10640               pr ", bool %s" n
10641           | Int n ->
10642               pr ", int %s" n
10643           | Int64 n ->
10644               pr ", long %s" n
10645         ) (snd style);
10646         pr ");\n"
10647
10648       and generate_public_prototype () =
10649         pr "    public %s %s (" (csharp_return_type ()) name;
10650         let comma = ref false in
10651         let next () =
10652           if !comma then pr ", ";
10653           comma := true
10654         in
10655         List.iter (
10656           function
10657           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10658           | FileIn n | FileOut n ->
10659               next (); pr "string %s" n
10660           | StringList n | DeviceList n ->
10661               next (); pr "string[] %s" n
10662           | Bool n ->
10663               next (); pr "bool %s" n
10664           | Int n ->
10665               next (); pr "int %s" n
10666           | Int64 n ->
10667               next (); pr "long %s" n
10668         ) (snd style);
10669         pr ")\n"
10670
10671       and generate_call () =
10672         pr "guestfs_%s (_handle" name;
10673         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10674         pr ");\n";
10675       in
10676
10677       pr "    [DllImport (\"%s\")]\n" library;
10678       generate_extern_prototype ();
10679       pr "\n";
10680       pr "    /// <summary>\n";
10681       pr "    /// %s\n" shortdesc;
10682       pr "    /// </summary>\n";
10683       generate_public_prototype ();
10684       pr "    {\n";
10685       pr "      %s r;\n" (c_return_type ());
10686       pr "      r = ";
10687       generate_call ();
10688       pr "      if (r %s)\n" (c_error_comparison ());
10689       pr "        throw new Error (guestfs_last_error (_handle));\n";
10690       (match fst style with
10691        | RErr -> ()
10692        | RBool _ ->
10693            pr "      return r != 0 ? true : false;\n"
10694        | RHashtable _ ->
10695            pr "      Hashtable rr = new Hashtable ();\n";
10696            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10697            pr "        rr.Add (r[i], r[i+1]);\n";
10698            pr "      return rr;\n"
10699        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10700        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10701        | RStructList _ ->
10702            pr "      return r;\n"
10703       );
10704       pr "    }\n";
10705       pr "\n";
10706   ) all_functions_sorted;
10707
10708   pr "  }
10709 }
10710 "
10711
10712 and generate_bindtests () =
10713   generate_header CStyle LGPLv2plus;
10714
10715   pr "\
10716 #include <stdio.h>
10717 #include <stdlib.h>
10718 #include <inttypes.h>
10719 #include <string.h>
10720
10721 #include \"guestfs.h\"
10722 #include \"guestfs-internal.h\"
10723 #include \"guestfs-internal-actions.h\"
10724 #include \"guestfs_protocol.h\"
10725
10726 #define error guestfs_error
10727 #define safe_calloc guestfs_safe_calloc
10728 #define safe_malloc guestfs_safe_malloc
10729
10730 static void
10731 print_strings (char *const *argv)
10732 {
10733   int argc;
10734
10735   printf (\"[\");
10736   for (argc = 0; argv[argc] != NULL; ++argc) {
10737     if (argc > 0) printf (\", \");
10738     printf (\"\\\"%%s\\\"\", argv[argc]);
10739   }
10740   printf (\"]\\n\");
10741 }
10742
10743 /* The test0 function prints its parameters to stdout. */
10744 ";
10745
10746   let test0, tests =
10747     match test_functions with
10748     | [] -> assert false
10749     | test0 :: tests -> test0, tests in
10750
10751   let () =
10752     let (name, style, _, _, _, _, _) = test0 in
10753     generate_prototype ~extern:false ~semicolon:false ~newline:true
10754       ~handle:"g" ~prefix:"guestfs__" name style;
10755     pr "{\n";
10756     List.iter (
10757       function
10758       | Pathname n
10759       | Device n | Dev_or_Path n
10760       | String n
10761       | FileIn n
10762       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10763       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10764       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10765       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10766       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10767       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10768     ) (snd style);
10769     pr "  /* Java changes stdout line buffering so we need this: */\n";
10770     pr "  fflush (stdout);\n";
10771     pr "  return 0;\n";
10772     pr "}\n";
10773     pr "\n" in
10774
10775   List.iter (
10776     fun (name, style, _, _, _, _, _) ->
10777       if String.sub name (String.length name - 3) 3 <> "err" then (
10778         pr "/* Test normal return. */\n";
10779         generate_prototype ~extern:false ~semicolon:false ~newline:true
10780           ~handle:"g" ~prefix:"guestfs__" name style;
10781         pr "{\n";
10782         (match fst style with
10783          | RErr ->
10784              pr "  return 0;\n"
10785          | RInt _ ->
10786              pr "  int r;\n";
10787              pr "  sscanf (val, \"%%d\", &r);\n";
10788              pr "  return r;\n"
10789          | RInt64 _ ->
10790              pr "  int64_t r;\n";
10791              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10792              pr "  return r;\n"
10793          | RBool _ ->
10794              pr "  return STREQ (val, \"true\");\n"
10795          | RConstString _
10796          | RConstOptString _ ->
10797              (* Can't return the input string here.  Return a static
10798               * string so we ensure we get a segfault if the caller
10799               * tries to free it.
10800               *)
10801              pr "  return \"static string\";\n"
10802          | RString _ ->
10803              pr "  return strdup (val);\n"
10804          | RStringList _ ->
10805              pr "  char **strs;\n";
10806              pr "  int n, i;\n";
10807              pr "  sscanf (val, \"%%d\", &n);\n";
10808              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10809              pr "  for (i = 0; i < n; ++i) {\n";
10810              pr "    strs[i] = safe_malloc (g, 16);\n";
10811              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10812              pr "  }\n";
10813              pr "  strs[n] = NULL;\n";
10814              pr "  return strs;\n"
10815          | RStruct (_, typ) ->
10816              pr "  struct guestfs_%s *r;\n" typ;
10817              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10818              pr "  return r;\n"
10819          | RStructList (_, typ) ->
10820              pr "  struct guestfs_%s_list *r;\n" typ;
10821              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10822              pr "  sscanf (val, \"%%d\", &r->len);\n";
10823              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10824              pr "  return r;\n"
10825          | RHashtable _ ->
10826              pr "  char **strs;\n";
10827              pr "  int n, i;\n";
10828              pr "  sscanf (val, \"%%d\", &n);\n";
10829              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10830              pr "  for (i = 0; i < n; ++i) {\n";
10831              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10832              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10833              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10834              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10835              pr "  }\n";
10836              pr "  strs[n*2] = NULL;\n";
10837              pr "  return strs;\n"
10838          | RBufferOut _ ->
10839              pr "  return strdup (val);\n"
10840         );
10841         pr "}\n";
10842         pr "\n"
10843       ) else (
10844         pr "/* Test error return. */\n";
10845         generate_prototype ~extern:false ~semicolon:false ~newline:true
10846           ~handle:"g" ~prefix:"guestfs__" name style;
10847         pr "{\n";
10848         pr "  error (g, \"error\");\n";
10849         (match fst style with
10850          | RErr | RInt _ | RInt64 _ | RBool _ ->
10851              pr "  return -1;\n"
10852          | RConstString _ | RConstOptString _
10853          | RString _ | RStringList _ | RStruct _
10854          | RStructList _
10855          | RHashtable _
10856          | RBufferOut _ ->
10857              pr "  return NULL;\n"
10858         );
10859         pr "}\n";
10860         pr "\n"
10861       )
10862   ) tests
10863
10864 and generate_ocaml_bindtests () =
10865   generate_header OCamlStyle GPLv2plus;
10866
10867   pr "\
10868 let () =
10869   let g = Guestfs.create () in
10870 ";
10871
10872   let mkargs args =
10873     String.concat " " (
10874       List.map (
10875         function
10876         | CallString s -> "\"" ^ s ^ "\""
10877         | CallOptString None -> "None"
10878         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10879         | CallStringList xs ->
10880             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10881         | CallInt i when i >= 0 -> string_of_int i
10882         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10883         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10884         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10885         | CallBool b -> string_of_bool b
10886       ) args
10887     )
10888   in
10889
10890   generate_lang_bindtests (
10891     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10892   );
10893
10894   pr "print_endline \"EOF\"\n"
10895
10896 and generate_perl_bindtests () =
10897   pr "#!/usr/bin/perl -w\n";
10898   generate_header HashStyle GPLv2plus;
10899
10900   pr "\
10901 use strict;
10902
10903 use Sys::Guestfs;
10904
10905 my $g = Sys::Guestfs->new ();
10906 ";
10907
10908   let mkargs args =
10909     String.concat ", " (
10910       List.map (
10911         function
10912         | CallString s -> "\"" ^ s ^ "\""
10913         | CallOptString None -> "undef"
10914         | CallOptString (Some s) -> sprintf "\"%s\"" s
10915         | CallStringList xs ->
10916             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10917         | CallInt i -> string_of_int i
10918         | CallInt64 i -> Int64.to_string i
10919         | CallBool b -> if b then "1" else "0"
10920       ) args
10921     )
10922   in
10923
10924   generate_lang_bindtests (
10925     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10926   );
10927
10928   pr "print \"EOF\\n\"\n"
10929
10930 and generate_python_bindtests () =
10931   generate_header HashStyle GPLv2plus;
10932
10933   pr "\
10934 import guestfs
10935
10936 g = guestfs.GuestFS ()
10937 ";
10938
10939   let mkargs args =
10940     String.concat ", " (
10941       List.map (
10942         function
10943         | CallString s -> "\"" ^ s ^ "\""
10944         | CallOptString None -> "None"
10945         | CallOptString (Some s) -> sprintf "\"%s\"" s
10946         | CallStringList xs ->
10947             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10948         | CallInt i -> string_of_int i
10949         | CallInt64 i -> Int64.to_string i
10950         | CallBool b -> if b then "1" else "0"
10951       ) args
10952     )
10953   in
10954
10955   generate_lang_bindtests (
10956     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10957   );
10958
10959   pr "print \"EOF\"\n"
10960
10961 and generate_ruby_bindtests () =
10962   generate_header HashStyle GPLv2plus;
10963
10964   pr "\
10965 require 'guestfs'
10966
10967 g = Guestfs::create()
10968 ";
10969
10970   let mkargs args =
10971     String.concat ", " (
10972       List.map (
10973         function
10974         | CallString s -> "\"" ^ s ^ "\""
10975         | CallOptString None -> "nil"
10976         | CallOptString (Some s) -> sprintf "\"%s\"" s
10977         | CallStringList xs ->
10978             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10979         | CallInt i -> string_of_int i
10980         | CallInt64 i -> Int64.to_string i
10981         | CallBool b -> string_of_bool b
10982       ) args
10983     )
10984   in
10985
10986   generate_lang_bindtests (
10987     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10988   );
10989
10990   pr "print \"EOF\\n\"\n"
10991
10992 and generate_java_bindtests () =
10993   generate_header CStyle GPLv2plus;
10994
10995   pr "\
10996 import com.redhat.et.libguestfs.*;
10997
10998 public class Bindtests {
10999     public static void main (String[] argv)
11000     {
11001         try {
11002             GuestFS g = new GuestFS ();
11003 ";
11004
11005   let mkargs args =
11006     String.concat ", " (
11007       List.map (
11008         function
11009         | CallString s -> "\"" ^ s ^ "\""
11010         | CallOptString None -> "null"
11011         | CallOptString (Some s) -> sprintf "\"%s\"" s
11012         | CallStringList xs ->
11013             "new String[]{" ^
11014               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11015         | CallInt i -> string_of_int i
11016         | CallInt64 i -> Int64.to_string i
11017         | CallBool b -> string_of_bool b
11018       ) args
11019     )
11020   in
11021
11022   generate_lang_bindtests (
11023     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11024   );
11025
11026   pr "
11027             System.out.println (\"EOF\");
11028         }
11029         catch (Exception exn) {
11030             System.err.println (exn);
11031             System.exit (1);
11032         }
11033     }
11034 }
11035 "
11036
11037 and generate_haskell_bindtests () =
11038   generate_header HaskellStyle GPLv2plus;
11039
11040   pr "\
11041 module Bindtests where
11042 import qualified Guestfs
11043
11044 main = do
11045   g <- Guestfs.create
11046 ";
11047
11048   let mkargs args =
11049     String.concat " " (
11050       List.map (
11051         function
11052         | CallString s -> "\"" ^ s ^ "\""
11053         | CallOptString None -> "Nothing"
11054         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11055         | CallStringList xs ->
11056             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11057         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11058         | CallInt i -> string_of_int i
11059         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11060         | CallInt64 i -> Int64.to_string i
11061         | CallBool true -> "True"
11062         | CallBool false -> "False"
11063       ) args
11064     )
11065   in
11066
11067   generate_lang_bindtests (
11068     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11069   );
11070
11071   pr "  putStrLn \"EOF\"\n"
11072
11073 (* Language-independent bindings tests - we do it this way to
11074  * ensure there is parity in testing bindings across all languages.
11075  *)
11076 and generate_lang_bindtests call =
11077   call "test0" [CallString "abc"; CallOptString (Some "def");
11078                 CallStringList []; CallBool false;
11079                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11080   call "test0" [CallString "abc"; CallOptString None;
11081                 CallStringList []; CallBool false;
11082                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11083   call "test0" [CallString ""; CallOptString (Some "def");
11084                 CallStringList []; CallBool false;
11085                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11086   call "test0" [CallString ""; CallOptString (Some "");
11087                 CallStringList []; CallBool false;
11088                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11089   call "test0" [CallString "abc"; CallOptString (Some "def");
11090                 CallStringList ["1"]; CallBool false;
11091                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11092   call "test0" [CallString "abc"; CallOptString (Some "def");
11093                 CallStringList ["1"; "2"]; CallBool false;
11094                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11095   call "test0" [CallString "abc"; CallOptString (Some "def");
11096                 CallStringList ["1"]; CallBool true;
11097                 CallInt 0; CallInt64 0L; 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 1; CallInt64 1L; CallString "123"; CallString "456"];
11107   call "test0" [CallString "abc"; CallOptString (Some "def");
11108                 CallStringList ["1"]; CallBool false;
11109                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11110   call "test0" [CallString "abc"; CallOptString (Some "def");
11111                 CallStringList ["1"]; CallBool false;
11112                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11113   call "test0" [CallString "abc"; CallOptString (Some "def");
11114                 CallStringList ["1"]; CallBool false;
11115                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11116
11117 (* XXX Add here tests of the return and error functions. *)
11118
11119 (* Code to generator bindings for virt-inspector.  Currently only
11120  * implemented for OCaml code (for virt-p2v 2.0).
11121  *)
11122 let rng_input = "inspector/virt-inspector.rng"
11123
11124 (* Read the input file and parse it into internal structures.  This is
11125  * by no means a complete RELAX NG parser, but is just enough to be
11126  * able to parse the specific input file.
11127  *)
11128 type rng =
11129   | Element of string * rng list        (* <element name=name/> *)
11130   | Attribute of string * rng list        (* <attribute name=name/> *)
11131   | Interleave of rng list                (* <interleave/> *)
11132   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11133   | OneOrMore of rng                        (* <oneOrMore/> *)
11134   | Optional of rng                        (* <optional/> *)
11135   | Choice of string list                (* <choice><value/>*</choice> *)
11136   | Value of string                        (* <value>str</value> *)
11137   | Text                                (* <text/> *)
11138
11139 let rec string_of_rng = function
11140   | Element (name, xs) ->
11141       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11142   | Attribute (name, xs) ->
11143       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11144   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11145   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11146   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11147   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11148   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11149   | Value value -> "Value \"" ^ value ^ "\""
11150   | Text -> "Text"
11151
11152 and string_of_rng_list xs =
11153   String.concat ", " (List.map string_of_rng xs)
11154
11155 let rec parse_rng ?defines context = function
11156   | [] -> []
11157   | Xml.Element ("element", ["name", name], children) :: rest ->
11158       Element (name, parse_rng ?defines context children)
11159       :: parse_rng ?defines context rest
11160   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11161       Attribute (name, parse_rng ?defines context children)
11162       :: parse_rng ?defines context rest
11163   | Xml.Element ("interleave", [], children) :: rest ->
11164       Interleave (parse_rng ?defines context children)
11165       :: parse_rng ?defines context rest
11166   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11167       let rng = parse_rng ?defines context [child] in
11168       (match rng with
11169        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11170        | _ ->
11171            failwithf "%s: <zeroOrMore> contains more than one child element"
11172              context
11173       )
11174   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11175       let rng = parse_rng ?defines context [child] in
11176       (match rng with
11177        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11178        | _ ->
11179            failwithf "%s: <oneOrMore> contains more than one child element"
11180              context
11181       )
11182   | Xml.Element ("optional", [], [child]) :: rest ->
11183       let rng = parse_rng ?defines context [child] in
11184       (match rng with
11185        | [child] -> Optional child :: parse_rng ?defines context rest
11186        | _ ->
11187            failwithf "%s: <optional> contains more than one child element"
11188              context
11189       )
11190   | Xml.Element ("choice", [], children) :: rest ->
11191       let values = List.map (
11192         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11193         | _ ->
11194             failwithf "%s: can't handle anything except <value> in <choice>"
11195               context
11196       ) children in
11197       Choice values
11198       :: parse_rng ?defines context rest
11199   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11200       Value value :: parse_rng ?defines context rest
11201   | Xml.Element ("text", [], []) :: rest ->
11202       Text :: parse_rng ?defines context rest
11203   | Xml.Element ("ref", ["name", name], []) :: rest ->
11204       (* Look up the reference.  Because of limitations in this parser,
11205        * we can't handle arbitrarily nested <ref> yet.  You can only
11206        * use <ref> from inside <start>.
11207        *)
11208       (match defines with
11209        | None ->
11210            failwithf "%s: contains <ref>, but no refs are defined yet" context
11211        | Some map ->
11212            let rng = StringMap.find name map in
11213            rng @ parse_rng ?defines context rest
11214       )
11215   | x :: _ ->
11216       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11217
11218 let grammar =
11219   let xml = Xml.parse_file rng_input in
11220   match xml with
11221   | Xml.Element ("grammar", _,
11222                  Xml.Element ("start", _, gram) :: defines) ->
11223       (* The <define/> elements are referenced in the <start> section,
11224        * so build a map of those first.
11225        *)
11226       let defines = List.fold_left (
11227         fun map ->
11228           function Xml.Element ("define", ["name", name], defn) ->
11229             StringMap.add name defn map
11230           | _ ->
11231               failwithf "%s: expected <define name=name/>" rng_input
11232       ) StringMap.empty defines in
11233       let defines = StringMap.mapi parse_rng defines in
11234
11235       (* Parse the <start> clause, passing the defines. *)
11236       parse_rng ~defines "<start>" gram
11237   | _ ->
11238       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11239         rng_input
11240
11241 let name_of_field = function
11242   | Element (name, _) | Attribute (name, _)
11243   | ZeroOrMore (Element (name, _))
11244   | OneOrMore (Element (name, _))
11245   | Optional (Element (name, _)) -> name
11246   | Optional (Attribute (name, _)) -> name
11247   | Text -> (* an unnamed field in an element *)
11248       "data"
11249   | rng ->
11250       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11251
11252 (* At the moment this function only generates OCaml types.  However we
11253  * should parameterize it later so it can generate types/structs in a
11254  * variety of languages.
11255  *)
11256 let generate_types xs =
11257   (* A simple type is one that can be printed out directly, eg.
11258    * "string option".  A complex type is one which has a name and has
11259    * to be defined via another toplevel definition, eg. a struct.
11260    *
11261    * generate_type generates code for either simple or complex types.
11262    * In the simple case, it returns the string ("string option").  In
11263    * the complex case, it returns the name ("mountpoint").  In the
11264    * complex case it has to print out the definition before returning,
11265    * so it should only be called when we are at the beginning of a
11266    * new line (BOL context).
11267    *)
11268   let rec generate_type = function
11269     | Text ->                                (* string *)
11270         "string", true
11271     | Choice values ->                        (* [`val1|`val2|...] *)
11272         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11273     | ZeroOrMore rng ->                        (* <rng> list *)
11274         let t, is_simple = generate_type rng in
11275         t ^ " list (* 0 or more *)", is_simple
11276     | OneOrMore rng ->                        (* <rng> list *)
11277         let t, is_simple = generate_type rng in
11278         t ^ " list (* 1 or more *)", is_simple
11279                                         (* virt-inspector hack: bool *)
11280     | Optional (Attribute (name, [Value "1"])) ->
11281         "bool", true
11282     | Optional rng ->                        (* <rng> list *)
11283         let t, is_simple = generate_type rng in
11284         t ^ " option", is_simple
11285                                         (* type name = { fields ... } *)
11286     | Element (name, fields) when is_attrs_interleave fields ->
11287         generate_type_struct name (get_attrs_interleave fields)
11288     | Element (name, [field])                (* type name = field *)
11289     | Attribute (name, [field]) ->
11290         let t, is_simple = generate_type field in
11291         if is_simple then (t, true)
11292         else (
11293           pr "type %s = %s\n" name t;
11294           name, false
11295         )
11296     | Element (name, fields) ->              (* type name = { fields ... } *)
11297         generate_type_struct name fields
11298     | rng ->
11299         failwithf "generate_type failed at: %s" (string_of_rng rng)
11300
11301   and is_attrs_interleave = function
11302     | [Interleave _] -> true
11303     | Attribute _ :: fields -> is_attrs_interleave fields
11304     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11305     | _ -> false
11306
11307   and get_attrs_interleave = function
11308     | [Interleave fields] -> fields
11309     | ((Attribute _) as field) :: fields
11310     | ((Optional (Attribute _)) as field) :: fields ->
11311         field :: get_attrs_interleave fields
11312     | _ -> assert false
11313
11314   and generate_types xs =
11315     List.iter (fun x -> ignore (generate_type x)) xs
11316
11317   and generate_type_struct name fields =
11318     (* Calculate the types of the fields first.  We have to do this
11319      * before printing anything so we are still in BOL context.
11320      *)
11321     let types = List.map fst (List.map generate_type fields) in
11322
11323     (* Special case of a struct containing just a string and another
11324      * field.  Turn it into an assoc list.
11325      *)
11326     match types with
11327     | ["string"; other] ->
11328         let fname1, fname2 =
11329           match fields with
11330           | [f1; f2] -> name_of_field f1, name_of_field f2
11331           | _ -> assert false in
11332         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11333         name, false
11334
11335     | types ->
11336         pr "type %s = {\n" name;
11337         List.iter (
11338           fun (field, ftype) ->
11339             let fname = name_of_field field in
11340             pr "  %s_%s : %s;\n" name fname ftype
11341         ) (List.combine fields types);
11342         pr "}\n";
11343         (* Return the name of this type, and
11344          * false because it's not a simple type.
11345          *)
11346         name, false
11347   in
11348
11349   generate_types xs
11350
11351 let generate_parsers xs =
11352   (* As for generate_type above, generate_parser makes a parser for
11353    * some type, and returns the name of the parser it has generated.
11354    * Because it (may) need to print something, it should always be
11355    * called in BOL context.
11356    *)
11357   let rec generate_parser = function
11358     | Text ->                                (* string *)
11359         "string_child_or_empty"
11360     | Choice values ->                        (* [`val1|`val2|...] *)
11361         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11362           (String.concat "|"
11363              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11364     | ZeroOrMore rng ->                        (* <rng> list *)
11365         let pa = generate_parser rng in
11366         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11367     | OneOrMore rng ->                        (* <rng> list *)
11368         let pa = generate_parser rng in
11369         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11370                                         (* virt-inspector hack: bool *)
11371     | Optional (Attribute (name, [Value "1"])) ->
11372         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11373     | Optional rng ->                        (* <rng> list *)
11374         let pa = generate_parser rng in
11375         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11376                                         (* type name = { fields ... } *)
11377     | Element (name, fields) when is_attrs_interleave fields ->
11378         generate_parser_struct name (get_attrs_interleave fields)
11379     | Element (name, [field]) ->        (* type name = field *)
11380         let pa = generate_parser field in
11381         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11382         pr "let %s =\n" parser_name;
11383         pr "  %s\n" pa;
11384         pr "let parse_%s = %s\n" name parser_name;
11385         parser_name
11386     | Attribute (name, [field]) ->
11387         let pa = generate_parser field in
11388         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11389         pr "let %s =\n" parser_name;
11390         pr "  %s\n" pa;
11391         pr "let parse_%s = %s\n" name parser_name;
11392         parser_name
11393     | Element (name, fields) ->              (* type name = { fields ... } *)
11394         generate_parser_struct name ([], fields)
11395     | rng ->
11396         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11397
11398   and is_attrs_interleave = function
11399     | [Interleave _] -> true
11400     | Attribute _ :: fields -> is_attrs_interleave fields
11401     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11402     | _ -> false
11403
11404   and get_attrs_interleave = function
11405     | [Interleave fields] -> [], fields
11406     | ((Attribute _) as field) :: fields
11407     | ((Optional (Attribute _)) as field) :: fields ->
11408         let attrs, interleaves = get_attrs_interleave fields in
11409         (field :: attrs), interleaves
11410     | _ -> assert false
11411
11412   and generate_parsers xs =
11413     List.iter (fun x -> ignore (generate_parser x)) xs
11414
11415   and generate_parser_struct name (attrs, interleaves) =
11416     (* Generate parsers for the fields first.  We have to do this
11417      * before printing anything so we are still in BOL context.
11418      *)
11419     let fields = attrs @ interleaves in
11420     let pas = List.map generate_parser fields in
11421
11422     (* Generate an intermediate tuple from all the fields first.
11423      * If the type is just a string + another field, then we will
11424      * return this directly, otherwise it is turned into a record.
11425      *
11426      * RELAX NG note: This code treats <interleave> and plain lists of
11427      * fields the same.  In other words, it doesn't bother enforcing
11428      * any ordering of fields in the XML.
11429      *)
11430     pr "let parse_%s x =\n" name;
11431     pr "  let t = (\n    ";
11432     let comma = ref false in
11433     List.iter (
11434       fun x ->
11435         if !comma then pr ",\n    ";
11436         comma := true;
11437         match x with
11438         | Optional (Attribute (fname, [field])), pa ->
11439             pr "%s x" pa
11440         | Optional (Element (fname, [field])), pa ->
11441             pr "%s (optional_child %S x)" pa fname
11442         | Attribute (fname, [Text]), _ ->
11443             pr "attribute %S x" fname
11444         | (ZeroOrMore _ | OneOrMore _), pa ->
11445             pr "%s x" pa
11446         | Text, pa ->
11447             pr "%s x" pa
11448         | (field, pa) ->
11449             let fname = name_of_field field in
11450             pr "%s (child %S x)" pa fname
11451     ) (List.combine fields pas);
11452     pr "\n  ) in\n";
11453
11454     (match fields with
11455      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11456          pr "  t\n"
11457
11458      | _ ->
11459          pr "  (Obj.magic t : %s)\n" name
11460 (*
11461          List.iter (
11462            function
11463            | (Optional (Attribute (fname, [field])), pa) ->
11464                pr "  %s_%s =\n" name fname;
11465                pr "    %s x;\n" pa
11466            | (Optional (Element (fname, [field])), pa) ->
11467                pr "  %s_%s =\n" name fname;
11468                pr "    (let x = optional_child %S x in\n" fname;
11469                pr "     %s x);\n" pa
11470            | (field, pa) ->
11471                let fname = name_of_field field in
11472                pr "  %s_%s =\n" name fname;
11473                pr "    (let x = child %S x in\n" fname;
11474                pr "     %s x);\n" pa
11475          ) (List.combine fields pas);
11476          pr "}\n"
11477 *)
11478     );
11479     sprintf "parse_%s" name
11480   in
11481
11482   generate_parsers xs
11483
11484 (* Generate ocaml/guestfs_inspector.mli. *)
11485 let generate_ocaml_inspector_mli () =
11486   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11487
11488   pr "\
11489 (** This is an OCaml language binding to the external [virt-inspector]
11490     program.
11491
11492     For more information, please read the man page [virt-inspector(1)].
11493 *)
11494
11495 ";
11496
11497   generate_types grammar;
11498   pr "(** The nested information returned from the {!inspect} function. *)\n";
11499   pr "\n";
11500
11501   pr "\
11502 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11503 (** To inspect a libvirt domain called [name], pass a singleton
11504     list: [inspect [name]].  When using libvirt only, you may
11505     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11506
11507     To inspect a disk image or images, pass a list of the filenames
11508     of the disk images: [inspect filenames]
11509
11510     This function inspects the given guest or disk images and
11511     returns a list of operating system(s) found and a large amount
11512     of information about them.  In the vast majority of cases,
11513     a virtual machine only contains a single operating system.
11514
11515     If the optional [~xml] parameter is given, then this function
11516     skips running the external virt-inspector program and just
11517     parses the given XML directly (which is expected to be XML
11518     produced from a previous run of virt-inspector).  The list of
11519     names and connect URI are ignored in this case.
11520
11521     This function can throw a wide variety of exceptions, for example
11522     if the external virt-inspector program cannot be found, or if
11523     it doesn't generate valid XML.
11524 *)
11525 "
11526
11527 (* Generate ocaml/guestfs_inspector.ml. *)
11528 let generate_ocaml_inspector_ml () =
11529   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11530
11531   pr "open Unix\n";
11532   pr "\n";
11533
11534   generate_types grammar;
11535   pr "\n";
11536
11537   pr "\
11538 (* Misc functions which are used by the parser code below. *)
11539 let first_child = function
11540   | Xml.Element (_, _, c::_) -> c
11541   | Xml.Element (name, _, []) ->
11542       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11543   | Xml.PCData str ->
11544       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11545
11546 let string_child_or_empty = function
11547   | Xml.Element (_, _, [Xml.PCData s]) -> s
11548   | Xml.Element (_, _, []) -> \"\"
11549   | Xml.Element (x, _, _) ->
11550       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11551                 x ^ \" instead\")
11552   | Xml.PCData str ->
11553       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11554
11555 let optional_child name xml =
11556   let children = Xml.children xml in
11557   try
11558     Some (List.find (function
11559                      | Xml.Element (n, _, _) when n = name -> true
11560                      | _ -> false) children)
11561   with
11562     Not_found -> None
11563
11564 let child name xml =
11565   match optional_child name xml with
11566   | Some c -> c
11567   | None ->
11568       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11569
11570 let attribute name xml =
11571   try Xml.attrib xml name
11572   with Xml.No_attribute _ ->
11573     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11574
11575 ";
11576
11577   generate_parsers grammar;
11578   pr "\n";
11579
11580   pr "\
11581 (* Run external virt-inspector, then use parser to parse the XML. *)
11582 let inspect ?connect ?xml names =
11583   let xml =
11584     match xml with
11585     | None ->
11586         if names = [] then invalid_arg \"inspect: no names given\";
11587         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11588           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11589           names in
11590         let cmd = List.map Filename.quote cmd in
11591         let cmd = String.concat \" \" cmd in
11592         let chan = open_process_in cmd in
11593         let xml = Xml.parse_in chan in
11594         (match close_process_in chan with
11595          | WEXITED 0 -> ()
11596          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11597          | WSIGNALED i | WSTOPPED i ->
11598              failwith (\"external virt-inspector command died or stopped on sig \" ^
11599                        string_of_int i)
11600         );
11601         xml
11602     | Some doc ->
11603         Xml.parse_string doc in
11604   parse_operatingsystems xml
11605 "
11606
11607 (* This is used to generate the src/MAX_PROC_NR file which
11608  * contains the maximum procedure number, a surrogate for the
11609  * ABI version number.  See src/Makefile.am for the details.
11610  *)
11611 and generate_max_proc_nr () =
11612   let proc_nrs = List.map (
11613     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11614   ) daemon_functions in
11615
11616   let max_proc_nr = List.fold_left max 0 proc_nrs in
11617
11618   pr "%d\n" max_proc_nr
11619
11620 let output_to filename k =
11621   let filename_new = filename ^ ".new" in
11622   chan := open_out filename_new;
11623   k ();
11624   close_out !chan;
11625   chan := Pervasives.stdout;
11626
11627   (* Is the new file different from the current file? *)
11628   if Sys.file_exists filename && files_equal filename filename_new then
11629     unlink filename_new                 (* same, so skip it *)
11630   else (
11631     (* different, overwrite old one *)
11632     (try chmod filename 0o644 with Unix_error _ -> ());
11633     rename filename_new filename;
11634     chmod filename 0o444;
11635     printf "written %s\n%!" filename;
11636   )
11637
11638 let perror msg = function
11639   | Unix_error (err, _, _) ->
11640       eprintf "%s: %s\n" msg (error_message err)
11641   | exn ->
11642       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11643
11644 (* Main program. *)
11645 let () =
11646   let lock_fd =
11647     try openfile "HACKING" [O_RDWR] 0
11648     with
11649     | Unix_error (ENOENT, _, _) ->
11650         eprintf "\
11651 You are probably running this from the wrong directory.
11652 Run it from the top source directory using the command
11653   src/generator.ml
11654 ";
11655         exit 1
11656     | exn ->
11657         perror "open: HACKING" exn;
11658         exit 1 in
11659
11660   (* Acquire a lock so parallel builds won't try to run the generator
11661    * twice at the same time.  Subsequent builds will wait for the first
11662    * one to finish.  Note the lock is released implicitly when the
11663    * program exits.
11664    *)
11665   (try lockf lock_fd F_LOCK 1
11666    with exn ->
11667      perror "lock: HACKING" exn;
11668      exit 1);
11669
11670   check_functions ();
11671
11672   output_to "src/guestfs_protocol.x" generate_xdr;
11673   output_to "src/guestfs-structs.h" generate_structs_h;
11674   output_to "src/guestfs-actions.h" generate_actions_h;
11675   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11676   output_to "src/guestfs-actions.c" generate_client_actions;
11677   output_to "src/guestfs-bindtests.c" generate_bindtests;
11678   output_to "src/guestfs-structs.pod" generate_structs_pod;
11679   output_to "src/guestfs-actions.pod" generate_actions_pod;
11680   output_to "src/guestfs-availability.pod" generate_availability_pod;
11681   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11682   output_to "src/libguestfs.syms" generate_linker_script;
11683   output_to "daemon/actions.h" generate_daemon_actions_h;
11684   output_to "daemon/stubs.c" generate_daemon_actions;
11685   output_to "daemon/names.c" generate_daemon_names;
11686   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11687   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11688   output_to "capitests/tests.c" generate_tests;
11689   output_to "fish/cmds.c" generate_fish_cmds;
11690   output_to "fish/completion.c" generate_fish_completion;
11691   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11692   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11693   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11694   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11695   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11696   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11697   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11698   output_to "perl/Guestfs.xs" generate_perl_xs;
11699   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11700   output_to "perl/bindtests.pl" generate_perl_bindtests;
11701   output_to "python/guestfs-py.c" generate_python_c;
11702   output_to "python/guestfs.py" generate_python_py;
11703   output_to "python/bindtests.py" generate_python_bindtests;
11704   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11705   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11706   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11707
11708   List.iter (
11709     fun (typ, jtyp) ->
11710       let cols = cols_of_struct typ in
11711       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11712       output_to filename (generate_java_struct jtyp cols);
11713   ) java_structs;
11714
11715   output_to "java/Makefile.inc" generate_java_makefile_inc;
11716   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11717   output_to "java/Bindtests.java" generate_java_bindtests;
11718   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11719   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11720   output_to "csharp/Libguestfs.cs" generate_csharp;
11721
11722   (* Always generate this file last, and unconditionally.  It's used
11723    * by the Makefile to know when we must re-run the generator.
11724    *)
11725   let chan = open_out "src/stamp-generator" in
11726   fprintf chan "1\n";
11727   close_out chan;
11728
11729   printf "generated %d lines of code\n" !lines