Rearrange library code into separate files.
[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     (* Opaque buffer which can contain arbitrary 8 bit data.
168      * In the C API, this is expressed as <const char *, size_t> pair.
169      * Most other languages have a string type which can contain
170      * ASCII NUL.  We use whatever type is appropriate for each
171      * language.
172      * Buffers are limited by the total message size.  To transfer
173      * large blocks of data, use FileIn/FileOut parameters instead.
174      * To return an arbitrary buffer, use RBufferOut.
175      *)
176   | BufferIn of string
177     (* Key material / passphrase.  Eventually we should treat this
178      * as sensitive and mlock it into physical RAM.  However this
179      * is highly complex because of all the places that XDR-encoded
180      * strings can end up.  So currently the only difference from
181      * 'String' is the way that guestfish requests these parameters
182      * from the user.
183      *)
184   | Key of string
185
186 type flags =
187   | ProtocolLimitWarning  (* display warning about protocol size limits *)
188   | DangerWillRobinson    (* flags particularly dangerous commands *)
189   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
190   | FishOutput of fish_output_t (* how to display output in guestfish *)
191   | NotInFish             (* do not export via guestfish *)
192   | NotInDocs             (* do not add this function to documentation *)
193   | DeprecatedBy of string (* function is deprecated, use .. instead *)
194   | Optional of string    (* function is part of an optional group *)
195
196 and fish_output_t =
197   | FishOutputOctal       (* for int return, print in octal *)
198   | FishOutputHexadecimal (* for int return, print in hex *)
199
200 (* You can supply zero or as many tests as you want per API call.
201  *
202  * Note that the test environment has 3 block devices, of size 500MB,
203  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
204  * a fourth ISO block device with some known files on it (/dev/sdd).
205  *
206  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
207  * Number of cylinders was 63 for IDE emulated disks with precisely
208  * the same size.  How exactly this is calculated is a mystery.
209  *
210  * The ISO block device (/dev/sdd) comes from images/test.iso.
211  *
212  * To be able to run the tests in a reasonable amount of time,
213  * the virtual machine and block devices are reused between tests.
214  * So don't try testing kill_subprocess :-x
215  *
216  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
217  *
218  * Don't assume anything about the previous contents of the block
219  * devices.  Use 'Init*' to create some initial scenarios.
220  *
221  * You can add a prerequisite clause to any individual test.  This
222  * is a run-time check, which, if it fails, causes the test to be
223  * skipped.  Useful if testing a command which might not work on
224  * all variations of libguestfs builds.  A test that has prerequisite
225  * of 'Always' is run unconditionally.
226  *
227  * In addition, packagers can skip individual tests by setting the
228  * environment variables:     eg:
229  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
230  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
231  *)
232 type tests = (test_init * test_prereq * test) list
233 and test =
234     (* Run the command sequence and just expect nothing to fail. *)
235   | TestRun of seq
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the string.
239      *)
240   | TestOutput of seq * string
241
242     (* Run the command sequence and expect the output of the final
243      * command to be the list of strings.
244      *)
245   | TestOutputList of seq * string list
246
247     (* Run the command sequence and expect the output of the final
248      * command to be the list of block devices (could be either
249      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
250      * character of each string).
251      *)
252   | TestOutputListOfDevices of seq * string list
253
254     (* Run the command sequence and expect the output of the final
255      * command to be the integer.
256      *)
257   | TestOutputInt of seq * int
258
259     (* Run the command sequence and expect the output of the final
260      * command to be <op> <int>, eg. ">=", "1".
261      *)
262   | TestOutputIntOp of seq * string * int
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a true value (!= 0 or != NULL).
266      *)
267   | TestOutputTrue of seq
268
269     (* Run the command sequence and expect the output of the final
270      * command to be a false value (== 0 or == NULL, but not an error).
271      *)
272   | TestOutputFalse of seq
273
274     (* Run the command sequence and expect the output of the final
275      * command to be a list of the given length (but don't care about
276      * content).
277      *)
278   | TestOutputLength of seq * int
279
280     (* Run the command sequence and expect the output of the final
281      * command to be a buffer (RBufferOut), ie. string + size.
282      *)
283   | TestOutputBuffer of seq * string
284
285     (* Run the command sequence and expect the output of the final
286      * command to be a structure.
287      *)
288   | TestOutputStruct of seq * test_field_compare list
289
290     (* Run the command sequence and expect the final command (only)
291      * to fail.
292      *)
293   | TestLastFail of seq
294
295 and test_field_compare =
296   | CompareWithInt of string * int
297   | CompareWithIntOp of string * string * int
298   | CompareWithString of string * string
299   | CompareFieldsIntEq of string * string
300   | CompareFieldsStrEq of string * string
301
302 (* Test prerequisites. *)
303 and test_prereq =
304     (* Test always runs. *)
305   | Always
306
307     (* Test is currently disabled - eg. it fails, or it tests some
308      * unimplemented feature.
309      *)
310   | Disabled
311
312     (* 'string' is some C code (a function body) that should return
313      * true or false.  The test will run if the code returns true.
314      *)
315   | If of string
316
317     (* As for 'If' but the test runs _unless_ the code returns true. *)
318   | Unless of string
319
320     (* Run the test only if 'string' is available in the daemon. *)
321   | IfAvailable of string
322
323 (* Some initial scenarios for testing. *)
324 and test_init =
325     (* Do nothing, block devices could contain random stuff including
326      * LVM PVs, and some filesystems might be mounted.  This is usually
327      * a bad idea.
328      *)
329   | InitNone
330
331     (* Block devices are empty and no filesystems are mounted. *)
332   | InitEmpty
333
334     (* /dev/sda contains a single partition /dev/sda1, with random
335      * content.  /dev/sdb and /dev/sdc may have random content.
336      * No LVM.
337      *)
338   | InitPartition
339
340     (* /dev/sda contains a single partition /dev/sda1, which is formatted
341      * as ext2, empty [except for lost+found] and mounted on /.
342      * /dev/sdb and /dev/sdc may have random content.
343      * No LVM.
344      *)
345   | InitBasicFS
346
347     (* /dev/sda:
348      *   /dev/sda1 (is a PV):
349      *     /dev/VG/LV (size 8MB):
350      *       formatted as ext2, empty [except for lost+found], mounted on /
351      * /dev/sdb and /dev/sdc may have random content.
352      *)
353   | InitBasicFSonLVM
354
355     (* /dev/sdd (the ISO, see images/ directory in source)
356      * is mounted on /
357      *)
358   | InitISOFS
359
360 (* Sequence of commands for testing. *)
361 and seq = cmd list
362 and cmd = string list
363
364 (* Note about long descriptions: When referring to another
365  * action, use the format C<guestfs_other> (ie. the full name of
366  * the C function).  This will be replaced as appropriate in other
367  * language bindings.
368  *
369  * Apart from that, long descriptions are just perldoc paragraphs.
370  *)
371
372 (* Generate a random UUID (used in tests). *)
373 let uuidgen () =
374   let chan = open_process_in "uuidgen" in
375   let uuid = input_line chan in
376   (match close_process_in chan with
377    | WEXITED 0 -> ()
378    | WEXITED _ ->
379        failwith "uuidgen: process exited with non-zero status"
380    | WSIGNALED _ | WSTOPPED _ ->
381        failwith "uuidgen: process signalled or stopped by signal"
382   );
383   uuid
384
385 (* These test functions are used in the language binding tests. *)
386
387 let test_all_args = [
388   String "str";
389   OptString "optstr";
390   StringList "strlist";
391   Bool "b";
392   Int "integer";
393   Int64 "integer64";
394   FileIn "filein";
395   FileOut "fileout";
396   BufferIn "bufferin";
397 ]
398
399 let test_all_rets = [
400   (* except for RErr, which is tested thoroughly elsewhere *)
401   "test0rint",         RInt "valout";
402   "test0rint64",       RInt64 "valout";
403   "test0rbool",        RBool "valout";
404   "test0rconststring", RConstString "valout";
405   "test0rconstoptstring", RConstOptString "valout";
406   "test0rstring",      RString "valout";
407   "test0rstringlist",  RStringList "valout";
408   "test0rstruct",      RStruct ("valout", "lvm_pv");
409   "test0rstructlist",  RStructList ("valout", "lvm_pv");
410   "test0rhashtable",   RHashtable "valout";
411 ]
412
413 let test_functions = [
414   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
415    [],
416    "internal test function - do not use",
417    "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 parameter type correctly.
421
422 It echos the contents of each parameter to stdout.
423
424 You probably don't want to call this function.");
425 ] @ List.flatten (
426   List.map (
427     fun (name, ret) ->
428       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
429         [],
430         "internal test function - do not use",
431         "\
432 This is an internal test function which is used to test whether
433 the automatically generated bindings can handle every possible
434 return type correctly.
435
436 It converts string C<val> to the return type.
437
438 You probably don't want to call this function.");
439        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
440         [],
441         "internal test function - do not use",
442         "\
443 This is an internal test function which is used to test whether
444 the automatically generated bindings can handle every possible
445 return type correctly.
446
447 This function always returns an error.
448
449 You probably don't want to call this function.")]
450   ) test_all_rets
451 )
452
453 (* non_daemon_functions are any functions which don't get processed
454  * in the daemon, eg. functions for setting and getting local
455  * configuration values.
456  *)
457
458 let non_daemon_functions = test_functions @ [
459   ("launch", (RErr, []), -1, [FishAlias "run"],
460    [],
461    "launch the qemu subprocess",
462    "\
463 Internally libguestfs is implemented by running a virtual machine
464 using L<qemu(1)>.
465
466 You should call this after configuring the handle
467 (eg. adding drives) but before performing any actions.");
468
469   ("wait_ready", (RErr, []), -1, [NotInFish],
470    [],
471    "wait until the qemu subprocess launches (no op)",
472    "\
473 This function is a no op.
474
475 In versions of the API E<lt> 1.0.71 you had to call this function
476 just after calling C<guestfs_launch> to wait for the launch
477 to complete.  However this is no longer necessary because
478 C<guestfs_launch> now does the waiting.
479
480 If you see any calls to this function in code then you can just
481 remove them, unless you want to retain compatibility with older
482 versions of the API.");
483
484   ("kill_subprocess", (RErr, []), -1, [],
485    [],
486    "kill the qemu subprocess",
487    "\
488 This kills the qemu subprocess.  You should never need to call this.");
489
490   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
491    [],
492    "add an image to examine or modify",
493    "\
494 This function adds a virtual machine disk image C<filename> to the
495 guest.  The first time you call this function, the disk appears as IDE
496 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
497 so on.
498
499 You don't necessarily need to be root when using libguestfs.  However
500 you obviously do need sufficient permissions to access the filename
501 for whatever operations you want to perform (ie. read access if you
502 just want to read the image or write access if you want to modify the
503 image).
504
505 This is equivalent to the qemu parameter
506 C<-drive file=filename,cache=off,if=...>.
507
508 C<cache=off> is omitted in cases where it is not supported by
509 the underlying filesystem.
510
511 C<if=...> is set at compile time by the configuration option
512 C<./configure --with-drive-if=...>.  In the rare case where you
513 might need to change this at run time, use C<guestfs_add_drive_with_if>
514 or C<guestfs_add_drive_ro_with_if>.
515
516 Note that this call checks for the existence of C<filename>.  This
517 stops you from specifying other types of drive which are supported
518 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
519 the general C<guestfs_config> call instead.");
520
521   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
522    [],
523    "add a CD-ROM disk image to examine",
524    "\
525 This function adds a virtual CD-ROM disk image to the guest.
526
527 This is equivalent to the qemu parameter C<-cdrom filename>.
528
529 Notes:
530
531 =over 4
532
533 =item *
534
535 This call checks for the existence of C<filename>.  This
536 stops you from specifying other types of drive which are supported
537 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
538 the general C<guestfs_config> call instead.
539
540 =item *
541
542 If you just want to add an ISO file (often you use this as an
543 efficient way to transfer large files into the guest), then you
544 should probably use C<guestfs_add_drive_ro> instead.
545
546 =back");
547
548   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
549    [],
550    "add a drive in snapshot mode (read-only)",
551    "\
552 This adds a drive in snapshot mode, making it effectively
553 read-only.
554
555 Note that writes to the device are allowed, and will be seen for
556 the duration of the guestfs handle, but they are written
557 to a temporary file which is discarded as soon as the guestfs
558 handle is closed.  We don't currently have any method to enable
559 changes to be committed, although qemu can support this.
560
561 This is equivalent to the qemu parameter
562 C<-drive file=filename,snapshot=on,if=...>.
563
564 C<if=...> is set at compile time by the configuration option
565 C<./configure --with-drive-if=...>.  In the rare case where you
566 might need to change this at run time, use C<guestfs_add_drive_with_if>
567 or C<guestfs_add_drive_ro_with_if>.
568
569 Note that this call checks for the existence of C<filename>.  This
570 stops you from specifying other types of drive which are supported
571 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
572 the general C<guestfs_config> call instead.");
573
574   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
575    [],
576    "add qemu parameters",
577    "\
578 This can be used to add arbitrary qemu command line parameters
579 of the form C<-param value>.  Actually it's not quite arbitrary - we
580 prevent you from setting some parameters which would interfere with
581 parameters that we use.
582
583 The first character of C<param> string must be a C<-> (dash).
584
585 C<value> can be NULL.");
586
587   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
588    [],
589    "set the qemu binary",
590    "\
591 Set the qemu binary that we will use.
592
593 The default is chosen when the library was compiled by the
594 configure script.
595
596 You can also override this by setting the C<LIBGUESTFS_QEMU>
597 environment variable.
598
599 Setting C<qemu> to C<NULL> restores the default qemu binary.
600
601 Note that you should call this function as early as possible
602 after creating the handle.  This is because some pre-launch
603 operations depend on testing qemu features (by running C<qemu -help>).
604 If the qemu binary changes, we don't retest features, and
605 so you might see inconsistent results.  Using the environment
606 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
607 the qemu binary at the same time as the handle is created.");
608
609   ("get_qemu", (RConstString "qemu", []), -1, [],
610    [InitNone, Always, TestRun (
611       [["get_qemu"]])],
612    "get the qemu binary",
613    "\
614 Return the current qemu binary.
615
616 This is always non-NULL.  If it wasn't set already, then this will
617 return the default qemu binary name.");
618
619   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
620    [],
621    "set the search path",
622    "\
623 Set the path that libguestfs searches for kernel and initrd.img.
624
625 The default is C<$libdir/guestfs> unless overridden by setting
626 C<LIBGUESTFS_PATH> environment variable.
627
628 Setting C<path> to C<NULL> restores the default path.");
629
630   ("get_path", (RConstString "path", []), -1, [],
631    [InitNone, Always, TestRun (
632       [["get_path"]])],
633    "get the search path",
634    "\
635 Return the current search path.
636
637 This is always non-NULL.  If it wasn't set already, then this will
638 return the default path.");
639
640   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
641    [],
642    "add options to kernel command line",
643    "\
644 This function is used to add additional options to the
645 guest kernel command line.
646
647 The default is C<NULL> unless overridden by setting
648 C<LIBGUESTFS_APPEND> environment variable.
649
650 Setting C<append> to C<NULL> means I<no> additional options
651 are passed (libguestfs always adds a few of its own).");
652
653   ("get_append", (RConstOptString "append", []), -1, [],
654    (* This cannot be tested with the current framework.  The
655     * function can return NULL in normal operations, which the
656     * test framework interprets as an error.
657     *)
658    [],
659    "get the additional kernel options",
660    "\
661 Return the additional kernel options which are added to the
662 guest kernel command line.
663
664 If C<NULL> then no options are added.");
665
666   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
667    [],
668    "set autosync mode",
669    "\
670 If C<autosync> is true, this enables autosync.  Libguestfs will make a
671 best effort attempt to run C<guestfs_umount_all> followed by
672 C<guestfs_sync> when the handle is closed
673 (also if the program exits without closing handles).
674
675 This is disabled by default (except in guestfish where it is
676 enabled by default).");
677
678   ("get_autosync", (RBool "autosync", []), -1, [],
679    [InitNone, Always, TestRun (
680       [["get_autosync"]])],
681    "get autosync mode",
682    "\
683 Get the autosync flag.");
684
685   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
686    [],
687    "set verbose mode",
688    "\
689 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
690
691 Verbose messages are disabled unless the environment variable
692 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
693
694   ("get_verbose", (RBool "verbose", []), -1, [],
695    [],
696    "get verbose mode",
697    "\
698 This returns the verbose messages flag.");
699
700   ("is_ready", (RBool "ready", []), -1, [],
701    [InitNone, Always, TestOutputTrue (
702       [["is_ready"]])],
703    "is ready to accept commands",
704    "\
705 This returns true iff this handle is ready to accept commands
706 (in the C<READY> state).
707
708 For more information on states, see L<guestfs(3)>.");
709
710   ("is_config", (RBool "config", []), -1, [],
711    [InitNone, Always, TestOutputFalse (
712       [["is_config"]])],
713    "is in configuration state",
714    "\
715 This returns true iff this handle is being configured
716 (in the C<CONFIG> state).
717
718 For more information on states, see L<guestfs(3)>.");
719
720   ("is_launching", (RBool "launching", []), -1, [],
721    [InitNone, Always, TestOutputFalse (
722       [["is_launching"]])],
723    "is launching subprocess",
724    "\
725 This returns true iff this handle is launching the subprocess
726 (in the C<LAUNCHING> state).
727
728 For more information on states, see L<guestfs(3)>.");
729
730   ("is_busy", (RBool "busy", []), -1, [],
731    [InitNone, Always, TestOutputFalse (
732       [["is_busy"]])],
733    "is busy processing a command",
734    "\
735 This returns true iff this handle is busy processing a command
736 (in the C<BUSY> state).
737
738 For more information on states, see L<guestfs(3)>.");
739
740   ("get_state", (RInt "state", []), -1, [],
741    [],
742    "get the current state",
743    "\
744 This returns the current state as an opaque integer.  This is
745 only useful for printing debug and internal error messages.
746
747 For more information on states, see L<guestfs(3)>.");
748
749   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
750    [InitNone, Always, TestOutputInt (
751       [["set_memsize"; "500"];
752        ["get_memsize"]], 500)],
753    "set memory allocated to the qemu subprocess",
754    "\
755 This sets the memory size in megabytes allocated to the
756 qemu subprocess.  This only has any effect if called before
757 C<guestfs_launch>.
758
759 You can also change this by setting the environment
760 variable C<LIBGUESTFS_MEMSIZE> before the handle is
761 created.
762
763 For more information on the architecture of libguestfs,
764 see L<guestfs(3)>.");
765
766   ("get_memsize", (RInt "memsize", []), -1, [],
767    [InitNone, Always, TestOutputIntOp (
768       [["get_memsize"]], ">=", 256)],
769    "get memory allocated to the qemu subprocess",
770    "\
771 This gets the memory size in megabytes allocated to the
772 qemu subprocess.
773
774 If C<guestfs_set_memsize> was not called
775 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
776 then this returns the compiled-in default value for memsize.
777
778 For more information on the architecture of libguestfs,
779 see L<guestfs(3)>.");
780
781   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
782    [InitNone, Always, TestOutputIntOp (
783       [["get_pid"]], ">=", 1)],
784    "get PID of qemu subprocess",
785    "\
786 Return the process ID of the qemu subprocess.  If there is no
787 qemu subprocess, then this will return an error.
788
789 This is an internal call used for debugging and testing.");
790
791   ("version", (RStruct ("version", "version"), []), -1, [],
792    [InitNone, Always, TestOutputStruct (
793       [["version"]], [CompareWithInt ("major", 1)])],
794    "get the library version number",
795    "\
796 Return the libguestfs version number that the program is linked
797 against.
798
799 Note that because of dynamic linking this is not necessarily
800 the version of libguestfs that you compiled against.  You can
801 compile the program, and then at runtime dynamically link
802 against a completely different C<libguestfs.so> library.
803
804 This call was added in version C<1.0.58>.  In previous
805 versions of libguestfs there was no way to get the version
806 number.  From C code you can use dynamic linker functions
807 to find out if this symbol exists (if it doesn't, then
808 it's an earlier version).
809
810 The call returns a structure with four elements.  The first
811 three (C<major>, C<minor> and C<release>) are numbers and
812 correspond to the usual version triplet.  The fourth element
813 (C<extra>) is a string and is normally empty, but may be
814 used for distro-specific information.
815
816 To construct the original version string:
817 C<$major.$minor.$release$extra>
818
819 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
820
821 I<Note:> Don't use this call to test for availability
822 of features.  In enterprise distributions we backport
823 features from later versions into earlier versions,
824 making this an unreliable way to test for features.
825 Use C<guestfs_available> instead.");
826
827   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
828    [InitNone, Always, TestOutputTrue (
829       [["set_selinux"; "true"];
830        ["get_selinux"]])],
831    "set SELinux enabled or disabled at appliance boot",
832    "\
833 This sets the selinux flag that is passed to the appliance
834 at boot time.  The default is C<selinux=0> (disabled).
835
836 Note that if SELinux is enabled, it is always in
837 Permissive mode (C<enforcing=0>).
838
839 For more information on the architecture of libguestfs,
840 see L<guestfs(3)>.");
841
842   ("get_selinux", (RBool "selinux", []), -1, [],
843    [],
844    "get SELinux enabled flag",
845    "\
846 This returns the current setting of the selinux flag which
847 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
848
849 For more information on the architecture of libguestfs,
850 see L<guestfs(3)>.");
851
852   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
853    [InitNone, Always, TestOutputFalse (
854       [["set_trace"; "false"];
855        ["get_trace"]])],
856    "enable or disable command traces",
857    "\
858 If the command trace flag is set to 1, then commands are
859 printed on stdout before they are executed in a format
860 which is very similar to the one used by guestfish.  In
861 other words, you can run a program with this enabled, and
862 you will get out a script which you can feed to guestfish
863 to perform the same set of actions.
864
865 If you want to trace C API calls into libguestfs (and
866 other libraries) then possibly a better way is to use
867 the external ltrace(1) command.
868
869 Command traces are disabled unless the environment variable
870 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
871
872   ("get_trace", (RBool "trace", []), -1, [],
873    [],
874    "get command trace enabled flag",
875    "\
876 Return the command trace flag.");
877
878   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
879    [InitNone, Always, TestOutputFalse (
880       [["set_direct"; "false"];
881        ["get_direct"]])],
882    "enable or disable direct appliance mode",
883    "\
884 If the direct appliance mode flag is enabled, then stdin and
885 stdout are passed directly through to the appliance once it
886 is launched.
887
888 One consequence of this is that log messages aren't caught
889 by the library and handled by C<guestfs_set_log_message_callback>,
890 but go straight to stdout.
891
892 You probably don't want to use this unless you know what you
893 are doing.
894
895 The default is disabled.");
896
897   ("get_direct", (RBool "direct", []), -1, [],
898    [],
899    "get direct appliance mode flag",
900    "\
901 Return the direct appliance mode flag.");
902
903   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
904    [InitNone, Always, TestOutputTrue (
905       [["set_recovery_proc"; "true"];
906        ["get_recovery_proc"]])],
907    "enable or disable the recovery process",
908    "\
909 If this is called with the parameter C<false> then
910 C<guestfs_launch> does not create a recovery process.  The
911 purpose of the recovery process is to stop runaway qemu
912 processes in the case where the main program aborts abruptly.
913
914 This only has any effect if called before C<guestfs_launch>,
915 and the default is true.
916
917 About the only time when you would want to disable this is
918 if the main process will fork itself into the background
919 (\"daemonize\" itself).  In this case the recovery process
920 thinks that the main program has disappeared and so kills
921 qemu, which is not very helpful.");
922
923   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
924    [],
925    "get recovery process enabled flag",
926    "\
927 Return the recovery process enabled flag.");
928
929   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
930    [],
931    "add a drive specifying the QEMU block emulation to use",
932    "\
933 This is the same as C<guestfs_add_drive> but it allows you
934 to specify the QEMU interface emulation to use at run time.");
935
936   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
937    [],
938    "add a drive read-only specifying the QEMU block emulation to use",
939    "\
940 This is the same as C<guestfs_add_drive_ro> but it allows you
941 to specify the QEMU interface emulation to use at run time.");
942
943 ]
944
945 (* daemon_functions are any functions which cause some action
946  * to take place in the daemon.
947  *)
948
949 let daemon_functions = [
950   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
951    [InitEmpty, Always, TestOutput (
952       [["part_disk"; "/dev/sda"; "mbr"];
953        ["mkfs"; "ext2"; "/dev/sda1"];
954        ["mount"; "/dev/sda1"; "/"];
955        ["write"; "/new"; "new file contents"];
956        ["cat"; "/new"]], "new file contents")],
957    "mount a guest disk at a position in the filesystem",
958    "\
959 Mount a guest disk at a position in the filesystem.  Block devices
960 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
961 the guest.  If those block devices contain partitions, they will have
962 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
963 names can be used.
964
965 The rules are the same as for L<mount(2)>:  A filesystem must
966 first be mounted on C</> before others can be mounted.  Other
967 filesystems can only be mounted on directories which already
968 exist.
969
970 The mounted filesystem is writable, if we have sufficient permissions
971 on the underlying device.
972
973 B<Important note:>
974 When you use this call, the filesystem options C<sync> and C<noatime>
975 are set implicitly.  This was originally done because we thought it
976 would improve reliability, but it turns out that I<-o sync> has a
977 very large negative performance impact and negligible effect on
978 reliability.  Therefore we recommend that you avoid using
979 C<guestfs_mount> in any code that needs performance, and instead
980 use C<guestfs_mount_options> (use an empty string for the first
981 parameter if you don't want any options).");
982
983   ("sync", (RErr, []), 2, [],
984    [ InitEmpty, Always, TestRun [["sync"]]],
985    "sync disks, writes are flushed through to the disk image",
986    "\
987 This syncs the disk, so that any writes are flushed through to the
988 underlying disk image.
989
990 You should always call this if you have modified a disk image, before
991 closing the handle.");
992
993   ("touch", (RErr, [Pathname "path"]), 3, [],
994    [InitBasicFS, Always, TestOutputTrue (
995       [["touch"; "/new"];
996        ["exists"; "/new"]])],
997    "update file timestamps or create a new file",
998    "\
999 Touch acts like the L<touch(1)> command.  It can be used to
1000 update the timestamps on a file, or, if the file does not exist,
1001 to create a new zero-length file.
1002
1003 This command only works on regular files, and will fail on other
1004 file types such as directories, symbolic links, block special etc.");
1005
1006   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
1007    [InitISOFS, Always, TestOutput (
1008       [["cat"; "/known-2"]], "abcdef\n")],
1009    "list the contents of a file",
1010    "\
1011 Return the contents of the file named C<path>.
1012
1013 Note that this function cannot correctly handle binary files
1014 (specifically, files containing C<\\0> character which is treated
1015 as end of string).  For those you need to use the C<guestfs_read_file>
1016 or C<guestfs_download> functions which have a more complex interface.");
1017
1018   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1019    [], (* XXX Tricky to test because it depends on the exact format
1020         * of the 'ls -l' command, which changes between F10 and F11.
1021         *)
1022    "list the files in a directory (long format)",
1023    "\
1024 List the files in C<directory> (relative to the root directory,
1025 there is no cwd) in the format of 'ls -la'.
1026
1027 This command is mostly useful for interactive sessions.  It
1028 is I<not> intended that you try to parse the output string.");
1029
1030   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1031    [InitBasicFS, Always, TestOutputList (
1032       [["touch"; "/new"];
1033        ["touch"; "/newer"];
1034        ["touch"; "/newest"];
1035        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1036    "list the files in a directory",
1037    "\
1038 List the files in C<directory> (relative to the root directory,
1039 there is no cwd).  The '.' and '..' entries are not returned, but
1040 hidden files are shown.
1041
1042 This command is mostly useful for interactive sessions.  Programs
1043 should probably use C<guestfs_readdir> instead.");
1044
1045   ("list_devices", (RStringList "devices", []), 7, [],
1046    [InitEmpty, Always, TestOutputListOfDevices (
1047       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1048    "list the block devices",
1049    "\
1050 List all the block devices.
1051
1052 The full block device names are returned, eg. C</dev/sda>");
1053
1054   ("list_partitions", (RStringList "partitions", []), 8, [],
1055    [InitBasicFS, Always, TestOutputListOfDevices (
1056       [["list_partitions"]], ["/dev/sda1"]);
1057     InitEmpty, Always, TestOutputListOfDevices (
1058       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1059        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1060    "list the partitions",
1061    "\
1062 List all the partitions detected on all block devices.
1063
1064 The full partition device names are returned, eg. C</dev/sda1>
1065
1066 This does not return logical volumes.  For that you will need to
1067 call C<guestfs_lvs>.");
1068
1069   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1070    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1071       [["pvs"]], ["/dev/sda1"]);
1072     InitEmpty, Always, TestOutputListOfDevices (
1073       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1074        ["pvcreate"; "/dev/sda1"];
1075        ["pvcreate"; "/dev/sda2"];
1076        ["pvcreate"; "/dev/sda3"];
1077        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1078    "list the LVM physical volumes (PVs)",
1079    "\
1080 List all the physical volumes detected.  This is the equivalent
1081 of the L<pvs(8)> command.
1082
1083 This returns a list of just the device names that contain
1084 PVs (eg. C</dev/sda2>).
1085
1086 See also C<guestfs_pvs_full>.");
1087
1088   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1089    [InitBasicFSonLVM, Always, TestOutputList (
1090       [["vgs"]], ["VG"]);
1091     InitEmpty, Always, TestOutputList (
1092       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1093        ["pvcreate"; "/dev/sda1"];
1094        ["pvcreate"; "/dev/sda2"];
1095        ["pvcreate"; "/dev/sda3"];
1096        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1097        ["vgcreate"; "VG2"; "/dev/sda3"];
1098        ["vgs"]], ["VG1"; "VG2"])],
1099    "list the LVM volume groups (VGs)",
1100    "\
1101 List all the volumes groups detected.  This is the equivalent
1102 of the L<vgs(8)> command.
1103
1104 This returns a list of just the volume group names that were
1105 detected (eg. C<VolGroup00>).
1106
1107 See also C<guestfs_vgs_full>.");
1108
1109   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1110    [InitBasicFSonLVM, Always, TestOutputList (
1111       [["lvs"]], ["/dev/VG/LV"]);
1112     InitEmpty, Always, TestOutputList (
1113       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1114        ["pvcreate"; "/dev/sda1"];
1115        ["pvcreate"; "/dev/sda2"];
1116        ["pvcreate"; "/dev/sda3"];
1117        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1118        ["vgcreate"; "VG2"; "/dev/sda3"];
1119        ["lvcreate"; "LV1"; "VG1"; "50"];
1120        ["lvcreate"; "LV2"; "VG1"; "50"];
1121        ["lvcreate"; "LV3"; "VG2"; "50"];
1122        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1123    "list the LVM logical volumes (LVs)",
1124    "\
1125 List all the logical volumes detected.  This is the equivalent
1126 of the L<lvs(8)> command.
1127
1128 This returns a list of the logical volume device names
1129 (eg. C</dev/VolGroup00/LogVol00>).
1130
1131 See also C<guestfs_lvs_full>.");
1132
1133   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1134    [], (* XXX how to test? *)
1135    "list the LVM physical volumes (PVs)",
1136    "\
1137 List all the physical volumes detected.  This is the equivalent
1138 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1139
1140   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1141    [], (* XXX how to test? *)
1142    "list the LVM volume groups (VGs)",
1143    "\
1144 List all the volumes groups detected.  This is the equivalent
1145 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1146
1147   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1148    [], (* XXX how to test? *)
1149    "list the LVM logical volumes (LVs)",
1150    "\
1151 List all the logical volumes detected.  This is the equivalent
1152 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1153
1154   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1155    [InitISOFS, Always, TestOutputList (
1156       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1157     InitISOFS, Always, TestOutputList (
1158       [["read_lines"; "/empty"]], [])],
1159    "read file as lines",
1160    "\
1161 Return the contents of the file named C<path>.
1162
1163 The file contents are returned as a list of lines.  Trailing
1164 C<LF> and C<CRLF> character sequences are I<not> returned.
1165
1166 Note that this function cannot correctly handle binary files
1167 (specifically, files containing C<\\0> character which is treated
1168 as end of line).  For those you need to use the C<guestfs_read_file>
1169 function which has a more complex interface.");
1170
1171   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1172    [], (* XXX Augeas code needs tests. *)
1173    "create a new Augeas handle",
1174    "\
1175 Create a new Augeas handle for editing configuration files.
1176 If there was any previous Augeas handle associated with this
1177 guestfs session, then it is closed.
1178
1179 You must call this before using any other C<guestfs_aug_*>
1180 commands.
1181
1182 C<root> is the filesystem root.  C<root> must not be NULL,
1183 use C</> instead.
1184
1185 The flags are the same as the flags defined in
1186 E<lt>augeas.hE<gt>, the logical I<or> of the following
1187 integers:
1188
1189 =over 4
1190
1191 =item C<AUG_SAVE_BACKUP> = 1
1192
1193 Keep the original file with a C<.augsave> extension.
1194
1195 =item C<AUG_SAVE_NEWFILE> = 2
1196
1197 Save changes into a file with extension C<.augnew>, and
1198 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1199
1200 =item C<AUG_TYPE_CHECK> = 4
1201
1202 Typecheck lenses (can be expensive).
1203
1204 =item C<AUG_NO_STDINC> = 8
1205
1206 Do not use standard load path for modules.
1207
1208 =item C<AUG_SAVE_NOOP> = 16
1209
1210 Make save a no-op, just record what would have been changed.
1211
1212 =item C<AUG_NO_LOAD> = 32
1213
1214 Do not load the tree in C<guestfs_aug_init>.
1215
1216 =back
1217
1218 To close the handle, you can call C<guestfs_aug_close>.
1219
1220 To find out more about Augeas, see L<http://augeas.net/>.");
1221
1222   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1223    [], (* XXX Augeas code needs tests. *)
1224    "close the current Augeas handle",
1225    "\
1226 Close the current Augeas handle and free up any resources
1227 used by it.  After calling this, you have to call
1228 C<guestfs_aug_init> again before you can use any other
1229 Augeas functions.");
1230
1231   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1232    [], (* XXX Augeas code needs tests. *)
1233    "define an Augeas variable",
1234    "\
1235 Defines an Augeas variable C<name> whose value is the result
1236 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1237 undefined.
1238
1239 On success this returns the number of nodes in C<expr>, or
1240 C<0> if C<expr> evaluates to something which is not a nodeset.");
1241
1242   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "define an Augeas node",
1245    "\
1246 Defines a variable C<name> whose value is the result of
1247 evaluating C<expr>.
1248
1249 If C<expr> evaluates to an empty nodeset, a node is created,
1250 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1251 C<name> will be the nodeset containing that single node.
1252
1253 On success this returns a pair containing the
1254 number of nodes in the nodeset, and a boolean flag
1255 if a node was created.");
1256
1257   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1258    [], (* XXX Augeas code needs tests. *)
1259    "look up the value of an Augeas path",
1260    "\
1261 Look up the value associated with C<path>.  If C<path>
1262 matches exactly one node, the C<value> is returned.");
1263
1264   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1265    [], (* XXX Augeas code needs tests. *)
1266    "set Augeas path to value",
1267    "\
1268 Set the value associated with C<path> to C<val>.
1269
1270 In the Augeas API, it is possible to clear a node by setting
1271 the value to NULL.  Due to an oversight in the libguestfs API
1272 you cannot do that with this call.  Instead you must use the
1273 C<guestfs_aug_clear> call.");
1274
1275   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1276    [], (* XXX Augeas code needs tests. *)
1277    "insert a sibling Augeas node",
1278    "\
1279 Create a new sibling C<label> for C<path>, inserting it into
1280 the tree before or after C<path> (depending on the boolean
1281 flag C<before>).
1282
1283 C<path> must match exactly one existing node in the tree, and
1284 C<label> must be a label, ie. not contain C</>, C<*> or end
1285 with a bracketed index C<[N]>.");
1286
1287   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "remove an Augeas path",
1290    "\
1291 Remove C<path> and all of its children.
1292
1293 On success this returns the number of entries which were removed.");
1294
1295   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1296    [], (* XXX Augeas code needs tests. *)
1297    "move Augeas node",
1298    "\
1299 Move the node C<src> to C<dest>.  C<src> must match exactly
1300 one node.  C<dest> is overwritten if it exists.");
1301
1302   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1303    [], (* XXX Augeas code needs tests. *)
1304    "return Augeas nodes which match augpath",
1305    "\
1306 Returns a list of paths which match the path expression C<path>.
1307 The returned paths are sufficiently qualified so that they match
1308 exactly one node in the current tree.");
1309
1310   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1311    [], (* XXX Augeas code needs tests. *)
1312    "write all pending Augeas changes to disk",
1313    "\
1314 This writes all pending changes to disk.
1315
1316 The flags which were passed to C<guestfs_aug_init> affect exactly
1317 how files are saved.");
1318
1319   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1320    [], (* XXX Augeas code needs tests. *)
1321    "load files into the tree",
1322    "\
1323 Load files into the tree.
1324
1325 See C<aug_load> in the Augeas documentation for the full gory
1326 details.");
1327
1328   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1329    [], (* XXX Augeas code needs tests. *)
1330    "list Augeas nodes under augpath",
1331    "\
1332 This is just a shortcut for listing C<guestfs_aug_match>
1333 C<path/*> and sorting the resulting nodes into alphabetical order.");
1334
1335   ("rm", (RErr, [Pathname "path"]), 29, [],
1336    [InitBasicFS, Always, TestRun
1337       [["touch"; "/new"];
1338        ["rm"; "/new"]];
1339     InitBasicFS, Always, TestLastFail
1340       [["rm"; "/new"]];
1341     InitBasicFS, Always, TestLastFail
1342       [["mkdir"; "/new"];
1343        ["rm"; "/new"]]],
1344    "remove a file",
1345    "\
1346 Remove the single file C<path>.");
1347
1348   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1349    [InitBasicFS, Always, TestRun
1350       [["mkdir"; "/new"];
1351        ["rmdir"; "/new"]];
1352     InitBasicFS, Always, TestLastFail
1353       [["rmdir"; "/new"]];
1354     InitBasicFS, Always, TestLastFail
1355       [["touch"; "/new"];
1356        ["rmdir"; "/new"]]],
1357    "remove a directory",
1358    "\
1359 Remove the single directory C<path>.");
1360
1361   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1362    [InitBasicFS, Always, TestOutputFalse
1363       [["mkdir"; "/new"];
1364        ["mkdir"; "/new/foo"];
1365        ["touch"; "/new/foo/bar"];
1366        ["rm_rf"; "/new"];
1367        ["exists"; "/new"]]],
1368    "remove a file or directory recursively",
1369    "\
1370 Remove the file or directory C<path>, recursively removing the
1371 contents if its a directory.  This is like the C<rm -rf> shell
1372 command.");
1373
1374   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1375    [InitBasicFS, Always, TestOutputTrue
1376       [["mkdir"; "/new"];
1377        ["is_dir"; "/new"]];
1378     InitBasicFS, Always, TestLastFail
1379       [["mkdir"; "/new/foo/bar"]]],
1380    "create a directory",
1381    "\
1382 Create a directory named C<path>.");
1383
1384   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1385    [InitBasicFS, Always, TestOutputTrue
1386       [["mkdir_p"; "/new/foo/bar"];
1387        ["is_dir"; "/new/foo/bar"]];
1388     InitBasicFS, Always, TestOutputTrue
1389       [["mkdir_p"; "/new/foo/bar"];
1390        ["is_dir"; "/new/foo"]];
1391     InitBasicFS, Always, TestOutputTrue
1392       [["mkdir_p"; "/new/foo/bar"];
1393        ["is_dir"; "/new"]];
1394     (* Regression tests for RHBZ#503133: *)
1395     InitBasicFS, Always, TestRun
1396       [["mkdir"; "/new"];
1397        ["mkdir_p"; "/new"]];
1398     InitBasicFS, Always, TestLastFail
1399       [["touch"; "/new"];
1400        ["mkdir_p"; "/new"]]],
1401    "create a directory and parents",
1402    "\
1403 Create a directory named C<path>, creating any parent directories
1404 as necessary.  This is like the C<mkdir -p> shell command.");
1405
1406   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1407    [], (* XXX Need stat command to test *)
1408    "change file mode",
1409    "\
1410 Change the mode (permissions) of C<path> to C<mode>.  Only
1411 numeric modes are supported.
1412
1413 I<Note>: When using this command from guestfish, C<mode>
1414 by default would be decimal, unless you prefix it with
1415 C<0> to get octal, ie. use C<0700> not C<700>.
1416
1417 The mode actually set is affected by the umask.");
1418
1419   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1420    [], (* XXX Need stat command to test *)
1421    "change file owner and group",
1422    "\
1423 Change the file owner to C<owner> and group to C<group>.
1424
1425 Only numeric uid and gid are supported.  If you want to use
1426 names, you will need to locate and parse the password file
1427 yourself (Augeas support makes this relatively easy).");
1428
1429   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1430    [InitISOFS, Always, TestOutputTrue (
1431       [["exists"; "/empty"]]);
1432     InitISOFS, Always, TestOutputTrue (
1433       [["exists"; "/directory"]])],
1434    "test if file or directory exists",
1435    "\
1436 This returns C<true> if and only if there is a file, directory
1437 (or anything) with the given C<path> name.
1438
1439 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1440
1441   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1442    [InitISOFS, Always, TestOutputTrue (
1443       [["is_file"; "/known-1"]]);
1444     InitISOFS, Always, TestOutputFalse (
1445       [["is_file"; "/directory"]])],
1446    "test if file exists",
1447    "\
1448 This returns C<true> if and only if there is a file
1449 with the given C<path> name.  Note that it returns false for
1450 other objects like directories.
1451
1452 See also C<guestfs_stat>.");
1453
1454   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1455    [InitISOFS, Always, TestOutputFalse (
1456       [["is_dir"; "/known-3"]]);
1457     InitISOFS, Always, TestOutputTrue (
1458       [["is_dir"; "/directory"]])],
1459    "test if file exists",
1460    "\
1461 This returns C<true> if and only if there is a directory
1462 with the given C<path> name.  Note that it returns false for
1463 other objects like files.
1464
1465 See also C<guestfs_stat>.");
1466
1467   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1468    [InitEmpty, Always, TestOutputListOfDevices (
1469       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1470        ["pvcreate"; "/dev/sda1"];
1471        ["pvcreate"; "/dev/sda2"];
1472        ["pvcreate"; "/dev/sda3"];
1473        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1474    "create an LVM physical volume",
1475    "\
1476 This creates an LVM physical volume on the named C<device>,
1477 where C<device> should usually be a partition name such
1478 as C</dev/sda1>.");
1479
1480   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1481    [InitEmpty, Always, TestOutputList (
1482       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1483        ["pvcreate"; "/dev/sda1"];
1484        ["pvcreate"; "/dev/sda2"];
1485        ["pvcreate"; "/dev/sda3"];
1486        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1487        ["vgcreate"; "VG2"; "/dev/sda3"];
1488        ["vgs"]], ["VG1"; "VG2"])],
1489    "create an LVM volume group",
1490    "\
1491 This creates an LVM volume group called C<volgroup>
1492 from the non-empty list of physical volumes C<physvols>.");
1493
1494   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1495    [InitEmpty, Always, TestOutputList (
1496       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1497        ["pvcreate"; "/dev/sda1"];
1498        ["pvcreate"; "/dev/sda2"];
1499        ["pvcreate"; "/dev/sda3"];
1500        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1501        ["vgcreate"; "VG2"; "/dev/sda3"];
1502        ["lvcreate"; "LV1"; "VG1"; "50"];
1503        ["lvcreate"; "LV2"; "VG1"; "50"];
1504        ["lvcreate"; "LV3"; "VG2"; "50"];
1505        ["lvcreate"; "LV4"; "VG2"; "50"];
1506        ["lvcreate"; "LV5"; "VG2"; "50"];
1507        ["lvs"]],
1508       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1509        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1510    "create an LVM logical volume",
1511    "\
1512 This creates an LVM logical volume called C<logvol>
1513 on the volume group C<volgroup>, with C<size> megabytes.");
1514
1515   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1516    [InitEmpty, Always, TestOutput (
1517       [["part_disk"; "/dev/sda"; "mbr"];
1518        ["mkfs"; "ext2"; "/dev/sda1"];
1519        ["mount_options"; ""; "/dev/sda1"; "/"];
1520        ["write"; "/new"; "new file contents"];
1521        ["cat"; "/new"]], "new file contents")],
1522    "make a filesystem",
1523    "\
1524 This creates a filesystem on C<device> (usually a partition
1525 or LVM logical volume).  The filesystem type is C<fstype>, for
1526 example C<ext3>.");
1527
1528   ("sfdisk", (RErr, [Device "device";
1529                      Int "cyls"; Int "heads"; Int "sectors";
1530                      StringList "lines"]), 43, [DangerWillRobinson],
1531    [],
1532    "create partitions on a block device",
1533    "\
1534 This is a direct interface to the L<sfdisk(8)> program for creating
1535 partitions on block devices.
1536
1537 C<device> should be a block device, for example C</dev/sda>.
1538
1539 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1540 and sectors on the device, which are passed directly to sfdisk as
1541 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1542 of these, then the corresponding parameter is omitted.  Usually for
1543 'large' disks, you can just pass C<0> for these, but for small
1544 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1545 out the right geometry and you will need to tell it.
1546
1547 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1548 information refer to the L<sfdisk(8)> manpage.
1549
1550 To create a single partition occupying the whole disk, you would
1551 pass C<lines> as a single element list, when the single element being
1552 the string C<,> (comma).
1553
1554 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1555 C<guestfs_part_init>");
1556
1557   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1558    (* Regression test for RHBZ#597135. *)
1559    [InitBasicFS, Always, TestLastFail
1560       [["write_file"; "/new"; "abc"; "10000"]]],
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
1574   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1575    [InitEmpty, Always, TestOutputListOfDevices (
1576       [["part_disk"; "/dev/sda"; "mbr"];
1577        ["mkfs"; "ext2"; "/dev/sda1"];
1578        ["mount_options"; ""; "/dev/sda1"; "/"];
1579        ["mounts"]], ["/dev/sda1"]);
1580     InitEmpty, Always, TestOutputList (
1581       [["part_disk"; "/dev/sda"; "mbr"];
1582        ["mkfs"; "ext2"; "/dev/sda1"];
1583        ["mount_options"; ""; "/dev/sda1"; "/"];
1584        ["umount"; "/"];
1585        ["mounts"]], [])],
1586    "unmount a filesystem",
1587    "\
1588 This unmounts the given filesystem.  The filesystem may be
1589 specified either by its mountpoint (path) or the device which
1590 contains the filesystem.");
1591
1592   ("mounts", (RStringList "devices", []), 46, [],
1593    [InitBasicFS, Always, TestOutputListOfDevices (
1594       [["mounts"]], ["/dev/sda1"])],
1595    "show mounted filesystems",
1596    "\
1597 This returns the list of currently mounted filesystems.  It returns
1598 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1599
1600 Some internal mounts are not shown.
1601
1602 See also: C<guestfs_mountpoints>");
1603
1604   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1605    [InitBasicFS, Always, TestOutputList (
1606       [["umount_all"];
1607        ["mounts"]], []);
1608     (* check that umount_all can unmount nested mounts correctly: *)
1609     InitEmpty, Always, TestOutputList (
1610       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1611        ["mkfs"; "ext2"; "/dev/sda1"];
1612        ["mkfs"; "ext2"; "/dev/sda2"];
1613        ["mkfs"; "ext2"; "/dev/sda3"];
1614        ["mount_options"; ""; "/dev/sda1"; "/"];
1615        ["mkdir"; "/mp1"];
1616        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1617        ["mkdir"; "/mp1/mp2"];
1618        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1619        ["mkdir"; "/mp1/mp2/mp3"];
1620        ["umount_all"];
1621        ["mounts"]], [])],
1622    "unmount all filesystems",
1623    "\
1624 This unmounts all mounted filesystems.
1625
1626 Some internal mounts are not unmounted by this call.");
1627
1628   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1629    [],
1630    "remove all LVM LVs, VGs and PVs",
1631    "\
1632 This command removes all LVM logical volumes, volume groups
1633 and physical volumes.");
1634
1635   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1636    [InitISOFS, Always, TestOutput (
1637       [["file"; "/empty"]], "empty");
1638     InitISOFS, Always, TestOutput (
1639       [["file"; "/known-1"]], "ASCII text");
1640     InitISOFS, Always, TestLastFail (
1641       [["file"; "/notexists"]]);
1642     InitISOFS, Always, TestOutput (
1643       [["file"; "/abssymlink"]], "symbolic link");
1644     InitISOFS, Always, TestOutput (
1645       [["file"; "/directory"]], "directory")],
1646    "determine file type",
1647    "\
1648 This call uses the standard L<file(1)> command to determine
1649 the type or contents of the file.
1650
1651 This call will also transparently look inside various types
1652 of compressed file.
1653
1654 The exact command which runs is C<file -zb path>.  Note in
1655 particular that the filename is not prepended to the output
1656 (the C<-b> option).
1657
1658 This command can also be used on C</dev/> devices
1659 (and partitions, LV names).  You can for example use this
1660 to determine if a device contains a filesystem, although
1661 it's usually better to use C<guestfs_vfs_type>.
1662
1663 If the C<path> does not begin with C</dev/> then
1664 this command only works for the content of regular files.
1665 For other file types (directory, symbolic link etc) it
1666 will just return the string C<directory> etc.");
1667
1668   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1669    [InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 1"]], "Result1");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 2"]], "Result2\n");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 3"]], "\nResult3");
1681     InitBasicFS, Always, TestOutput (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command 4"]], "\nResult4\n");
1685     InitBasicFS, Always, TestOutput (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command"; "/test-command 5"]], "\nResult5\n\n");
1689     InitBasicFS, Always, TestOutput (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1693     InitBasicFS, Always, TestOutput (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command"; "/test-command 7"]], "");
1697     InitBasicFS, Always, TestOutput (
1698       [["upload"; "test-command"; "/test-command"];
1699        ["chmod"; "0o755"; "/test-command"];
1700        ["command"; "/test-command 8"]], "\n");
1701     InitBasicFS, Always, TestOutput (
1702       [["upload"; "test-command"; "/test-command"];
1703        ["chmod"; "0o755"; "/test-command"];
1704        ["command"; "/test-command 9"]], "\n\n");
1705     InitBasicFS, Always, TestOutput (
1706       [["upload"; "test-command"; "/test-command"];
1707        ["chmod"; "0o755"; "/test-command"];
1708        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1709     InitBasicFS, Always, TestOutput (
1710       [["upload"; "test-command"; "/test-command"];
1711        ["chmod"; "0o755"; "/test-command"];
1712        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1713     InitBasicFS, Always, TestLastFail (
1714       [["upload"; "test-command"; "/test-command"];
1715        ["chmod"; "0o755"; "/test-command"];
1716        ["command"; "/test-command"]])],
1717    "run a command from the guest filesystem",
1718    "\
1719 This call runs a command from the guest filesystem.  The
1720 filesystem must be mounted, and must contain a compatible
1721 operating system (ie. something Linux, with the same
1722 or compatible processor architecture).
1723
1724 The single parameter is an argv-style list of arguments.
1725 The first element is the name of the program to run.
1726 Subsequent elements are parameters.  The list must be
1727 non-empty (ie. must contain a program name).  Note that
1728 the command runs directly, and is I<not> invoked via
1729 the shell (see C<guestfs_sh>).
1730
1731 The return value is anything printed to I<stdout> by
1732 the command.
1733
1734 If the command returns a non-zero exit status, then
1735 this function returns an error message.  The error message
1736 string is the content of I<stderr> from the command.
1737
1738 The C<$PATH> environment variable will contain at least
1739 C</usr/bin> and C</bin>.  If you require a program from
1740 another location, you should provide the full path in the
1741 first parameter.
1742
1743 Shared libraries and data files required by the program
1744 must be available on filesystems which are mounted in the
1745 correct places.  It is the caller's responsibility to ensure
1746 all filesystems that are needed are mounted at the right
1747 locations.");
1748
1749   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1750    [InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 1"]], ["Result1"]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 2"]], ["Result2"]);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1762     InitBasicFS, Always, TestOutputList (
1763       [["upload"; "test-command"; "/test-command"];
1764        ["chmod"; "0o755"; "/test-command"];
1765        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1766     InitBasicFS, Always, TestOutputList (
1767       [["upload"; "test-command"; "/test-command"];
1768        ["chmod"; "0o755"; "/test-command"];
1769        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1770     InitBasicFS, Always, TestOutputList (
1771       [["upload"; "test-command"; "/test-command"];
1772        ["chmod"; "0o755"; "/test-command"];
1773        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1774     InitBasicFS, Always, TestOutputList (
1775       [["upload"; "test-command"; "/test-command"];
1776        ["chmod"; "0o755"; "/test-command"];
1777        ["command_lines"; "/test-command 7"]], []);
1778     InitBasicFS, Always, TestOutputList (
1779       [["upload"; "test-command"; "/test-command"];
1780        ["chmod"; "0o755"; "/test-command"];
1781        ["command_lines"; "/test-command 8"]], [""]);
1782     InitBasicFS, Always, TestOutputList (
1783       [["upload"; "test-command"; "/test-command"];
1784        ["chmod"; "0o755"; "/test-command"];
1785        ["command_lines"; "/test-command 9"]], ["";""]);
1786     InitBasicFS, Always, TestOutputList (
1787       [["upload"; "test-command"; "/test-command"];
1788        ["chmod"; "0o755"; "/test-command"];
1789        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1790     InitBasicFS, Always, TestOutputList (
1791       [["upload"; "test-command"; "/test-command"];
1792        ["chmod"; "0o755"; "/test-command"];
1793        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1794    "run a command, returning lines",
1795    "\
1796 This is the same as C<guestfs_command>, but splits the
1797 result into a list of lines.
1798
1799 See also: C<guestfs_sh_lines>");
1800
1801   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1802    [InitISOFS, Always, TestOutputStruct (
1803       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1804    "get file information",
1805    "\
1806 Returns file information for the given C<path>.
1807
1808 This is the same as the C<stat(2)> system call.");
1809
1810   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1811    [InitISOFS, Always, TestOutputStruct (
1812       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1813    "get file information for a symbolic link",
1814    "\
1815 Returns file information for the given C<path>.
1816
1817 This is the same as C<guestfs_stat> except that if C<path>
1818 is a symbolic link, then the link is stat-ed, not the file it
1819 refers to.
1820
1821 This is the same as the C<lstat(2)> system call.");
1822
1823   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1824    [InitISOFS, Always, TestOutputStruct (
1825       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1826    "get file system statistics",
1827    "\
1828 Returns file system statistics for any mounted file system.
1829 C<path> should be a file or directory in the mounted file system
1830 (typically it is the mount point itself, but it doesn't need to be).
1831
1832 This is the same as the C<statvfs(2)> system call.");
1833
1834   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1835    [], (* XXX test *)
1836    "get ext2/ext3/ext4 superblock details",
1837    "\
1838 This returns the contents of the ext2, ext3 or ext4 filesystem
1839 superblock on C<device>.
1840
1841 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1842 manpage for more details.  The list of fields returned isn't
1843 clearly defined, and depends on both the version of C<tune2fs>
1844 that libguestfs was built against, and the filesystem itself.");
1845
1846   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1847    [InitEmpty, Always, TestOutputTrue (
1848       [["blockdev_setro"; "/dev/sda"];
1849        ["blockdev_getro"; "/dev/sda"]])],
1850    "set block device to read-only",
1851    "\
1852 Sets the block device named C<device> to read-only.
1853
1854 This uses the L<blockdev(8)> command.");
1855
1856   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1857    [InitEmpty, Always, TestOutputFalse (
1858       [["blockdev_setrw"; "/dev/sda"];
1859        ["blockdev_getro"; "/dev/sda"]])],
1860    "set block device to read-write",
1861    "\
1862 Sets the block device named C<device> to read-write.
1863
1864 This uses the L<blockdev(8)> command.");
1865
1866   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1867    [InitEmpty, Always, TestOutputTrue (
1868       [["blockdev_setro"; "/dev/sda"];
1869        ["blockdev_getro"; "/dev/sda"]])],
1870    "is block device set to read-only",
1871    "\
1872 Returns a boolean indicating if the block device is read-only
1873 (true if read-only, false if not).
1874
1875 This uses the L<blockdev(8)> command.");
1876
1877   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1878    [InitEmpty, Always, TestOutputInt (
1879       [["blockdev_getss"; "/dev/sda"]], 512)],
1880    "get sectorsize of block device",
1881    "\
1882 This returns the size of sectors on a block device.
1883 Usually 512, but can be larger for modern devices.
1884
1885 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1886 for that).
1887
1888 This uses the L<blockdev(8)> command.");
1889
1890   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1891    [InitEmpty, Always, TestOutputInt (
1892       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1893    "get blocksize of block device",
1894    "\
1895 This returns 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_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1903    [], (* XXX test *)
1904    "set blocksize of block device",
1905    "\
1906 This sets the block size of a device.
1907
1908 (Note this is different from both I<size in blocks> and
1909 I<filesystem block size>).
1910
1911 This uses the L<blockdev(8)> command.");
1912
1913   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1914    [InitEmpty, Always, TestOutputInt (
1915       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1916    "get total size of device in 512-byte sectors",
1917    "\
1918 This returns the size of the device in units of 512-byte sectors
1919 (even if the sectorsize isn't 512 bytes ... weird).
1920
1921 See also C<guestfs_blockdev_getss> for the real sector size of
1922 the device, and C<guestfs_blockdev_getsize64> for the more
1923 useful I<size in bytes>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1928    [InitEmpty, Always, TestOutputInt (
1929       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1930    "get total size of device in bytes",
1931    "\
1932 This returns the size of the device in bytes.
1933
1934 See also C<guestfs_blockdev_getsz>.
1935
1936 This uses the L<blockdev(8)> command.");
1937
1938   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1939    [InitEmpty, Always, TestRun
1940       [["blockdev_flushbufs"; "/dev/sda"]]],
1941    "flush device buffers",
1942    "\
1943 This tells the kernel to flush internal buffers associated
1944 with C<device>.
1945
1946 This uses the L<blockdev(8)> command.");
1947
1948   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1949    [InitEmpty, Always, TestRun
1950       [["blockdev_rereadpt"; "/dev/sda"]]],
1951    "reread partition table",
1952    "\
1953 Reread the partition table on C<device>.
1954
1955 This uses the L<blockdev(8)> command.");
1956
1957   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1958    [InitBasicFS, Always, TestOutput (
1959       (* Pick a file from cwd which isn't likely to change. *)
1960       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1961        ["checksum"; "md5"; "/COPYING.LIB"]],
1962       Digest.to_hex (Digest.file "COPYING.LIB"))],
1963    "upload a file from the local machine",
1964    "\
1965 Upload local file C<filename> to C<remotefilename> on the
1966 filesystem.
1967
1968 C<filename> can also be a named pipe.
1969
1970 See also C<guestfs_download>.");
1971
1972   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1973    [InitBasicFS, Always, TestOutput (
1974       (* Pick a file from cwd which isn't likely to change. *)
1975       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1976        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1977        ["upload"; "testdownload.tmp"; "/upload"];
1978        ["checksum"; "md5"; "/upload"]],
1979       Digest.to_hex (Digest.file "COPYING.LIB"))],
1980    "download a file to the local machine",
1981    "\
1982 Download file C<remotefilename> and save it as C<filename>
1983 on the local machine.
1984
1985 C<filename> can also be a named pipe.
1986
1987 See also C<guestfs_upload>, C<guestfs_cat>.");
1988
1989   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1990    [InitISOFS, Always, TestOutput (
1991       [["checksum"; "crc"; "/known-3"]], "2891671662");
1992     InitISOFS, Always, TestLastFail (
1993       [["checksum"; "crc"; "/notexists"]]);
1994     InitISOFS, Always, TestOutput (
1995       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1996     InitISOFS, Always, TestOutput (
1997       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1998     InitISOFS, Always, TestOutput (
1999       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
2000     InitISOFS, Always, TestOutput (
2001       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
2002     InitISOFS, Always, TestOutput (
2003       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
2004     InitISOFS, Always, TestOutput (
2005       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
2006     (* Test for RHBZ#579608, absolute symbolic links. *)
2007     InitISOFS, Always, TestOutput (
2008       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
2009    "compute MD5, SHAx or CRC checksum of file",
2010    "\
2011 This call computes the MD5, SHAx or CRC checksum of the
2012 file named C<path>.
2013
2014 The type of checksum to compute is given by the C<csumtype>
2015 parameter which must have one of the following values:
2016
2017 =over 4
2018
2019 =item C<crc>
2020
2021 Compute the cyclic redundancy check (CRC) specified by POSIX
2022 for the C<cksum> command.
2023
2024 =item C<md5>
2025
2026 Compute the MD5 hash (using the C<md5sum> program).
2027
2028 =item C<sha1>
2029
2030 Compute the SHA1 hash (using the C<sha1sum> program).
2031
2032 =item C<sha224>
2033
2034 Compute the SHA224 hash (using the C<sha224sum> program).
2035
2036 =item C<sha256>
2037
2038 Compute the SHA256 hash (using the C<sha256sum> program).
2039
2040 =item C<sha384>
2041
2042 Compute the SHA384 hash (using the C<sha384sum> program).
2043
2044 =item C<sha512>
2045
2046 Compute the SHA512 hash (using the C<sha512sum> program).
2047
2048 =back
2049
2050 The checksum is returned as a printable string.
2051
2052 To get the checksum for a device, use C<guestfs_checksum_device>.
2053
2054 To get the checksums for many files, use C<guestfs_checksums_out>.");
2055
2056   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2057    [InitBasicFS, Always, TestOutput (
2058       [["tar_in"; "../images/helloworld.tar"; "/"];
2059        ["cat"; "/hello"]], "hello\n")],
2060    "unpack tarfile to directory",
2061    "\
2062 This command uploads and unpacks local file C<tarfile> (an
2063 I<uncompressed> tar file) into C<directory>.
2064
2065 To upload a compressed tarball, use C<guestfs_tgz_in>
2066 or C<guestfs_txz_in>.");
2067
2068   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2069    [],
2070    "pack directory into tarfile",
2071    "\
2072 This command packs the contents of C<directory> and downloads
2073 it to local file C<tarfile>.
2074
2075 To download a compressed tarball, use C<guestfs_tgz_out>
2076 or C<guestfs_txz_out>.");
2077
2078   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2079    [InitBasicFS, Always, TestOutput (
2080       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2081        ["cat"; "/hello"]], "hello\n")],
2082    "unpack compressed tarball to directory",
2083    "\
2084 This command uploads and unpacks local file C<tarball> (a
2085 I<gzip compressed> tar file) into C<directory>.
2086
2087 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2088
2089   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2090    [],
2091    "pack directory into compressed tarball",
2092    "\
2093 This command packs the contents of C<directory> and downloads
2094 it to local file C<tarball>.
2095
2096 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2097
2098   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2099    [InitBasicFS, Always, TestLastFail (
2100       [["umount"; "/"];
2101        ["mount_ro"; "/dev/sda1"; "/"];
2102        ["touch"; "/new"]]);
2103     InitBasicFS, Always, TestOutput (
2104       [["write"; "/new"; "data"];
2105        ["umount"; "/"];
2106        ["mount_ro"; "/dev/sda1"; "/"];
2107        ["cat"; "/new"]], "data")],
2108    "mount a guest disk, read-only",
2109    "\
2110 This is the same as the C<guestfs_mount> command, but it
2111 mounts the filesystem with the read-only (I<-o ro>) flag.");
2112
2113   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2114    [],
2115    "mount a guest disk with mount options",
2116    "\
2117 This is the same as the C<guestfs_mount> command, but it
2118 allows you to set the mount options as for the
2119 L<mount(8)> I<-o> flag.
2120
2121 If the C<options> parameter is an empty string, then
2122 no options are passed (all options default to whatever
2123 the filesystem uses).");
2124
2125   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2126    [],
2127    "mount a guest disk with mount options and vfstype",
2128    "\
2129 This is the same as the C<guestfs_mount> command, but it
2130 allows you to set both the mount options and the vfstype
2131 as for the L<mount(8)> I<-o> and I<-t> flags.");
2132
2133   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2134    [],
2135    "debugging and internals",
2136    "\
2137 The C<guestfs_debug> command exposes some internals of
2138 C<guestfsd> (the guestfs daemon) that runs inside the
2139 qemu subprocess.
2140
2141 There is no comprehensive help for this command.  You have
2142 to look at the file C<daemon/debug.c> in the libguestfs source
2143 to find out what you can do.");
2144
2145   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2146    [InitEmpty, Always, TestOutputList (
2147       [["part_disk"; "/dev/sda"; "mbr"];
2148        ["pvcreate"; "/dev/sda1"];
2149        ["vgcreate"; "VG"; "/dev/sda1"];
2150        ["lvcreate"; "LV1"; "VG"; "50"];
2151        ["lvcreate"; "LV2"; "VG"; "50"];
2152        ["lvremove"; "/dev/VG/LV1"];
2153        ["lvs"]], ["/dev/VG/LV2"]);
2154     InitEmpty, Always, TestOutputList (
2155       [["part_disk"; "/dev/sda"; "mbr"];
2156        ["pvcreate"; "/dev/sda1"];
2157        ["vgcreate"; "VG"; "/dev/sda1"];
2158        ["lvcreate"; "LV1"; "VG"; "50"];
2159        ["lvcreate"; "LV2"; "VG"; "50"];
2160        ["lvremove"; "/dev/VG"];
2161        ["lvs"]], []);
2162     InitEmpty, Always, TestOutputList (
2163       [["part_disk"; "/dev/sda"; "mbr"];
2164        ["pvcreate"; "/dev/sda1"];
2165        ["vgcreate"; "VG"; "/dev/sda1"];
2166        ["lvcreate"; "LV1"; "VG"; "50"];
2167        ["lvcreate"; "LV2"; "VG"; "50"];
2168        ["lvremove"; "/dev/VG"];
2169        ["vgs"]], ["VG"])],
2170    "remove an LVM logical volume",
2171    "\
2172 Remove an LVM logical volume C<device>, where C<device> is
2173 the path to the LV, such as C</dev/VG/LV>.
2174
2175 You can also remove all LVs in a volume group by specifying
2176 the VG name, C</dev/VG>.");
2177
2178   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2179    [InitEmpty, Always, TestOutputList (
2180       [["part_disk"; "/dev/sda"; "mbr"];
2181        ["pvcreate"; "/dev/sda1"];
2182        ["vgcreate"; "VG"; "/dev/sda1"];
2183        ["lvcreate"; "LV1"; "VG"; "50"];
2184        ["lvcreate"; "LV2"; "VG"; "50"];
2185        ["vgremove"; "VG"];
2186        ["lvs"]], []);
2187     InitEmpty, Always, TestOutputList (
2188       [["part_disk"; "/dev/sda"; "mbr"];
2189        ["pvcreate"; "/dev/sda1"];
2190        ["vgcreate"; "VG"; "/dev/sda1"];
2191        ["lvcreate"; "LV1"; "VG"; "50"];
2192        ["lvcreate"; "LV2"; "VG"; "50"];
2193        ["vgremove"; "VG"];
2194        ["vgs"]], [])],
2195    "remove an LVM volume group",
2196    "\
2197 Remove an LVM volume group C<vgname>, (for example C<VG>).
2198
2199 This also forcibly removes all logical volumes in the volume
2200 group (if any).");
2201
2202   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2203    [InitEmpty, Always, TestOutputListOfDevices (
2204       [["part_disk"; "/dev/sda"; "mbr"];
2205        ["pvcreate"; "/dev/sda1"];
2206        ["vgcreate"; "VG"; "/dev/sda1"];
2207        ["lvcreate"; "LV1"; "VG"; "50"];
2208        ["lvcreate"; "LV2"; "VG"; "50"];
2209        ["vgremove"; "VG"];
2210        ["pvremove"; "/dev/sda1"];
2211        ["lvs"]], []);
2212     InitEmpty, Always, TestOutputListOfDevices (
2213       [["part_disk"; "/dev/sda"; "mbr"];
2214        ["pvcreate"; "/dev/sda1"];
2215        ["vgcreate"; "VG"; "/dev/sda1"];
2216        ["lvcreate"; "LV1"; "VG"; "50"];
2217        ["lvcreate"; "LV2"; "VG"; "50"];
2218        ["vgremove"; "VG"];
2219        ["pvremove"; "/dev/sda1"];
2220        ["vgs"]], []);
2221     InitEmpty, Always, TestOutputListOfDevices (
2222       [["part_disk"; "/dev/sda"; "mbr"];
2223        ["pvcreate"; "/dev/sda1"];
2224        ["vgcreate"; "VG"; "/dev/sda1"];
2225        ["lvcreate"; "LV1"; "VG"; "50"];
2226        ["lvcreate"; "LV2"; "VG"; "50"];
2227        ["vgremove"; "VG"];
2228        ["pvremove"; "/dev/sda1"];
2229        ["pvs"]], [])],
2230    "remove an LVM physical volume",
2231    "\
2232 This wipes a physical volume C<device> so that LVM will no longer
2233 recognise it.
2234
2235 The implementation uses the C<pvremove> command which refuses to
2236 wipe physical volumes that contain any volume groups, so you have
2237 to remove those first.");
2238
2239   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2240    [InitBasicFS, Always, TestOutput (
2241       [["set_e2label"; "/dev/sda1"; "testlabel"];
2242        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2243    "set the ext2/3/4 filesystem label",
2244    "\
2245 This sets the ext2/3/4 filesystem label of the filesystem on
2246 C<device> to C<label>.  Filesystem labels are limited to
2247 16 characters.
2248
2249 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2250 to return the existing label on a filesystem.");
2251
2252   ("get_e2label", (RString "label", [Device "device"]), 81, [DeprecatedBy "vfs_label"],
2253    [],
2254    "get the ext2/3/4 filesystem label",
2255    "\
2256 This returns the ext2/3/4 filesystem label of the filesystem on
2257 C<device>.");
2258
2259   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2260    (let uuid = uuidgen () in
2261     [InitBasicFS, Always, TestOutput (
2262        [["set_e2uuid"; "/dev/sda1"; uuid];
2263         ["get_e2uuid"; "/dev/sda1"]], uuid);
2264      InitBasicFS, Always, TestOutput (
2265        [["set_e2uuid"; "/dev/sda1"; "clear"];
2266         ["get_e2uuid"; "/dev/sda1"]], "");
2267      (* We can't predict what UUIDs will be, so just check the commands run. *)
2268      InitBasicFS, Always, TestRun (
2269        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2270      InitBasicFS, Always, TestRun (
2271        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2272    "set the ext2/3/4 filesystem UUID",
2273    "\
2274 This sets the ext2/3/4 filesystem UUID of the filesystem on
2275 C<device> to C<uuid>.  The format of the UUID and alternatives
2276 such as C<clear>, C<random> and C<time> are described in the
2277 L<tune2fs(8)> manpage.
2278
2279 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2280 to return the existing UUID of a filesystem.");
2281
2282   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [DeprecatedBy "vfs_uuid"],
2283    (* Regression test for RHBZ#597112. *)
2284    (let uuid = uuidgen () in
2285     [InitBasicFS, Always, TestOutput (
2286        [["mke2journal"; "1024"; "/dev/sdb"];
2287         ["set_e2uuid"; "/dev/sdb"; uuid];
2288         ["get_e2uuid"; "/dev/sdb"]], uuid)]),
2289    "get the ext2/3/4 filesystem UUID",
2290    "\
2291 This returns the ext2/3/4 filesystem UUID of the filesystem on
2292 C<device>.");
2293
2294   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2295    [InitBasicFS, Always, TestOutputInt (
2296       [["umount"; "/dev/sda1"];
2297        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2298     InitBasicFS, Always, TestOutputInt (
2299       [["umount"; "/dev/sda1"];
2300        ["zero"; "/dev/sda1"];
2301        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2302    "run the filesystem checker",
2303    "\
2304 This runs the filesystem checker (fsck) on C<device> which
2305 should have filesystem type C<fstype>.
2306
2307 The returned integer is the status.  See L<fsck(8)> for the
2308 list of status codes from C<fsck>.
2309
2310 Notes:
2311
2312 =over 4
2313
2314 =item *
2315
2316 Multiple status codes can be summed together.
2317
2318 =item *
2319
2320 A non-zero return code can mean \"success\", for example if
2321 errors have been corrected on the filesystem.
2322
2323 =item *
2324
2325 Checking or repairing NTFS volumes is not supported
2326 (by linux-ntfs).
2327
2328 =back
2329
2330 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2331
2332   ("zero", (RErr, [Device "device"]), 85, [],
2333    [InitBasicFS, Always, TestOutput (
2334       [["umount"; "/dev/sda1"];
2335        ["zero"; "/dev/sda1"];
2336        ["file"; "/dev/sda1"]], "data")],
2337    "write zeroes to the device",
2338    "\
2339 This command writes zeroes over the first few blocks of C<device>.
2340
2341 How many blocks are zeroed isn't specified (but it's I<not> enough
2342 to securely wipe the device).  It should be sufficient to remove
2343 any partition tables, filesystem superblocks and so on.
2344
2345 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2346
2347   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2348    (* See:
2349     * https://bugzilla.redhat.com/show_bug.cgi?id=484986
2350     * https://bugzilla.redhat.com/show_bug.cgi?id=479760
2351     *)
2352    [InitBasicFS, Always, TestOutputTrue (
2353       [["mkdir_p"; "/boot/grub"];
2354        ["write"; "/boot/grub/device.map"; "(hd0) /dev/vda"];
2355        ["grub_install"; "/"; "/dev/vda"];
2356        ["is_dir"; "/boot"]])],
2357    "install GRUB",
2358    "\
2359 This command installs GRUB (the Grand Unified Bootloader) on
2360 C<device>, with the root directory being C<root>.
2361
2362 Note: If grub-install reports the error
2363 \"No suitable drive was found in the generated device map.\"
2364 it may be that you need to create a C</boot/grub/device.map>
2365 file first that contains the mapping between grub device names
2366 and Linux device names.  It is usually sufficient to create
2367 a file containing:
2368
2369  (hd0) /dev/vda
2370
2371 replacing C</dev/vda> with the name of the installation device.");
2372
2373   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2374    [InitBasicFS, Always, TestOutput (
2375       [["write"; "/old"; "file content"];
2376        ["cp"; "/old"; "/new"];
2377        ["cat"; "/new"]], "file content");
2378     InitBasicFS, Always, TestOutputTrue (
2379       [["write"; "/old"; "file content"];
2380        ["cp"; "/old"; "/new"];
2381        ["is_file"; "/old"]]);
2382     InitBasicFS, Always, TestOutput (
2383       [["write"; "/old"; "file content"];
2384        ["mkdir"; "/dir"];
2385        ["cp"; "/old"; "/dir/new"];
2386        ["cat"; "/dir/new"]], "file content")],
2387    "copy a file",
2388    "\
2389 This copies a file from C<src> to C<dest> where C<dest> is
2390 either a destination filename or destination directory.");
2391
2392   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2393    [InitBasicFS, Always, TestOutput (
2394       [["mkdir"; "/olddir"];
2395        ["mkdir"; "/newdir"];
2396        ["write"; "/olddir/file"; "file content"];
2397        ["cp_a"; "/olddir"; "/newdir"];
2398        ["cat"; "/newdir/olddir/file"]], "file content")],
2399    "copy a file or directory recursively",
2400    "\
2401 This copies a file or directory from C<src> to C<dest>
2402 recursively using the C<cp -a> command.");
2403
2404   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2405    [InitBasicFS, Always, TestOutput (
2406       [["write"; "/old"; "file content"];
2407        ["mv"; "/old"; "/new"];
2408        ["cat"; "/new"]], "file content");
2409     InitBasicFS, Always, TestOutputFalse (
2410       [["write"; "/old"; "file content"];
2411        ["mv"; "/old"; "/new"];
2412        ["is_file"; "/old"]])],
2413    "move a file",
2414    "\
2415 This moves a file from C<src> to C<dest> where C<dest> is
2416 either a destination filename or destination directory.");
2417
2418   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2419    [InitEmpty, Always, TestRun (
2420       [["drop_caches"; "3"]])],
2421    "drop kernel page cache, dentries and inodes",
2422    "\
2423 This instructs the guest kernel to drop its page cache,
2424 and/or dentries and inode caches.  The parameter C<whattodrop>
2425 tells the kernel what precisely to drop, see
2426 L<http://linux-mm.org/Drop_Caches>
2427
2428 Setting C<whattodrop> to 3 should drop everything.
2429
2430 This automatically calls L<sync(2)> before the operation,
2431 so that the maximum guest memory is freed.");
2432
2433   ("dmesg", (RString "kmsgs", []), 91, [],
2434    [InitEmpty, Always, TestRun (
2435       [["dmesg"]])],
2436    "return kernel messages",
2437    "\
2438 This returns the kernel messages (C<dmesg> output) from
2439 the guest kernel.  This is sometimes useful for extended
2440 debugging of problems.
2441
2442 Another way to get the same information is to enable
2443 verbose messages with C<guestfs_set_verbose> or by setting
2444 the environment variable C<LIBGUESTFS_DEBUG=1> before
2445 running the program.");
2446
2447   ("ping_daemon", (RErr, []), 92, [],
2448    [InitEmpty, Always, TestRun (
2449       [["ping_daemon"]])],
2450    "ping the guest daemon",
2451    "\
2452 This is a test probe into the guestfs daemon running inside
2453 the qemu subprocess.  Calling this function checks that the
2454 daemon responds to the ping message, without affecting the daemon
2455 or attached block device(s) in any other way.");
2456
2457   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2458    [InitBasicFS, Always, TestOutputTrue (
2459       [["write"; "/file1"; "contents of a file"];
2460        ["cp"; "/file1"; "/file2"];
2461        ["equal"; "/file1"; "/file2"]]);
2462     InitBasicFS, Always, TestOutputFalse (
2463       [["write"; "/file1"; "contents of a file"];
2464        ["write"; "/file2"; "contents of another file"];
2465        ["equal"; "/file1"; "/file2"]]);
2466     InitBasicFS, Always, TestLastFail (
2467       [["equal"; "/file1"; "/file2"]])],
2468    "test if two files have equal contents",
2469    "\
2470 This compares the two files C<file1> and C<file2> and returns
2471 true if their content is exactly equal, or false otherwise.
2472
2473 The external L<cmp(1)> program is used for the comparison.");
2474
2475   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2476    [InitISOFS, Always, TestOutputList (
2477       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2478     InitISOFS, Always, TestOutputList (
2479       [["strings"; "/empty"]], []);
2480     (* Test for RHBZ#579608, absolute symbolic links. *)
2481     InitISOFS, Always, TestRun (
2482       [["strings"; "/abssymlink"]])],
2483    "print the printable strings in a file",
2484    "\
2485 This runs the L<strings(1)> command on a file and returns
2486 the list of printable strings found.");
2487
2488   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2489    [InitISOFS, Always, TestOutputList (
2490       [["strings_e"; "b"; "/known-5"]], []);
2491     InitBasicFS, Always, TestOutputList (
2492       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2493        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2494    "print the printable strings in a file",
2495    "\
2496 This is like the C<guestfs_strings> command, but allows you to
2497 specify the encoding of strings that are looked for in
2498 the source file C<path>.
2499
2500 Allowed encodings are:
2501
2502 =over 4
2503
2504 =item s
2505
2506 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2507 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2508
2509 =item S
2510
2511 Single 8-bit-byte characters.
2512
2513 =item b
2514
2515 16-bit big endian strings such as those encoded in
2516 UTF-16BE or UCS-2BE.
2517
2518 =item l (lower case letter L)
2519
2520 16-bit little endian such as UTF-16LE and UCS-2LE.
2521 This is useful for examining binaries in Windows guests.
2522
2523 =item B
2524
2525 32-bit big endian such as UCS-4BE.
2526
2527 =item L
2528
2529 32-bit little endian such as UCS-4LE.
2530
2531 =back
2532
2533 The returned strings are transcoded to UTF-8.");
2534
2535   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2536    [InitISOFS, Always, TestOutput (
2537       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2538     (* Test for RHBZ#501888c2 regression which caused large hexdump
2539      * commands to segfault.
2540      *)
2541     InitISOFS, Always, TestRun (
2542       [["hexdump"; "/100krandom"]]);
2543     (* Test for RHBZ#579608, absolute symbolic links. *)
2544     InitISOFS, Always, TestRun (
2545       [["hexdump"; "/abssymlink"]])],
2546    "dump a file in hexadecimal",
2547    "\
2548 This runs C<hexdump -C> on the given C<path>.  The result is
2549 the human-readable, canonical hex dump of the file.");
2550
2551   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2552    [InitNone, Always, TestOutput (
2553       [["part_disk"; "/dev/sda"; "mbr"];
2554        ["mkfs"; "ext3"; "/dev/sda1"];
2555        ["mount_options"; ""; "/dev/sda1"; "/"];
2556        ["write"; "/new"; "test file"];
2557        ["umount"; "/dev/sda1"];
2558        ["zerofree"; "/dev/sda1"];
2559        ["mount_options"; ""; "/dev/sda1"; "/"];
2560        ["cat"; "/new"]], "test file")],
2561    "zero unused inodes and disk blocks on ext2/3 filesystem",
2562    "\
2563 This runs the I<zerofree> program on C<device>.  This program
2564 claims to zero unused inodes and disk blocks on an ext2/3
2565 filesystem, thus making it possible to compress the filesystem
2566 more effectively.
2567
2568 You should B<not> run this program if the filesystem is
2569 mounted.
2570
2571 It is possible that using this program can damage the filesystem
2572 or data on the filesystem.");
2573
2574   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2575    [],
2576    "resize an LVM physical volume",
2577    "\
2578 This resizes (expands or shrinks) an existing LVM physical
2579 volume to match the new size of the underlying device.");
2580
2581   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2582                        Int "cyls"; Int "heads"; Int "sectors";
2583                        String "line"]), 99, [DangerWillRobinson],
2584    [],
2585    "modify a single partition on a block device",
2586    "\
2587 This runs L<sfdisk(8)> option to modify just the single
2588 partition C<n> (note: C<n> counts from 1).
2589
2590 For other parameters, see C<guestfs_sfdisk>.  You should usually
2591 pass C<0> for the cyls/heads/sectors parameters.
2592
2593 See also: C<guestfs_part_add>");
2594
2595   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2596    [],
2597    "display the partition table",
2598    "\
2599 This displays the partition table on C<device>, in the
2600 human-readable output of the L<sfdisk(8)> command.  It is
2601 not intended to be parsed.
2602
2603 See also: C<guestfs_part_list>");
2604
2605   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2606    [],
2607    "display the kernel geometry",
2608    "\
2609 This displays the kernel's idea of the geometry of C<device>.
2610
2611 The result is in human-readable format, and not designed to
2612 be parsed.");
2613
2614   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2615    [],
2616    "display the disk geometry from the partition table",
2617    "\
2618 This displays the disk geometry of C<device> read from the
2619 partition table.  Especially in the case where the underlying
2620 block device has been resized, this can be different from the
2621 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2622
2623 The result is in human-readable format, and not designed to
2624 be parsed.");
2625
2626   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2627    [],
2628    "activate or deactivate all volume groups",
2629    "\
2630 This command activates or (if C<activate> is false) deactivates
2631 all logical volumes in all volume groups.
2632 If activated, then they are made known to the
2633 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2634 then those devices disappear.
2635
2636 This command is the same as running C<vgchange -a y|n>");
2637
2638   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2639    [],
2640    "activate or deactivate some volume groups",
2641    "\
2642 This command activates or (if C<activate> is false) deactivates
2643 all logical volumes in the listed volume groups C<volgroups>.
2644 If activated, then they are made known to the
2645 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2646 then those devices disappear.
2647
2648 This command is the same as running C<vgchange -a y|n volgroups...>
2649
2650 Note that if C<volgroups> is an empty list then B<all> volume groups
2651 are activated or deactivated.");
2652
2653   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2654    [InitNone, Always, TestOutput (
2655       [["part_disk"; "/dev/sda"; "mbr"];
2656        ["pvcreate"; "/dev/sda1"];
2657        ["vgcreate"; "VG"; "/dev/sda1"];
2658        ["lvcreate"; "LV"; "VG"; "10"];
2659        ["mkfs"; "ext2"; "/dev/VG/LV"];
2660        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2661        ["write"; "/new"; "test content"];
2662        ["umount"; "/"];
2663        ["lvresize"; "/dev/VG/LV"; "20"];
2664        ["e2fsck_f"; "/dev/VG/LV"];
2665        ["resize2fs"; "/dev/VG/LV"];
2666        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2667        ["cat"; "/new"]], "test content");
2668     InitNone, Always, TestRun (
2669       (* Make an LV smaller to test RHBZ#587484. *)
2670       [["part_disk"; "/dev/sda"; "mbr"];
2671        ["pvcreate"; "/dev/sda1"];
2672        ["vgcreate"; "VG"; "/dev/sda1"];
2673        ["lvcreate"; "LV"; "VG"; "20"];
2674        ["lvresize"; "/dev/VG/LV"; "10"]])],
2675    "resize an LVM logical volume",
2676    "\
2677 This resizes (expands or shrinks) an existing LVM logical
2678 volume to C<mbytes>.  When reducing, data in the reduced part
2679 is lost.");
2680
2681   ("resize2fs", (RErr, [Device "device"]), 106, [],
2682    [], (* lvresize tests this *)
2683    "resize an ext2, ext3 or ext4 filesystem",
2684    "\
2685 This resizes an ext2, ext3 or ext4 filesystem to match the size of
2686 the underlying device.
2687
2688 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2689 on the C<device> before calling this command.  For unknown reasons
2690 C<resize2fs> sometimes gives an error about this and sometimes not.
2691 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2692 calling this function.");
2693
2694   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2695    [InitBasicFS, Always, TestOutputList (
2696       [["find"; "/"]], ["lost+found"]);
2697     InitBasicFS, Always, TestOutputList (
2698       [["touch"; "/a"];
2699        ["mkdir"; "/b"];
2700        ["touch"; "/b/c"];
2701        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2702     InitBasicFS, Always, TestOutputList (
2703       [["mkdir_p"; "/a/b/c"];
2704        ["touch"; "/a/b/c/d"];
2705        ["find"; "/a/b/"]], ["c"; "c/d"])],
2706    "find all files and directories",
2707    "\
2708 This command lists out all files and directories, recursively,
2709 starting at C<directory>.  It is essentially equivalent to
2710 running the shell command C<find directory -print> but some
2711 post-processing happens on the output, described below.
2712
2713 This returns a list of strings I<without any prefix>.  Thus
2714 if the directory structure was:
2715
2716  /tmp/a
2717  /tmp/b
2718  /tmp/c/d
2719
2720 then the returned list from C<guestfs_find> C</tmp> would be
2721 4 elements:
2722
2723  a
2724  b
2725  c
2726  c/d
2727
2728 If C<directory> is not a directory, then this command returns
2729 an error.
2730
2731 The returned list is sorted.
2732
2733 See also C<guestfs_find0>.");
2734
2735   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2736    [], (* lvresize tests this *)
2737    "check an ext2/ext3 filesystem",
2738    "\
2739 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2740 filesystem checker on C<device>, noninteractively (C<-p>),
2741 even if the filesystem appears to be clean (C<-f>).
2742
2743 This command is only needed because of C<guestfs_resize2fs>
2744 (q.v.).  Normally you should use C<guestfs_fsck>.");
2745
2746   ("sleep", (RErr, [Int "secs"]), 109, [],
2747    [InitNone, Always, TestRun (
2748       [["sleep"; "1"]])],
2749    "sleep for some seconds",
2750    "\
2751 Sleep for C<secs> seconds.");
2752
2753   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2754    [InitNone, Always, TestOutputInt (
2755       [["part_disk"; "/dev/sda"; "mbr"];
2756        ["mkfs"; "ntfs"; "/dev/sda1"];
2757        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2758     InitNone, Always, TestOutputInt (
2759       [["part_disk"; "/dev/sda"; "mbr"];
2760        ["mkfs"; "ext2"; "/dev/sda1"];
2761        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2762    "probe NTFS volume",
2763    "\
2764 This command runs the L<ntfs-3g.probe(8)> command which probes
2765 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2766 be mounted read-write, and some cannot be mounted at all).
2767
2768 C<rw> is a boolean flag.  Set it to true if you want to test
2769 if the volume can be mounted read-write.  Set it to false if
2770 you want to test if the volume can be mounted read-only.
2771
2772 The return value is an integer which C<0> if the operation
2773 would succeed, or some non-zero value documented in the
2774 L<ntfs-3g.probe(8)> manual page.");
2775
2776   ("sh", (RString "output", [String "command"]), 111, [],
2777    [], (* XXX needs tests *)
2778    "run a command via the shell",
2779    "\
2780 This call runs a command from the guest filesystem via the
2781 guest's C</bin/sh>.
2782
2783 This is like C<guestfs_command>, but passes the command to:
2784
2785  /bin/sh -c \"command\"
2786
2787 Depending on the guest's shell, this usually results in
2788 wildcards being expanded, shell expressions being interpolated
2789 and so on.
2790
2791 All the provisos about C<guestfs_command> apply to this call.");
2792
2793   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2794    [], (* XXX needs tests *)
2795    "run a command via the shell returning lines",
2796    "\
2797 This is the same as C<guestfs_sh>, but splits the result
2798 into a list of lines.
2799
2800 See also: C<guestfs_command_lines>");
2801
2802   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2803    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2804     * code in stubs.c, since all valid glob patterns must start with "/".
2805     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2806     *)
2807    [InitBasicFS, Always, TestOutputList (
2808       [["mkdir_p"; "/a/b/c"];
2809        ["touch"; "/a/b/c/d"];
2810        ["touch"; "/a/b/c/e"];
2811        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2812     InitBasicFS, Always, TestOutputList (
2813       [["mkdir_p"; "/a/b/c"];
2814        ["touch"; "/a/b/c/d"];
2815        ["touch"; "/a/b/c/e"];
2816        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2817     InitBasicFS, Always, TestOutputList (
2818       [["mkdir_p"; "/a/b/c"];
2819        ["touch"; "/a/b/c/d"];
2820        ["touch"; "/a/b/c/e"];
2821        ["glob_expand"; "/a/*/x/*"]], [])],
2822    "expand a wildcard path",
2823    "\
2824 This command searches for all the pathnames matching
2825 C<pattern> according to the wildcard expansion rules
2826 used by the shell.
2827
2828 If no paths match, then this returns an empty list
2829 (note: not an error).
2830
2831 It is just a wrapper around the C L<glob(3)> function
2832 with flags C<GLOB_MARK|GLOB_BRACE>.
2833 See that manual page for more details.");
2834
2835   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2836    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2837       [["scrub_device"; "/dev/sdc"]])],
2838    "scrub (securely wipe) a device",
2839    "\
2840 This command writes patterns over C<device> to make data retrieval
2841 more difficult.
2842
2843 It is an interface to the L<scrub(1)> program.  See that
2844 manual page for more details.");
2845
2846   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2847    [InitBasicFS, Always, TestRun (
2848       [["write"; "/file"; "content"];
2849        ["scrub_file"; "/file"]])],
2850    "scrub (securely wipe) a file",
2851    "\
2852 This command writes patterns over a file to make data retrieval
2853 more difficult.
2854
2855 The file is I<removed> after scrubbing.
2856
2857 It is an interface to the L<scrub(1)> program.  See that
2858 manual page for more details.");
2859
2860   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2861    [], (* XXX needs testing *)
2862    "scrub (securely wipe) free space",
2863    "\
2864 This command creates the directory C<dir> and then fills it
2865 with files until the filesystem is full, and scrubs the files
2866 as for C<guestfs_scrub_file>, and deletes them.
2867 The intention is to scrub any free space on the partition
2868 containing C<dir>.
2869
2870 It is an interface to the L<scrub(1)> program.  See that
2871 manual page for more details.");
2872
2873   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2874    [InitBasicFS, Always, TestRun (
2875       [["mkdir"; "/tmp"];
2876        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2877    "create a temporary directory",
2878    "\
2879 This command creates a temporary directory.  The
2880 C<template> parameter should be a full pathname for the
2881 temporary directory name with the final six characters being
2882 \"XXXXXX\".
2883
2884 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2885 the second one being suitable for Windows filesystems.
2886
2887 The name of the temporary directory that was created
2888 is returned.
2889
2890 The temporary directory is created with mode 0700
2891 and is owned by root.
2892
2893 The caller is responsible for deleting the temporary
2894 directory and its contents after use.
2895
2896 See also: L<mkdtemp(3)>");
2897
2898   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2899    [InitISOFS, Always, TestOutputInt (
2900       [["wc_l"; "/10klines"]], 10000);
2901     (* Test for RHBZ#579608, absolute symbolic links. *)
2902     InitISOFS, Always, TestOutputInt (
2903       [["wc_l"; "/abssymlink"]], 10000)],
2904    "count lines in a file",
2905    "\
2906 This command counts the lines in a file, using the
2907 C<wc -l> external command.");
2908
2909   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2910    [InitISOFS, Always, TestOutputInt (
2911       [["wc_w"; "/10klines"]], 10000)],
2912    "count words in a file",
2913    "\
2914 This command counts the words in a file, using the
2915 C<wc -w> external command.");
2916
2917   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2918    [InitISOFS, Always, TestOutputInt (
2919       [["wc_c"; "/100kallspaces"]], 102400)],
2920    "count characters in a file",
2921    "\
2922 This command counts the characters in a file, using the
2923 C<wc -c> external command.");
2924
2925   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2926    [InitISOFS, Always, TestOutputList (
2927       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2928     (* Test for RHBZ#579608, absolute symbolic links. *)
2929     InitISOFS, Always, TestOutputList (
2930       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2931    "return first 10 lines of a file",
2932    "\
2933 This command returns up to the first 10 lines of a file as
2934 a list of strings.");
2935
2936   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2937    [InitISOFS, Always, TestOutputList (
2938       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2939     InitISOFS, Always, TestOutputList (
2940       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2941     InitISOFS, Always, TestOutputList (
2942       [["head_n"; "0"; "/10klines"]], [])],
2943    "return first N lines of a file",
2944    "\
2945 If the parameter C<nrlines> is a positive number, this returns the first
2946 C<nrlines> lines of the file C<path>.
2947
2948 If the parameter C<nrlines> is a negative number, this returns lines
2949 from the file C<path>, excluding the last C<nrlines> lines.
2950
2951 If the parameter C<nrlines> is zero, this returns an empty list.");
2952
2953   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2954    [InitISOFS, Always, TestOutputList (
2955       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2956    "return last 10 lines of a file",
2957    "\
2958 This command returns up to the last 10 lines of a file as
2959 a list of strings.");
2960
2961   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2962    [InitISOFS, Always, TestOutputList (
2963       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2964     InitISOFS, Always, TestOutputList (
2965       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2966     InitISOFS, Always, TestOutputList (
2967       [["tail_n"; "0"; "/10klines"]], [])],
2968    "return last N lines of a file",
2969    "\
2970 If the parameter C<nrlines> is a positive number, this returns the last
2971 C<nrlines> lines of the file C<path>.
2972
2973 If the parameter C<nrlines> is a negative number, this returns lines
2974 from the file C<path>, starting with the C<-nrlines>th line.
2975
2976 If the parameter C<nrlines> is zero, this returns an empty list.");
2977
2978   ("df", (RString "output", []), 125, [],
2979    [], (* XXX Tricky to test because it depends on the exact format
2980         * of the 'df' command and other imponderables.
2981         *)
2982    "report file system disk space usage",
2983    "\
2984 This command runs the C<df> command to report disk space used.
2985
2986 This command is mostly useful for interactive sessions.  It
2987 is I<not> intended that you try to parse the output string.
2988 Use C<statvfs> from programs.");
2989
2990   ("df_h", (RString "output", []), 126, [],
2991    [], (* XXX Tricky to test because it depends on the exact format
2992         * of the 'df' command and other imponderables.
2993         *)
2994    "report file system disk space usage (human readable)",
2995    "\
2996 This command runs the C<df -h> command to report disk space used
2997 in human-readable format.
2998
2999 This command is mostly useful for interactive sessions.  It
3000 is I<not> intended that you try to parse the output string.
3001 Use C<statvfs> from programs.");
3002
3003   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
3004    [InitISOFS, Always, TestOutputInt (
3005       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
3006    "estimate file space usage",
3007    "\
3008 This command runs the C<du -s> command to estimate file space
3009 usage for C<path>.
3010
3011 C<path> can be a file or a directory.  If C<path> is a directory
3012 then the estimate includes the contents of the directory and all
3013 subdirectories (recursively).
3014
3015 The result is the estimated size in I<kilobytes>
3016 (ie. units of 1024 bytes).");
3017
3018   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
3019    [InitISOFS, Always, TestOutputList (
3020       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
3021    "list files in an initrd",
3022    "\
3023 This command lists out files contained in an initrd.
3024
3025 The files are listed without any initial C</> character.  The
3026 files are listed in the order they appear (not necessarily
3027 alphabetical).  Directory names are listed as separate items.
3028
3029 Old Linux kernels (2.4 and earlier) used a compressed ext2
3030 filesystem as initrd.  We I<only> support the newer initramfs
3031 format (compressed cpio files).");
3032
3033   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3034    [],
3035    "mount a file using the loop device",
3036    "\
3037 This command lets you mount C<file> (a filesystem image
3038 in a file) on a mount point.  It is entirely equivalent to
3039 the command C<mount -o loop file mountpoint>.");
3040
3041   ("mkswap", (RErr, [Device "device"]), 130, [],
3042    [InitEmpty, Always, TestRun (
3043       [["part_disk"; "/dev/sda"; "mbr"];
3044        ["mkswap"; "/dev/sda1"]])],
3045    "create a swap partition",
3046    "\
3047 Create a swap partition on C<device>.");
3048
3049   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3050    [InitEmpty, Always, TestRun (
3051       [["part_disk"; "/dev/sda"; "mbr"];
3052        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3053    "create a swap partition with a label",
3054    "\
3055 Create a swap partition on C<device> with label C<label>.
3056
3057 Note that you cannot attach a swap label to a block device
3058 (eg. C</dev/sda>), just to a partition.  This appears to be
3059 a limitation of the kernel or swap tools.");
3060
3061   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3062    (let uuid = uuidgen () in
3063     [InitEmpty, Always, TestRun (
3064        [["part_disk"; "/dev/sda"; "mbr"];
3065         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3066    "create a swap partition with an explicit UUID",
3067    "\
3068 Create a swap partition on C<device> with UUID C<uuid>.");
3069
3070   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3071    [InitBasicFS, Always, TestOutputStruct (
3072       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3073        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3074        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3075     InitBasicFS, Always, TestOutputStruct (
3076       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3077        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3078    "make block, character or FIFO devices",
3079    "\
3080 This call creates block or character special devices, or
3081 named pipes (FIFOs).
3082
3083 The C<mode> parameter should be the mode, using the standard
3084 constants.  C<devmajor> and C<devminor> are the
3085 device major and minor numbers, only used when creating block
3086 and character special devices.
3087
3088 Note that, just like L<mknod(2)>, the mode must be bitwise
3089 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3090 just creates a regular file).  These constants are
3091 available in the standard Linux header files, or you can use
3092 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3093 which are wrappers around this command which bitwise OR
3094 in the appropriate constant for you.
3095
3096 The mode actually set is affected by the umask.");
3097
3098   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3099    [InitBasicFS, Always, TestOutputStruct (
3100       [["mkfifo"; "0o777"; "/node"];
3101        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3102    "make FIFO (named pipe)",
3103    "\
3104 This call creates a FIFO (named pipe) called C<path> with
3105 mode C<mode>.  It is just a convenient wrapper around
3106 C<guestfs_mknod>.
3107
3108 The mode actually set is affected by the umask.");
3109
3110   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3111    [InitBasicFS, Always, TestOutputStruct (
3112       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3113        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3114    "make block device node",
3115    "\
3116 This call creates a block device node called C<path> with
3117 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3118 It is just a convenient wrapper around C<guestfs_mknod>.
3119
3120 The mode actually set is affected by the umask.");
3121
3122   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3123    [InitBasicFS, Always, TestOutputStruct (
3124       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3125        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3126    "make char device node",
3127    "\
3128 This call creates a char device node called C<path> with
3129 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3130 It is just a convenient wrapper around C<guestfs_mknod>.
3131
3132 The mode actually set is affected by the umask.");
3133
3134   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3135    [InitEmpty, Always, TestOutputInt (
3136       [["umask"; "0o22"]], 0o22)],
3137    "set file mode creation mask (umask)",
3138    "\
3139 This function sets the mask used for creating new files and
3140 device nodes to C<mask & 0777>.
3141
3142 Typical umask values would be C<022> which creates new files
3143 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3144 C<002> which creates new files with permissions like
3145 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3146
3147 The default umask is C<022>.  This is important because it
3148 means that directories and device nodes will be created with
3149 C<0644> or C<0755> mode even if you specify C<0777>.
3150
3151 See also C<guestfs_get_umask>,
3152 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3153
3154 This call returns the previous umask.");
3155
3156   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3157    [],
3158    "read directories entries",
3159    "\
3160 This returns the list of directory entries in directory C<dir>.
3161
3162 All entries in the directory are returned, including C<.> and
3163 C<..>.  The entries are I<not> sorted, but returned in the same
3164 order as the underlying filesystem.
3165
3166 Also this call returns basic file type information about each
3167 file.  The C<ftyp> field will contain one of the following characters:
3168
3169 =over 4
3170
3171 =item 'b'
3172
3173 Block special
3174
3175 =item 'c'
3176
3177 Char special
3178
3179 =item 'd'
3180
3181 Directory
3182
3183 =item 'f'
3184
3185 FIFO (named pipe)
3186
3187 =item 'l'
3188
3189 Symbolic link
3190
3191 =item 'r'
3192
3193 Regular file
3194
3195 =item 's'
3196
3197 Socket
3198
3199 =item 'u'
3200
3201 Unknown file type
3202
3203 =item '?'
3204
3205 The L<readdir(3)> call returned a C<d_type> field with an
3206 unexpected value
3207
3208 =back
3209
3210 This function is primarily intended for use by programs.  To
3211 get a simple list of names, use C<guestfs_ls>.  To get a printable
3212 directory for human consumption, use C<guestfs_ll>.");
3213
3214   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3215    [],
3216    "create partitions on a block device",
3217    "\
3218 This is a simplified interface to the C<guestfs_sfdisk>
3219 command, where partition sizes are specified in megabytes
3220 only (rounded to the nearest cylinder) and you don't need
3221 to specify the cyls, heads and sectors parameters which
3222 were rarely if ever used anyway.
3223
3224 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3225 and C<guestfs_part_disk>");
3226
3227   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3228    [],
3229    "determine file type inside a compressed file",
3230    "\
3231 This command runs C<file> after first decompressing C<path>
3232 using C<method>.
3233
3234 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3235
3236 Since 1.0.63, use C<guestfs_file> instead which can now
3237 process compressed files.");
3238
3239   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3240    [],
3241    "list extended attributes of a file or directory",
3242    "\
3243 This call lists the extended attributes of the file or directory
3244 C<path>.
3245
3246 At the system call level, this is a combination of the
3247 L<listxattr(2)> and L<getxattr(2)> calls.
3248
3249 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3250
3251   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3252    [],
3253    "list extended attributes of a file or directory",
3254    "\
3255 This is the same as C<guestfs_getxattrs>, but if C<path>
3256 is a symbolic link, then it returns the extended attributes
3257 of the link itself.");
3258
3259   ("setxattr", (RErr, [String "xattr";
3260                        String "val"; Int "vallen"; (* will be BufferIn *)
3261                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3262    [],
3263    "set extended attribute of a file or directory",
3264    "\
3265 This call sets the extended attribute named C<xattr>
3266 of the file C<path> to the value C<val> (of length C<vallen>).
3267 The value is arbitrary 8 bit data.
3268
3269 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3270
3271   ("lsetxattr", (RErr, [String "xattr";
3272                         String "val"; Int "vallen"; (* will be BufferIn *)
3273                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3274    [],
3275    "set extended attribute of a file or directory",
3276    "\
3277 This is the same as C<guestfs_setxattr>, but if C<path>
3278 is a symbolic link, then it sets an extended attribute
3279 of the link itself.");
3280
3281   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3282    [],
3283    "remove extended attribute of a file or directory",
3284    "\
3285 This call removes the extended attribute named C<xattr>
3286 of the file C<path>.
3287
3288 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3289
3290   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3291    [],
3292    "remove extended attribute of a file or directory",
3293    "\
3294 This is the same as C<guestfs_removexattr>, but if C<path>
3295 is a symbolic link, then it removes an extended attribute
3296 of the link itself.");
3297
3298   ("mountpoints", (RHashtable "mps", []), 147, [],
3299    [],
3300    "show mountpoints",
3301    "\
3302 This call is similar to C<guestfs_mounts>.  That call returns
3303 a list of devices.  This one returns a hash table (map) of
3304 device name to directory where the device is mounted.");
3305
3306   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3307    (* This is a special case: while you would expect a parameter
3308     * of type "Pathname", that doesn't work, because it implies
3309     * NEED_ROOT in the generated calling code in stubs.c, and
3310     * this function cannot use NEED_ROOT.
3311     *)
3312    [],
3313    "create a mountpoint",
3314    "\
3315 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3316 specialized calls that can be used to create extra mountpoints
3317 before mounting the first filesystem.
3318
3319 These calls are I<only> necessary in some very limited circumstances,
3320 mainly the case where you want to mount a mix of unrelated and/or
3321 read-only filesystems together.
3322
3323 For example, live CDs often contain a \"Russian doll\" nest of
3324 filesystems, an ISO outer layer, with a squashfs image inside, with
3325 an ext2/3 image inside that.  You can unpack this as follows
3326 in guestfish:
3327
3328  add-ro Fedora-11-i686-Live.iso
3329  run
3330  mkmountpoint /cd
3331  mkmountpoint /squash
3332  mkmountpoint /ext3
3333  mount /dev/sda /cd
3334  mount-loop /cd/LiveOS/squashfs.img /squash
3335  mount-loop /squash/LiveOS/ext3fs.img /ext3
3336
3337 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3338
3339   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3340    [],
3341    "remove a mountpoint",
3342    "\
3343 This calls removes a mountpoint that was previously created
3344 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3345 for full details.");
3346
3347   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3348    [InitISOFS, Always, TestOutputBuffer (
3349       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3350     (* Test various near large, large and too large files (RHBZ#589039). *)
3351     InitBasicFS, Always, TestLastFail (
3352       [["touch"; "/a"];
3353        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3354        ["read_file"; "/a"]]);
3355     InitBasicFS, Always, TestLastFail (
3356       [["touch"; "/a"];
3357        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3358        ["read_file"; "/a"]]);
3359     InitBasicFS, Always, TestLastFail (
3360       [["touch"; "/a"];
3361        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3362        ["read_file"; "/a"]])],
3363    "read a file",
3364    "\
3365 This calls returns the contents of the file C<path> as a
3366 buffer.
3367
3368 Unlike C<guestfs_cat>, this function can correctly
3369 handle files that contain embedded ASCII NUL characters.
3370 However unlike C<guestfs_download>, this function is limited
3371 in the total size of file that can be handled.");
3372
3373   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3374    [InitISOFS, Always, TestOutputList (
3375       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3376     InitISOFS, Always, TestOutputList (
3377       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3378     (* Test for RHBZ#579608, absolute symbolic links. *)
3379     InitISOFS, Always, TestOutputList (
3380       [["grep"; "nomatch"; "/abssymlink"]], [])],
3381    "return lines matching a pattern",
3382    "\
3383 This calls the external C<grep> program and returns the
3384 matching lines.");
3385
3386   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3387    [InitISOFS, Always, TestOutputList (
3388       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3389    "return lines matching a pattern",
3390    "\
3391 This calls the external C<egrep> program and returns the
3392 matching lines.");
3393
3394   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3395    [InitISOFS, Always, TestOutputList (
3396       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3397    "return lines matching a pattern",
3398    "\
3399 This calls the external C<fgrep> program and returns the
3400 matching lines.");
3401
3402   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3403    [InitISOFS, Always, TestOutputList (
3404       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3405    "return lines matching a pattern",
3406    "\
3407 This calls the external C<grep -i> program and returns the
3408 matching lines.");
3409
3410   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3411    [InitISOFS, Always, TestOutputList (
3412       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3413    "return lines matching a pattern",
3414    "\
3415 This calls the external C<egrep -i> program and returns the
3416 matching lines.");
3417
3418   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3419    [InitISOFS, Always, TestOutputList (
3420       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3421    "return lines matching a pattern",
3422    "\
3423 This calls the external C<fgrep -i> program and returns the
3424 matching lines.");
3425
3426   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3427    [InitISOFS, Always, TestOutputList (
3428       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3429    "return lines matching a pattern",
3430    "\
3431 This calls the external C<zgrep> program and returns the
3432 matching lines.");
3433
3434   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3435    [InitISOFS, Always, TestOutputList (
3436       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3437    "return lines matching a pattern",
3438    "\
3439 This calls the external C<zegrep> program and returns the
3440 matching lines.");
3441
3442   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3443    [InitISOFS, Always, TestOutputList (
3444       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3445    "return lines matching a pattern",
3446    "\
3447 This calls the external C<zfgrep> program and returns the
3448 matching lines.");
3449
3450   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3451    [InitISOFS, Always, TestOutputList (
3452       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3453    "return lines matching a pattern",
3454    "\
3455 This calls the external C<zgrep -i> program and returns the
3456 matching lines.");
3457
3458   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3459    [InitISOFS, Always, TestOutputList (
3460       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3461    "return lines matching a pattern",
3462    "\
3463 This calls the external C<zegrep -i> program and returns the
3464 matching lines.");
3465
3466   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3467    [InitISOFS, Always, TestOutputList (
3468       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3469    "return lines matching a pattern",
3470    "\
3471 This calls the external C<zfgrep -i> program and returns the
3472 matching lines.");
3473
3474   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3475    [InitISOFS, Always, TestOutput (
3476       [["realpath"; "/../directory"]], "/directory")],
3477    "canonicalized absolute pathname",
3478    "\
3479 Return the canonicalized absolute pathname of C<path>.  The
3480 returned path has no C<.>, C<..> or symbolic link path elements.");
3481
3482   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3483    [InitBasicFS, Always, TestOutputStruct (
3484       [["touch"; "/a"];
3485        ["ln"; "/a"; "/b"];
3486        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3487    "create a hard link",
3488    "\
3489 This command creates a hard link using the C<ln> command.");
3490
3491   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3492    [InitBasicFS, Always, TestOutputStruct (
3493       [["touch"; "/a"];
3494        ["touch"; "/b"];
3495        ["ln_f"; "/a"; "/b"];
3496        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3497    "create a hard link",
3498    "\
3499 This command creates a hard link using the C<ln -f> command.
3500 The C<-f> option removes the link (C<linkname>) if it exists already.");
3501
3502   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3503    [InitBasicFS, Always, TestOutputStruct (
3504       [["touch"; "/a"];
3505        ["ln_s"; "a"; "/b"];
3506        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3507    "create a symbolic link",
3508    "\
3509 This command creates a symbolic link using the C<ln -s> command.");
3510
3511   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3512    [InitBasicFS, Always, TestOutput (
3513       [["mkdir_p"; "/a/b"];
3514        ["touch"; "/a/b/c"];
3515        ["ln_sf"; "../d"; "/a/b/c"];
3516        ["readlink"; "/a/b/c"]], "../d")],
3517    "create a symbolic link",
3518    "\
3519 This command creates a symbolic link using the C<ln -sf> command,
3520 The C<-f> option removes the link (C<linkname>) if it exists already.");
3521
3522   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3523    [] (* XXX tested above *),
3524    "read the target of a symbolic link",
3525    "\
3526 This command reads the target of a symbolic link.");
3527
3528   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3529    [InitBasicFS, Always, TestOutputStruct (
3530       [["fallocate"; "/a"; "1000000"];
3531        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3532    "preallocate a file in the guest filesystem",
3533    "\
3534 This command preallocates a file (containing zero bytes) named
3535 C<path> of size C<len> bytes.  If the file exists already, it
3536 is overwritten.
3537
3538 Do not confuse this with the guestfish-specific
3539 C<alloc> command which allocates a file in the host and
3540 attaches it as a device.");
3541
3542   ("swapon_device", (RErr, [Device "device"]), 170, [],
3543    [InitPartition, Always, TestRun (
3544       [["mkswap"; "/dev/sda1"];
3545        ["swapon_device"; "/dev/sda1"];
3546        ["swapoff_device"; "/dev/sda1"]])],
3547    "enable swap on device",
3548    "\
3549 This command enables the libguestfs appliance to use the
3550 swap device or partition named C<device>.  The increased
3551 memory is made available for all commands, for example
3552 those run using C<guestfs_command> or C<guestfs_sh>.
3553
3554 Note that you should not swap to existing guest swap
3555 partitions unless you know what you are doing.  They may
3556 contain hibernation information, or other information that
3557 the guest doesn't want you to trash.  You also risk leaking
3558 information about the host to the guest this way.  Instead,
3559 attach a new host device to the guest and swap on that.");
3560
3561   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3562    [], (* XXX tested by swapon_device *)
3563    "disable swap on device",
3564    "\
3565 This command disables the libguestfs appliance swap
3566 device or partition named C<device>.
3567 See C<guestfs_swapon_device>.");
3568
3569   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3570    [InitBasicFS, Always, TestRun (
3571       [["fallocate"; "/swap"; "8388608"];
3572        ["mkswap_file"; "/swap"];
3573        ["swapon_file"; "/swap"];
3574        ["swapoff_file"; "/swap"]])],
3575    "enable swap on file",
3576    "\
3577 This command enables swap to a file.
3578 See C<guestfs_swapon_device> for other notes.");
3579
3580   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3581    [], (* XXX tested by swapon_file *)
3582    "disable swap on file",
3583    "\
3584 This command disables the libguestfs appliance swap on file.");
3585
3586   ("swapon_label", (RErr, [String "label"]), 174, [],
3587    [InitEmpty, Always, TestRun (
3588       [["part_disk"; "/dev/sdb"; "mbr"];
3589        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3590        ["swapon_label"; "swapit"];
3591        ["swapoff_label"; "swapit"];
3592        ["zero"; "/dev/sdb"];
3593        ["blockdev_rereadpt"; "/dev/sdb"]])],
3594    "enable swap on labeled swap partition",
3595    "\
3596 This command enables swap to a labeled swap partition.
3597 See C<guestfs_swapon_device> for other notes.");
3598
3599   ("swapoff_label", (RErr, [String "label"]), 175, [],
3600    [], (* XXX tested by swapon_label *)
3601    "disable swap on labeled swap partition",
3602    "\
3603 This command disables the libguestfs appliance swap on
3604 labeled swap partition.");
3605
3606   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3607    (let uuid = uuidgen () in
3608     [InitEmpty, Always, TestRun (
3609        [["mkswap_U"; uuid; "/dev/sdb"];
3610         ["swapon_uuid"; uuid];
3611         ["swapoff_uuid"; uuid]])]),
3612    "enable swap on swap partition by UUID",
3613    "\
3614 This command enables swap to a swap partition with the given UUID.
3615 See C<guestfs_swapon_device> for other notes.");
3616
3617   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3618    [], (* XXX tested by swapon_uuid *)
3619    "disable swap on swap partition by UUID",
3620    "\
3621 This command disables the libguestfs appliance swap partition
3622 with the given UUID.");
3623
3624   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3625    [InitBasicFS, Always, TestRun (
3626       [["fallocate"; "/swap"; "8388608"];
3627        ["mkswap_file"; "/swap"]])],
3628    "create a swap file",
3629    "\
3630 Create a swap file.
3631
3632 This command just writes a swap file signature to an existing
3633 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3634
3635   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3636    [InitISOFS, Always, TestRun (
3637       [["inotify_init"; "0"]])],
3638    "create an inotify handle",
3639    "\
3640 This command creates a new inotify handle.
3641 The inotify subsystem can be used to notify events which happen to
3642 objects in the guest filesystem.
3643
3644 C<maxevents> is the maximum number of events which will be
3645 queued up between calls to C<guestfs_inotify_read> or
3646 C<guestfs_inotify_files>.
3647 If this is passed as C<0>, then the kernel (or previously set)
3648 default is used.  For Linux 2.6.29 the default was 16384 events.
3649 Beyond this limit, the kernel throws away events, but records
3650 the fact that it threw them away by setting a flag
3651 C<IN_Q_OVERFLOW> in the returned structure list (see
3652 C<guestfs_inotify_read>).
3653
3654 Before any events are generated, you have to add some
3655 watches to the internal watch list.  See:
3656 C<guestfs_inotify_add_watch>,
3657 C<guestfs_inotify_rm_watch> and
3658 C<guestfs_inotify_watch_all>.
3659
3660 Queued up events should be read periodically by calling
3661 C<guestfs_inotify_read>
3662 (or C<guestfs_inotify_files> which is just a helpful
3663 wrapper around C<guestfs_inotify_read>).  If you don't
3664 read the events out often enough then you risk the internal
3665 queue overflowing.
3666
3667 The handle should be closed after use by calling
3668 C<guestfs_inotify_close>.  This also removes any
3669 watches automatically.
3670
3671 See also L<inotify(7)> for an overview of the inotify interface
3672 as exposed by the Linux kernel, which is roughly what we expose
3673 via libguestfs.  Note that there is one global inotify handle
3674 per libguestfs instance.");
3675
3676   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3677    [InitBasicFS, Always, TestOutputList (
3678       [["inotify_init"; "0"];
3679        ["inotify_add_watch"; "/"; "1073741823"];
3680        ["touch"; "/a"];
3681        ["touch"; "/b"];
3682        ["inotify_files"]], ["a"; "b"])],
3683    "add an inotify watch",
3684    "\
3685 Watch C<path> for the events listed in C<mask>.
3686
3687 Note that if C<path> is a directory then events within that
3688 directory are watched, but this does I<not> happen recursively
3689 (in subdirectories).
3690
3691 Note for non-C or non-Linux callers: the inotify events are
3692 defined by the Linux kernel ABI and are listed in
3693 C</usr/include/sys/inotify.h>.");
3694
3695   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3696    [],
3697    "remove an inotify watch",
3698    "\
3699 Remove a previously defined inotify watch.
3700 See C<guestfs_inotify_add_watch>.");
3701
3702   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3703    [],
3704    "return list of inotify events",
3705    "\
3706 Return the complete queue of events that have happened
3707 since the previous read call.
3708
3709 If no events have happened, this returns an empty list.
3710
3711 I<Note>: In order to make sure that all events have been
3712 read, you must call this function repeatedly until it
3713 returns an empty list.  The reason is that the call will
3714 read events up to the maximum appliance-to-host message
3715 size and leave remaining events in the queue.");
3716
3717   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3718    [],
3719    "return list of watched files that had events",
3720    "\
3721 This function is a helpful wrapper around C<guestfs_inotify_read>
3722 which just returns a list of pathnames of objects that were
3723 touched.  The returned pathnames are sorted and deduplicated.");
3724
3725   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3726    [],
3727    "close the inotify handle",
3728    "\
3729 This closes the inotify handle which was previously
3730 opened by inotify_init.  It removes all watches, throws
3731 away any pending events, and deallocates all resources.");
3732
3733   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3734    [],
3735    "set SELinux security context",
3736    "\
3737 This sets the SELinux security context of the daemon
3738 to the string C<context>.
3739
3740 See the documentation about SELINUX in L<guestfs(3)>.");
3741
3742   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3743    [],
3744    "get SELinux security context",
3745    "\
3746 This gets the SELinux security context of the daemon.
3747
3748 See the documentation about SELINUX in L<guestfs(3)>,
3749 and C<guestfs_setcon>");
3750
3751   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3752    [InitEmpty, Always, TestOutput (
3753       [["part_disk"; "/dev/sda"; "mbr"];
3754        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3755        ["mount_options"; ""; "/dev/sda1"; "/"];
3756        ["write"; "/new"; "new file contents"];
3757        ["cat"; "/new"]], "new file contents");
3758     InitEmpty, Always, TestRun (
3759       [["part_disk"; "/dev/sda"; "mbr"];
3760        ["mkfs_b"; "vfat"; "32768"; "/dev/sda1"]]);
3761     InitEmpty, Always, TestLastFail (
3762       [["part_disk"; "/dev/sda"; "mbr"];
3763        ["mkfs_b"; "vfat"; "32769"; "/dev/sda1"]]);
3764     InitEmpty, Always, TestLastFail (
3765       [["part_disk"; "/dev/sda"; "mbr"];
3766        ["mkfs_b"; "vfat"; "33280"; "/dev/sda1"]]);
3767     InitEmpty, IfAvailable "ntfsprogs", TestRun (
3768       [["part_disk"; "/dev/sda"; "mbr"];
3769        ["mkfs_b"; "ntfs"; "32768"; "/dev/sda1"]])],
3770    "make a filesystem with block size",
3771    "\
3772 This call is similar to C<guestfs_mkfs>, but it allows you to
3773 control the block size of the resulting filesystem.  Supported
3774 block sizes depend on the filesystem type, but typically they
3775 are C<1024>, C<2048> or C<4096> only.
3776
3777 For VFAT and NTFS the C<blocksize> parameter is treated as
3778 the requested cluster size.");
3779
3780   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3781    [InitEmpty, Always, TestOutput (
3782       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3783        ["mke2journal"; "4096"; "/dev/sda1"];
3784        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3785        ["mount_options"; ""; "/dev/sda2"; "/"];
3786        ["write"; "/new"; "new file contents"];
3787        ["cat"; "/new"]], "new file contents")],
3788    "make ext2/3/4 external journal",
3789    "\
3790 This creates an ext2 external journal on C<device>.  It is equivalent
3791 to the command:
3792
3793  mke2fs -O journal_dev -b blocksize device");
3794
3795   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3796    [InitEmpty, Always, TestOutput (
3797       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3798        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3799        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3800        ["mount_options"; ""; "/dev/sda2"; "/"];
3801        ["write"; "/new"; "new file contents"];
3802        ["cat"; "/new"]], "new file contents")],
3803    "make ext2/3/4 external journal with label",
3804    "\
3805 This creates an ext2 external journal on C<device> with label C<label>.");
3806
3807   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3808    (let uuid = uuidgen () in
3809     [InitEmpty, Always, TestOutput (
3810        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3811         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3812         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3813         ["mount_options"; ""; "/dev/sda2"; "/"];
3814         ["write"; "/new"; "new file contents"];
3815         ["cat"; "/new"]], "new file contents")]),
3816    "make ext2/3/4 external journal with UUID",
3817    "\
3818 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3819
3820   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3821    [],
3822    "make ext2/3/4 filesystem with external journal",
3823    "\
3824 This creates an ext2/3/4 filesystem on C<device> with
3825 an external journal on C<journal>.  It is equivalent
3826 to the command:
3827
3828  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3829
3830 See also C<guestfs_mke2journal>.");
3831
3832   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3833    [],
3834    "make ext2/3/4 filesystem with external journal",
3835    "\
3836 This creates an ext2/3/4 filesystem on C<device> with
3837 an external journal on the journal labeled C<label>.
3838
3839 See also C<guestfs_mke2journal_L>.");
3840
3841   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3842    [],
3843    "make ext2/3/4 filesystem with external journal",
3844    "\
3845 This creates an ext2/3/4 filesystem on C<device> with
3846 an external journal on the journal with UUID C<uuid>.
3847
3848 See also C<guestfs_mke2journal_U>.");
3849
3850   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3851    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3852    "load a kernel module",
3853    "\
3854 This loads a kernel module in the appliance.
3855
3856 The kernel module must have been whitelisted when libguestfs
3857 was built (see C<appliance/kmod.whitelist.in> in the source).");
3858
3859   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3860    [InitNone, Always, TestOutput (
3861       [["echo_daemon"; "This is a test"]], "This is a test"
3862     )],
3863    "echo arguments back to the client",
3864    "\
3865 This command concatenates the list of C<words> passed with single spaces
3866 between them and returns the resulting string.
3867
3868 You can use this command to test the connection through to the daemon.
3869
3870 See also C<guestfs_ping_daemon>.");
3871
3872   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3873    [], (* There is a regression test for this. *)
3874    "find all files and directories, returning NUL-separated list",
3875    "\
3876 This command lists out all files and directories, recursively,
3877 starting at C<directory>, placing the resulting list in the
3878 external file called C<files>.
3879
3880 This command works the same way as C<guestfs_find> with the
3881 following exceptions:
3882
3883 =over 4
3884
3885 =item *
3886
3887 The resulting list is written to an external file.
3888
3889 =item *
3890
3891 Items (filenames) in the result are separated
3892 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3893
3894 =item *
3895
3896 This command is not limited in the number of names that it
3897 can return.
3898
3899 =item *
3900
3901 The result list is not sorted.
3902
3903 =back");
3904
3905   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3906    [InitISOFS, Always, TestOutput (
3907       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3908     InitISOFS, Always, TestOutput (
3909       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3910     InitISOFS, Always, TestOutput (
3911       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3912     InitISOFS, Always, TestLastFail (
3913       [["case_sensitive_path"; "/Known-1/"]]);
3914     InitBasicFS, Always, TestOutput (
3915       [["mkdir"; "/a"];
3916        ["mkdir"; "/a/bbb"];
3917        ["touch"; "/a/bbb/c"];
3918        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3919     InitBasicFS, Always, TestOutput (
3920       [["mkdir"; "/a"];
3921        ["mkdir"; "/a/bbb"];
3922        ["touch"; "/a/bbb/c"];
3923        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3924     InitBasicFS, Always, TestLastFail (
3925       [["mkdir"; "/a"];
3926        ["mkdir"; "/a/bbb"];
3927        ["touch"; "/a/bbb/c"];
3928        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3929    "return true path on case-insensitive filesystem",
3930    "\
3931 This can be used to resolve case insensitive paths on
3932 a filesystem which is case sensitive.  The use case is
3933 to resolve paths which you have read from Windows configuration
3934 files or the Windows Registry, to the true path.
3935
3936 The command handles a peculiarity of the Linux ntfs-3g
3937 filesystem driver (and probably others), which is that although
3938 the underlying filesystem is case-insensitive, the driver
3939 exports the filesystem to Linux as case-sensitive.
3940
3941 One consequence of this is that special directories such
3942 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3943 (or other things) depending on the precise details of how
3944 they were created.  In Windows itself this would not be
3945 a problem.
3946
3947 Bug or feature?  You decide:
3948 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3949
3950 This function resolves the true case of each element in the
3951 path and returns the case-sensitive path.
3952
3953 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3954 might return C<\"/WINDOWS/system32\"> (the exact return value
3955 would depend on details of how the directories were originally
3956 created under Windows).
3957
3958 I<Note>:
3959 This function does not handle drive names, backslashes etc.
3960
3961 See also C<guestfs_realpath>.");
3962
3963   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3964    [InitBasicFS, Always, TestOutput (
3965       [["vfs_type"; "/dev/sda1"]], "ext2")],
3966    "get the Linux VFS type corresponding to a mounted device",
3967    "\
3968 This command gets the filesystem type corresponding to
3969 the filesystem on C<device>.
3970
3971 For most filesystems, the result is the name of the Linux
3972 VFS module which would be used to mount this filesystem
3973 if you mounted it without specifying the filesystem type.
3974 For example a string such as C<ext3> or C<ntfs>.");
3975
3976   ("truncate", (RErr, [Pathname "path"]), 199, [],
3977    [InitBasicFS, Always, TestOutputStruct (
3978       [["write"; "/test"; "some stuff so size is not zero"];
3979        ["truncate"; "/test"];
3980        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3981    "truncate a file to zero size",
3982    "\
3983 This command truncates C<path> to a zero-length file.  The
3984 file must exist already.");
3985
3986   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3987    [InitBasicFS, Always, TestOutputStruct (
3988       [["touch"; "/test"];
3989        ["truncate_size"; "/test"; "1000"];
3990        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3991    "truncate a file to a particular size",
3992    "\
3993 This command truncates C<path> to size C<size> bytes.  The file
3994 must exist already.
3995
3996 If the current file size is less than C<size> then
3997 the file is extended to the required size with zero bytes.
3998 This creates a sparse file (ie. disk blocks are not allocated
3999 for the file until you write to it).  To create a non-sparse
4000 file of zeroes, use C<guestfs_fallocate64> instead.");
4001
4002   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
4003    [InitBasicFS, Always, TestOutputStruct (
4004       [["touch"; "/test"];
4005        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
4006        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
4007    "set timestamp of a file with nanosecond precision",
4008    "\
4009 This command sets the timestamps of a file with nanosecond
4010 precision.
4011
4012 C<atsecs, atnsecs> are the last access time (atime) in secs and
4013 nanoseconds from the epoch.
4014
4015 C<mtsecs, mtnsecs> are the last modification time (mtime) in
4016 secs and nanoseconds from the epoch.
4017
4018 If the C<*nsecs> field contains the special value C<-1> then
4019 the corresponding timestamp is set to the current time.  (The
4020 C<*secs> field is ignored in this case).
4021
4022 If the C<*nsecs> field contains the special value C<-2> then
4023 the corresponding timestamp is left unchanged.  (The
4024 C<*secs> field is ignored in this case).");
4025
4026   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
4027    [InitBasicFS, Always, TestOutputStruct (
4028       [["mkdir_mode"; "/test"; "0o111"];
4029        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
4030    "create a directory with a particular mode",
4031    "\
4032 This command creates a directory, setting the initial permissions
4033 of the directory to C<mode>.
4034
4035 For common Linux filesystems, the actual mode which is set will
4036 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
4037 interpret the mode in other ways.
4038
4039 See also C<guestfs_mkdir>, C<guestfs_umask>");
4040
4041   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
4042    [], (* XXX *)
4043    "change file owner and group",
4044    "\
4045 Change the file owner to C<owner> and group to C<group>.
4046 This is like C<guestfs_chown> but if C<path> is a symlink then
4047 the link itself is changed, not the target.
4048
4049 Only numeric uid and gid are supported.  If you want to use
4050 names, you will need to locate and parse the password file
4051 yourself (Augeas support makes this relatively easy).");
4052
4053   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4054    [], (* XXX *)
4055    "lstat on multiple files",
4056    "\
4057 This call allows you to perform the C<guestfs_lstat> operation
4058 on multiple files, where all files are in the directory C<path>.
4059 C<names> is the list of files from this directory.
4060
4061 On return you get a list of stat structs, with a one-to-one
4062 correspondence to the C<names> list.  If any name did not exist
4063 or could not be lstat'd, then the C<ino> field of that structure
4064 is set to C<-1>.
4065
4066 This call is intended for programs that want to efficiently
4067 list a directory contents without making many round-trips.
4068 See also C<guestfs_lxattrlist> for a similarly efficient call
4069 for getting extended attributes.  Very long directory listings
4070 might cause the protocol message size to be exceeded, causing
4071 this call to fail.  The caller must split up such requests
4072 into smaller groups of names.");
4073
4074   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4075    [], (* XXX *)
4076    "lgetxattr on multiple files",
4077    "\
4078 This call allows you to get the extended attributes
4079 of multiple files, where all files are in the directory C<path>.
4080 C<names> is the list of files from this directory.
4081
4082 On return you get a flat list of xattr structs which must be
4083 interpreted sequentially.  The first xattr struct always has a zero-length
4084 C<attrname>.  C<attrval> in this struct is zero-length
4085 to indicate there was an error doing C<lgetxattr> for this
4086 file, I<or> is a C string which is a decimal number
4087 (the number of following attributes for this file, which could
4088 be C<\"0\">).  Then after the first xattr struct are the
4089 zero or more attributes for the first named file.
4090 This repeats for the second and subsequent files.
4091
4092 This call is intended for programs that want to efficiently
4093 list a directory contents without making many round-trips.
4094 See also C<guestfs_lstatlist> for a similarly efficient call
4095 for getting standard stats.  Very long directory listings
4096 might cause the protocol message size to be exceeded, causing
4097 this call to fail.  The caller must split up such requests
4098 into smaller groups of names.");
4099
4100   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4101    [], (* XXX *)
4102    "readlink on multiple files",
4103    "\
4104 This call allows you to do a C<readlink> operation
4105 on multiple files, where all files are in the directory C<path>.
4106 C<names> is the list of files from this directory.
4107
4108 On return you get a list of strings, with a one-to-one
4109 correspondence to the C<names> list.  Each string is the
4110 value of the symbolic link.
4111
4112 If the C<readlink(2)> operation fails on any name, then
4113 the corresponding result string is the empty string C<\"\">.
4114 However the whole operation is completed even if there
4115 were C<readlink(2)> errors, and so you can call this
4116 function with names where you don't know if they are
4117 symbolic links already (albeit slightly less efficient).
4118
4119 This call is intended for programs that want to efficiently
4120 list a directory contents without making many round-trips.
4121 Very long directory listings might cause the protocol
4122 message size to be exceeded, causing
4123 this call to fail.  The caller must split up such requests
4124 into smaller groups of names.");
4125
4126   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4127    [InitISOFS, Always, TestOutputBuffer (
4128       [["pread"; "/known-4"; "1"; "3"]], "\n");
4129     InitISOFS, Always, TestOutputBuffer (
4130       [["pread"; "/empty"; "0"; "100"]], "")],
4131    "read part of a file",
4132    "\
4133 This command lets you read part of a file.  It reads C<count>
4134 bytes of the file, starting at C<offset>, from file C<path>.
4135
4136 This may read fewer bytes than requested.  For further details
4137 see the L<pread(2)> system call.
4138
4139 See also C<guestfs_pwrite>.");
4140
4141   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4142    [InitEmpty, Always, TestRun (
4143       [["part_init"; "/dev/sda"; "gpt"]])],
4144    "create an empty partition table",
4145    "\
4146 This creates an empty partition table on C<device> of one of the
4147 partition types listed below.  Usually C<parttype> should be
4148 either C<msdos> or C<gpt> (for large disks).
4149
4150 Initially there are no partitions.  Following this, you should
4151 call C<guestfs_part_add> for each partition required.
4152
4153 Possible values for C<parttype> are:
4154
4155 =over 4
4156
4157 =item B<efi> | B<gpt>
4158
4159 Intel EFI / GPT partition table.
4160
4161 This is recommended for >= 2 TB partitions that will be accessed
4162 from Linux and Intel-based Mac OS X.  It also has limited backwards
4163 compatibility with the C<mbr> format.
4164
4165 =item B<mbr> | B<msdos>
4166
4167 The standard PC \"Master Boot Record\" (MBR) format used
4168 by MS-DOS and Windows.  This partition type will B<only> work
4169 for device sizes up to 2 TB.  For large disks we recommend
4170 using C<gpt>.
4171
4172 =back
4173
4174 Other partition table types that may work but are not
4175 supported include:
4176
4177 =over 4
4178
4179 =item B<aix>
4180
4181 AIX disk labels.
4182
4183 =item B<amiga> | B<rdb>
4184
4185 Amiga \"Rigid Disk Block\" format.
4186
4187 =item B<bsd>
4188
4189 BSD disk labels.
4190
4191 =item B<dasd>
4192
4193 DASD, used on IBM mainframes.
4194
4195 =item B<dvh>
4196
4197 MIPS/SGI volumes.
4198
4199 =item B<mac>
4200
4201 Old Mac partition format.  Modern Macs use C<gpt>.
4202
4203 =item B<pc98>
4204
4205 NEC PC-98 format, common in Japan apparently.
4206
4207 =item B<sun>
4208
4209 Sun disk labels.
4210
4211 =back");
4212
4213   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4214    [InitEmpty, Always, TestRun (
4215       [["part_init"; "/dev/sda"; "mbr"];
4216        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4217     InitEmpty, Always, TestRun (
4218       [["part_init"; "/dev/sda"; "gpt"];
4219        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4220        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4221     InitEmpty, Always, TestRun (
4222       [["part_init"; "/dev/sda"; "mbr"];
4223        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4224        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4225        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4226        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4227    "add a partition to the device",
4228    "\
4229 This command adds a partition to C<device>.  If there is no partition
4230 table on the device, call C<guestfs_part_init> first.
4231
4232 The C<prlogex> parameter is the type of partition.  Normally you
4233 should pass C<p> or C<primary> here, but MBR partition tables also
4234 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4235 types.
4236
4237 C<startsect> and C<endsect> are the start and end of the partition
4238 in I<sectors>.  C<endsect> may be negative, which means it counts
4239 backwards from the end of the disk (C<-1> is the last sector).
4240
4241 Creating a partition which covers the whole disk is not so easy.
4242 Use C<guestfs_part_disk> to do that.");
4243
4244   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4245    [InitEmpty, Always, TestRun (
4246       [["part_disk"; "/dev/sda"; "mbr"]]);
4247     InitEmpty, Always, TestRun (
4248       [["part_disk"; "/dev/sda"; "gpt"]])],
4249    "partition whole disk with a single primary partition",
4250    "\
4251 This command is simply a combination of C<guestfs_part_init>
4252 followed by C<guestfs_part_add> to create a single primary partition
4253 covering the whole disk.
4254
4255 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4256 but other possible values are described in C<guestfs_part_init>.");
4257
4258   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4259    [InitEmpty, Always, TestRun (
4260       [["part_disk"; "/dev/sda"; "mbr"];
4261        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4262    "make a partition bootable",
4263    "\
4264 This sets the bootable flag on partition numbered C<partnum> on
4265 device C<device>.  Note that partitions are numbered from 1.
4266
4267 The bootable flag is used by some operating systems (notably
4268 Windows) to determine which partition to boot from.  It is by
4269 no means universally recognized.");
4270
4271   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4272    [InitEmpty, Always, TestRun (
4273       [["part_disk"; "/dev/sda"; "gpt"];
4274        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4275    "set partition name",
4276    "\
4277 This sets the partition name on partition numbered C<partnum> on
4278 device C<device>.  Note that partitions are numbered from 1.
4279
4280 The partition name can only be set on certain types of partition
4281 table.  This works on C<gpt> but not on C<mbr> partitions.");
4282
4283   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4284    [], (* XXX Add a regression test for this. *)
4285    "list partitions on a device",
4286    "\
4287 This command parses the partition table on C<device> and
4288 returns the list of partitions found.
4289
4290 The fields in the returned structure are:
4291
4292 =over 4
4293
4294 =item B<part_num>
4295
4296 Partition number, counting from 1.
4297
4298 =item B<part_start>
4299
4300 Start of the partition I<in bytes>.  To get sectors you have to
4301 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4302
4303 =item B<part_end>
4304
4305 End of the partition in bytes.
4306
4307 =item B<part_size>
4308
4309 Size of the partition in bytes.
4310
4311 =back");
4312
4313   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4314    [InitEmpty, Always, TestOutput (
4315       [["part_disk"; "/dev/sda"; "gpt"];
4316        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4317    "get the partition table type",
4318    "\
4319 This command examines the partition table on C<device> and
4320 returns the partition table type (format) being used.
4321
4322 Common return values include: C<msdos> (a DOS/Windows style MBR
4323 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4324 values are possible, although unusual.  See C<guestfs_part_init>
4325 for a full list.");
4326
4327   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4328    [InitBasicFS, Always, TestOutputBuffer (
4329       [["fill"; "0x63"; "10"; "/test"];
4330        ["read_file"; "/test"]], "cccccccccc")],
4331    "fill a file with octets",
4332    "\
4333 This command creates a new file called C<path>.  The initial
4334 content of the file is C<len> octets of C<c>, where C<c>
4335 must be a number in the range C<[0..255]>.
4336
4337 To fill a file with zero bytes (sparsely), it is
4338 much more efficient to use C<guestfs_truncate_size>.
4339 To create a file with a pattern of repeating bytes
4340 use C<guestfs_fill_pattern>.");
4341
4342   ("available", (RErr, [StringList "groups"]), 216, [],
4343    [InitNone, Always, TestRun [["available"; ""]]],
4344    "test availability of some parts of the API",
4345    "\
4346 This command is used to check the availability of some
4347 groups of functionality in the appliance, which not all builds of
4348 the libguestfs appliance will be able to provide.
4349
4350 The libguestfs groups, and the functions that those
4351 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4352 You can also fetch this list at runtime by calling
4353 C<guestfs_available_all_groups>.
4354
4355 The argument C<groups> is a list of group names, eg:
4356 C<[\"inotify\", \"augeas\"]> would check for the availability of
4357 the Linux inotify functions and Augeas (configuration file
4358 editing) functions.
4359
4360 The command returns no error if I<all> requested groups are available.
4361
4362 It fails with an error if one or more of the requested
4363 groups is unavailable in the appliance.
4364
4365 If an unknown group name is included in the
4366 list of groups then an error is always returned.
4367
4368 I<Notes:>
4369
4370 =over 4
4371
4372 =item *
4373
4374 You must call C<guestfs_launch> before calling this function.
4375
4376 The reason is because we don't know what groups are
4377 supported by the appliance/daemon until it is running and can
4378 be queried.
4379
4380 =item *
4381
4382 If a group of functions is available, this does not necessarily
4383 mean that they will work.  You still have to check for errors
4384 when calling individual API functions even if they are
4385 available.
4386
4387 =item *
4388
4389 It is usually the job of distro packagers to build
4390 complete functionality into the libguestfs appliance.
4391 Upstream libguestfs, if built from source with all
4392 requirements satisfied, will support everything.
4393
4394 =item *
4395
4396 This call was added in version C<1.0.80>.  In previous
4397 versions of libguestfs all you could do would be to speculatively
4398 execute a command to find out if the daemon implemented it.
4399 See also C<guestfs_version>.
4400
4401 =back");
4402
4403   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4404    [InitBasicFS, Always, TestOutputBuffer (
4405       [["write"; "/src"; "hello, world"];
4406        ["dd"; "/src"; "/dest"];
4407        ["read_file"; "/dest"]], "hello, world")],
4408    "copy from source to destination using dd",
4409    "\
4410 This command copies from one source device or file C<src>
4411 to another destination device or file C<dest>.  Normally you
4412 would use this to copy to or from a device or partition, for
4413 example to duplicate a filesystem.
4414
4415 If the destination is a device, it must be as large or larger
4416 than the source file or device, otherwise the copy will fail.
4417 This command cannot do partial copies (see C<guestfs_copy_size>).");
4418
4419   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4420    [InitBasicFS, Always, TestOutputInt (
4421       [["write"; "/file"; "hello, world"];
4422        ["filesize"; "/file"]], 12)],
4423    "return the size of the file in bytes",
4424    "\
4425 This command returns the size of C<file> in bytes.
4426
4427 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4428 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4429 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4430
4431   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4432    [InitBasicFSonLVM, Always, TestOutputList (
4433       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4434        ["lvs"]], ["/dev/VG/LV2"])],
4435    "rename an LVM logical volume",
4436    "\
4437 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4438
4439   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4440    [InitBasicFSonLVM, Always, TestOutputList (
4441       [["umount"; "/"];
4442        ["vg_activate"; "false"; "VG"];
4443        ["vgrename"; "VG"; "VG2"];
4444        ["vg_activate"; "true"; "VG2"];
4445        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4446        ["vgs"]], ["VG2"])],
4447    "rename an LVM volume group",
4448    "\
4449 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4450
4451   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4452    [InitISOFS, Always, TestOutputBuffer (
4453       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4454    "list the contents of a single file in an initrd",
4455    "\
4456 This command unpacks the file C<filename> from the initrd file
4457 called C<initrdpath>.  The filename must be given I<without> the
4458 initial C</> character.
4459
4460 For example, in guestfish you could use the following command
4461 to examine the boot script (usually called C</init>)
4462 contained in a Linux initrd or initramfs image:
4463
4464  initrd-cat /boot/initrd-<version>.img init
4465
4466 See also C<guestfs_initrd_list>.");
4467
4468   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4469    [],
4470    "get the UUID of a physical volume",
4471    "\
4472 This command returns the UUID of the LVM PV C<device>.");
4473
4474   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4475    [],
4476    "get the UUID of a volume group",
4477    "\
4478 This command returns the UUID of the LVM VG named C<vgname>.");
4479
4480   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4481    [],
4482    "get the UUID of a logical volume",
4483    "\
4484 This command returns the UUID of the LVM LV C<device>.");
4485
4486   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4487    [],
4488    "get the PV UUIDs containing the volume group",
4489    "\
4490 Given a VG called C<vgname>, this returns the UUIDs of all
4491 the physical volumes that this volume group resides on.
4492
4493 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4494 calls to associate physical volumes and volume groups.
4495
4496 See also C<guestfs_vglvuuids>.");
4497
4498   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4499    [],
4500    "get the LV UUIDs of all LVs in the volume group",
4501    "\
4502 Given a VG called C<vgname>, this returns the UUIDs of all
4503 the logical volumes created in this volume group.
4504
4505 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4506 calls to associate logical volumes and volume groups.
4507
4508 See also C<guestfs_vgpvuuids>.");
4509
4510   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4511    [InitBasicFS, Always, TestOutputBuffer (
4512       [["write"; "/src"; "hello, world"];
4513        ["copy_size"; "/src"; "/dest"; "5"];
4514        ["read_file"; "/dest"]], "hello")],
4515    "copy size bytes from source to destination using dd",
4516    "\
4517 This command copies exactly C<size> bytes from one source device
4518 or file C<src> to another destination device or file C<dest>.
4519
4520 Note this will fail if the source is too short or if the destination
4521 is not large enough.");
4522
4523   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4524    [InitBasicFSonLVM, Always, TestRun (
4525       [["zero_device"; "/dev/VG/LV"]])],
4526    "write zeroes to an entire device",
4527    "\
4528 This command writes zeroes over the entire C<device>.  Compare
4529 with C<guestfs_zero> which just zeroes the first few blocks of
4530 a device.");
4531
4532   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4533    [InitBasicFS, Always, TestOutput (
4534       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4535        ["cat"; "/hello"]], "hello\n")],
4536    "unpack compressed tarball to directory",
4537    "\
4538 This command uploads and unpacks local file C<tarball> (an
4539 I<xz compressed> tar file) into C<directory>.");
4540
4541   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4542    [],
4543    "pack directory into compressed tarball",
4544    "\
4545 This command packs the contents of C<directory> and downloads
4546 it to local file C<tarball> (as an xz compressed tar archive).");
4547
4548   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4549    [],
4550    "resize an NTFS filesystem",
4551    "\
4552 This command resizes an NTFS filesystem, expanding or
4553 shrinking it to the size of the underlying device.
4554 See also L<ntfsresize(8)>.");
4555
4556   ("vgscan", (RErr, []), 232, [],
4557    [InitEmpty, Always, TestRun (
4558       [["vgscan"]])],
4559    "rescan for LVM physical volumes, volume groups and logical volumes",
4560    "\
4561 This rescans all block devices and rebuilds the list of LVM
4562 physical volumes, volume groups and logical volumes.");
4563
4564   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4565    [InitEmpty, Always, TestRun (
4566       [["part_init"; "/dev/sda"; "mbr"];
4567        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4568        ["part_del"; "/dev/sda"; "1"]])],
4569    "delete a partition",
4570    "\
4571 This command deletes the partition numbered C<partnum> on C<device>.
4572
4573 Note that in the case of MBR partitioning, deleting an
4574 extended partition also deletes any logical partitions
4575 it contains.");
4576
4577   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4578    [InitEmpty, Always, TestOutputTrue (
4579       [["part_init"; "/dev/sda"; "mbr"];
4580        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4581        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4582        ["part_get_bootable"; "/dev/sda"; "1"]])],
4583    "return true if a partition is bootable",
4584    "\
4585 This command returns true if the partition C<partnum> on
4586 C<device> has the bootable flag set.
4587
4588 See also C<guestfs_part_set_bootable>.");
4589
4590   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4591    [InitEmpty, Always, TestOutputInt (
4592       [["part_init"; "/dev/sda"; "mbr"];
4593        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4594        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4595        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4596    "get the MBR type byte (ID byte) from a partition",
4597    "\
4598 Returns the MBR type byte (also known as the ID byte) from
4599 the numbered partition C<partnum>.
4600
4601 Note that only MBR (old DOS-style) partitions have type bytes.
4602 You will get undefined results for other partition table
4603 types (see C<guestfs_part_get_parttype>).");
4604
4605   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4606    [], (* tested by part_get_mbr_id *)
4607    "set the MBR type byte (ID byte) of a partition",
4608    "\
4609 Sets the MBR type byte (also known as the ID byte) of
4610 the numbered partition C<partnum> to C<idbyte>.  Note
4611 that the type bytes quoted in most documentation are
4612 in fact hexadecimal numbers, but usually documented
4613 without any leading \"0x\" which might be confusing.
4614
4615 Note that only MBR (old DOS-style) partitions have type bytes.
4616 You will get undefined results for other partition table
4617 types (see C<guestfs_part_get_parttype>).");
4618
4619   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4620    [InitISOFS, Always, TestOutput (
4621       [["checksum_device"; "md5"; "/dev/sdd"]],
4622       (Digest.to_hex (Digest.file "images/test.iso")))],
4623    "compute MD5, SHAx or CRC checksum of the contents of a device",
4624    "\
4625 This call computes the MD5, SHAx or CRC checksum of the
4626 contents of the device named C<device>.  For the types of
4627 checksums supported see the C<guestfs_checksum> command.");
4628
4629   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4630    [InitNone, Always, TestRun (
4631       [["part_disk"; "/dev/sda"; "mbr"];
4632        ["pvcreate"; "/dev/sda1"];
4633        ["vgcreate"; "VG"; "/dev/sda1"];
4634        ["lvcreate"; "LV"; "VG"; "10"];
4635        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4636    "expand an LV to fill free space",
4637    "\
4638 This expands an existing logical volume C<lv> so that it fills
4639 C<pc>% of the remaining free space in the volume group.  Commonly
4640 you would call this with pc = 100 which expands the logical volume
4641 as much as possible, using all remaining free space in the volume
4642 group.");
4643
4644   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4645    [], (* XXX Augeas code needs tests. *)
4646    "clear Augeas path",
4647    "\
4648 Set the value associated with C<path> to C<NULL>.  This
4649 is the same as the L<augtool(1)> C<clear> command.");
4650
4651   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4652    [InitEmpty, Always, TestOutputInt (
4653       [["get_umask"]], 0o22)],
4654    "get the current umask",
4655    "\
4656 Return the current umask.  By default the umask is C<022>
4657 unless it has been set by calling C<guestfs_umask>.");
4658
4659   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4660    [],
4661    "upload a file to the appliance (internal use only)",
4662    "\
4663 The C<guestfs_debug_upload> command uploads a file to
4664 the libguestfs appliance.
4665
4666 There is no comprehensive help for this command.  You have
4667 to look at the file C<daemon/debug.c> in the libguestfs source
4668 to find out what it is for.");
4669
4670   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4671    [InitBasicFS, Always, TestOutput (
4672       [["base64_in"; "../images/hello.b64"; "/hello"];
4673        ["cat"; "/hello"]], "hello\n")],
4674    "upload base64-encoded data to file",
4675    "\
4676 This command uploads base64-encoded data from C<base64file>
4677 to C<filename>.");
4678
4679   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4680    [],
4681    "download file and encode as base64",
4682    "\
4683 This command downloads the contents of C<filename>, writing
4684 it out to local file C<base64file> encoded as base64.");
4685
4686   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4687    [],
4688    "compute MD5, SHAx or CRC checksum of files in a directory",
4689    "\
4690 This command computes the checksums of all regular files in
4691 C<directory> and then emits a list of those checksums to
4692 the local output file C<sumsfile>.
4693
4694 This can be used for verifying the integrity of a virtual
4695 machine.  However to be properly secure you should pay
4696 attention to the output of the checksum command (it uses
4697 the ones from GNU coreutils).  In particular when the
4698 filename is not printable, coreutils uses a special
4699 backslash syntax.  For more information, see the GNU
4700 coreutils info file.");
4701
4702   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4703    [InitBasicFS, Always, TestOutputBuffer (
4704       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4705        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4706    "fill a file with a repeating pattern of bytes",
4707    "\
4708 This function is like C<guestfs_fill> except that it creates
4709 a new file of length C<len> containing the repeating pattern
4710 of bytes in C<pattern>.  The pattern is truncated if necessary
4711 to ensure the length of the file is exactly C<len> bytes.");
4712
4713   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4714    [InitBasicFS, Always, TestOutput (
4715       [["write"; "/new"; "new file contents"];
4716        ["cat"; "/new"]], "new file contents");
4717     InitBasicFS, Always, TestOutput (
4718       [["write"; "/new"; "\nnew file contents\n"];
4719        ["cat"; "/new"]], "\nnew file contents\n");
4720     InitBasicFS, Always, TestOutput (
4721       [["write"; "/new"; "\n\n"];
4722        ["cat"; "/new"]], "\n\n");
4723     InitBasicFS, Always, TestOutput (
4724       [["write"; "/new"; ""];
4725        ["cat"; "/new"]], "");
4726     InitBasicFS, Always, TestOutput (
4727       [["write"; "/new"; "\n\n\n"];
4728        ["cat"; "/new"]], "\n\n\n");
4729     InitBasicFS, Always, TestOutput (
4730       [["write"; "/new"; "\n"];
4731        ["cat"; "/new"]], "\n")],
4732    "create a new file",
4733    "\
4734 This call creates a file called C<path>.  The content of the
4735 file is the string C<content> (which can contain any 8 bit data).");
4736
4737   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4738    [InitBasicFS, Always, TestOutput (
4739       [["write"; "/new"; "new file contents"];
4740        ["pwrite"; "/new"; "data"; "4"];
4741        ["cat"; "/new"]], "new data contents");
4742     InitBasicFS, Always, TestOutput (
4743       [["write"; "/new"; "new file contents"];
4744        ["pwrite"; "/new"; "is extended"; "9"];
4745        ["cat"; "/new"]], "new file is extended");
4746     InitBasicFS, Always, TestOutput (
4747       [["write"; "/new"; "new file contents"];
4748        ["pwrite"; "/new"; ""; "4"];
4749        ["cat"; "/new"]], "new file contents")],
4750    "write to part of a file",
4751    "\
4752 This command writes to part of a file.  It writes the data
4753 buffer C<content> to the file C<path> starting at offset C<offset>.
4754
4755 This command implements the L<pwrite(2)> system call, and like
4756 that system call it may not write the full data requested.  The
4757 return value is the number of bytes that were actually written
4758 to the file.  This could even be 0, although short writes are
4759 unlikely for regular files in ordinary circumstances.
4760
4761 See also C<guestfs_pread>.");
4762
4763   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4764    [],
4765    "resize an ext2, ext3 or ext4 filesystem (with size)",
4766    "\
4767 This command is the same as C<guestfs_resize2fs> except that it
4768 allows you to specify the new size (in bytes) explicitly.");
4769
4770   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4771    [],
4772    "resize an LVM physical volume (with size)",
4773    "\
4774 This command is the same as C<guestfs_pvresize> except that it
4775 allows you to specify the new size (in bytes) explicitly.");
4776
4777   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4778    [],
4779    "resize an NTFS filesystem (with size)",
4780    "\
4781 This command is the same as C<guestfs_ntfsresize> except that it
4782 allows you to specify the new size (in bytes) explicitly.");
4783
4784   ("available_all_groups", (RStringList "groups", []), 251, [],
4785    [InitNone, Always, TestRun [["available_all_groups"]]],
4786    "return a list of all optional groups",
4787    "\
4788 This command returns a list of all optional groups that this
4789 daemon knows about.  Note this returns both supported and unsupported
4790 groups.  To find out which ones the daemon can actually support
4791 you have to call C<guestfs_available> on each member of the
4792 returned list.
4793
4794 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4795
4796   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4797    [InitBasicFS, Always, TestOutputStruct (
4798       [["fallocate64"; "/a"; "1000000"];
4799        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4800    "preallocate a file in the guest filesystem",
4801    "\
4802 This command preallocates a file (containing zero bytes) named
4803 C<path> of size C<len> bytes.  If the file exists already, it
4804 is overwritten.
4805
4806 Note that this call allocates disk blocks for the file.
4807 To create a sparse file use C<guestfs_truncate_size> instead.
4808
4809 The deprecated call C<guestfs_fallocate> does the same,
4810 but owing to an oversight it only allowed 30 bit lengths
4811 to be specified, effectively limiting the maximum size
4812 of files created through that call to 1GB.
4813
4814 Do not confuse this with the guestfish-specific
4815 C<alloc> and C<sparse> commands which create
4816 a file in the host and attach it as a device.");
4817
4818   ("vfs_label", (RString "label", [Device "device"]), 253, [],
4819    [InitBasicFS, Always, TestOutput (
4820        [["set_e2label"; "/dev/sda1"; "LTEST"];
4821         ["vfs_label"; "/dev/sda1"]], "LTEST")],
4822    "get the filesystem label",
4823    "\
4824 This returns the filesystem label of the filesystem on
4825 C<device>.
4826
4827 If the filesystem is unlabeled, this returns the empty string.");
4828
4829   ("vfs_uuid", (RString "uuid", [Device "device"]), 254, [],
4830    (let uuid = uuidgen () in
4831     [InitBasicFS, Always, TestOutput (
4832        [["set_e2uuid"; "/dev/sda1"; uuid];
4833         ["vfs_uuid"; "/dev/sda1"]], uuid)]),
4834    "get the filesystem UUID",
4835    "\
4836 This returns the filesystem UUID of the filesystem on
4837 C<device>.
4838
4839 If the filesystem does not have a UUID, this returns the empty string.");
4840
4841   ("lvm_set_filter", (RErr, [DeviceList "devices"]), 255, [Optional "lvm2"],
4842    (* Can't be tested with the current framework because
4843     * the VG is being used by the mounted filesystem, so
4844     * the vgchange -an command we do first will fail.
4845     *)
4846     [],
4847    "set LVM device filter",
4848    "\
4849 This sets the LVM device filter so that LVM will only be
4850 able to \"see\" the block devices in the list C<devices>,
4851 and will ignore all other attached block devices.
4852
4853 Where disk image(s) contain duplicate PVs or VGs, this
4854 command is useful to get LVM to ignore the duplicates, otherwise
4855 LVM can get confused.  Note also there are two types
4856 of duplication possible: either cloned PVs/VGs which have
4857 identical UUIDs; or VGs that are not cloned but just happen
4858 to have the same name.  In normal operation you cannot
4859 create this situation, but you can do it outside LVM, eg.
4860 by cloning disk images or by bit twiddling inside the LVM
4861 metadata.
4862
4863 This command also clears the LVM cache and performs a volume
4864 group scan.
4865
4866 You can filter whole block devices or individual partitions.
4867
4868 You cannot use this if any VG is currently in use (eg.
4869 contains a mounted filesystem), even if you are not
4870 filtering out that VG.");
4871
4872   ("lvm_clear_filter", (RErr, []), 256, [],
4873    [], (* see note on lvm_set_filter *)
4874    "clear LVM device filter",
4875    "\
4876 This undoes the effect of C<guestfs_lvm_set_filter>.  LVM
4877 will be able to see every block device.
4878
4879 This command also clears the LVM cache and performs a volume
4880 group scan.");
4881
4882   ("luks_open", (RErr, [Device "device"; Key "key"; String "mapname"]), 257, [Optional "luks"],
4883    [],
4884    "open a LUKS-encrypted block device",
4885    "\
4886 This command opens a block device which has been encrypted
4887 according to the Linux Unified Key Setup (LUKS) standard.
4888
4889 C<device> is the encrypted block device or partition.
4890
4891 The caller must supply one of the keys associated with the
4892 LUKS block device, in the C<key> parameter.
4893
4894 This creates a new block device called C</dev/mapper/mapname>.
4895 Reads and writes to this block device are decrypted from and
4896 encrypted to the underlying C<device> respectively.
4897
4898 If this block device contains LVM volume groups, then
4899 calling C<guestfs_vgscan> followed by C<guestfs_vg_activate_all>
4900 will make them visible.");
4901
4902   ("luks_open_ro", (RErr, [Device "device"; Key "key"; String "mapname"]), 258, [Optional "luks"],
4903    [],
4904    "open a LUKS-encrypted block device read-only",
4905    "\
4906 This is the same as C<guestfs_luks_open> except that a read-only
4907 mapping is created.");
4908
4909   ("luks_close", (RErr, [Device "device"]), 259, [Optional "luks"],
4910    [],
4911    "close a LUKS device",
4912    "\
4913 This closes a LUKS device that was created earlier by
4914 C<guestfs_luks_open> or C<guestfs_luks_open_ro>.  The
4915 C<device> parameter must be the name of the LUKS mapping
4916 device (ie. C</dev/mapper/mapname>) and I<not> the name
4917 of the underlying block device.");
4918
4919   ("luks_format", (RErr, [Device "device"; Key "key"; Int "keyslot"]), 260, [Optional "luks"; DangerWillRobinson],
4920    [],
4921    "format a block device as a LUKS encrypted device",
4922    "\
4923 This command erases existing data on C<device> and formats
4924 the device as a LUKS encrypted device.  C<key> is the
4925 initial key, which is added to key slot C<slot>.  (LUKS
4926 supports 8 key slots, numbered 0-7).");
4927
4928   ("luks_format_cipher", (RErr, [Device "device"; Key "key"; Int "keyslot"; String "cipher"]), 261, [Optional "luks"; DangerWillRobinson],
4929    [],
4930    "format a block device as a LUKS encrypted device",
4931    "\
4932 This command is the same as C<guestfs_luks_format> but
4933 it also allows you to set the C<cipher> used.");
4934
4935   ("luks_add_key", (RErr, [Device "device"; Key "key"; Key "newkey"; Int "keyslot"]), 262, [Optional "luks"],
4936    [],
4937    "add a key on a LUKS encrypted device",
4938    "\
4939 This command adds a new key on LUKS device C<device>.
4940 C<key> is any existing key, and is used to access the device.
4941 C<newkey> is the new key to add.  C<keyslot> is the key slot
4942 that will be replaced.
4943
4944 Note that if C<keyslot> already contains a key, then this
4945 command will fail.  You have to use C<guestfs_luks_kill_slot>
4946 first to remove that key.");
4947
4948   ("luks_kill_slot", (RErr, [Device "device"; Key "key"; Int "keyslot"]), 263, [Optional "luks"],
4949    [],
4950    "remove a key from a LUKS encrypted device",
4951    "\
4952 This command deletes the key in key slot C<keyslot> from the
4953 encrypted LUKS device C<device>.  C<key> must be one of the
4954 I<other> keys.");
4955
4956 ]
4957
4958 let all_functions = non_daemon_functions @ daemon_functions
4959
4960 (* In some places we want the functions to be displayed sorted
4961  * alphabetically, so this is useful:
4962  *)
4963 let all_functions_sorted =
4964   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4965                compare n1 n2) all_functions
4966
4967 (* This is used to generate the src/MAX_PROC_NR file which
4968  * contains the maximum procedure number, a surrogate for the
4969  * ABI version number.  See src/Makefile.am for the details.
4970  *)
4971 let max_proc_nr =
4972   let proc_nrs = List.map (
4973     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4974   ) daemon_functions in
4975   List.fold_left max 0 proc_nrs
4976
4977 (* Field types for structures. *)
4978 type field =
4979   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4980   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4981   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4982   | FUInt32
4983   | FInt32
4984   | FUInt64
4985   | FInt64
4986   | FBytes                      (* Any int measure that counts bytes. *)
4987   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4988   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4989
4990 (* Because we generate extra parsing code for LVM command line tools,
4991  * we have to pull out the LVM columns separately here.
4992  *)
4993 let lvm_pv_cols = [
4994   "pv_name", FString;
4995   "pv_uuid", FUUID;
4996   "pv_fmt", FString;
4997   "pv_size", FBytes;
4998   "dev_size", FBytes;
4999   "pv_free", FBytes;
5000   "pv_used", FBytes;
5001   "pv_attr", FString (* XXX *);
5002   "pv_pe_count", FInt64;
5003   "pv_pe_alloc_count", FInt64;
5004   "pv_tags", FString;
5005   "pe_start", FBytes;
5006   "pv_mda_count", FInt64;
5007   "pv_mda_free", FBytes;
5008   (* Not in Fedora 10:
5009      "pv_mda_size", FBytes;
5010   *)
5011 ]
5012 let lvm_vg_cols = [
5013   "vg_name", FString;
5014   "vg_uuid", FUUID;
5015   "vg_fmt", FString;
5016   "vg_attr", FString (* XXX *);
5017   "vg_size", FBytes;
5018   "vg_free", FBytes;
5019   "vg_sysid", FString;
5020   "vg_extent_size", FBytes;
5021   "vg_extent_count", FInt64;
5022   "vg_free_count", FInt64;
5023   "max_lv", FInt64;
5024   "max_pv", FInt64;
5025   "pv_count", FInt64;
5026   "lv_count", FInt64;
5027   "snap_count", FInt64;
5028   "vg_seqno", FInt64;
5029   "vg_tags", FString;
5030   "vg_mda_count", FInt64;
5031   "vg_mda_free", FBytes;
5032   (* Not in Fedora 10:
5033      "vg_mda_size", FBytes;
5034   *)
5035 ]
5036 let lvm_lv_cols = [
5037   "lv_name", FString;
5038   "lv_uuid", FUUID;
5039   "lv_attr", FString (* XXX *);
5040   "lv_major", FInt64;
5041   "lv_minor", FInt64;
5042   "lv_kernel_major", FInt64;
5043   "lv_kernel_minor", FInt64;
5044   "lv_size", FBytes;
5045   "seg_count", FInt64;
5046   "origin", FString;
5047   "snap_percent", FOptPercent;
5048   "copy_percent", FOptPercent;
5049   "move_pv", FString;
5050   "lv_tags", FString;
5051   "mirror_log", FString;
5052   "modules", FString;
5053 ]
5054
5055 (* Names and fields in all structures (in RStruct and RStructList)
5056  * that we support.
5057  *)
5058 let structs = [
5059   (* The old RIntBool return type, only ever used for aug_defnode.  Do
5060    * not use this struct in any new code.
5061    *)
5062   "int_bool", [
5063     "i", FInt32;                (* for historical compatibility *)
5064     "b", FInt32;                (* for historical compatibility *)
5065   ];
5066
5067   (* LVM PVs, VGs, LVs. *)
5068   "lvm_pv", lvm_pv_cols;
5069   "lvm_vg", lvm_vg_cols;
5070   "lvm_lv", lvm_lv_cols;
5071
5072   (* Column names and types from stat structures.
5073    * NB. Can't use things like 'st_atime' because glibc header files
5074    * define some of these as macros.  Ugh.
5075    *)
5076   "stat", [
5077     "dev", FInt64;
5078     "ino", FInt64;
5079     "mode", FInt64;
5080     "nlink", FInt64;
5081     "uid", FInt64;
5082     "gid", FInt64;
5083     "rdev", FInt64;
5084     "size", FInt64;
5085     "blksize", FInt64;
5086     "blocks", FInt64;
5087     "atime", FInt64;
5088     "mtime", FInt64;
5089     "ctime", FInt64;
5090   ];
5091   "statvfs", [
5092     "bsize", FInt64;
5093     "frsize", FInt64;
5094     "blocks", FInt64;
5095     "bfree", FInt64;
5096     "bavail", FInt64;
5097     "files", FInt64;
5098     "ffree", FInt64;
5099     "favail", FInt64;
5100     "fsid", FInt64;
5101     "flag", FInt64;
5102     "namemax", FInt64;
5103   ];
5104
5105   (* Column names in dirent structure. *)
5106   "dirent", [
5107     "ino", FInt64;
5108     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
5109     "ftyp", FChar;
5110     "name", FString;
5111   ];
5112
5113   (* Version numbers. *)
5114   "version", [
5115     "major", FInt64;
5116     "minor", FInt64;
5117     "release", FInt64;
5118     "extra", FString;
5119   ];
5120
5121   (* Extended attribute. *)
5122   "xattr", [
5123     "attrname", FString;
5124     "attrval", FBuffer;
5125   ];
5126
5127   (* Inotify events. *)
5128   "inotify_event", [
5129     "in_wd", FInt64;
5130     "in_mask", FUInt32;
5131     "in_cookie", FUInt32;
5132     "in_name", FString;
5133   ];
5134
5135   (* Partition table entry. *)
5136   "partition", [
5137     "part_num", FInt32;
5138     "part_start", FBytes;
5139     "part_end", FBytes;
5140     "part_size", FBytes;
5141   ];
5142 ] (* end of structs *)
5143
5144 (* Ugh, Java has to be different ..
5145  * These names are also used by the Haskell bindings.
5146  *)
5147 let java_structs = [
5148   "int_bool", "IntBool";
5149   "lvm_pv", "PV";
5150   "lvm_vg", "VG";
5151   "lvm_lv", "LV";
5152   "stat", "Stat";
5153   "statvfs", "StatVFS";
5154   "dirent", "Dirent";
5155   "version", "Version";
5156   "xattr", "XAttr";
5157   "inotify_event", "INotifyEvent";
5158   "partition", "Partition";
5159 ]
5160
5161 (* What structs are actually returned. *)
5162 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
5163
5164 (* Returns a list of RStruct/RStructList structs that are returned
5165  * by any function.  Each element of returned list is a pair:
5166  *
5167  * (structname, RStructOnly)
5168  *    == there exists function which returns RStruct (_, structname)
5169  * (structname, RStructListOnly)
5170  *    == there exists function which returns RStructList (_, structname)
5171  * (structname, RStructAndList)
5172  *    == there are functions returning both RStruct (_, structname)
5173  *                                      and RStructList (_, structname)
5174  *)
5175 let rstructs_used_by functions =
5176   (* ||| is a "logical OR" for rstructs_used_t *)
5177   let (|||) a b =
5178     match a, b with
5179     | RStructAndList, _
5180     | _, RStructAndList -> RStructAndList
5181     | RStructOnly, RStructListOnly
5182     | RStructListOnly, RStructOnly -> RStructAndList
5183     | RStructOnly, RStructOnly -> RStructOnly
5184     | RStructListOnly, RStructListOnly -> RStructListOnly
5185   in
5186
5187   let h = Hashtbl.create 13 in
5188
5189   (* if elem->oldv exists, update entry using ||| operator,
5190    * else just add elem->newv to the hash
5191    *)
5192   let update elem newv =
5193     try  let oldv = Hashtbl.find h elem in
5194          Hashtbl.replace h elem (newv ||| oldv)
5195     with Not_found -> Hashtbl.add h elem newv
5196   in
5197
5198   List.iter (
5199     fun (_, style, _, _, _, _, _) ->
5200       match fst style with
5201       | RStruct (_, structname) -> update structname RStructOnly
5202       | RStructList (_, structname) -> update structname RStructListOnly
5203       | _ -> ()
5204   ) functions;
5205
5206   (* return key->values as a list of (key,value) *)
5207   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5208
5209 (* Used for testing language bindings. *)
5210 type callt =
5211   | CallString of string
5212   | CallOptString of string option
5213   | CallStringList of string list
5214   | CallInt of int
5215   | CallInt64 of int64
5216   | CallBool of bool
5217   | CallBuffer of string
5218
5219 (* Used to memoize the result of pod2text. *)
5220 let pod2text_memo_filename = "src/.pod2text.data"
5221 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5222   try
5223     let chan = open_in pod2text_memo_filename in
5224     let v = input_value chan in
5225     close_in chan;
5226     v
5227   with
5228     _ -> Hashtbl.create 13
5229 let pod2text_memo_updated () =
5230   let chan = open_out pod2text_memo_filename in
5231   output_value chan pod2text_memo;
5232   close_out chan
5233
5234 (* Useful functions.
5235  * Note we don't want to use any external OCaml libraries which
5236  * makes this a bit harder than it should be.
5237  *)
5238 module StringMap = Map.Make (String)
5239
5240 let failwithf fs = ksprintf failwith fs
5241
5242 let unique = let i = ref 0 in fun () -> incr i; !i
5243
5244 let replace_char s c1 c2 =
5245   let s2 = String.copy s in
5246   let r = ref false in
5247   for i = 0 to String.length s2 - 1 do
5248     if String.unsafe_get s2 i = c1 then (
5249       String.unsafe_set s2 i c2;
5250       r := true
5251     )
5252   done;
5253   if not !r then s else s2
5254
5255 let isspace c =
5256   c = ' '
5257   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5258
5259 let triml ?(test = isspace) str =
5260   let i = ref 0 in
5261   let n = ref (String.length str) in
5262   while !n > 0 && test str.[!i]; do
5263     decr n;
5264     incr i
5265   done;
5266   if !i = 0 then str
5267   else String.sub str !i !n
5268
5269 let trimr ?(test = isspace) str =
5270   let n = ref (String.length str) in
5271   while !n > 0 && test str.[!n-1]; do
5272     decr n
5273   done;
5274   if !n = String.length str then str
5275   else String.sub str 0 !n
5276
5277 let trim ?(test = isspace) str =
5278   trimr ~test (triml ~test str)
5279
5280 let rec find s sub =
5281   let len = String.length s in
5282   let sublen = String.length sub in
5283   let rec loop i =
5284     if i <= len-sublen then (
5285       let rec loop2 j =
5286         if j < sublen then (
5287           if s.[i+j] = sub.[j] then loop2 (j+1)
5288           else -1
5289         ) else
5290           i (* found *)
5291       in
5292       let r = loop2 0 in
5293       if r = -1 then loop (i+1) else r
5294     ) else
5295       -1 (* not found *)
5296   in
5297   loop 0
5298
5299 let rec replace_str s s1 s2 =
5300   let len = String.length s in
5301   let sublen = String.length s1 in
5302   let i = find s s1 in
5303   if i = -1 then s
5304   else (
5305     let s' = String.sub s 0 i in
5306     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5307     s' ^ s2 ^ replace_str s'' s1 s2
5308   )
5309
5310 let rec string_split sep str =
5311   let len = String.length str in
5312   let seplen = String.length sep in
5313   let i = find str sep in
5314   if i = -1 then [str]
5315   else (
5316     let s' = String.sub str 0 i in
5317     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5318     s' :: string_split sep s''
5319   )
5320
5321 let files_equal n1 n2 =
5322   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5323   match Sys.command cmd with
5324   | 0 -> true
5325   | 1 -> false
5326   | i -> failwithf "%s: failed with error code %d" cmd i
5327
5328 let rec filter_map f = function
5329   | [] -> []
5330   | x :: xs ->
5331       match f x with
5332       | Some y -> y :: filter_map f xs
5333       | None -> filter_map f xs
5334
5335 let rec find_map f = function
5336   | [] -> raise Not_found
5337   | x :: xs ->
5338       match f x with
5339       | Some y -> y
5340       | None -> find_map f xs
5341
5342 let iteri f xs =
5343   let rec loop i = function
5344     | [] -> ()
5345     | x :: xs -> f i x; loop (i+1) xs
5346   in
5347   loop 0 xs
5348
5349 let mapi f xs =
5350   let rec loop i = function
5351     | [] -> []
5352     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5353   in
5354   loop 0 xs
5355
5356 let count_chars c str =
5357   let count = ref 0 in
5358   for i = 0 to String.length str - 1 do
5359     if c = String.unsafe_get str i then incr count
5360   done;
5361   !count
5362
5363 let explode str =
5364   let r = ref [] in
5365   for i = 0 to String.length str - 1 do
5366     let c = String.unsafe_get str i in
5367     r := c :: !r;
5368   done;
5369   List.rev !r
5370
5371 let map_chars f str =
5372   List.map f (explode str)
5373
5374 let name_of_argt = function
5375   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5376   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5377   | FileIn n | FileOut n | BufferIn n | Key n -> n
5378
5379 let java_name_of_struct typ =
5380   try List.assoc typ java_structs
5381   with Not_found ->
5382     failwithf
5383       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5384
5385 let cols_of_struct typ =
5386   try List.assoc typ structs
5387   with Not_found ->
5388     failwithf "cols_of_struct: unknown struct %s" typ
5389
5390 let seq_of_test = function
5391   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5392   | TestOutputListOfDevices (s, _)
5393   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5394   | TestOutputTrue s | TestOutputFalse s
5395   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5396   | TestOutputStruct (s, _)
5397   | TestLastFail s -> s
5398
5399 (* Handling for function flags. *)
5400 let protocol_limit_warning =
5401   "Because of the message protocol, there is a transfer limit
5402 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5403
5404 let danger_will_robinson =
5405   "B<This command is dangerous.  Without careful use you
5406 can easily destroy all your data>."
5407
5408 let deprecation_notice flags =
5409   try
5410     let alt =
5411       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5412     let txt =
5413       sprintf "This function is deprecated.
5414 In new code, use the C<%s> call instead.
5415
5416 Deprecated functions will not be removed from the API, but the
5417 fact that they are deprecated indicates that there are problems
5418 with correct use of these functions." alt in
5419     Some txt
5420   with
5421     Not_found -> None
5422
5423 (* Create list of optional groups. *)
5424 let optgroups =
5425   let h = Hashtbl.create 13 in
5426   List.iter (
5427     fun (name, _, _, flags, _, _, _) ->
5428       List.iter (
5429         function
5430         | Optional group ->
5431             let names = try Hashtbl.find h group with Not_found -> [] in
5432             Hashtbl.replace h group (name :: names)
5433         | _ -> ()
5434       ) flags
5435   ) daemon_functions;
5436   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5437   let groups =
5438     List.map (
5439       fun group -> group, List.sort compare (Hashtbl.find h group)
5440     ) groups in
5441   List.sort (fun x y -> compare (fst x) (fst y)) groups
5442
5443 (* Check function names etc. for consistency. *)
5444 let check_functions () =
5445   let contains_uppercase str =
5446     let len = String.length str in
5447     let rec loop i =
5448       if i >= len then false
5449       else (
5450         let c = str.[i] in
5451         if c >= 'A' && c <= 'Z' then true
5452         else loop (i+1)
5453       )
5454     in
5455     loop 0
5456   in
5457
5458   (* Check function names. *)
5459   List.iter (
5460     fun (name, _, _, _, _, _, _) ->
5461       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5462         failwithf "function name %s does not need 'guestfs' prefix" name;
5463       if name = "" then
5464         failwithf "function name is empty";
5465       if name.[0] < 'a' || name.[0] > 'z' then
5466         failwithf "function name %s must start with lowercase a-z" name;
5467       if String.contains name '-' then
5468         failwithf "function name %s should not contain '-', use '_' instead."
5469           name
5470   ) all_functions;
5471
5472   (* Check function parameter/return names. *)
5473   List.iter (
5474     fun (name, style, _, _, _, _, _) ->
5475       let check_arg_ret_name n =
5476         if contains_uppercase n then
5477           failwithf "%s param/ret %s should not contain uppercase chars"
5478             name n;
5479         if String.contains n '-' || String.contains n '_' then
5480           failwithf "%s param/ret %s should not contain '-' or '_'"
5481             name n;
5482         if n = "value" then
5483           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;
5484         if n = "int" || n = "char" || n = "short" || n = "long" then
5485           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5486         if n = "i" || n = "n" then
5487           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5488         if n = "argv" || n = "args" then
5489           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5490
5491         (* List Haskell, OCaml and C keywords here.
5492          * http://www.haskell.org/haskellwiki/Keywords
5493          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5494          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5495          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5496          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5497          * Omitting _-containing words, since they're handled above.
5498          * Omitting the OCaml reserved word, "val", is ok,
5499          * and saves us from renaming several parameters.
5500          *)
5501         let reserved = [
5502           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5503           "char"; "class"; "const"; "constraint"; "continue"; "data";
5504           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5505           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5506           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5507           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5508           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5509           "interface";
5510           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5511           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5512           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5513           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5514           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5515           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5516           "volatile"; "when"; "where"; "while";
5517           ] in
5518         if List.mem n reserved then
5519           failwithf "%s has param/ret using reserved word %s" name n;
5520       in
5521
5522       (match fst style with
5523        | RErr -> ()
5524        | RInt n | RInt64 n | RBool n
5525        | RConstString n | RConstOptString n | RString n
5526        | RStringList n | RStruct (n, _) | RStructList (n, _)
5527        | RHashtable n | RBufferOut n ->
5528            check_arg_ret_name n
5529       );
5530       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5531   ) all_functions;
5532
5533   (* Check short descriptions. *)
5534   List.iter (
5535     fun (name, _, _, _, _, shortdesc, _) ->
5536       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5537         failwithf "short description of %s should begin with lowercase." name;
5538       let c = shortdesc.[String.length shortdesc-1] in
5539       if c = '\n' || c = '.' then
5540         failwithf "short description of %s should not end with . or \\n." name
5541   ) all_functions;
5542
5543   (* Check long descriptions. *)
5544   List.iter (
5545     fun (name, _, _, _, _, _, longdesc) ->
5546       if longdesc.[String.length longdesc-1] = '\n' then
5547         failwithf "long description of %s should not end with \\n." name
5548   ) all_functions;
5549
5550   (* Check proc_nrs. *)
5551   List.iter (
5552     fun (name, _, proc_nr, _, _, _, _) ->
5553       if proc_nr <= 0 then
5554         failwithf "daemon function %s should have proc_nr > 0" name
5555   ) daemon_functions;
5556
5557   List.iter (
5558     fun (name, _, proc_nr, _, _, _, _) ->
5559       if proc_nr <> -1 then
5560         failwithf "non-daemon function %s should have proc_nr -1" name
5561   ) non_daemon_functions;
5562
5563   let proc_nrs =
5564     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5565       daemon_functions in
5566   let proc_nrs =
5567     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5568   let rec loop = function
5569     | [] -> ()
5570     | [_] -> ()
5571     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5572         loop rest
5573     | (name1,nr1) :: (name2,nr2) :: _ ->
5574         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5575           name1 name2 nr1 nr2
5576   in
5577   loop proc_nrs;
5578
5579   (* Check tests. *)
5580   List.iter (
5581     function
5582       (* Ignore functions that have no tests.  We generate a
5583        * warning when the user does 'make check' instead.
5584        *)
5585     | name, _, _, _, [], _, _ -> ()
5586     | name, _, _, _, tests, _, _ ->
5587         let funcs =
5588           List.map (
5589             fun (_, _, test) ->
5590               match seq_of_test test with
5591               | [] ->
5592                   failwithf "%s has a test containing an empty sequence" name
5593               | cmds -> List.map List.hd cmds
5594           ) tests in
5595         let funcs = List.flatten funcs in
5596
5597         let tested = List.mem name funcs in
5598
5599         if not tested then
5600           failwithf "function %s has tests but does not test itself" name
5601   ) all_functions
5602
5603 (* 'pr' prints to the current output file. *)
5604 let chan = ref Pervasives.stdout
5605 let lines = ref 0
5606 let pr fs =
5607   ksprintf
5608     (fun str ->
5609        let i = count_chars '\n' str in
5610        lines := !lines + i;
5611        output_string !chan str
5612     ) fs
5613
5614 let copyright_years =
5615   let this_year = 1900 + (localtime (time ())).tm_year in
5616   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5617
5618 (* Generate a header block in a number of standard styles. *)
5619 type comment_style =
5620     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5621 type license = GPLv2plus | LGPLv2plus
5622
5623 let generate_header ?(extra_inputs = []) comment license =
5624   let inputs = "src/generator.ml" :: extra_inputs in
5625   let c = match comment with
5626     | CStyle ->         pr "/* "; " *"
5627     | CPlusPlusStyle -> pr "// "; "//"
5628     | HashStyle ->      pr "# ";  "#"
5629     | OCamlStyle ->     pr "(* "; " *"
5630     | HaskellStyle ->   pr "{- "; "  " in
5631   pr "libguestfs generated file\n";
5632   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5633   List.iter (pr "%s   %s\n" c) inputs;
5634   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5635   pr "%s\n" c;
5636   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5637   pr "%s\n" c;
5638   (match license with
5639    | GPLv2plus ->
5640        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5641        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5642        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5643        pr "%s (at your option) any later version.\n" c;
5644        pr "%s\n" c;
5645        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5646        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5647        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5648        pr "%s GNU General Public License for more details.\n" c;
5649        pr "%s\n" c;
5650        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5651        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5652        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5653
5654    | LGPLv2plus ->
5655        pr "%s This library is free software; you can redistribute it and/or\n" c;
5656        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5657        pr "%s License as published by the Free Software Foundation; either\n" c;
5658        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5659        pr "%s\n" c;
5660        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5661        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5662        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5663        pr "%s Lesser General Public License for more details.\n" c;
5664        pr "%s\n" c;
5665        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5666        pr "%s License along with this library; if not, write to the Free Software\n" c;
5667        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5668   );
5669   (match comment with
5670    | CStyle -> pr " */\n"
5671    | CPlusPlusStyle
5672    | HashStyle -> ()
5673    | OCamlStyle -> pr " *)\n"
5674    | HaskellStyle -> pr "-}\n"
5675   );
5676   pr "\n"
5677
5678 (* Start of main code generation functions below this line. *)
5679
5680 (* Generate the pod documentation for the C API. *)
5681 let rec generate_actions_pod () =
5682   List.iter (
5683     fun (shortname, style, _, flags, _, _, longdesc) ->
5684       if not (List.mem NotInDocs flags) then (
5685         let name = "guestfs_" ^ shortname in
5686         pr "=head2 %s\n\n" name;
5687         pr " ";
5688         generate_prototype ~extern:false ~handle:"g" name style;
5689         pr "\n\n";
5690         pr "%s\n\n" longdesc;
5691         (match fst style with
5692          | RErr ->
5693              pr "This function returns 0 on success or -1 on error.\n\n"
5694          | RInt _ ->
5695              pr "On error this function returns -1.\n\n"
5696          | RInt64 _ ->
5697              pr "On error this function returns -1.\n\n"
5698          | RBool _ ->
5699              pr "This function returns a C truth value on success or -1 on error.\n\n"
5700          | RConstString _ ->
5701              pr "This function returns a string, or NULL on error.
5702 The string is owned by the guest handle and must I<not> be freed.\n\n"
5703          | RConstOptString _ ->
5704              pr "This function returns a string which may be NULL.
5705 There is way to return an error from this function.
5706 The string is owned by the guest handle and must I<not> be freed.\n\n"
5707          | RString _ ->
5708              pr "This function returns a string, or NULL on error.
5709 I<The caller must free the returned string after use>.\n\n"
5710          | RStringList _ ->
5711              pr "This function returns a NULL-terminated array of strings
5712 (like L<environ(3)>), or NULL if there was an error.
5713 I<The caller must free the strings and the array after use>.\n\n"
5714          | RStruct (_, typ) ->
5715              pr "This function returns a C<struct guestfs_%s *>,
5716 or NULL if there was an error.
5717 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5718          | RStructList (_, typ) ->
5719              pr "This function returns a C<struct guestfs_%s_list *>
5720 (see E<lt>guestfs-structs.hE<gt>),
5721 or NULL if there was an error.
5722 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5723          | RHashtable _ ->
5724              pr "This function returns a NULL-terminated array of
5725 strings, or NULL if there was an error.
5726 The array of strings will always have length C<2n+1>, where
5727 C<n> keys and values alternate, followed by the trailing NULL entry.
5728 I<The caller must free the strings and the array after use>.\n\n"
5729          | RBufferOut _ ->
5730              pr "This function returns a buffer, or NULL on error.
5731 The size of the returned buffer is written to C<*size_r>.
5732 I<The caller must free the returned buffer after use>.\n\n"
5733         );
5734         if List.mem ProtocolLimitWarning flags then
5735           pr "%s\n\n" protocol_limit_warning;
5736         if List.mem DangerWillRobinson flags then
5737           pr "%s\n\n" danger_will_robinson;
5738         if List.exists (function Key _ -> true | _ -> false) (snd style) then
5739           pr "This function takes a key or passphrase parameter which
5740 could contain sensitive material.  Read the section
5741 L</KEYS AND PASSPHRASES> for more information.\n\n";
5742         match deprecation_notice flags with
5743         | None -> ()
5744         | Some txt -> pr "%s\n\n" txt
5745       )
5746   ) all_functions_sorted
5747
5748 and generate_structs_pod () =
5749   (* Structs documentation. *)
5750   List.iter (
5751     fun (typ, cols) ->
5752       pr "=head2 guestfs_%s\n" typ;
5753       pr "\n";
5754       pr " struct guestfs_%s {\n" typ;
5755       List.iter (
5756         function
5757         | name, FChar -> pr "   char %s;\n" name
5758         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5759         | name, FInt32 -> pr "   int32_t %s;\n" name
5760         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5761         | name, FInt64 -> pr "   int64_t %s;\n" name
5762         | name, FString -> pr "   char *%s;\n" name
5763         | name, FBuffer ->
5764             pr "   /* The next two fields describe a byte array. */\n";
5765             pr "   uint32_t %s_len;\n" name;
5766             pr "   char *%s;\n" name
5767         | name, FUUID ->
5768             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5769             pr "   char %s[32];\n" name
5770         | name, FOptPercent ->
5771             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5772             pr "   float %s;\n" name
5773       ) cols;
5774       pr " };\n";
5775       pr " \n";
5776       pr " struct guestfs_%s_list {\n" typ;
5777       pr "   uint32_t len; /* Number of elements in list. */\n";
5778       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5779       pr " };\n";
5780       pr " \n";
5781       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5782       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5783         typ typ;
5784       pr "\n"
5785   ) structs
5786
5787 and generate_availability_pod () =
5788   (* Availability documentation. *)
5789   pr "=over 4\n";
5790   pr "\n";
5791   List.iter (
5792     fun (group, functions) ->
5793       pr "=item B<%s>\n" group;
5794       pr "\n";
5795       pr "The following functions:\n";
5796       List.iter (pr "L</guestfs_%s>\n") functions;
5797       pr "\n"
5798   ) optgroups;
5799   pr "=back\n";
5800   pr "\n"
5801
5802 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5803  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5804  *
5805  * We have to use an underscore instead of a dash because otherwise
5806  * rpcgen generates incorrect code.
5807  *
5808  * This header is NOT exported to clients, but see also generate_structs_h.
5809  *)
5810 and generate_xdr () =
5811   generate_header CStyle LGPLv2plus;
5812
5813   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5814   pr "typedef string str<>;\n";
5815   pr "\n";
5816
5817   (* Internal structures. *)
5818   List.iter (
5819     function
5820     | typ, cols ->
5821         pr "struct guestfs_int_%s {\n" typ;
5822         List.iter (function
5823                    | name, FChar -> pr "  char %s;\n" name
5824                    | name, FString -> pr "  string %s<>;\n" name
5825                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5826                    | name, FUUID -> pr "  opaque %s[32];\n" name
5827                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5828                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5829                    | name, FOptPercent -> pr "  float %s;\n" name
5830                   ) cols;
5831         pr "};\n";
5832         pr "\n";
5833         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5834         pr "\n";
5835   ) structs;
5836
5837   List.iter (
5838     fun (shortname, style, _, _, _, _, _) ->
5839       let name = "guestfs_" ^ shortname in
5840
5841       (match snd style with
5842        | [] -> ()
5843        | args ->
5844            pr "struct %s_args {\n" name;
5845            List.iter (
5846              function
5847              | Pathname n | Device n | Dev_or_Path n | String n | Key n ->
5848                  pr "  string %s<>;\n" n
5849              | OptString n -> pr "  str *%s;\n" n
5850              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5851              | Bool n -> pr "  bool %s;\n" n
5852              | Int n -> pr "  int %s;\n" n
5853              | Int64 n -> pr "  hyper %s;\n" n
5854              | BufferIn n ->
5855                  pr "  opaque %s<>;\n" n
5856              | FileIn _ | FileOut _ -> ()
5857            ) args;
5858            pr "};\n\n"
5859       );
5860       (match fst style with
5861        | RErr -> ()
5862        | RInt n ->
5863            pr "struct %s_ret {\n" name;
5864            pr "  int %s;\n" n;
5865            pr "};\n\n"
5866        | RInt64 n ->
5867            pr "struct %s_ret {\n" name;
5868            pr "  hyper %s;\n" n;
5869            pr "};\n\n"
5870        | RBool n ->
5871            pr "struct %s_ret {\n" name;
5872            pr "  bool %s;\n" n;
5873            pr "};\n\n"
5874        | RConstString _ | RConstOptString _ ->
5875            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5876        | RString n ->
5877            pr "struct %s_ret {\n" name;
5878            pr "  string %s<>;\n" n;
5879            pr "};\n\n"
5880        | RStringList n ->
5881            pr "struct %s_ret {\n" name;
5882            pr "  str %s<>;\n" n;
5883            pr "};\n\n"
5884        | RStruct (n, typ) ->
5885            pr "struct %s_ret {\n" name;
5886            pr "  guestfs_int_%s %s;\n" typ n;
5887            pr "};\n\n"
5888        | RStructList (n, typ) ->
5889            pr "struct %s_ret {\n" name;
5890            pr "  guestfs_int_%s_list %s;\n" typ n;
5891            pr "};\n\n"
5892        | RHashtable n ->
5893            pr "struct %s_ret {\n" name;
5894            pr "  str %s<>;\n" n;
5895            pr "};\n\n"
5896        | RBufferOut n ->
5897            pr "struct %s_ret {\n" name;
5898            pr "  opaque %s<>;\n" n;
5899            pr "};\n\n"
5900       );
5901   ) daemon_functions;
5902
5903   (* Table of procedure numbers. *)
5904   pr "enum guestfs_procedure {\n";
5905   List.iter (
5906     fun (shortname, _, proc_nr, _, _, _, _) ->
5907       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5908   ) daemon_functions;
5909   pr "  GUESTFS_PROC_NR_PROCS\n";
5910   pr "};\n";
5911   pr "\n";
5912
5913   (* Having to choose a maximum message size is annoying for several
5914    * reasons (it limits what we can do in the API), but it (a) makes
5915    * the protocol a lot simpler, and (b) provides a bound on the size
5916    * of the daemon which operates in limited memory space.
5917    *)
5918   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5919   pr "\n";
5920
5921   (* Message header, etc. *)
5922   pr "\
5923 /* The communication protocol is now documented in the guestfs(3)
5924  * manpage.
5925  */
5926
5927 const GUESTFS_PROGRAM = 0x2000F5F5;
5928 const GUESTFS_PROTOCOL_VERSION = 1;
5929
5930 /* These constants must be larger than any possible message length. */
5931 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5932 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5933
5934 enum guestfs_message_direction {
5935   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5936   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5937 };
5938
5939 enum guestfs_message_status {
5940   GUESTFS_STATUS_OK = 0,
5941   GUESTFS_STATUS_ERROR = 1
5942 };
5943
5944 const GUESTFS_ERROR_LEN = 256;
5945
5946 struct guestfs_message_error {
5947   string error_message<GUESTFS_ERROR_LEN>;
5948 };
5949
5950 struct guestfs_message_header {
5951   unsigned prog;                     /* GUESTFS_PROGRAM */
5952   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5953   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5954   guestfs_message_direction direction;
5955   unsigned serial;                   /* message serial number */
5956   guestfs_message_status status;
5957 };
5958
5959 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5960
5961 struct guestfs_chunk {
5962   int cancel;                        /* if non-zero, transfer is cancelled */
5963   /* data size is 0 bytes if the transfer has finished successfully */
5964   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5965 };
5966 "
5967
5968 (* Generate the guestfs-structs.h file. *)
5969 and generate_structs_h () =
5970   generate_header CStyle LGPLv2plus;
5971
5972   (* This is a public exported header file containing various
5973    * structures.  The structures are carefully written to have
5974    * exactly the same in-memory format as the XDR structures that
5975    * we use on the wire to the daemon.  The reason for creating
5976    * copies of these structures here is just so we don't have to
5977    * export the whole of guestfs_protocol.h (which includes much
5978    * unrelated and XDR-dependent stuff that we don't want to be
5979    * public, or required by clients).
5980    *
5981    * To reiterate, we will pass these structures to and from the
5982    * client with a simple assignment or memcpy, so the format
5983    * must be identical to what rpcgen / the RFC defines.
5984    *)
5985
5986   (* Public structures. *)
5987   List.iter (
5988     fun (typ, cols) ->
5989       pr "struct guestfs_%s {\n" typ;
5990       List.iter (
5991         function
5992         | name, FChar -> pr "  char %s;\n" name
5993         | name, FString -> pr "  char *%s;\n" name
5994         | name, FBuffer ->
5995             pr "  uint32_t %s_len;\n" name;
5996             pr "  char *%s;\n" name
5997         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5998         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5999         | name, FInt32 -> pr "  int32_t %s;\n" name
6000         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
6001         | name, FInt64 -> pr "  int64_t %s;\n" name
6002         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
6003       ) cols;
6004       pr "};\n";
6005       pr "\n";
6006       pr "struct guestfs_%s_list {\n" typ;
6007       pr "  uint32_t len;\n";
6008       pr "  struct guestfs_%s *val;\n" typ;
6009       pr "};\n";
6010       pr "\n";
6011       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
6012       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
6013       pr "\n"
6014   ) structs
6015
6016 (* Generate the guestfs-actions.h file. *)
6017 and generate_actions_h () =
6018   generate_header CStyle LGPLv2plus;
6019   List.iter (
6020     fun (shortname, style, _, _, _, _, _) ->
6021       let name = "guestfs_" ^ shortname in
6022       generate_prototype ~single_line:true ~newline:true ~handle:"g"
6023         name style
6024   ) all_functions
6025
6026 (* Generate the guestfs-internal-actions.h file. *)
6027 and generate_internal_actions_h () =
6028   generate_header CStyle LGPLv2plus;
6029   List.iter (
6030     fun (shortname, style, _, _, _, _, _) ->
6031       let name = "guestfs__" ^ shortname in
6032       generate_prototype ~single_line:true ~newline:true ~handle:"g"
6033         name style
6034   ) non_daemon_functions
6035
6036 (* Generate the client-side dispatch stubs. *)
6037 and generate_client_actions () =
6038   generate_header CStyle LGPLv2plus;
6039
6040   pr "\
6041 #include <stdio.h>
6042 #include <stdlib.h>
6043 #include <stdint.h>
6044 #include <string.h>
6045 #include <inttypes.h>
6046
6047 #include \"guestfs.h\"
6048 #include \"guestfs-internal.h\"
6049 #include \"guestfs-internal-actions.h\"
6050 #include \"guestfs_protocol.h\"
6051
6052 #define error guestfs_error
6053 //#define perrorf guestfs_perrorf
6054 #define safe_malloc guestfs_safe_malloc
6055 #define safe_realloc guestfs_safe_realloc
6056 //#define safe_strdup guestfs_safe_strdup
6057 #define safe_memdup guestfs_safe_memdup
6058
6059 /* Check the return message from a call for validity. */
6060 static int
6061 check_reply_header (guestfs_h *g,
6062                     const struct guestfs_message_header *hdr,
6063                     unsigned int proc_nr, unsigned int serial)
6064 {
6065   if (hdr->prog != GUESTFS_PROGRAM) {
6066     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
6067     return -1;
6068   }
6069   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
6070     error (g, \"wrong protocol version (%%d/%%d)\",
6071            hdr->vers, GUESTFS_PROTOCOL_VERSION);
6072     return -1;
6073   }
6074   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
6075     error (g, \"unexpected message direction (%%d/%%d)\",
6076            hdr->direction, GUESTFS_DIRECTION_REPLY);
6077     return -1;
6078   }
6079   if (hdr->proc != proc_nr) {
6080     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
6081     return -1;
6082   }
6083   if (hdr->serial != serial) {
6084     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
6085     return -1;
6086   }
6087
6088   return 0;
6089 }
6090
6091 /* Check we are in the right state to run a high-level action. */
6092 static int
6093 check_state (guestfs_h *g, const char *caller)
6094 {
6095   if (!guestfs__is_ready (g)) {
6096     if (guestfs__is_config (g) || guestfs__is_launching (g))
6097       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
6098         caller);
6099     else
6100       error (g, \"%%s called from the wrong state, %%d != READY\",
6101         caller, guestfs__get_state (g));
6102     return -1;
6103   }
6104   return 0;
6105 }
6106
6107 ";
6108
6109   let error_code_of = function
6110     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
6111     | RConstString _ | RConstOptString _
6112     | RString _ | RStringList _
6113     | RStruct _ | RStructList _
6114     | RHashtable _ | RBufferOut _ -> "NULL"
6115   in
6116
6117   (* Generate code to check String-like parameters are not passed in
6118    * as NULL (returning an error if they are).
6119    *)
6120   let check_null_strings shortname style =
6121     let pr_newline = ref false in
6122     List.iter (
6123       function
6124       (* parameters which should not be NULL *)
6125       | String n
6126       | Device n
6127       | Pathname n
6128       | Dev_or_Path n
6129       | FileIn n
6130       | FileOut n
6131       | BufferIn n
6132       | StringList n
6133       | DeviceList n
6134       | Key n ->
6135           pr "  if (%s == NULL) {\n" n;
6136           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
6137           pr "           \"%s\", \"%s\");\n" shortname n;
6138           pr "    return %s;\n" (error_code_of (fst style));
6139           pr "  }\n";
6140           pr_newline := true
6141
6142       (* can be NULL *)
6143       | OptString _
6144
6145       (* not applicable *)
6146       | Bool _
6147       | Int _
6148       | Int64 _ -> ()
6149     ) (snd style);
6150
6151     if !pr_newline then pr "\n";
6152   in
6153
6154   (* Generate code to generate guestfish call traces. *)
6155   let trace_call shortname style =
6156     pr "  if (guestfs__get_trace (g)) {\n";
6157
6158     let needs_i =
6159       List.exists (function
6160                    | StringList _ | DeviceList _ -> true
6161                    | _ -> false) (snd style) in
6162     if needs_i then (
6163       pr "    size_t i;\n";
6164       pr "\n"
6165     );
6166
6167     pr "    printf (\"%s\");\n" shortname;
6168     List.iter (
6169       function
6170       | String n                        (* strings *)
6171       | Device n
6172       | Pathname n
6173       | Dev_or_Path n
6174       | FileIn n
6175       | FileOut n
6176       | BufferIn n
6177       | Key n ->
6178           (* guestfish doesn't support string escaping, so neither do we *)
6179           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
6180       | OptString n ->                  (* string option *)
6181           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
6182           pr "    else printf (\" null\");\n"
6183       | StringList n
6184       | DeviceList n ->                 (* string list *)
6185           pr "    putchar (' ');\n";
6186           pr "    putchar ('\"');\n";
6187           pr "    for (i = 0; %s[i]; ++i) {\n" n;
6188           pr "      if (i > 0) putchar (' ');\n";
6189           pr "      fputs (%s[i], stdout);\n" n;
6190           pr "    }\n";
6191           pr "    putchar ('\"');\n";
6192       | Bool n ->                       (* boolean *)
6193           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
6194       | Int n ->                        (* int *)
6195           pr "    printf (\" %%d\", %s);\n" n
6196       | Int64 n ->
6197           pr "    printf (\" %%\" PRIi64, %s);\n" n
6198     ) (snd style);
6199     pr "    putchar ('\\n');\n";
6200     pr "  }\n";
6201     pr "\n";
6202   in
6203
6204   (* For non-daemon functions, generate a wrapper around each function. *)
6205   List.iter (
6206     fun (shortname, style, _, _, _, _, _) ->
6207       let name = "guestfs_" ^ shortname in
6208
6209       generate_prototype ~extern:false ~semicolon:false ~newline:true
6210         ~handle:"g" name style;
6211       pr "{\n";
6212       check_null_strings shortname style;
6213       trace_call shortname style;
6214       pr "  return guestfs__%s " shortname;
6215       generate_c_call_args ~handle:"g" style;
6216       pr ";\n";
6217       pr "}\n";
6218       pr "\n"
6219   ) non_daemon_functions;
6220
6221   (* Client-side stubs for each function. *)
6222   List.iter (
6223     fun (shortname, style, _, _, _, _, _) ->
6224       let name = "guestfs_" ^ shortname in
6225       let error_code = error_code_of (fst style) in
6226
6227       (* Generate the action stub. *)
6228       generate_prototype ~extern:false ~semicolon:false ~newline:true
6229         ~handle:"g" name style;
6230
6231       pr "{\n";
6232
6233       (match snd style with
6234        | [] -> ()
6235        | _ -> pr "  struct %s_args args;\n" name
6236       );
6237
6238       pr "  guestfs_message_header hdr;\n";
6239       pr "  guestfs_message_error err;\n";
6240       let has_ret =
6241         match fst style with
6242         | RErr -> false
6243         | RConstString _ | RConstOptString _ ->
6244             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6245         | RInt _ | RInt64 _
6246         | RBool _ | RString _ | RStringList _
6247         | RStruct _ | RStructList _
6248         | RHashtable _ | RBufferOut _ ->
6249             pr "  struct %s_ret ret;\n" name;
6250             true in
6251
6252       pr "  int serial;\n";
6253       pr "  int r;\n";
6254       pr "\n";
6255       check_null_strings shortname style;
6256       trace_call shortname style;
6257       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6258         shortname error_code;
6259       pr "  guestfs___set_busy (g);\n";
6260       pr "\n";
6261
6262       (* Send the main header and arguments. *)
6263       (match snd style with
6264        | [] ->
6265            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6266              (String.uppercase shortname)
6267        | args ->
6268            List.iter (
6269              function
6270              | Pathname n | Device n | Dev_or_Path n | String n | Key n ->
6271                  pr "  args.%s = (char *) %s;\n" n n
6272              | OptString n ->
6273                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6274              | StringList n | DeviceList n ->
6275                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6276                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6277              | Bool n ->
6278                  pr "  args.%s = %s;\n" n n
6279              | Int n ->
6280                  pr "  args.%s = %s;\n" n n
6281              | Int64 n ->
6282                  pr "  args.%s = %s;\n" n n
6283              | FileIn _ | FileOut _ -> ()
6284              | BufferIn n ->
6285                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6286                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6287                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6288                    shortname;
6289                  pr "    guestfs___end_busy (g);\n";
6290                  pr "    return %s;\n" error_code;
6291                  pr "  }\n";
6292                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6293                  pr "  args.%s.%s_len = %s_size;\n" n n n
6294            ) args;
6295            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6296              (String.uppercase shortname);
6297            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6298              name;
6299       );
6300       pr "  if (serial == -1) {\n";
6301       pr "    guestfs___end_busy (g);\n";
6302       pr "    return %s;\n" error_code;
6303       pr "  }\n";
6304       pr "\n";
6305
6306       (* Send any additional files (FileIn) requested. *)
6307       let need_read_reply_label = ref false in
6308       List.iter (
6309         function
6310         | FileIn n ->
6311             pr "  r = guestfs___send_file (g, %s);\n" n;
6312             pr "  if (r == -1) {\n";
6313             pr "    guestfs___end_busy (g);\n";
6314             pr "    return %s;\n" error_code;
6315             pr "  }\n";
6316             pr "  if (r == -2) /* daemon cancelled */\n";
6317             pr "    goto read_reply;\n";
6318             need_read_reply_label := true;
6319             pr "\n";
6320         | _ -> ()
6321       ) (snd style);
6322
6323       (* Wait for the reply from the remote end. *)
6324       if !need_read_reply_label then pr " read_reply:\n";
6325       pr "  memset (&hdr, 0, sizeof hdr);\n";
6326       pr "  memset (&err, 0, sizeof err);\n";
6327       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6328       pr "\n";
6329       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6330       if not has_ret then
6331         pr "NULL, NULL"
6332       else
6333         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6334       pr ");\n";
6335
6336       pr "  if (r == -1) {\n";
6337       pr "    guestfs___end_busy (g);\n";
6338       pr "    return %s;\n" error_code;
6339       pr "  }\n";
6340       pr "\n";
6341
6342       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6343         (String.uppercase shortname);
6344       pr "    guestfs___end_busy (g);\n";
6345       pr "    return %s;\n" error_code;
6346       pr "  }\n";
6347       pr "\n";
6348
6349       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6350       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6351       pr "    free (err.error_message);\n";
6352       pr "    guestfs___end_busy (g);\n";
6353       pr "    return %s;\n" error_code;
6354       pr "  }\n";
6355       pr "\n";
6356
6357       (* Expecting to receive further files (FileOut)? *)
6358       List.iter (
6359         function
6360         | FileOut n ->
6361             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6362             pr "    guestfs___end_busy (g);\n";
6363             pr "    return %s;\n" error_code;
6364             pr "  }\n";
6365             pr "\n";
6366         | _ -> ()
6367       ) (snd style);
6368
6369       pr "  guestfs___end_busy (g);\n";
6370
6371       (match fst style with
6372        | RErr -> pr "  return 0;\n"
6373        | RInt n | RInt64 n | RBool n ->
6374            pr "  return ret.%s;\n" n
6375        | RConstString _ | RConstOptString _ ->
6376            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6377        | RString n ->
6378            pr "  return ret.%s; /* caller will free */\n" n
6379        | RStringList n | RHashtable n ->
6380            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6381            pr "  ret.%s.%s_val =\n" n n;
6382            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6383            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6384              n n;
6385            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6386            pr "  return ret.%s.%s_val;\n" n n
6387        | RStruct (n, _) ->
6388            pr "  /* caller will free this */\n";
6389            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6390        | RStructList (n, _) ->
6391            pr "  /* caller will free this */\n";
6392            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6393        | RBufferOut n ->
6394            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6395            pr "   * _val might be NULL here.  To make the API saner for\n";
6396            pr "   * callers, we turn this case into a unique pointer (using\n";
6397            pr "   * malloc(1)).\n";
6398            pr "   */\n";
6399            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6400            pr "    *size_r = ret.%s.%s_len;\n" n n;
6401            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6402            pr "  } else {\n";
6403            pr "    free (ret.%s.%s_val);\n" n n;
6404            pr "    char *p = safe_malloc (g, 1);\n";
6405            pr "    *size_r = ret.%s.%s_len;\n" n n;
6406            pr "    return p;\n";
6407            pr "  }\n";
6408       );
6409
6410       pr "}\n\n"
6411   ) daemon_functions;
6412
6413   (* Functions to free structures. *)
6414   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6415   pr " * structure format is identical to the XDR format.  See note in\n";
6416   pr " * generator.ml.\n";
6417   pr " */\n";
6418   pr "\n";
6419
6420   List.iter (
6421     fun (typ, _) ->
6422       pr "void\n";
6423       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6424       pr "{\n";
6425       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6426       pr "  free (x);\n";
6427       pr "}\n";
6428       pr "\n";
6429
6430       pr "void\n";
6431       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6432       pr "{\n";
6433       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6434       pr "  free (x);\n";
6435       pr "}\n";
6436       pr "\n";
6437
6438   ) structs;
6439
6440 (* Generate daemon/actions.h. *)
6441 and generate_daemon_actions_h () =
6442   generate_header CStyle GPLv2plus;
6443
6444   pr "#include \"../src/guestfs_protocol.h\"\n";
6445   pr "\n";
6446
6447   List.iter (
6448     fun (name, style, _, _, _, _, _) ->
6449       generate_prototype
6450         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6451         name style;
6452   ) daemon_functions
6453
6454 (* Generate the linker script which controls the visibility of
6455  * symbols in the public ABI and ensures no other symbols get
6456  * exported accidentally.
6457  *)
6458 and generate_linker_script () =
6459   generate_header HashStyle GPLv2plus;
6460
6461   let globals = [
6462     "guestfs_create";
6463     "guestfs_close";
6464     "guestfs_get_error_handler";
6465     "guestfs_get_out_of_memory_handler";
6466     "guestfs_last_error";
6467     "guestfs_set_close_callback";
6468     "guestfs_set_error_handler";
6469     "guestfs_set_launch_done_callback";
6470     "guestfs_set_log_message_callback";
6471     "guestfs_set_out_of_memory_handler";
6472     "guestfs_set_subprocess_quit_callback";
6473
6474     (* Unofficial parts of the API: the bindings code use these
6475      * functions, so it is useful to export them.
6476      *)
6477     "guestfs_safe_calloc";
6478     "guestfs_safe_malloc";
6479     "guestfs_safe_strdup";
6480     "guestfs_safe_memdup";
6481   ] in
6482   let functions =
6483     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6484       all_functions in
6485   let structs =
6486     List.concat (
6487       List.map (fun (typ, _) ->
6488                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6489         structs
6490     ) in
6491   let globals = List.sort compare (globals @ functions @ structs) in
6492
6493   pr "{\n";
6494   pr "    global:\n";
6495   List.iter (pr "        %s;\n") globals;
6496   pr "\n";
6497
6498   pr "    local:\n";
6499   pr "        *;\n";
6500   pr "};\n"
6501
6502 (* Generate the server-side stubs. *)
6503 and generate_daemon_actions () =
6504   generate_header CStyle GPLv2plus;
6505
6506   pr "#include <config.h>\n";
6507   pr "\n";
6508   pr "#include <stdio.h>\n";
6509   pr "#include <stdlib.h>\n";
6510   pr "#include <string.h>\n";
6511   pr "#include <inttypes.h>\n";
6512   pr "#include <rpc/types.h>\n";
6513   pr "#include <rpc/xdr.h>\n";
6514   pr "\n";
6515   pr "#include \"daemon.h\"\n";
6516   pr "#include \"c-ctype.h\"\n";
6517   pr "#include \"../src/guestfs_protocol.h\"\n";
6518   pr "#include \"actions.h\"\n";
6519   pr "\n";
6520
6521   List.iter (
6522     fun (name, style, _, _, _, _, _) ->
6523       (* Generate server-side stubs. *)
6524       pr "static void %s_stub (XDR *xdr_in)\n" name;
6525       pr "{\n";
6526       let error_code =
6527         match fst style with
6528         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6529         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6530         | RBool _ -> pr "  int r;\n"; "-1"
6531         | RConstString _ | RConstOptString _ ->
6532             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6533         | RString _ -> pr "  char *r;\n"; "NULL"
6534         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6535         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6536         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6537         | RBufferOut _ ->
6538             pr "  size_t size = 1;\n";
6539             pr "  char *r;\n";
6540             "NULL" in
6541
6542       (match snd style with
6543        | [] -> ()
6544        | args ->
6545            pr "  struct guestfs_%s_args args;\n" name;
6546            List.iter (
6547              function
6548              | Device n | Dev_or_Path n
6549              | Pathname n
6550              | String n
6551              | Key n -> ()
6552              | OptString n -> pr "  char *%s;\n" n
6553              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6554              | Bool n -> pr "  int %s;\n" n
6555              | Int n -> pr "  int %s;\n" n
6556              | Int64 n -> pr "  int64_t %s;\n" n
6557              | FileIn _ | FileOut _ -> ()
6558              | BufferIn n ->
6559                  pr "  const char *%s;\n" n;
6560                  pr "  size_t %s_size;\n" n
6561            ) args
6562       );
6563       pr "\n";
6564
6565       let is_filein =
6566         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6567
6568       (match snd style with
6569        | [] -> ()
6570        | args ->
6571            pr "  memset (&args, 0, sizeof args);\n";
6572            pr "\n";
6573            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6574            if is_filein then
6575              pr "    if (cancel_receive () != -2)\n";
6576            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6577            pr "    goto done;\n";
6578            pr "  }\n";
6579            let pr_args n =
6580              pr "  char *%s = args.%s;\n" n n
6581            in
6582            let pr_list_handling_code n =
6583              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6584              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6585              pr "  if (%s == NULL) {\n" n;
6586              if is_filein then
6587                pr "    if (cancel_receive () != -2)\n";
6588              pr "      reply_with_perror (\"realloc\");\n";
6589              pr "    goto done;\n";
6590              pr "  }\n";
6591              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6592              pr "  args.%s.%s_val = %s;\n" n n n;
6593            in
6594            List.iter (
6595              function
6596              | Pathname n ->
6597                  pr_args n;
6598                  pr "  ABS_PATH (%s, %s, goto done);\n"
6599                    n (if is_filein then "cancel_receive ()" else "0");
6600              | Device n ->
6601                  pr_args n;
6602                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6603                    n (if is_filein then "cancel_receive ()" else "0");
6604              | Dev_or_Path n ->
6605                  pr_args n;
6606                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6607                    n (if is_filein then "cancel_receive ()" else "0");
6608              | String n | Key n -> pr_args n
6609              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6610              | StringList n ->
6611                  pr_list_handling_code n;
6612              | DeviceList n ->
6613                  pr_list_handling_code n;
6614                  pr "  /* Ensure that each is a device,\n";
6615                  pr "   * and perform device name translation.\n";
6616                  pr "   */\n";
6617                  pr "  {\n";
6618                  pr "    size_t i;\n";
6619                  pr "    for (i = 0; %s[i] != NULL; ++i)\n" n;
6620                  pr "      RESOLVE_DEVICE (%s[i], %s, goto done);\n" n
6621                    (if is_filein then "cancel_receive ()" else "0");
6622                  pr "  }\n";
6623              | Bool n -> pr "  %s = args.%s;\n" n n
6624              | Int n -> pr "  %s = args.%s;\n" n n
6625              | Int64 n -> pr "  %s = args.%s;\n" n n
6626              | FileIn _ | FileOut _ -> ()
6627              | BufferIn n ->
6628                  pr "  %s = args.%s.%s_val;\n" n n n;
6629                  pr "  %s_size = args.%s.%s_len;\n" n n n
6630            ) args;
6631            pr "\n"
6632       );
6633
6634       (* this is used at least for do_equal *)
6635       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6636         (* Emit NEED_ROOT just once, even when there are two or
6637            more Pathname args *)
6638         pr "  NEED_ROOT (%s, goto done);\n"
6639           (if is_filein then "cancel_receive ()" else "0");
6640       );
6641
6642       (* Don't want to call the impl with any FileIn or FileOut
6643        * parameters, since these go "outside" the RPC protocol.
6644        *)
6645       let args' =
6646         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6647           (snd style) in
6648       pr "  r = do_%s " name;
6649       generate_c_call_args (fst style, args');
6650       pr ";\n";
6651
6652       (match fst style with
6653        | RErr | RInt _ | RInt64 _ | RBool _
6654        | RConstString _ | RConstOptString _
6655        | RString _ | RStringList _ | RHashtable _
6656        | RStruct (_, _) | RStructList (_, _) ->
6657            pr "  if (r == %s)\n" error_code;
6658            pr "    /* do_%s has already called reply_with_error */\n" name;
6659            pr "    goto done;\n";
6660            pr "\n"
6661        | RBufferOut _ ->
6662            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6663            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6664            pr "   */\n";
6665            pr "  if (size == 1 && r == %s)\n" error_code;
6666            pr "    /* do_%s has already called reply_with_error */\n" name;
6667            pr "    goto done;\n";
6668            pr "\n"
6669       );
6670
6671       (* If there are any FileOut parameters, then the impl must
6672        * send its own reply.
6673        *)
6674       let no_reply =
6675         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6676       if no_reply then
6677         pr "  /* do_%s has already sent a reply */\n" name
6678       else (
6679         match fst style with
6680         | RErr -> pr "  reply (NULL, NULL);\n"
6681         | RInt n | RInt64 n | RBool n ->
6682             pr "  struct guestfs_%s_ret ret;\n" name;
6683             pr "  ret.%s = r;\n" n;
6684             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6685               name
6686         | RConstString _ | RConstOptString _ ->
6687             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6688         | RString n ->
6689             pr "  struct guestfs_%s_ret ret;\n" name;
6690             pr "  ret.%s = r;\n" n;
6691             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6692               name;
6693             pr "  free (r);\n"
6694         | RStringList n | RHashtable n ->
6695             pr "  struct guestfs_%s_ret ret;\n" name;
6696             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6697             pr "  ret.%s.%s_val = r;\n" n n;
6698             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6699               name;
6700             pr "  free_strings (r);\n"
6701         | RStruct (n, _) ->
6702             pr "  struct guestfs_%s_ret ret;\n" name;
6703             pr "  ret.%s = *r;\n" n;
6704             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6705               name;
6706             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6707               name
6708         | RStructList (n, _) ->
6709             pr "  struct guestfs_%s_ret ret;\n" name;
6710             pr "  ret.%s = *r;\n" n;
6711             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6712               name;
6713             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6714               name
6715         | RBufferOut n ->
6716             pr "  struct guestfs_%s_ret ret;\n" name;
6717             pr "  ret.%s.%s_val = r;\n" n n;
6718             pr "  ret.%s.%s_len = size;\n" n n;
6719             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6720               name;
6721             pr "  free (r);\n"
6722       );
6723
6724       (* Free the args. *)
6725       pr "done:\n";
6726       (match snd style with
6727        | [] -> ()
6728        | _ ->
6729            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6730              name
6731       );
6732       pr "  return;\n";
6733       pr "}\n\n";
6734   ) daemon_functions;
6735
6736   (* Dispatch function. *)
6737   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6738   pr "{\n";
6739   pr "  switch (proc_nr) {\n";
6740
6741   List.iter (
6742     fun (name, style, _, _, _, _, _) ->
6743       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6744       pr "      %s_stub (xdr_in);\n" name;
6745       pr "      break;\n"
6746   ) daemon_functions;
6747
6748   pr "    default:\n";
6749   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";
6750   pr "  }\n";
6751   pr "}\n";
6752   pr "\n";
6753
6754   (* LVM columns and tokenization functions. *)
6755   (* XXX This generates crap code.  We should rethink how we
6756    * do this parsing.
6757    *)
6758   List.iter (
6759     function
6760     | typ, cols ->
6761         pr "static const char *lvm_%s_cols = \"%s\";\n"
6762           typ (String.concat "," (List.map fst cols));
6763         pr "\n";
6764
6765         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6766         pr "{\n";
6767         pr "  char *tok, *p, *next;\n";
6768         pr "  size_t i, j;\n";
6769         pr "\n";
6770         (*
6771           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6772           pr "\n";
6773         *)
6774         pr "  if (!str) {\n";
6775         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6776         pr "    return -1;\n";
6777         pr "  }\n";
6778         pr "  if (!*str || c_isspace (*str)) {\n";
6779         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6780         pr "    return -1;\n";
6781         pr "  }\n";
6782         pr "  tok = str;\n";
6783         List.iter (
6784           fun (name, coltype) ->
6785             pr "  if (!tok) {\n";
6786             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6787             pr "    return -1;\n";
6788             pr "  }\n";
6789             pr "  p = strchrnul (tok, ',');\n";
6790             pr "  if (*p) next = p+1; else next = NULL;\n";
6791             pr "  *p = '\\0';\n";
6792             (match coltype with
6793              | FString ->
6794                  pr "  r->%s = strdup (tok);\n" name;
6795                  pr "  if (r->%s == NULL) {\n" name;
6796                  pr "    perror (\"strdup\");\n";
6797                  pr "    return -1;\n";
6798                  pr "  }\n"
6799              | FUUID ->
6800                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6801                  pr "    if (tok[j] == '\\0') {\n";
6802                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6803                  pr "      return -1;\n";
6804                  pr "    } else if (tok[j] != '-')\n";
6805                  pr "      r->%s[i++] = tok[j];\n" name;
6806                  pr "  }\n";
6807              | FBytes ->
6808                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6809                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6810                  pr "    return -1;\n";
6811                  pr "  }\n";
6812              | FInt64 ->
6813                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6814                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6815                  pr "    return -1;\n";
6816                  pr "  }\n";
6817              | FOptPercent ->
6818                  pr "  if (tok[0] == '\\0')\n";
6819                  pr "    r->%s = -1;\n" name;
6820                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6821                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6822                  pr "    return -1;\n";
6823                  pr "  }\n";
6824              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6825                  assert false (* can never be an LVM column *)
6826             );
6827             pr "  tok = next;\n";
6828         ) cols;
6829
6830         pr "  if (tok != NULL) {\n";
6831         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6832         pr "    return -1;\n";
6833         pr "  }\n";
6834         pr "  return 0;\n";
6835         pr "}\n";
6836         pr "\n";
6837
6838         pr "guestfs_int_lvm_%s_list *\n" typ;
6839         pr "parse_command_line_%ss (void)\n" typ;
6840         pr "{\n";
6841         pr "  char *out, *err;\n";
6842         pr "  char *p, *pend;\n";
6843         pr "  int r, i;\n";
6844         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6845         pr "  void *newp;\n";
6846         pr "\n";
6847         pr "  ret = malloc (sizeof *ret);\n";
6848         pr "  if (!ret) {\n";
6849         pr "    reply_with_perror (\"malloc\");\n";
6850         pr "    return NULL;\n";
6851         pr "  }\n";
6852         pr "\n";
6853         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6854         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6855         pr "\n";
6856         pr "  r = command (&out, &err,\n";
6857         pr "           \"lvm\", \"%ss\",\n" typ;
6858         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6859         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6860         pr "  if (r == -1) {\n";
6861         pr "    reply_with_error (\"%%s\", err);\n";
6862         pr "    free (out);\n";
6863         pr "    free (err);\n";
6864         pr "    free (ret);\n";
6865         pr "    return NULL;\n";
6866         pr "  }\n";
6867         pr "\n";
6868         pr "  free (err);\n";
6869         pr "\n";
6870         pr "  /* Tokenize each line of the output. */\n";
6871         pr "  p = out;\n";
6872         pr "  i = 0;\n";
6873         pr "  while (p) {\n";
6874         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6875         pr "    if (pend) {\n";
6876         pr "      *pend = '\\0';\n";
6877         pr "      pend++;\n";
6878         pr "    }\n";
6879         pr "\n";
6880         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6881         pr "      p++;\n";
6882         pr "\n";
6883         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6884         pr "      p = pend;\n";
6885         pr "      continue;\n";
6886         pr "    }\n";
6887         pr "\n";
6888         pr "    /* Allocate some space to store this next entry. */\n";
6889         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6890         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6891         pr "    if (newp == NULL) {\n";
6892         pr "      reply_with_perror (\"realloc\");\n";
6893         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6894         pr "      free (ret);\n";
6895         pr "      free (out);\n";
6896         pr "      return NULL;\n";
6897         pr "    }\n";
6898         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6899         pr "\n";
6900         pr "    /* Tokenize the next entry. */\n";
6901         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6902         pr "    if (r == -1) {\n";
6903         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6904         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6905         pr "      free (ret);\n";
6906         pr "      free (out);\n";
6907         pr "      return NULL;\n";
6908         pr "    }\n";
6909         pr "\n";
6910         pr "    ++i;\n";
6911         pr "    p = pend;\n";
6912         pr "  }\n";
6913         pr "\n";
6914         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6915         pr "\n";
6916         pr "  free (out);\n";
6917         pr "  return ret;\n";
6918         pr "}\n"
6919
6920   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6921
6922 (* Generate a list of function names, for debugging in the daemon.. *)
6923 and generate_daemon_names () =
6924   generate_header CStyle GPLv2plus;
6925
6926   pr "#include <config.h>\n";
6927   pr "\n";
6928   pr "#include \"daemon.h\"\n";
6929   pr "\n";
6930
6931   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6932   pr "const char *function_names[] = {\n";
6933   List.iter (
6934     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6935   ) daemon_functions;
6936   pr "};\n";
6937
6938 (* Generate the optional groups for the daemon to implement
6939  * guestfs_available.
6940  *)
6941 and generate_daemon_optgroups_c () =
6942   generate_header CStyle GPLv2plus;
6943
6944   pr "#include <config.h>\n";
6945   pr "\n";
6946   pr "#include \"daemon.h\"\n";
6947   pr "#include \"optgroups.h\"\n";
6948   pr "\n";
6949
6950   pr "struct optgroup optgroups[] = {\n";
6951   List.iter (
6952     fun (group, _) ->
6953       pr "  { \"%s\", optgroup_%s_available },\n" group group
6954   ) optgroups;
6955   pr "  { NULL, NULL }\n";
6956   pr "};\n"
6957
6958 and generate_daemon_optgroups_h () =
6959   generate_header CStyle GPLv2plus;
6960
6961   List.iter (
6962     fun (group, _) ->
6963       pr "extern int optgroup_%s_available (void);\n" group
6964   ) optgroups
6965
6966 (* Generate the tests. *)
6967 and generate_tests () =
6968   generate_header CStyle GPLv2plus;
6969
6970   pr "\
6971 #include <stdio.h>
6972 #include <stdlib.h>
6973 #include <string.h>
6974 #include <unistd.h>
6975 #include <sys/types.h>
6976 #include <fcntl.h>
6977
6978 #include \"guestfs.h\"
6979 #include \"guestfs-internal.h\"
6980
6981 static guestfs_h *g;
6982 static int suppress_error = 0;
6983
6984 static void print_error (guestfs_h *g, void *data, const char *msg)
6985 {
6986   if (!suppress_error)
6987     fprintf (stderr, \"%%s\\n\", msg);
6988 }
6989
6990 /* FIXME: nearly identical code appears in fish.c */
6991 static void print_strings (char *const *argv)
6992 {
6993   size_t argc;
6994
6995   for (argc = 0; argv[argc] != NULL; ++argc)
6996     printf (\"\\t%%s\\n\", argv[argc]);
6997 }
6998
6999 /*
7000 static void print_table (char const *const *argv)
7001 {
7002   size_t i;
7003
7004   for (i = 0; argv[i] != NULL; i += 2)
7005     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
7006 }
7007 */
7008
7009 static int
7010 is_available (const char *group)
7011 {
7012   const char *groups[] = { group, NULL };
7013   int r;
7014
7015   suppress_error = 1;
7016   r = guestfs_available (g, (char **) groups);
7017   suppress_error = 0;
7018
7019   return r == 0;
7020 }
7021
7022 static void
7023 incr (guestfs_h *g, void *iv)
7024 {
7025   int *i = (int *) iv;
7026   (*i)++;
7027 }
7028
7029 ";
7030
7031   (* Generate a list of commands which are not tested anywhere. *)
7032   pr "static void no_test_warnings (void)\n";
7033   pr "{\n";
7034
7035   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
7036   List.iter (
7037     fun (_, _, _, _, tests, _, _) ->
7038       let tests = filter_map (
7039         function
7040         | (_, (Always|If _|Unless _|IfAvailable _), test) -> Some test
7041         | (_, Disabled, _) -> None
7042       ) tests in
7043       let seq = List.concat (List.map seq_of_test tests) in
7044       let cmds_tested = List.map List.hd seq in
7045       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
7046   ) all_functions;
7047
7048   List.iter (
7049     fun (name, _, _, _, _, _, _) ->
7050       if not (Hashtbl.mem hash name) then
7051         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
7052   ) all_functions;
7053
7054   pr "}\n";
7055   pr "\n";
7056
7057   (* Generate the actual tests.  Note that we generate the tests
7058    * in reverse order, deliberately, so that (in general) the
7059    * newest tests run first.  This makes it quicker and easier to
7060    * debug them.
7061    *)
7062   let test_names =
7063     List.map (
7064       fun (name, _, _, flags, tests, _, _) ->
7065         mapi (generate_one_test name flags) tests
7066     ) (List.rev all_functions) in
7067   let test_names = List.concat test_names in
7068   let nr_tests = List.length test_names in
7069
7070   pr "\
7071 int main (int argc, char *argv[])
7072 {
7073   char c = 0;
7074   unsigned long int n_failed = 0;
7075   const char *filename;
7076   int fd;
7077   int nr_tests, test_num = 0;
7078
7079   setbuf (stdout, NULL);
7080
7081   no_test_warnings ();
7082
7083   g = guestfs_create ();
7084   if (g == NULL) {
7085     printf (\"guestfs_create FAILED\\n\");
7086     exit (EXIT_FAILURE);
7087   }
7088
7089   guestfs_set_error_handler (g, print_error, NULL);
7090
7091   guestfs_set_path (g, \"../appliance\");
7092
7093   filename = \"test1.img\";
7094   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7095   if (fd == -1) {
7096     perror (filename);
7097     exit (EXIT_FAILURE);
7098   }
7099   if (lseek (fd, %d, SEEK_SET) == -1) {
7100     perror (\"lseek\");
7101     close (fd);
7102     unlink (filename);
7103     exit (EXIT_FAILURE);
7104   }
7105   if (write (fd, &c, 1) == -1) {
7106     perror (\"write\");
7107     close (fd);
7108     unlink (filename);
7109     exit (EXIT_FAILURE);
7110   }
7111   if (close (fd) == -1) {
7112     perror (filename);
7113     unlink (filename);
7114     exit (EXIT_FAILURE);
7115   }
7116   if (guestfs_add_drive (g, filename) == -1) {
7117     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7118     exit (EXIT_FAILURE);
7119   }
7120
7121   filename = \"test2.img\";
7122   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7123   if (fd == -1) {
7124     perror (filename);
7125     exit (EXIT_FAILURE);
7126   }
7127   if (lseek (fd, %d, SEEK_SET) == -1) {
7128     perror (\"lseek\");
7129     close (fd);
7130     unlink (filename);
7131     exit (EXIT_FAILURE);
7132   }
7133   if (write (fd, &c, 1) == -1) {
7134     perror (\"write\");
7135     close (fd);
7136     unlink (filename);
7137     exit (EXIT_FAILURE);
7138   }
7139   if (close (fd) == -1) {
7140     perror (filename);
7141     unlink (filename);
7142     exit (EXIT_FAILURE);
7143   }
7144   if (guestfs_add_drive (g, filename) == -1) {
7145     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7146     exit (EXIT_FAILURE);
7147   }
7148
7149   filename = \"test3.img\";
7150   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7151   if (fd == -1) {
7152     perror (filename);
7153     exit (EXIT_FAILURE);
7154   }
7155   if (lseek (fd, %d, SEEK_SET) == -1) {
7156     perror (\"lseek\");
7157     close (fd);
7158     unlink (filename);
7159     exit (EXIT_FAILURE);
7160   }
7161   if (write (fd, &c, 1) == -1) {
7162     perror (\"write\");
7163     close (fd);
7164     unlink (filename);
7165     exit (EXIT_FAILURE);
7166   }
7167   if (close (fd) == -1) {
7168     perror (filename);
7169     unlink (filename);
7170     exit (EXIT_FAILURE);
7171   }
7172   if (guestfs_add_drive (g, filename) == -1) {
7173     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7174     exit (EXIT_FAILURE);
7175   }
7176
7177   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
7178     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
7179     exit (EXIT_FAILURE);
7180   }
7181
7182   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
7183   alarm (600);
7184
7185   if (guestfs_launch (g) == -1) {
7186     printf (\"guestfs_launch FAILED\\n\");
7187     exit (EXIT_FAILURE);
7188   }
7189
7190   /* Cancel previous alarm. */
7191   alarm (0);
7192
7193   nr_tests = %d;
7194
7195 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
7196
7197   iteri (
7198     fun i test_name ->
7199       pr "  test_num++;\n";
7200       pr "  if (guestfs_get_verbose (g))\n";
7201       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
7202       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
7203       pr "  if (%s () == -1) {\n" test_name;
7204       pr "    printf (\"%s FAILED\\n\");\n" test_name;
7205       pr "    n_failed++;\n";
7206       pr "  }\n";
7207   ) test_names;
7208   pr "\n";
7209
7210   pr "  /* Check close callback is called. */
7211   int close_sentinel = 1;
7212   guestfs_set_close_callback (g, incr, &close_sentinel);
7213
7214   guestfs_close (g);
7215
7216   if (close_sentinel != 2) {
7217     fprintf (stderr, \"close callback was not called\\n\");
7218     exit (EXIT_FAILURE);
7219   }
7220
7221   unlink (\"test1.img\");
7222   unlink (\"test2.img\");
7223   unlink (\"test3.img\");
7224
7225 ";
7226
7227   pr "  if (n_failed > 0) {\n";
7228   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7229   pr "    exit (EXIT_FAILURE);\n";
7230   pr "  }\n";
7231   pr "\n";
7232
7233   pr "  exit (EXIT_SUCCESS);\n";
7234   pr "}\n"
7235
7236 and generate_one_test name flags i (init, prereq, test) =
7237   let test_name = sprintf "test_%s_%d" name i in
7238
7239   pr "\
7240 static int %s_skip (void)
7241 {
7242   const char *str;
7243
7244   str = getenv (\"TEST_ONLY\");
7245   if (str)
7246     return strstr (str, \"%s\") == NULL;
7247   str = getenv (\"SKIP_%s\");
7248   if (str && STREQ (str, \"1\")) return 1;
7249   str = getenv (\"SKIP_TEST_%s\");
7250   if (str && STREQ (str, \"1\")) return 1;
7251   return 0;
7252 }
7253
7254 " test_name name (String.uppercase test_name) (String.uppercase name);
7255
7256   (match prereq with
7257    | Disabled | Always | IfAvailable _ -> ()
7258    | If code | Unless code ->
7259        pr "static int %s_prereq (void)\n" test_name;
7260        pr "{\n";
7261        pr "  %s\n" code;
7262        pr "}\n";
7263        pr "\n";
7264   );
7265
7266   pr "\
7267 static int %s (void)
7268 {
7269   if (%s_skip ()) {
7270     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7271     return 0;
7272   }
7273
7274 " test_name test_name test_name;
7275
7276   (* Optional functions should only be tested if the relevant
7277    * support is available in the daemon.
7278    *)
7279   List.iter (
7280     function
7281     | Optional group ->
7282         pr "  if (!is_available (\"%s\")) {\n" group;
7283         pr "    printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", \"%s\");\n" test_name group;
7284         pr "    return 0;\n";
7285         pr "  }\n";
7286     | _ -> ()
7287   ) flags;
7288
7289   (match prereq with
7290    | Disabled ->
7291        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7292    | If _ ->
7293        pr "  if (! %s_prereq ()) {\n" test_name;
7294        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7295        pr "    return 0;\n";
7296        pr "  }\n";
7297        pr "\n";
7298        generate_one_test_body name i test_name init test;
7299    | Unless _ ->
7300        pr "  if (%s_prereq ()) {\n" test_name;
7301        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7302        pr "    return 0;\n";
7303        pr "  }\n";
7304        pr "\n";
7305        generate_one_test_body name i test_name init test;
7306    | IfAvailable group ->
7307        pr "  if (!is_available (\"%s\")) {\n" group;
7308        pr "    printf (\"        %%s skipped (reason: %%s not available)\\n\", \"%s\", \"%s\");\n" test_name group;
7309        pr "    return 0;\n";
7310        pr "  }\n";
7311        pr "\n";
7312        generate_one_test_body name i test_name init test;
7313    | Always ->
7314        generate_one_test_body name i test_name init test
7315   );
7316
7317   pr "  return 0;\n";
7318   pr "}\n";
7319   pr "\n";
7320   test_name
7321
7322 and generate_one_test_body name i test_name init test =
7323   (match init with
7324    | InitNone (* XXX at some point, InitNone and InitEmpty became
7325                * folded together as the same thing.  Really we should
7326                * make InitNone do nothing at all, but the tests may
7327                * need to be checked to make sure this is OK.
7328                *)
7329    | InitEmpty ->
7330        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7331        List.iter (generate_test_command_call test_name)
7332          [["blockdev_setrw"; "/dev/sda"];
7333           ["umount_all"];
7334           ["lvm_remove_all"]]
7335    | InitPartition ->
7336        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7337        List.iter (generate_test_command_call test_name)
7338          [["blockdev_setrw"; "/dev/sda"];
7339           ["umount_all"];
7340           ["lvm_remove_all"];
7341           ["part_disk"; "/dev/sda"; "mbr"]]
7342    | InitBasicFS ->
7343        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7344        List.iter (generate_test_command_call test_name)
7345          [["blockdev_setrw"; "/dev/sda"];
7346           ["umount_all"];
7347           ["lvm_remove_all"];
7348           ["part_disk"; "/dev/sda"; "mbr"];
7349           ["mkfs"; "ext2"; "/dev/sda1"];
7350           ["mount_options"; ""; "/dev/sda1"; "/"]]
7351    | InitBasicFSonLVM ->
7352        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7353          test_name;
7354        List.iter (generate_test_command_call test_name)
7355          [["blockdev_setrw"; "/dev/sda"];
7356           ["umount_all"];
7357           ["lvm_remove_all"];
7358           ["part_disk"; "/dev/sda"; "mbr"];
7359           ["pvcreate"; "/dev/sda1"];
7360           ["vgcreate"; "VG"; "/dev/sda1"];
7361           ["lvcreate"; "LV"; "VG"; "8"];
7362           ["mkfs"; "ext2"; "/dev/VG/LV"];
7363           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7364    | InitISOFS ->
7365        pr "  /* InitISOFS for %s */\n" test_name;
7366        List.iter (generate_test_command_call test_name)
7367          [["blockdev_setrw"; "/dev/sda"];
7368           ["umount_all"];
7369           ["lvm_remove_all"];
7370           ["mount_ro"; "/dev/sdd"; "/"]]
7371   );
7372
7373   let get_seq_last = function
7374     | [] ->
7375         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7376           test_name
7377     | seq ->
7378         let seq = List.rev seq in
7379         List.rev (List.tl seq), List.hd seq
7380   in
7381
7382   match test with
7383   | TestRun seq ->
7384       pr "  /* TestRun for %s (%d) */\n" name i;
7385       List.iter (generate_test_command_call test_name) seq
7386   | TestOutput (seq, expected) ->
7387       pr "  /* TestOutput for %s (%d) */\n" name i;
7388       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7389       let seq, last = get_seq_last seq in
7390       let test () =
7391         pr "    if (STRNEQ (r, expected)) {\n";
7392         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7393         pr "      return -1;\n";
7394         pr "    }\n"
7395       in
7396       List.iter (generate_test_command_call test_name) seq;
7397       generate_test_command_call ~test test_name last
7398   | TestOutputList (seq, expected) ->
7399       pr "  /* TestOutputList for %s (%d) */\n" name i;
7400       let seq, last = get_seq_last seq in
7401       let test () =
7402         iteri (
7403           fun i str ->
7404             pr "    if (!r[%d]) {\n" i;
7405             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7406             pr "      print_strings (r);\n";
7407             pr "      return -1;\n";
7408             pr "    }\n";
7409             pr "    {\n";
7410             pr "      const char *expected = \"%s\";\n" (c_quote str);
7411             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7412             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7413             pr "        return -1;\n";
7414             pr "      }\n";
7415             pr "    }\n"
7416         ) expected;
7417         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7418         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7419           test_name;
7420         pr "      print_strings (r);\n";
7421         pr "      return -1;\n";
7422         pr "    }\n"
7423       in
7424       List.iter (generate_test_command_call test_name) seq;
7425       generate_test_command_call ~test test_name last
7426   | TestOutputListOfDevices (seq, expected) ->
7427       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7428       let seq, last = get_seq_last seq in
7429       let test () =
7430         iteri (
7431           fun i str ->
7432             pr "    if (!r[%d]) {\n" i;
7433             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7434             pr "      print_strings (r);\n";
7435             pr "      return -1;\n";
7436             pr "    }\n";
7437             pr "    {\n";
7438             pr "      const char *expected = \"%s\";\n" (c_quote str);
7439             pr "      r[%d][5] = 's';\n" i;
7440             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7441             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7442             pr "        return -1;\n";
7443             pr "      }\n";
7444             pr "    }\n"
7445         ) expected;
7446         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7447         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7448           test_name;
7449         pr "      print_strings (r);\n";
7450         pr "      return -1;\n";
7451         pr "    }\n"
7452       in
7453       List.iter (generate_test_command_call test_name) seq;
7454       generate_test_command_call ~test test_name last
7455   | TestOutputInt (seq, expected) ->
7456       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7457       let seq, last = get_seq_last seq in
7458       let test () =
7459         pr "    if (r != %d) {\n" expected;
7460         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7461           test_name expected;
7462         pr "               (int) r);\n";
7463         pr "      return -1;\n";
7464         pr "    }\n"
7465       in
7466       List.iter (generate_test_command_call test_name) seq;
7467       generate_test_command_call ~test test_name last
7468   | TestOutputIntOp (seq, op, expected) ->
7469       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7470       let seq, last = get_seq_last seq in
7471       let test () =
7472         pr "    if (! (r %s %d)) {\n" op expected;
7473         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7474           test_name op expected;
7475         pr "               (int) r);\n";
7476         pr "      return -1;\n";
7477         pr "    }\n"
7478       in
7479       List.iter (generate_test_command_call test_name) seq;
7480       generate_test_command_call ~test test_name last
7481   | TestOutputTrue seq ->
7482       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7483       let seq, last = get_seq_last seq in
7484       let test () =
7485         pr "    if (!r) {\n";
7486         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7487           test_name;
7488         pr "      return -1;\n";
7489         pr "    }\n"
7490       in
7491       List.iter (generate_test_command_call test_name) seq;
7492       generate_test_command_call ~test test_name last
7493   | TestOutputFalse seq ->
7494       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7495       let seq, last = get_seq_last seq in
7496       let test () =
7497         pr "    if (r) {\n";
7498         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7499           test_name;
7500         pr "      return -1;\n";
7501         pr "    }\n"
7502       in
7503       List.iter (generate_test_command_call test_name) seq;
7504       generate_test_command_call ~test test_name last
7505   | TestOutputLength (seq, expected) ->
7506       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7507       let seq, last = get_seq_last seq in
7508       let test () =
7509         pr "    int j;\n";
7510         pr "    for (j = 0; j < %d; ++j)\n" expected;
7511         pr "      if (r[j] == NULL) {\n";
7512         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7513           test_name;
7514         pr "        print_strings (r);\n";
7515         pr "        return -1;\n";
7516         pr "      }\n";
7517         pr "    if (r[j] != NULL) {\n";
7518         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7519           test_name;
7520         pr "      print_strings (r);\n";
7521         pr "      return -1;\n";
7522         pr "    }\n"
7523       in
7524       List.iter (generate_test_command_call test_name) seq;
7525       generate_test_command_call ~test test_name last
7526   | TestOutputBuffer (seq, expected) ->
7527       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7528       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7529       let seq, last = get_seq_last seq in
7530       let len = String.length expected in
7531       let test () =
7532         pr "    if (size != %d) {\n" len;
7533         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7534         pr "      return -1;\n";
7535         pr "    }\n";
7536         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7537         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7538         pr "      return -1;\n";
7539         pr "    }\n"
7540       in
7541       List.iter (generate_test_command_call test_name) seq;
7542       generate_test_command_call ~test test_name last
7543   | TestOutputStruct (seq, checks) ->
7544       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7545       let seq, last = get_seq_last seq in
7546       let test () =
7547         List.iter (
7548           function
7549           | CompareWithInt (field, expected) ->
7550               pr "    if (r->%s != %d) {\n" field expected;
7551               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7552                 test_name field expected;
7553               pr "               (int) r->%s);\n" field;
7554               pr "      return -1;\n";
7555               pr "    }\n"
7556           | CompareWithIntOp (field, op, expected) ->
7557               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7558               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7559                 test_name field op expected;
7560               pr "               (int) r->%s);\n" field;
7561               pr "      return -1;\n";
7562               pr "    }\n"
7563           | CompareWithString (field, expected) ->
7564               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7565               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7566                 test_name field expected;
7567               pr "               r->%s);\n" field;
7568               pr "      return -1;\n";
7569               pr "    }\n"
7570           | CompareFieldsIntEq (field1, field2) ->
7571               pr "    if (r->%s != r->%s) {\n" field1 field2;
7572               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7573                 test_name field1 field2;
7574               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7575               pr "      return -1;\n";
7576               pr "    }\n"
7577           | CompareFieldsStrEq (field1, field2) ->
7578               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7579               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7580                 test_name field1 field2;
7581               pr "               r->%s, r->%s);\n" field1 field2;
7582               pr "      return -1;\n";
7583               pr "    }\n"
7584         ) checks
7585       in
7586       List.iter (generate_test_command_call test_name) seq;
7587       generate_test_command_call ~test test_name last
7588   | TestLastFail seq ->
7589       pr "  /* TestLastFail for %s (%d) */\n" name i;
7590       let seq, last = get_seq_last seq in
7591       List.iter (generate_test_command_call test_name) seq;
7592       generate_test_command_call test_name ~expect_error:true last
7593
7594 (* Generate the code to run a command, leaving the result in 'r'.
7595  * If you expect to get an error then you should set expect_error:true.
7596  *)
7597 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7598   match cmd with
7599   | [] -> assert false
7600   | name :: args ->
7601       (* Look up the command to find out what args/ret it has. *)
7602       let style =
7603         try
7604           let _, style, _, _, _, _, _ =
7605             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7606           style
7607         with Not_found ->
7608           failwithf "%s: in test, command %s was not found" test_name name in
7609
7610       if List.length (snd style) <> List.length args then
7611         failwithf "%s: in test, wrong number of args given to %s"
7612           test_name name;
7613
7614       pr "  {\n";
7615
7616       List.iter (
7617         function
7618         | OptString n, "NULL" -> ()
7619         | Pathname n, arg
7620         | Device n, arg
7621         | Dev_or_Path n, arg
7622         | String n, arg
7623         | OptString n, arg
7624         | Key n, arg ->
7625             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7626         | BufferIn n, arg ->
7627             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7628             pr "    size_t %s_size = %d;\n" n (String.length arg)
7629         | Int _, _
7630         | Int64 _, _
7631         | Bool _, _
7632         | FileIn _, _ | FileOut _, _ -> ()
7633         | StringList n, "" | DeviceList n, "" ->
7634             pr "    const char *const %s[1] = { NULL };\n" n
7635         | StringList n, arg | DeviceList n, arg ->
7636             let strs = string_split " " arg in
7637             iteri (
7638               fun i str ->
7639                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7640             ) strs;
7641             pr "    const char *const %s[] = {\n" n;
7642             iteri (
7643               fun i _ -> pr "      %s_%d,\n" n i
7644             ) strs;
7645             pr "      NULL\n";
7646             pr "    };\n";
7647       ) (List.combine (snd style) args);
7648
7649       let error_code =
7650         match fst style with
7651         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7652         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7653         | RConstString _ | RConstOptString _ ->
7654             pr "    const char *r;\n"; "NULL"
7655         | RString _ -> pr "    char *r;\n"; "NULL"
7656         | RStringList _ | RHashtable _ ->
7657             pr "    char **r;\n";
7658             pr "    size_t i;\n";
7659             "NULL"
7660         | RStruct (_, typ) ->
7661             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7662         | RStructList (_, typ) ->
7663             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7664         | RBufferOut _ ->
7665             pr "    char *r;\n";
7666             pr "    size_t size;\n";
7667             "NULL" in
7668
7669       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7670       pr "    r = guestfs_%s (g" name;
7671
7672       (* Generate the parameters. *)
7673       List.iter (
7674         function
7675         | OptString _, "NULL" -> pr ", NULL"
7676         | Pathname n, _
7677         | Device n, _ | Dev_or_Path n, _
7678         | String n, _
7679         | OptString n, _
7680         | Key n, _ ->
7681             pr ", %s" n
7682         | BufferIn n, _ ->
7683             pr ", %s, %s_size" n n
7684         | FileIn _, arg | FileOut _, arg ->
7685             pr ", \"%s\"" (c_quote arg)
7686         | StringList n, _ | DeviceList n, _ ->
7687             pr ", (char **) %s" n
7688         | Int _, arg ->
7689             let i =
7690               try int_of_string arg
7691               with Failure "int_of_string" ->
7692                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7693             pr ", %d" i
7694         | Int64 _, arg ->
7695             let i =
7696               try Int64.of_string arg
7697               with Failure "int_of_string" ->
7698                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7699             pr ", %Ld" i
7700         | Bool _, arg ->
7701             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7702       ) (List.combine (snd style) args);
7703
7704       (match fst style with
7705        | RBufferOut _ -> pr ", &size"
7706        | _ -> ()
7707       );
7708
7709       pr ");\n";
7710
7711       if not expect_error then
7712         pr "    if (r == %s)\n" error_code
7713       else
7714         pr "    if (r != %s)\n" error_code;
7715       pr "      return -1;\n";
7716
7717       (* Insert the test code. *)
7718       (match test with
7719        | None -> ()
7720        | Some f -> f ()
7721       );
7722
7723       (match fst style with
7724        | RErr | RInt _ | RInt64 _ | RBool _
7725        | RConstString _ | RConstOptString _ -> ()
7726        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7727        | RStringList _ | RHashtable _ ->
7728            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7729            pr "      free (r[i]);\n";
7730            pr "    free (r);\n"
7731        | RStruct (_, typ) ->
7732            pr "    guestfs_free_%s (r);\n" typ
7733        | RStructList (_, typ) ->
7734            pr "    guestfs_free_%s_list (r);\n" typ
7735       );
7736
7737       pr "  }\n"
7738
7739 and c_quote str =
7740   let str = replace_str str "\r" "\\r" in
7741   let str = replace_str str "\n" "\\n" in
7742   let str = replace_str str "\t" "\\t" in
7743   let str = replace_str str "\000" "\\0" in
7744   str
7745
7746 (* Generate a lot of different functions for guestfish. *)
7747 and generate_fish_cmds () =
7748   generate_header CStyle GPLv2plus;
7749
7750   let all_functions =
7751     List.filter (
7752       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7753     ) all_functions in
7754   let all_functions_sorted =
7755     List.filter (
7756       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7757     ) all_functions_sorted in
7758
7759   pr "#include <config.h>\n";
7760   pr "\n";
7761   pr "#include <stdio.h>\n";
7762   pr "#include <stdlib.h>\n";
7763   pr "#include <string.h>\n";
7764   pr "#include <inttypes.h>\n";
7765   pr "\n";
7766   pr "#include <guestfs.h>\n";
7767   pr "#include \"c-ctype.h\"\n";
7768   pr "#include \"full-write.h\"\n";
7769   pr "#include \"xstrtol.h\"\n";
7770   pr "#include \"fish.h\"\n";
7771   pr "\n";
7772   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7773   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7774   pr "\n";
7775
7776   (* list_commands function, which implements guestfish -h *)
7777   pr "void list_commands (void)\n";
7778   pr "{\n";
7779   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7780   pr "  list_builtin_commands ();\n";
7781   List.iter (
7782     fun (name, _, _, flags, _, shortdesc, _) ->
7783       let name = replace_char name '_' '-' in
7784       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7785         name shortdesc
7786   ) all_functions_sorted;
7787   pr "  printf (\"    %%s\\n\",";
7788   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7789   pr "}\n";
7790   pr "\n";
7791
7792   (* display_command function, which implements guestfish -h cmd *)
7793   pr "int display_command (const char *cmd)\n";
7794   pr "{\n";
7795   List.iter (
7796     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7797       let name2 = replace_char name '_' '-' in
7798       let alias =
7799         try find_map (function FishAlias n -> Some n | _ -> None) flags
7800         with Not_found -> name in
7801       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7802       let synopsis =
7803         match snd style with
7804         | [] -> name2
7805         | args ->
7806             let args = List.filter (function Key _ -> false | _ -> true) args in
7807             sprintf "%s %s"
7808               name2 (String.concat " " (List.map name_of_argt args)) in
7809
7810       let warnings =
7811         if List.exists (function Key _ -> true | _ -> false) (snd style) then
7812           "\n\nThis command has one or more key or passphrase parameters.
7813 Guestfish will prompt for these separately."
7814         else "" in
7815
7816       let warnings =
7817         warnings ^
7818           if List.mem ProtocolLimitWarning flags then
7819             ("\n\n" ^ protocol_limit_warning)
7820           else "" in
7821
7822       (* For DangerWillRobinson commands, we should probably have
7823        * guestfish prompt before allowing you to use them (especially
7824        * in interactive mode). XXX
7825        *)
7826       let warnings =
7827         warnings ^
7828           if List.mem DangerWillRobinson flags then
7829             ("\n\n" ^ danger_will_robinson)
7830           else "" in
7831
7832       let warnings =
7833         warnings ^
7834           match deprecation_notice flags with
7835           | None -> ""
7836           | Some txt -> "\n\n" ^ txt in
7837
7838       let describe_alias =
7839         if name <> alias then
7840           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7841         else "" in
7842
7843       pr "  if (";
7844       pr "STRCASEEQ (cmd, \"%s\")" name;
7845       if name <> name2 then
7846         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7847       if name <> alias then
7848         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7849       pr ") {\n";
7850       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7851         name2 shortdesc
7852         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7853          "=head1 DESCRIPTION\n\n" ^
7854          longdesc ^ warnings ^ describe_alias);
7855       pr "    return 0;\n";
7856       pr "  }\n";
7857       pr "  else\n"
7858   ) all_functions;
7859   pr "    return display_builtin_command (cmd);\n";
7860   pr "}\n";
7861   pr "\n";
7862
7863   let emit_print_list_function typ =
7864     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7865       typ typ typ;
7866     pr "{\n";
7867     pr "  unsigned int i;\n";
7868     pr "\n";
7869     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7870     pr "    printf (\"[%%d] = {\\n\", i);\n";
7871     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7872     pr "    printf (\"}\\n\");\n";
7873     pr "  }\n";
7874     pr "}\n";
7875     pr "\n";
7876   in
7877
7878   (* print_* functions *)
7879   List.iter (
7880     fun (typ, cols) ->
7881       let needs_i =
7882         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7883
7884       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7885       pr "{\n";
7886       if needs_i then (
7887         pr "  unsigned int i;\n";
7888         pr "\n"
7889       );
7890       List.iter (
7891         function
7892         | name, FString ->
7893             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7894         | name, FUUID ->
7895             pr "  printf (\"%%s%s: \", indent);\n" name;
7896             pr "  for (i = 0; i < 32; ++i)\n";
7897             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7898             pr "  printf (\"\\n\");\n"
7899         | name, FBuffer ->
7900             pr "  printf (\"%%s%s: \", indent);\n" name;
7901             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7902             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7903             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7904             pr "    else\n";
7905             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7906             pr "  printf (\"\\n\");\n"
7907         | name, (FUInt64|FBytes) ->
7908             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7909               name typ name
7910         | name, FInt64 ->
7911             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7912               name typ name
7913         | name, FUInt32 ->
7914             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7915               name typ name
7916         | name, FInt32 ->
7917             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7918               name typ name
7919         | name, FChar ->
7920             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7921               name typ name
7922         | name, FOptPercent ->
7923             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7924               typ name name typ name;
7925             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7926       ) cols;
7927       pr "}\n";
7928       pr "\n";
7929   ) structs;
7930
7931   (* Emit a print_TYPE_list function definition only if that function is used. *)
7932   List.iter (
7933     function
7934     | typ, (RStructListOnly | RStructAndList) ->
7935         (* generate the function for typ *)
7936         emit_print_list_function typ
7937     | typ, _ -> () (* empty *)
7938   ) (rstructs_used_by all_functions);
7939
7940   (* Emit a print_TYPE function definition only if that function is used. *)
7941   List.iter (
7942     function
7943     | typ, (RStructOnly | RStructAndList) ->
7944         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7945         pr "{\n";
7946         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7947         pr "}\n";
7948         pr "\n";
7949     | typ, _ -> () (* empty *)
7950   ) (rstructs_used_by all_functions);
7951
7952   (* run_<action> actions *)
7953   List.iter (
7954     fun (name, style, _, flags, _, _, _) ->
7955       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7956       pr "{\n";
7957       (match fst style with
7958        | RErr
7959        | RInt _
7960        | RBool _ -> pr "  int r;\n"
7961        | RInt64 _ -> pr "  int64_t r;\n"
7962        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7963        | RString _ -> pr "  char *r;\n"
7964        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7965        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7966        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7967        | RBufferOut _ ->
7968            pr "  char *r;\n";
7969            pr "  size_t size;\n";
7970       );
7971       List.iter (
7972         function
7973         | Device n
7974         | String n
7975         | OptString n -> pr "  const char *%s;\n" n
7976         | Pathname n
7977         | Dev_or_Path n
7978         | FileIn n
7979         | FileOut n
7980         | Key n -> pr "  char *%s;\n" n
7981         | BufferIn n ->
7982             pr "  const char *%s;\n" n;
7983             pr "  size_t %s_size;\n" n
7984         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7985         | Bool n -> pr "  int %s;\n" n
7986         | Int n -> pr "  int %s;\n" n
7987         | Int64 n -> pr "  int64_t %s;\n" n
7988       ) (snd style);
7989
7990       (* Check and convert parameters. *)
7991       let argc_expected =
7992         let args_no_keys =
7993           List.filter (function Key _ -> false | _ -> true) (snd style) in
7994         List.length args_no_keys in
7995       pr "  if (argc != %d) {\n" argc_expected;
7996       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7997         argc_expected;
7998       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7999       pr "    return -1;\n";
8000       pr "  }\n";
8001
8002       let parse_integer fn fntyp rtyp range name =
8003         pr "  {\n";
8004         pr "    strtol_error xerr;\n";
8005         pr "    %s r;\n" fntyp;
8006         pr "\n";
8007         pr "    xerr = %s (argv[i++], NULL, 0, &r, xstrtol_suffixes);\n" fn;
8008         pr "    if (xerr != LONGINT_OK) {\n";
8009         pr "      fprintf (stderr,\n";
8010         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
8011         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
8012         pr "      return -1;\n";
8013         pr "    }\n";
8014         (match range with
8015          | None -> ()
8016          | Some (min, max, comment) ->
8017              pr "    /* %s */\n" comment;
8018              pr "    if (r < %s || r > %s) {\n" min max;
8019              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
8020                name;
8021              pr "      return -1;\n";
8022              pr "    }\n";
8023              pr "    /* The check above should ensure this assignment does not overflow. */\n";
8024         );
8025         pr "    %s = r;\n" name;
8026         pr "  }\n";
8027       in
8028
8029       if snd style <> [] then
8030         pr "  size_t i = 0;\n";
8031
8032       List.iter (
8033         function
8034         | Device name
8035         | String name ->
8036             pr "  %s = argv[i++];\n" name
8037         | Pathname name
8038         | Dev_or_Path name ->
8039             pr "  %s = resolve_win_path (argv[i++]);\n" name;
8040             pr "  if (%s == NULL) return -1;\n" name
8041         | OptString name ->
8042             pr "  %s = STRNEQ (argv[i], \"\") ? argv[i] : NULL;\n" name;
8043             pr "  i++;\n"
8044         | BufferIn name ->
8045             pr "  %s = argv[i];\n" name;
8046             pr "  %s_size = strlen (argv[i]);\n" name;
8047             pr "  i++;\n"
8048         | FileIn name ->
8049             pr "  %s = file_in (argv[i++]);\n" name;
8050             pr "  if (%s == NULL) return -1;\n" name
8051         | FileOut name ->
8052             pr "  %s = file_out (argv[i++]);\n" name;
8053             pr "  if (%s == NULL) return -1;\n" name
8054         | StringList name | DeviceList name ->
8055             pr "  %s = parse_string_list (argv[i++]);\n" name;
8056             pr "  if (%s == NULL) return -1;\n" name
8057         | Key name ->
8058             pr "  %s = read_key (\"%s\");\n" name name;
8059             pr "  if (%s == NULL) return -1;\n" name
8060         | Bool name ->
8061             pr "  %s = is_true (argv[i++]) ? 1 : 0;\n" name
8062         | Int name ->
8063             let range =
8064               let min = "(-(2LL<<30))"
8065               and max = "((2LL<<30)-1)"
8066               and comment =
8067                 "The Int type in the generator is a signed 31 bit int." in
8068               Some (min, max, comment) in
8069             parse_integer "xstrtoll" "long long" "int" range name
8070         | Int64 name ->
8071             parse_integer "xstrtoll" "long long" "int64_t" None name
8072       ) (snd style);
8073
8074       (* Call C API function. *)
8075       pr "  r = guestfs_%s " name;
8076       generate_c_call_args ~handle:"g" style;
8077       pr ";\n";
8078
8079       List.iter (
8080         function
8081         | Device _ | String _
8082         | OptString _ | Bool _
8083         | Int _ | Int64 _
8084         | BufferIn _ -> ()
8085         | Pathname name | Dev_or_Path name | FileOut name
8086         | Key name ->
8087             pr "  free (%s);\n" name
8088         | FileIn name ->
8089             pr "  free_file_in (%s);\n" name
8090         | StringList name | DeviceList name ->
8091             pr "  free_strings (%s);\n" name
8092       ) (snd style);
8093
8094       (* Any output flags? *)
8095       let fish_output =
8096         let flags = filter_map (
8097           function FishOutput flag -> Some flag | _ -> None
8098         ) flags in
8099         match flags with
8100         | [] -> None
8101         | [f] -> Some f
8102         | _ ->
8103             failwithf "%s: more than one FishOutput flag is not allowed" name in
8104
8105       (* Check return value for errors and display command results. *)
8106       (match fst style with
8107        | RErr -> pr "  return r;\n"
8108        | RInt _ ->
8109            pr "  if (r == -1) return -1;\n";
8110            (match fish_output with
8111             | None ->
8112                 pr "  printf (\"%%d\\n\", r);\n";
8113             | Some FishOutputOctal ->
8114                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
8115             | Some FishOutputHexadecimal ->
8116                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
8117            pr "  return 0;\n"
8118        | RInt64 _ ->
8119            pr "  if (r == -1) return -1;\n";
8120            (match fish_output with
8121             | None ->
8122                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
8123             | Some FishOutputOctal ->
8124                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
8125             | Some FishOutputHexadecimal ->
8126                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
8127            pr "  return 0;\n"
8128        | RBool _ ->
8129            pr "  if (r == -1) return -1;\n";
8130            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
8131            pr "  return 0;\n"
8132        | RConstString _ ->
8133            pr "  if (r == NULL) return -1;\n";
8134            pr "  printf (\"%%s\\n\", r);\n";
8135            pr "  return 0;\n"
8136        | RConstOptString _ ->
8137            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
8138            pr "  return 0;\n"
8139        | RString _ ->
8140            pr "  if (r == NULL) return -1;\n";
8141            pr "  printf (\"%%s\\n\", r);\n";
8142            pr "  free (r);\n";
8143            pr "  return 0;\n"
8144        | RStringList _ ->
8145            pr "  if (r == NULL) return -1;\n";
8146            pr "  print_strings (r);\n";
8147            pr "  free_strings (r);\n";
8148            pr "  return 0;\n"
8149        | RStruct (_, typ) ->
8150            pr "  if (r == NULL) return -1;\n";
8151            pr "  print_%s (r);\n" typ;
8152            pr "  guestfs_free_%s (r);\n" typ;
8153            pr "  return 0;\n"
8154        | RStructList (_, typ) ->
8155            pr "  if (r == NULL) return -1;\n";
8156            pr "  print_%s_list (r);\n" typ;
8157            pr "  guestfs_free_%s_list (r);\n" typ;
8158            pr "  return 0;\n"
8159        | RHashtable _ ->
8160            pr "  if (r == NULL) return -1;\n";
8161            pr "  print_table (r);\n";
8162            pr "  free_strings (r);\n";
8163            pr "  return 0;\n"
8164        | RBufferOut _ ->
8165            pr "  if (r == NULL) return -1;\n";
8166            pr "  if (full_write (1, r, size) != size) {\n";
8167            pr "    perror (\"write\");\n";
8168            pr "    free (r);\n";
8169            pr "    return -1;\n";
8170            pr "  }\n";
8171            pr "  free (r);\n";
8172            pr "  return 0;\n"
8173       );
8174       pr "}\n";
8175       pr "\n"
8176   ) all_functions;
8177
8178   (* run_action function *)
8179   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
8180   pr "{\n";
8181   List.iter (
8182     fun (name, _, _, flags, _, _, _) ->
8183       let name2 = replace_char name '_' '-' in
8184       let alias =
8185         try find_map (function FishAlias n -> Some n | _ -> None) flags
8186         with Not_found -> name in
8187       pr "  if (";
8188       pr "STRCASEEQ (cmd, \"%s\")" name;
8189       if name <> name2 then
8190         pr " || STRCASEEQ (cmd, \"%s\")" name2;
8191       if name <> alias then
8192         pr " || STRCASEEQ (cmd, \"%s\")" alias;
8193       pr ")\n";
8194       pr "    return run_%s (cmd, argc, argv);\n" name;
8195       pr "  else\n";
8196   ) all_functions;
8197   pr "    {\n";
8198   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
8199   pr "      if (command_num == 1)\n";
8200   pr "        extended_help_message ();\n";
8201   pr "      return -1;\n";
8202   pr "    }\n";
8203   pr "  return 0;\n";
8204   pr "}\n";
8205   pr "\n"
8206
8207 (* Readline completion for guestfish. *)
8208 and generate_fish_completion () =
8209   generate_header CStyle GPLv2plus;
8210
8211   let all_functions =
8212     List.filter (
8213       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
8214     ) all_functions in
8215
8216   pr "\
8217 #include <config.h>
8218
8219 #include <stdio.h>
8220 #include <stdlib.h>
8221 #include <string.h>
8222
8223 #ifdef HAVE_LIBREADLINE
8224 #include <readline/readline.h>
8225 #endif
8226
8227 #include \"fish.h\"
8228
8229 #ifdef HAVE_LIBREADLINE
8230
8231 static const char *const commands[] = {
8232   BUILTIN_COMMANDS_FOR_COMPLETION,
8233 ";
8234
8235   (* Get the commands, including the aliases.  They don't need to be
8236    * sorted - the generator() function just does a dumb linear search.
8237    *)
8238   let commands =
8239     List.map (
8240       fun (name, _, _, flags, _, _, _) ->
8241         let name2 = replace_char name '_' '-' in
8242         let alias =
8243           try find_map (function FishAlias n -> Some n | _ -> None) flags
8244           with Not_found -> name in
8245
8246         if name <> alias then [name2; alias] else [name2]
8247     ) all_functions in
8248   let commands = List.flatten commands in
8249
8250   List.iter (pr "  \"%s\",\n") commands;
8251
8252   pr "  NULL
8253 };
8254
8255 static char *
8256 generator (const char *text, int state)
8257 {
8258   static size_t index, len;
8259   const char *name;
8260
8261   if (!state) {
8262     index = 0;
8263     len = strlen (text);
8264   }
8265
8266   rl_attempted_completion_over = 1;
8267
8268   while ((name = commands[index]) != NULL) {
8269     index++;
8270     if (STRCASEEQLEN (name, text, len))
8271       return strdup (name);
8272   }
8273
8274   return NULL;
8275 }
8276
8277 #endif /* HAVE_LIBREADLINE */
8278
8279 #ifdef HAVE_RL_COMPLETION_MATCHES
8280 #define RL_COMPLETION_MATCHES rl_completion_matches
8281 #else
8282 #ifdef HAVE_COMPLETION_MATCHES
8283 #define RL_COMPLETION_MATCHES completion_matches
8284 #endif
8285 #endif /* else just fail if we don't have either symbol */
8286
8287 char **
8288 do_completion (const char *text, int start, int end)
8289 {
8290   char **matches = NULL;
8291
8292 #ifdef HAVE_LIBREADLINE
8293   rl_completion_append_character = ' ';
8294
8295   if (start == 0)
8296     matches = RL_COMPLETION_MATCHES (text, generator);
8297   else if (complete_dest_paths)
8298     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8299 #endif
8300
8301   return matches;
8302 }
8303 ";
8304
8305 (* Generate the POD documentation for guestfish. *)
8306 and generate_fish_actions_pod () =
8307   let all_functions_sorted =
8308     List.filter (
8309       fun (_, _, _, flags, _, _, _) ->
8310         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8311     ) all_functions_sorted in
8312
8313   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8314
8315   List.iter (
8316     fun (name, style, _, flags, _, _, longdesc) ->
8317       let longdesc =
8318         Str.global_substitute rex (
8319           fun s ->
8320             let sub =
8321               try Str.matched_group 1 s
8322               with Not_found ->
8323                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8324             "C<" ^ replace_char sub '_' '-' ^ ">"
8325         ) longdesc in
8326       let name = replace_char name '_' '-' in
8327       let alias =
8328         try find_map (function FishAlias n -> Some n | _ -> None) flags
8329         with Not_found -> name in
8330
8331       pr "=head2 %s" name;
8332       if name <> alias then
8333         pr " | %s" alias;
8334       pr "\n";
8335       pr "\n";
8336       pr " %s" name;
8337       List.iter (
8338         function
8339         | Pathname n | Device n | Dev_or_Path n | String n ->
8340             pr " %s" n
8341         | OptString n -> pr " %s" n
8342         | StringList n | DeviceList n -> pr " '%s ...'" n
8343         | Bool _ -> pr " true|false"
8344         | Int n -> pr " %s" n
8345         | Int64 n -> pr " %s" n
8346         | FileIn n | FileOut n -> pr " (%s|-)" n
8347         | BufferIn n -> pr " %s" n
8348         | Key _ -> () (* keys are entered at a prompt *)
8349       ) (snd style);
8350       pr "\n";
8351       pr "\n";
8352       pr "%s\n\n" longdesc;
8353
8354       if List.exists (function FileIn _ | FileOut _ -> true
8355                       | _ -> false) (snd style) then
8356         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8357
8358       if List.exists (function Key _ -> true | _ -> false) (snd style) then
8359         pr "This command has one or more key or passphrase parameters.
8360 Guestfish will prompt for these separately.\n\n";
8361
8362       if List.mem ProtocolLimitWarning flags then
8363         pr "%s\n\n" protocol_limit_warning;
8364
8365       if List.mem DangerWillRobinson flags then
8366         pr "%s\n\n" danger_will_robinson;
8367
8368       match deprecation_notice flags with
8369       | None -> ()
8370       | Some txt -> pr "%s\n\n" txt
8371   ) all_functions_sorted
8372
8373 (* Generate a C function prototype. *)
8374 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8375     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8376     ?(prefix = "")
8377     ?handle name style =
8378   if extern then pr "extern ";
8379   if static then pr "static ";
8380   (match fst style with
8381    | RErr -> pr "int "
8382    | RInt _ -> pr "int "
8383    | RInt64 _ -> pr "int64_t "
8384    | RBool _ -> pr "int "
8385    | RConstString _ | RConstOptString _ -> pr "const char *"
8386    | RString _ | RBufferOut _ -> pr "char *"
8387    | RStringList _ | RHashtable _ -> pr "char **"
8388    | RStruct (_, typ) ->
8389        if not in_daemon then pr "struct guestfs_%s *" typ
8390        else pr "guestfs_int_%s *" typ
8391    | RStructList (_, typ) ->
8392        if not in_daemon then pr "struct guestfs_%s_list *" typ
8393        else pr "guestfs_int_%s_list *" typ
8394   );
8395   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8396   pr "%s%s (" prefix name;
8397   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8398     pr "void"
8399   else (
8400     let comma = ref false in
8401     (match handle with
8402      | None -> ()
8403      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8404     );
8405     let next () =
8406       if !comma then (
8407         if single_line then pr ", " else pr ",\n\t\t"
8408       );
8409       comma := true
8410     in
8411     List.iter (
8412       function
8413       | Pathname n
8414       | Device n | Dev_or_Path n
8415       | String n
8416       | OptString n
8417       | Key n ->
8418           next ();
8419           pr "const char *%s" n
8420       | StringList n | DeviceList n ->
8421           next ();
8422           pr "char *const *%s" n
8423       | Bool n -> next (); pr "int %s" n
8424       | Int n -> next (); pr "int %s" n
8425       | Int64 n -> next (); pr "int64_t %s" n
8426       | FileIn n
8427       | FileOut n ->
8428           if not in_daemon then (next (); pr "const char *%s" n)
8429       | BufferIn n ->
8430           next ();
8431           pr "const char *%s" n;
8432           next ();
8433           pr "size_t %s_size" n
8434     ) (snd style);
8435     if is_RBufferOut then (next (); pr "size_t *size_r");
8436   );
8437   pr ")";
8438   if semicolon then pr ";";
8439   if newline then pr "\n"
8440
8441 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8442 and generate_c_call_args ?handle ?(decl = false) style =
8443   pr "(";
8444   let comma = ref false in
8445   let next () =
8446     if !comma then pr ", ";
8447     comma := true
8448   in
8449   (match handle with
8450    | None -> ()
8451    | Some handle -> pr "%s" handle; comma := true
8452   );
8453   List.iter (
8454     function
8455     | BufferIn n ->
8456         next ();
8457         pr "%s, %s_size" n n
8458     | arg ->
8459         next ();
8460         pr "%s" (name_of_argt arg)
8461   ) (snd style);
8462   (* For RBufferOut calls, add implicit &size parameter. *)
8463   if not decl then (
8464     match fst style with
8465     | RBufferOut _ ->
8466         next ();
8467         pr "&size"
8468     | _ -> ()
8469   );
8470   pr ")"
8471
8472 (* Generate the OCaml bindings interface. *)
8473 and generate_ocaml_mli () =
8474   generate_header OCamlStyle LGPLv2plus;
8475
8476   pr "\
8477 (** For API documentation you should refer to the C API
8478     in the guestfs(3) manual page.  The OCaml API uses almost
8479     exactly the same calls. *)
8480
8481 type t
8482 (** A [guestfs_h] handle. *)
8483
8484 exception Error of string
8485 (** This exception is raised when there is an error. *)
8486
8487 exception Handle_closed of string
8488 (** This exception is raised if you use a {!Guestfs.t} handle
8489     after calling {!close} on it.  The string is the name of
8490     the function. *)
8491
8492 val create : unit -> t
8493 (** Create a {!Guestfs.t} handle. *)
8494
8495 val close : t -> unit
8496 (** Close the {!Guestfs.t} handle and free up all resources used
8497     by it immediately.
8498
8499     Handles are closed by the garbage collector when they become
8500     unreferenced, but callers can call this in order to provide
8501     predictable cleanup. *)
8502
8503 ";
8504   generate_ocaml_structure_decls ();
8505
8506   (* The actions. *)
8507   List.iter (
8508     fun (name, style, _, _, _, shortdesc, _) ->
8509       generate_ocaml_prototype name style;
8510       pr "(** %s *)\n" shortdesc;
8511       pr "\n"
8512   ) all_functions_sorted
8513
8514 (* Generate the OCaml bindings implementation. *)
8515 and generate_ocaml_ml () =
8516   generate_header OCamlStyle LGPLv2plus;
8517
8518   pr "\
8519 type t
8520
8521 exception Error of string
8522 exception Handle_closed of string
8523
8524 external create : unit -> t = \"ocaml_guestfs_create\"
8525 external close : t -> unit = \"ocaml_guestfs_close\"
8526
8527 (* Give the exceptions names, so they can be raised from the C code. *)
8528 let () =
8529   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8530   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8531
8532 ";
8533
8534   generate_ocaml_structure_decls ();
8535
8536   (* The actions. *)
8537   List.iter (
8538     fun (name, style, _, _, _, shortdesc, _) ->
8539       generate_ocaml_prototype ~is_external:true name style;
8540   ) all_functions_sorted
8541
8542 (* Generate the OCaml bindings C implementation. *)
8543 and generate_ocaml_c () =
8544   generate_header CStyle LGPLv2plus;
8545
8546   pr "\
8547 #include <stdio.h>
8548 #include <stdlib.h>
8549 #include <string.h>
8550
8551 #include <caml/config.h>
8552 #include <caml/alloc.h>
8553 #include <caml/callback.h>
8554 #include <caml/fail.h>
8555 #include <caml/memory.h>
8556 #include <caml/mlvalues.h>
8557 #include <caml/signals.h>
8558
8559 #include \"guestfs.h\"
8560
8561 #include \"guestfs_c.h\"
8562
8563 /* Copy a hashtable of string pairs into an assoc-list.  We return
8564  * the list in reverse order, but hashtables aren't supposed to be
8565  * ordered anyway.
8566  */
8567 static CAMLprim value
8568 copy_table (char * const * argv)
8569 {
8570   CAMLparam0 ();
8571   CAMLlocal5 (rv, pairv, kv, vv, cons);
8572   size_t i;
8573
8574   rv = Val_int (0);
8575   for (i = 0; argv[i] != NULL; i += 2) {
8576     kv = caml_copy_string (argv[i]);
8577     vv = caml_copy_string (argv[i+1]);
8578     pairv = caml_alloc (2, 0);
8579     Store_field (pairv, 0, kv);
8580     Store_field (pairv, 1, vv);
8581     cons = caml_alloc (2, 0);
8582     Store_field (cons, 1, rv);
8583     rv = cons;
8584     Store_field (cons, 0, pairv);
8585   }
8586
8587   CAMLreturn (rv);
8588 }
8589
8590 ";
8591
8592   (* Struct copy functions. *)
8593
8594   let emit_ocaml_copy_list_function typ =
8595     pr "static CAMLprim value\n";
8596     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8597     pr "{\n";
8598     pr "  CAMLparam0 ();\n";
8599     pr "  CAMLlocal2 (rv, v);\n";
8600     pr "  unsigned int i;\n";
8601     pr "\n";
8602     pr "  if (%ss->len == 0)\n" typ;
8603     pr "    CAMLreturn (Atom (0));\n";
8604     pr "  else {\n";
8605     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8606     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8607     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8608     pr "      caml_modify (&Field (rv, i), v);\n";
8609     pr "    }\n";
8610     pr "    CAMLreturn (rv);\n";
8611     pr "  }\n";
8612     pr "}\n";
8613     pr "\n";
8614   in
8615
8616   List.iter (
8617     fun (typ, cols) ->
8618       let has_optpercent_col =
8619         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8620
8621       pr "static CAMLprim value\n";
8622       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8623       pr "{\n";
8624       pr "  CAMLparam0 ();\n";
8625       if has_optpercent_col then
8626         pr "  CAMLlocal3 (rv, v, v2);\n"
8627       else
8628         pr "  CAMLlocal2 (rv, v);\n";
8629       pr "\n";
8630       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8631       iteri (
8632         fun i col ->
8633           (match col with
8634            | name, FString ->
8635                pr "  v = caml_copy_string (%s->%s);\n" typ name
8636            | name, FBuffer ->
8637                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8638                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8639                  typ name typ name
8640            | name, FUUID ->
8641                pr "  v = caml_alloc_string (32);\n";
8642                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8643            | name, (FBytes|FInt64|FUInt64) ->
8644                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8645            | name, (FInt32|FUInt32) ->
8646                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8647            | name, FOptPercent ->
8648                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8649                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8650                pr "    v = caml_alloc (1, 0);\n";
8651                pr "    Store_field (v, 0, v2);\n";
8652                pr "  } else /* None */\n";
8653                pr "    v = Val_int (0);\n";
8654            | name, FChar ->
8655                pr "  v = Val_int (%s->%s);\n" typ name
8656           );
8657           pr "  Store_field (rv, %d, v);\n" i
8658       ) cols;
8659       pr "  CAMLreturn (rv);\n";
8660       pr "}\n";
8661       pr "\n";
8662   ) structs;
8663
8664   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8665   List.iter (
8666     function
8667     | typ, (RStructListOnly | RStructAndList) ->
8668         (* generate the function for typ *)
8669         emit_ocaml_copy_list_function typ
8670     | typ, _ -> () (* empty *)
8671   ) (rstructs_used_by all_functions);
8672
8673   (* The wrappers. *)
8674   List.iter (
8675     fun (name, style, _, _, _, _, _) ->
8676       pr "/* Automatically generated wrapper for function\n";
8677       pr " * ";
8678       generate_ocaml_prototype name style;
8679       pr " */\n";
8680       pr "\n";
8681
8682       let params =
8683         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8684
8685       let needs_extra_vs =
8686         match fst style with RConstOptString _ -> true | _ -> false in
8687
8688       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8689       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8690       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8691       pr "\n";
8692
8693       pr "CAMLprim value\n";
8694       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8695       List.iter (pr ", value %s") (List.tl params);
8696       pr ")\n";
8697       pr "{\n";
8698
8699       (match params with
8700        | [p1; p2; p3; p4; p5] ->
8701            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8702        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8703            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8704            pr "  CAMLxparam%d (%s);\n"
8705              (List.length rest) (String.concat ", " rest)
8706        | ps ->
8707            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8708       );
8709       if not needs_extra_vs then
8710         pr "  CAMLlocal1 (rv);\n"
8711       else
8712         pr "  CAMLlocal3 (rv, v, v2);\n";
8713       pr "\n";
8714
8715       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8716       pr "  if (g == NULL)\n";
8717       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8718       pr "\n";
8719
8720       List.iter (
8721         function
8722         | Pathname n
8723         | Device n | Dev_or_Path n
8724         | String n
8725         | FileIn n
8726         | FileOut n
8727         | Key n ->
8728             (* Copy strings in case the GC moves them: RHBZ#604691 *)
8729             pr "  char *%s = guestfs_safe_strdup (g, String_val (%sv));\n" n n
8730         | OptString n ->
8731             pr "  char *%s =\n" n;
8732             pr "    %sv != Val_int (0) ?" n;
8733             pr "      guestfs_safe_strdup (g, String_val (Field (%sv, 0))) : NULL;\n" n
8734         | BufferIn n ->
8735             pr "  size_t %s_size = caml_string_length (%sv);\n" n n;
8736             pr "  char *%s = guestfs_safe_memdup (g, String_val (%sv), %s_size);\n" n n n
8737         | StringList n | DeviceList n ->
8738             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8739         | Bool n ->
8740             pr "  int %s = Bool_val (%sv);\n" n n
8741         | Int n ->
8742             pr "  int %s = Int_val (%sv);\n" n n
8743         | Int64 n ->
8744             pr "  int64_t %s = Int64_val (%sv);\n" n n
8745       ) (snd style);
8746       let error_code =
8747         match fst style with
8748         | RErr -> pr "  int r;\n"; "-1"
8749         | RInt _ -> pr "  int r;\n"; "-1"
8750         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8751         | RBool _ -> pr "  int r;\n"; "-1"
8752         | RConstString _ | RConstOptString _ ->
8753             pr "  const char *r;\n"; "NULL"
8754         | RString _ -> pr "  char *r;\n"; "NULL"
8755         | RStringList _ ->
8756             pr "  size_t i;\n";
8757             pr "  char **r;\n";
8758             "NULL"
8759         | RStruct (_, typ) ->
8760             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8761         | RStructList (_, typ) ->
8762             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8763         | RHashtable _ ->
8764             pr "  size_t i;\n";
8765             pr "  char **r;\n";
8766             "NULL"
8767         | RBufferOut _ ->
8768             pr "  char *r;\n";
8769             pr "  size_t size;\n";
8770             "NULL" in
8771       pr "\n";
8772
8773       pr "  caml_enter_blocking_section ();\n";
8774       pr "  r = guestfs_%s " name;
8775       generate_c_call_args ~handle:"g" style;
8776       pr ";\n";
8777       pr "  caml_leave_blocking_section ();\n";
8778
8779       (* Free strings if we copied them above. *)
8780       List.iter (
8781         function
8782         | Pathname n | Device n | Dev_or_Path n | String n | OptString n
8783         | FileIn n | FileOut n | BufferIn n | Key n ->
8784             pr "  free (%s);\n" n
8785         | StringList n | DeviceList n ->
8786             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8787         | Bool _ | Int _ | Int64 _ -> ()
8788       ) (snd style);
8789
8790       pr "  if (r == %s)\n" error_code;
8791       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8792       pr "\n";
8793
8794       (match fst style with
8795        | RErr -> pr "  rv = Val_unit;\n"
8796        | RInt _ -> pr "  rv = Val_int (r);\n"
8797        | RInt64 _ ->
8798            pr "  rv = caml_copy_int64 (r);\n"
8799        | RBool _ -> pr "  rv = Val_bool (r);\n"
8800        | RConstString _ ->
8801            pr "  rv = caml_copy_string (r);\n"
8802        | RConstOptString _ ->
8803            pr "  if (r) { /* Some string */\n";
8804            pr "    v = caml_alloc (1, 0);\n";
8805            pr "    v2 = caml_copy_string (r);\n";
8806            pr "    Store_field (v, 0, v2);\n";
8807            pr "  } else /* None */\n";
8808            pr "    v = Val_int (0);\n";
8809        | RString _ ->
8810            pr "  rv = caml_copy_string (r);\n";
8811            pr "  free (r);\n"
8812        | RStringList _ ->
8813            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8814            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8815            pr "  free (r);\n"
8816        | RStruct (_, typ) ->
8817            pr "  rv = copy_%s (r);\n" typ;
8818            pr "  guestfs_free_%s (r);\n" typ;
8819        | RStructList (_, typ) ->
8820            pr "  rv = copy_%s_list (r);\n" typ;
8821            pr "  guestfs_free_%s_list (r);\n" typ;
8822        | RHashtable _ ->
8823            pr "  rv = copy_table (r);\n";
8824            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8825            pr "  free (r);\n";
8826        | RBufferOut _ ->
8827            pr "  rv = caml_alloc_string (size);\n";
8828            pr "  memcpy (String_val (rv), r, size);\n";
8829       );
8830
8831       pr "  CAMLreturn (rv);\n";
8832       pr "}\n";
8833       pr "\n";
8834
8835       if List.length params > 5 then (
8836         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8837         pr "CAMLprim value ";
8838         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8839         pr "CAMLprim value\n";
8840         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8841         pr "{\n";
8842         pr "  return ocaml_guestfs_%s (argv[0]" name;
8843         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8844         pr ");\n";
8845         pr "}\n";
8846         pr "\n"
8847       )
8848   ) all_functions_sorted
8849
8850 and generate_ocaml_structure_decls () =
8851   List.iter (
8852     fun (typ, cols) ->
8853       pr "type %s = {\n" typ;
8854       List.iter (
8855         function
8856         | name, FString -> pr "  %s : string;\n" name
8857         | name, FBuffer -> pr "  %s : string;\n" name
8858         | name, FUUID -> pr "  %s : string;\n" name
8859         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8860         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8861         | name, FChar -> pr "  %s : char;\n" name
8862         | name, FOptPercent -> pr "  %s : float option;\n" name
8863       ) cols;
8864       pr "}\n";
8865       pr "\n"
8866   ) structs
8867
8868 and generate_ocaml_prototype ?(is_external = false) name style =
8869   if is_external then pr "external " else pr "val ";
8870   pr "%s : t -> " name;
8871   List.iter (
8872     function
8873     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8874     | BufferIn _ | Key _ -> pr "string -> "
8875     | OptString _ -> pr "string option -> "
8876     | StringList _ | DeviceList _ -> pr "string array -> "
8877     | Bool _ -> pr "bool -> "
8878     | Int _ -> pr "int -> "
8879     | Int64 _ -> pr "int64 -> "
8880   ) (snd style);
8881   (match fst style with
8882    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8883    | RInt _ -> pr "int"
8884    | RInt64 _ -> pr "int64"
8885    | RBool _ -> pr "bool"
8886    | RConstString _ -> pr "string"
8887    | RConstOptString _ -> pr "string option"
8888    | RString _ | RBufferOut _ -> pr "string"
8889    | RStringList _ -> pr "string array"
8890    | RStruct (_, typ) -> pr "%s" typ
8891    | RStructList (_, typ) -> pr "%s array" typ
8892    | RHashtable _ -> pr "(string * string) list"
8893   );
8894   if is_external then (
8895     pr " = ";
8896     if List.length (snd style) + 1 > 5 then
8897       pr "\"ocaml_guestfs_%s_byte\" " name;
8898     pr "\"ocaml_guestfs_%s\"" name
8899   );
8900   pr "\n"
8901
8902 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8903 and generate_perl_xs () =
8904   generate_header CStyle LGPLv2plus;
8905
8906   pr "\
8907 #include \"EXTERN.h\"
8908 #include \"perl.h\"
8909 #include \"XSUB.h\"
8910
8911 #include <guestfs.h>
8912
8913 #ifndef PRId64
8914 #define PRId64 \"lld\"
8915 #endif
8916
8917 static SV *
8918 my_newSVll(long long val) {
8919 #ifdef USE_64_BIT_ALL
8920   return newSViv(val);
8921 #else
8922   char buf[100];
8923   int len;
8924   len = snprintf(buf, 100, \"%%\" PRId64, val);
8925   return newSVpv(buf, len);
8926 #endif
8927 }
8928
8929 #ifndef PRIu64
8930 #define PRIu64 \"llu\"
8931 #endif
8932
8933 static SV *
8934 my_newSVull(unsigned long long val) {
8935 #ifdef USE_64_BIT_ALL
8936   return newSVuv(val);
8937 #else
8938   char buf[100];
8939   int len;
8940   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8941   return newSVpv(buf, len);
8942 #endif
8943 }
8944
8945 /* http://www.perlmonks.org/?node_id=680842 */
8946 static char **
8947 XS_unpack_charPtrPtr (SV *arg) {
8948   char **ret;
8949   AV *av;
8950   I32 i;
8951
8952   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8953     croak (\"array reference expected\");
8954
8955   av = (AV *)SvRV (arg);
8956   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8957   if (!ret)
8958     croak (\"malloc failed\");
8959
8960   for (i = 0; i <= av_len (av); i++) {
8961     SV **elem = av_fetch (av, i, 0);
8962
8963     if (!elem || !*elem)
8964       croak (\"missing element in list\");
8965
8966     ret[i] = SvPV_nolen (*elem);
8967   }
8968
8969   ret[i] = NULL;
8970
8971   return ret;
8972 }
8973
8974 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8975
8976 PROTOTYPES: ENABLE
8977
8978 guestfs_h *
8979 _create ()
8980    CODE:
8981       RETVAL = guestfs_create ();
8982       if (!RETVAL)
8983         croak (\"could not create guestfs handle\");
8984       guestfs_set_error_handler (RETVAL, NULL, NULL);
8985  OUTPUT:
8986       RETVAL
8987
8988 void
8989 DESTROY (sv)
8990       SV *sv;
8991  PPCODE:
8992       /* For the 'g' argument above we do the conversion explicitly and
8993        * don't rely on the typemap, because if the handle has been
8994        * explicitly closed we don't want the typemap conversion to
8995        * display an error.
8996        */
8997       HV *hv = (HV *) SvRV (sv);
8998       SV **svp = hv_fetch (hv, \"_g\", 2, 0);
8999       if (svp != NULL) {
9000         guestfs_h *g = (guestfs_h *) SvIV (*svp);
9001         assert (g != NULL);
9002         guestfs_close (g);
9003       }
9004
9005 void
9006 close (g)
9007       guestfs_h *g;
9008  PPCODE:
9009       guestfs_close (g);
9010       /* Avoid double-free in DESTROY method. */
9011       HV *hv = (HV *) SvRV (ST(0));
9012       (void) hv_delete (hv, \"_g\", 2, G_DISCARD);
9013
9014 ";
9015
9016   List.iter (
9017     fun (name, style, _, _, _, _, _) ->
9018       (match fst style with
9019        | RErr -> pr "void\n"
9020        | RInt _ -> pr "SV *\n"
9021        | RInt64 _ -> pr "SV *\n"
9022        | RBool _ -> pr "SV *\n"
9023        | RConstString _ -> pr "SV *\n"
9024        | RConstOptString _ -> pr "SV *\n"
9025        | RString _ -> pr "SV *\n"
9026        | RBufferOut _ -> pr "SV *\n"
9027        | RStringList _
9028        | RStruct _ | RStructList _
9029        | RHashtable _ ->
9030            pr "void\n" (* all lists returned implictly on the stack *)
9031       );
9032       (* Call and arguments. *)
9033       pr "%s (g" name;
9034       List.iter (
9035         fun arg -> pr ", %s" (name_of_argt arg)
9036       ) (snd style);
9037       pr ")\n";
9038       pr "      guestfs_h *g;\n";
9039       iteri (
9040         fun i ->
9041           function
9042           | Pathname n | Device n | Dev_or_Path n | String n
9043           | FileIn n | FileOut n | Key n ->
9044               pr "      char *%s;\n" n
9045           | BufferIn n ->
9046               pr "      char *%s;\n" n;
9047               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
9048           | OptString n ->
9049               (* http://www.perlmonks.org/?node_id=554277
9050                * Note that the implicit handle argument means we have
9051                * to add 1 to the ST(x) operator.
9052                *)
9053               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
9054           | StringList n | DeviceList n -> pr "      char **%s;\n" n
9055           | Bool n -> pr "      int %s;\n" n
9056           | Int n -> pr "      int %s;\n" n
9057           | Int64 n -> pr "      int64_t %s;\n" n
9058       ) (snd style);
9059
9060       let do_cleanups () =
9061         List.iter (
9062           function
9063           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
9064           | Bool _ | Int _ | Int64 _
9065           | FileIn _ | FileOut _
9066           | BufferIn _ | Key _ -> ()
9067           | StringList n | DeviceList n -> pr "      free (%s);\n" n
9068         ) (snd style)
9069       in
9070
9071       (* Code. *)
9072       (match fst style with
9073        | RErr ->
9074            pr "PREINIT:\n";
9075            pr "      int r;\n";
9076            pr " PPCODE:\n";
9077            pr "      r = guestfs_%s " name;
9078            generate_c_call_args ~handle:"g" style;
9079            pr ";\n";
9080            do_cleanups ();
9081            pr "      if (r == -1)\n";
9082            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9083        | RInt n
9084        | RBool n ->
9085            pr "PREINIT:\n";
9086            pr "      int %s;\n" n;
9087            pr "   CODE:\n";
9088            pr "      %s = guestfs_%s " n name;
9089            generate_c_call_args ~handle:"g" style;
9090            pr ";\n";
9091            do_cleanups ();
9092            pr "      if (%s == -1)\n" n;
9093            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9094            pr "      RETVAL = newSViv (%s);\n" n;
9095            pr " OUTPUT:\n";
9096            pr "      RETVAL\n"
9097        | RInt64 n ->
9098            pr "PREINIT:\n";
9099            pr "      int64_t %s;\n" n;
9100            pr "   CODE:\n";
9101            pr "      %s = guestfs_%s " n name;
9102            generate_c_call_args ~handle:"g" style;
9103            pr ";\n";
9104            do_cleanups ();
9105            pr "      if (%s == -1)\n" n;
9106            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9107            pr "      RETVAL = my_newSVll (%s);\n" n;
9108            pr " OUTPUT:\n";
9109            pr "      RETVAL\n"
9110        | RConstString n ->
9111            pr "PREINIT:\n";
9112            pr "      const char *%s;\n" n;
9113            pr "   CODE:\n";
9114            pr "      %s = guestfs_%s " n name;
9115            generate_c_call_args ~handle:"g" style;
9116            pr ";\n";
9117            do_cleanups ();
9118            pr "      if (%s == NULL)\n" n;
9119            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9120            pr "      RETVAL = newSVpv (%s, 0);\n" n;
9121            pr " OUTPUT:\n";
9122            pr "      RETVAL\n"
9123        | RConstOptString n ->
9124            pr "PREINIT:\n";
9125            pr "      const char *%s;\n" n;
9126            pr "   CODE:\n";
9127            pr "      %s = guestfs_%s " n name;
9128            generate_c_call_args ~handle:"g" style;
9129            pr ";\n";
9130            do_cleanups ();
9131            pr "      if (%s == NULL)\n" n;
9132            pr "        RETVAL = &PL_sv_undef;\n";
9133            pr "      else\n";
9134            pr "        RETVAL = newSVpv (%s, 0);\n" n;
9135            pr " OUTPUT:\n";
9136            pr "      RETVAL\n"
9137        | RString n ->
9138            pr "PREINIT:\n";
9139            pr "      char *%s;\n" n;
9140            pr "   CODE:\n";
9141            pr "      %s = guestfs_%s " n name;
9142            generate_c_call_args ~handle:"g" style;
9143            pr ";\n";
9144            do_cleanups ();
9145            pr "      if (%s == NULL)\n" n;
9146            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9147            pr "      RETVAL = newSVpv (%s, 0);\n" n;
9148            pr "      free (%s);\n" n;
9149            pr " OUTPUT:\n";
9150            pr "      RETVAL\n"
9151        | RStringList n | RHashtable n ->
9152            pr "PREINIT:\n";
9153            pr "      char **%s;\n" n;
9154            pr "      size_t i, n;\n";
9155            pr " PPCODE:\n";
9156            pr "      %s = guestfs_%s " n name;
9157            generate_c_call_args ~handle:"g" style;
9158            pr ";\n";
9159            do_cleanups ();
9160            pr "      if (%s == NULL)\n" n;
9161            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9162            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
9163            pr "      EXTEND (SP, n);\n";
9164            pr "      for (i = 0; i < n; ++i) {\n";
9165            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
9166            pr "        free (%s[i]);\n" n;
9167            pr "      }\n";
9168            pr "      free (%s);\n" n;
9169        | RStruct (n, typ) ->
9170            let cols = cols_of_struct typ in
9171            generate_perl_struct_code typ cols name style n do_cleanups
9172        | RStructList (n, typ) ->
9173            let cols = cols_of_struct typ in
9174            generate_perl_struct_list_code typ cols name style n do_cleanups
9175        | RBufferOut n ->
9176            pr "PREINIT:\n";
9177            pr "      char *%s;\n" n;
9178            pr "      size_t size;\n";
9179            pr "   CODE:\n";
9180            pr "      %s = guestfs_%s " n name;
9181            generate_c_call_args ~handle:"g" style;
9182            pr ";\n";
9183            do_cleanups ();
9184            pr "      if (%s == NULL)\n" n;
9185            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9186            pr "      RETVAL = newSVpvn (%s, size);\n" n;
9187            pr "      free (%s);\n" n;
9188            pr " OUTPUT:\n";
9189            pr "      RETVAL\n"
9190       );
9191
9192       pr "\n"
9193   ) all_functions
9194
9195 and generate_perl_struct_list_code typ cols name style n do_cleanups =
9196   pr "PREINIT:\n";
9197   pr "      struct guestfs_%s_list *%s;\n" typ n;
9198   pr "      size_t i;\n";
9199   pr "      HV *hv;\n";
9200   pr " PPCODE:\n";
9201   pr "      %s = guestfs_%s " n name;
9202   generate_c_call_args ~handle:"g" style;
9203   pr ";\n";
9204   do_cleanups ();
9205   pr "      if (%s == NULL)\n" n;
9206   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9207   pr "      EXTEND (SP, %s->len);\n" n;
9208   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
9209   pr "        hv = newHV ();\n";
9210   List.iter (
9211     function
9212     | name, FString ->
9213         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
9214           name (String.length name) n name
9215     | name, FUUID ->
9216         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
9217           name (String.length name) n name
9218     | name, FBuffer ->
9219         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
9220           name (String.length name) n name n name
9221     | name, (FBytes|FUInt64) ->
9222         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
9223           name (String.length name) n name
9224     | name, FInt64 ->
9225         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
9226           name (String.length name) n name
9227     | name, (FInt32|FUInt32) ->
9228         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9229           name (String.length name) n name
9230     | name, FChar ->
9231         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
9232           name (String.length name) n name
9233     | name, FOptPercent ->
9234         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9235           name (String.length name) n name
9236   ) cols;
9237   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
9238   pr "      }\n";
9239   pr "      guestfs_free_%s_list (%s);\n" typ n
9240
9241 and generate_perl_struct_code typ cols name style n do_cleanups =
9242   pr "PREINIT:\n";
9243   pr "      struct guestfs_%s *%s;\n" typ n;
9244   pr " PPCODE:\n";
9245   pr "      %s = guestfs_%s " n name;
9246   generate_c_call_args ~handle:"g" style;
9247   pr ";\n";
9248   do_cleanups ();
9249   pr "      if (%s == NULL)\n" n;
9250   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9251   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
9252   List.iter (
9253     fun ((name, _) as col) ->
9254       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
9255
9256       match col with
9257       | name, FString ->
9258           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
9259             n name
9260       | name, FBuffer ->
9261           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
9262             n name n name
9263       | name, FUUID ->
9264           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
9265             n name
9266       | name, (FBytes|FUInt64) ->
9267           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
9268             n name
9269       | name, FInt64 ->
9270           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
9271             n name
9272       | name, (FInt32|FUInt32) ->
9273           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9274             n name
9275       | name, FChar ->
9276           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9277             n name
9278       | name, FOptPercent ->
9279           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9280             n name
9281   ) cols;
9282   pr "      free (%s);\n" n
9283
9284 (* Generate Sys/Guestfs.pm. *)
9285 and generate_perl_pm () =
9286   generate_header HashStyle LGPLv2plus;
9287
9288   pr "\
9289 =pod
9290
9291 =head1 NAME
9292
9293 Sys::Guestfs - Perl bindings for libguestfs
9294
9295 =head1 SYNOPSIS
9296
9297  use Sys::Guestfs;
9298
9299  my $h = Sys::Guestfs->new ();
9300  $h->add_drive ('guest.img');
9301  $h->launch ();
9302  $h->mount ('/dev/sda1', '/');
9303  $h->touch ('/hello');
9304  $h->sync ();
9305
9306 =head1 DESCRIPTION
9307
9308 The C<Sys::Guestfs> module provides a Perl XS binding to the
9309 libguestfs API for examining and modifying virtual machine
9310 disk images.
9311
9312 Amongst the things this is good for: making batch configuration
9313 changes to guests, getting disk used/free statistics (see also:
9314 virt-df), migrating between virtualization systems (see also:
9315 virt-p2v), performing partial backups, performing partial guest
9316 clones, cloning guests and changing registry/UUID/hostname info, and
9317 much else besides.
9318
9319 Libguestfs uses Linux kernel and qemu code, and can access any type of
9320 guest filesystem that Linux and qemu can, including but not limited
9321 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9322 schemes, qcow, qcow2, vmdk.
9323
9324 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9325 LVs, what filesystem is in each LV, etc.).  It can also run commands
9326 in the context of the guest.  Also you can access filesystems over
9327 FUSE.
9328
9329 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9330 functions for using libguestfs from Perl, including integration
9331 with libvirt.
9332
9333 =head1 ERRORS
9334
9335 All errors turn into calls to C<croak> (see L<Carp(3)>).
9336
9337 =head1 METHODS
9338
9339 =over 4
9340
9341 =cut
9342
9343 package Sys::Guestfs;
9344
9345 use strict;
9346 use warnings;
9347
9348 # This version number changes whenever a new function
9349 # is added to the libguestfs API.  It is not directly
9350 # related to the libguestfs version number.
9351 use vars qw($VERSION);
9352 $VERSION = '0.%d';
9353
9354 require XSLoader;
9355 XSLoader::load ('Sys::Guestfs');
9356
9357 =item $h = Sys::Guestfs->new ();
9358
9359 Create a new guestfs handle.
9360
9361 =cut
9362
9363 sub new {
9364   my $proto = shift;
9365   my $class = ref ($proto) || $proto;
9366
9367   my $g = Sys::Guestfs::_create ();
9368   my $self = { _g => $g };
9369   bless $self, $class;
9370   return $self;
9371 }
9372
9373 =item $h->close ();
9374
9375 Explicitly close the guestfs handle.
9376
9377 B<Note:> You should not usually call this function.  The handle will
9378 be closed implicitly when its reference count goes to zero (eg.
9379 when it goes out of scope or the program ends).  This call is
9380 only required in some exceptional cases, such as where the program
9381 may contain cached references to the handle 'somewhere' and you
9382 really have to have the close happen right away.  After calling
9383 C<close> the program must not call any method (including C<close>)
9384 on the handle (but the implicit call to C<DESTROY> that happens
9385 when the final reference is cleaned up is OK).
9386
9387 =cut
9388
9389 " max_proc_nr;
9390
9391   (* Actions.  We only need to print documentation for these as
9392    * they are pulled in from the XS code automatically.
9393    *)
9394   List.iter (
9395     fun (name, style, _, flags, _, _, longdesc) ->
9396       if not (List.mem NotInDocs flags) then (
9397         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9398         pr "=item ";
9399         generate_perl_prototype name style;
9400         pr "\n\n";
9401         pr "%s\n\n" longdesc;
9402         if List.mem ProtocolLimitWarning flags then
9403           pr "%s\n\n" protocol_limit_warning;
9404         if List.mem DangerWillRobinson flags then
9405           pr "%s\n\n" danger_will_robinson;
9406         match deprecation_notice flags with
9407         | None -> ()
9408         | Some txt -> pr "%s\n\n" txt
9409       )
9410   ) all_functions_sorted;
9411
9412   (* End of file. *)
9413   pr "\
9414 =cut
9415
9416 1;
9417
9418 =back
9419
9420 =head1 COPYRIGHT
9421
9422 Copyright (C) %s Red Hat Inc.
9423
9424 =head1 LICENSE
9425
9426 Please see the file COPYING.LIB for the full license.
9427
9428 =head1 SEE ALSO
9429
9430 L<guestfs(3)>,
9431 L<guestfish(1)>,
9432 L<http://libguestfs.org>,
9433 L<Sys::Guestfs::Lib(3)>.
9434
9435 =cut
9436 " copyright_years
9437
9438 and generate_perl_prototype name style =
9439   (match fst style with
9440    | RErr -> ()
9441    | RBool n
9442    | RInt n
9443    | RInt64 n
9444    | RConstString n
9445    | RConstOptString n
9446    | RString n
9447    | RBufferOut n -> pr "$%s = " n
9448    | RStruct (n,_)
9449    | RHashtable n -> pr "%%%s = " n
9450    | RStringList n
9451    | RStructList (n,_) -> pr "@%s = " n
9452   );
9453   pr "$h->%s (" name;
9454   let comma = ref false in
9455   List.iter (
9456     fun arg ->
9457       if !comma then pr ", ";
9458       comma := true;
9459       match arg with
9460       | Pathname n | Device n | Dev_or_Path n | String n
9461       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9462       | BufferIn n | Key n ->
9463           pr "$%s" n
9464       | StringList n | DeviceList n ->
9465           pr "\\@%s" n
9466   ) (snd style);
9467   pr ");"
9468
9469 (* Generate Python C module. *)
9470 and generate_python_c () =
9471   generate_header CStyle LGPLv2plus;
9472
9473   pr "\
9474 #define PY_SSIZE_T_CLEAN 1
9475 #include <Python.h>
9476
9477 #if PY_VERSION_HEX < 0x02050000
9478 typedef int Py_ssize_t;
9479 #define PY_SSIZE_T_MAX INT_MAX
9480 #define PY_SSIZE_T_MIN INT_MIN
9481 #endif
9482
9483 #include <stdio.h>
9484 #include <stdlib.h>
9485 #include <assert.h>
9486
9487 #include \"guestfs.h\"
9488
9489 typedef struct {
9490   PyObject_HEAD
9491   guestfs_h *g;
9492 } Pyguestfs_Object;
9493
9494 static guestfs_h *
9495 get_handle (PyObject *obj)
9496 {
9497   assert (obj);
9498   assert (obj != Py_None);
9499   return ((Pyguestfs_Object *) obj)->g;
9500 }
9501
9502 static PyObject *
9503 put_handle (guestfs_h *g)
9504 {
9505   assert (g);
9506   return
9507     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9508 }
9509
9510 /* This list should be freed (but not the strings) after use. */
9511 static char **
9512 get_string_list (PyObject *obj)
9513 {
9514   size_t i, len;
9515   char **r;
9516
9517   assert (obj);
9518
9519   if (!PyList_Check (obj)) {
9520     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9521     return NULL;
9522   }
9523
9524   Py_ssize_t slen = PyList_Size (obj);
9525   if (slen == -1) {
9526     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
9527     return NULL;
9528   }
9529   len = (size_t) slen;
9530   r = malloc (sizeof (char *) * (len+1));
9531   if (r == NULL) {
9532     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9533     return NULL;
9534   }
9535
9536   for (i = 0; i < len; ++i)
9537     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9538   r[len] = NULL;
9539
9540   return r;
9541 }
9542
9543 static PyObject *
9544 put_string_list (char * const * const argv)
9545 {
9546   PyObject *list;
9547   int argc, i;
9548
9549   for (argc = 0; argv[argc] != NULL; ++argc)
9550     ;
9551
9552   list = PyList_New (argc);
9553   for (i = 0; i < argc; ++i)
9554     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9555
9556   return list;
9557 }
9558
9559 static PyObject *
9560 put_table (char * const * const argv)
9561 {
9562   PyObject *list, *item;
9563   int argc, i;
9564
9565   for (argc = 0; argv[argc] != NULL; ++argc)
9566     ;
9567
9568   list = PyList_New (argc >> 1);
9569   for (i = 0; i < argc; i += 2) {
9570     item = PyTuple_New (2);
9571     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9572     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9573     PyList_SetItem (list, i >> 1, item);
9574   }
9575
9576   return list;
9577 }
9578
9579 static void
9580 free_strings (char **argv)
9581 {
9582   int argc;
9583
9584   for (argc = 0; argv[argc] != NULL; ++argc)
9585     free (argv[argc]);
9586   free (argv);
9587 }
9588
9589 static PyObject *
9590 py_guestfs_create (PyObject *self, PyObject *args)
9591 {
9592   guestfs_h *g;
9593
9594   g = guestfs_create ();
9595   if (g == NULL) {
9596     PyErr_SetString (PyExc_RuntimeError,
9597                      \"guestfs.create: failed to allocate handle\");
9598     return NULL;
9599   }
9600   guestfs_set_error_handler (g, NULL, NULL);
9601   return put_handle (g);
9602 }
9603
9604 static PyObject *
9605 py_guestfs_close (PyObject *self, PyObject *args)
9606 {
9607   PyObject *py_g;
9608   guestfs_h *g;
9609
9610   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9611     return NULL;
9612   g = get_handle (py_g);
9613
9614   guestfs_close (g);
9615
9616   Py_INCREF (Py_None);
9617   return Py_None;
9618 }
9619
9620 ";
9621
9622   let emit_put_list_function typ =
9623     pr "static PyObject *\n";
9624     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9625     pr "{\n";
9626     pr "  PyObject *list;\n";
9627     pr "  size_t i;\n";
9628     pr "\n";
9629     pr "  list = PyList_New (%ss->len);\n" typ;
9630     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9631     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9632     pr "  return list;\n";
9633     pr "};\n";
9634     pr "\n"
9635   in
9636
9637   (* Structures, turned into Python dictionaries. *)
9638   List.iter (
9639     fun (typ, cols) ->
9640       pr "static PyObject *\n";
9641       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9642       pr "{\n";
9643       pr "  PyObject *dict;\n";
9644       pr "\n";
9645       pr "  dict = PyDict_New ();\n";
9646       List.iter (
9647         function
9648         | name, FString ->
9649             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9650             pr "                        PyString_FromString (%s->%s));\n"
9651               typ name
9652         | name, FBuffer ->
9653             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9654             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9655               typ name typ name
9656         | name, FUUID ->
9657             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9658             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9659               typ name
9660         | name, (FBytes|FUInt64) ->
9661             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9662             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9663               typ name
9664         | name, FInt64 ->
9665             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9666             pr "                        PyLong_FromLongLong (%s->%s));\n"
9667               typ name
9668         | name, FUInt32 ->
9669             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9670             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9671               typ name
9672         | name, FInt32 ->
9673             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9674             pr "                        PyLong_FromLong (%s->%s));\n"
9675               typ name
9676         | name, FOptPercent ->
9677             pr "  if (%s->%s >= 0)\n" typ name;
9678             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9679             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9680               typ name;
9681             pr "  else {\n";
9682             pr "    Py_INCREF (Py_None);\n";
9683             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9684             pr "  }\n"
9685         | name, FChar ->
9686             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9687             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9688       ) cols;
9689       pr "  return dict;\n";
9690       pr "};\n";
9691       pr "\n";
9692
9693   ) structs;
9694
9695   (* Emit a put_TYPE_list function definition only if that function is used. *)
9696   List.iter (
9697     function
9698     | typ, (RStructListOnly | RStructAndList) ->
9699         (* generate the function for typ *)
9700         emit_put_list_function typ
9701     | typ, _ -> () (* empty *)
9702   ) (rstructs_used_by all_functions);
9703
9704   (* Python wrapper functions. *)
9705   List.iter (
9706     fun (name, style, _, _, _, _, _) ->
9707       pr "static PyObject *\n";
9708       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9709       pr "{\n";
9710
9711       pr "  PyObject *py_g;\n";
9712       pr "  guestfs_h *g;\n";
9713       pr "  PyObject *py_r;\n";
9714
9715       let error_code =
9716         match fst style with
9717         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9718         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9719         | RConstString _ | RConstOptString _ ->
9720             pr "  const char *r;\n"; "NULL"
9721         | RString _ -> pr "  char *r;\n"; "NULL"
9722         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9723         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9724         | RStructList (_, typ) ->
9725             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9726         | RBufferOut _ ->
9727             pr "  char *r;\n";
9728             pr "  size_t size;\n";
9729             "NULL" in
9730
9731       List.iter (
9732         function
9733         | Pathname n | Device n | Dev_or_Path n | String n | Key n
9734         | FileIn n | FileOut n ->
9735             pr "  const char *%s;\n" n
9736         | OptString n -> pr "  const char *%s;\n" n
9737         | BufferIn n ->
9738             pr "  const char *%s;\n" n;
9739             pr "  Py_ssize_t %s_size;\n" n
9740         | StringList n | DeviceList n ->
9741             pr "  PyObject *py_%s;\n" n;
9742             pr "  char **%s;\n" n
9743         | Bool n -> pr "  int %s;\n" n
9744         | Int n -> pr "  int %s;\n" n
9745         | Int64 n -> pr "  long long %s;\n" n
9746       ) (snd style);
9747
9748       pr "\n";
9749
9750       (* Convert the parameters. *)
9751       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9752       List.iter (
9753         function
9754         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
9755         | FileIn _ | FileOut _ -> pr "s"
9756         | OptString _ -> pr "z"
9757         | StringList _ | DeviceList _ -> pr "O"
9758         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9759         | Int _ -> pr "i"
9760         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9761                              * emulate C's int/long/long long in Python?
9762                              *)
9763         | BufferIn _ -> pr "s#"
9764       ) (snd style);
9765       pr ":guestfs_%s\",\n" name;
9766       pr "                         &py_g";
9767       List.iter (
9768         function
9769         | Pathname n | Device n | Dev_or_Path n | String n | Key n
9770         | FileIn n | FileOut n -> pr ", &%s" n
9771         | OptString n -> pr ", &%s" n
9772         | StringList n | DeviceList n -> pr ", &py_%s" n
9773         | Bool n -> pr ", &%s" n
9774         | Int n -> pr ", &%s" n
9775         | Int64 n -> pr ", &%s" n
9776         | BufferIn n -> pr ", &%s, &%s_size" n n
9777       ) (snd style);
9778
9779       pr "))\n";
9780       pr "    return NULL;\n";
9781
9782       pr "  g = get_handle (py_g);\n";
9783       List.iter (
9784         function
9785         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
9786         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9787         | BufferIn _ -> ()
9788         | StringList n | DeviceList n ->
9789             pr "  %s = get_string_list (py_%s);\n" n n;
9790             pr "  if (!%s) return NULL;\n" n
9791       ) (snd style);
9792
9793       pr "\n";
9794
9795       pr "  r = guestfs_%s " name;
9796       generate_c_call_args ~handle:"g" style;
9797       pr ";\n";
9798
9799       List.iter (
9800         function
9801         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
9802         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9803         | BufferIn _ -> ()
9804         | StringList n | DeviceList n ->
9805             pr "  free (%s);\n" n
9806       ) (snd style);
9807
9808       pr "  if (r == %s) {\n" error_code;
9809       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9810       pr "    return NULL;\n";
9811       pr "  }\n";
9812       pr "\n";
9813
9814       (match fst style with
9815        | RErr ->
9816            pr "  Py_INCREF (Py_None);\n";
9817            pr "  py_r = Py_None;\n"
9818        | RInt _
9819        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9820        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9821        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9822        | RConstOptString _ ->
9823            pr "  if (r)\n";
9824            pr "    py_r = PyString_FromString (r);\n";
9825            pr "  else {\n";
9826            pr "    Py_INCREF (Py_None);\n";
9827            pr "    py_r = Py_None;\n";
9828            pr "  }\n"
9829        | RString _ ->
9830            pr "  py_r = PyString_FromString (r);\n";
9831            pr "  free (r);\n"
9832        | RStringList _ ->
9833            pr "  py_r = put_string_list (r);\n";
9834            pr "  free_strings (r);\n"
9835        | RStruct (_, typ) ->
9836            pr "  py_r = put_%s (r);\n" typ;
9837            pr "  guestfs_free_%s (r);\n" typ
9838        | RStructList (_, typ) ->
9839            pr "  py_r = put_%s_list (r);\n" typ;
9840            pr "  guestfs_free_%s_list (r);\n" typ
9841        | RHashtable n ->
9842            pr "  py_r = put_table (r);\n";
9843            pr "  free_strings (r);\n"
9844        | RBufferOut _ ->
9845            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9846            pr "  free (r);\n"
9847       );
9848
9849       pr "  return py_r;\n";
9850       pr "}\n";
9851       pr "\n"
9852   ) all_functions;
9853
9854   (* Table of functions. *)
9855   pr "static PyMethodDef methods[] = {\n";
9856   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9857   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9858   List.iter (
9859     fun (name, _, _, _, _, _, _) ->
9860       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9861         name name
9862   ) all_functions;
9863   pr "  { NULL, NULL, 0, NULL }\n";
9864   pr "};\n";
9865   pr "\n";
9866
9867   (* Init function. *)
9868   pr "\
9869 void
9870 initlibguestfsmod (void)
9871 {
9872   static int initialized = 0;
9873
9874   if (initialized) return;
9875   Py_InitModule ((char *) \"libguestfsmod\", methods);
9876   initialized = 1;
9877 }
9878 "
9879
9880 (* Generate Python module. *)
9881 and generate_python_py () =
9882   generate_header HashStyle LGPLv2plus;
9883
9884   pr "\
9885 u\"\"\"Python bindings for libguestfs
9886
9887 import guestfs
9888 g = guestfs.GuestFS ()
9889 g.add_drive (\"guest.img\")
9890 g.launch ()
9891 parts = g.list_partitions ()
9892
9893 The guestfs module provides a Python binding to the libguestfs API
9894 for examining and modifying virtual machine disk images.
9895
9896 Amongst the things this is good for: making batch configuration
9897 changes to guests, getting disk used/free statistics (see also:
9898 virt-df), migrating between virtualization systems (see also:
9899 virt-p2v), performing partial backups, performing partial guest
9900 clones, cloning guests and changing registry/UUID/hostname info, and
9901 much else besides.
9902
9903 Libguestfs uses Linux kernel and qemu code, and can access any type of
9904 guest filesystem that Linux and qemu can, including but not limited
9905 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9906 schemes, qcow, qcow2, vmdk.
9907
9908 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9909 LVs, what filesystem is in each LV, etc.).  It can also run commands
9910 in the context of the guest.  Also you can access filesystems over
9911 FUSE.
9912
9913 Errors which happen while using the API are turned into Python
9914 RuntimeError exceptions.
9915
9916 To create a guestfs handle you usually have to perform the following
9917 sequence of calls:
9918
9919 # Create the handle, call add_drive at least once, and possibly
9920 # several times if the guest has multiple block devices:
9921 g = guestfs.GuestFS ()
9922 g.add_drive (\"guest.img\")
9923
9924 # Launch the qemu subprocess and wait for it to become ready:
9925 g.launch ()
9926
9927 # Now you can issue commands, for example:
9928 logvols = g.lvs ()
9929
9930 \"\"\"
9931
9932 import libguestfsmod
9933
9934 class GuestFS:
9935     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9936
9937     def __init__ (self):
9938         \"\"\"Create a new libguestfs handle.\"\"\"
9939         self._o = libguestfsmod.create ()
9940
9941     def __del__ (self):
9942         libguestfsmod.close (self._o)
9943
9944 ";
9945
9946   List.iter (
9947     fun (name, style, _, flags, _, _, longdesc) ->
9948       pr "    def %s " name;
9949       generate_py_call_args ~handle:"self" (snd style);
9950       pr ":\n";
9951
9952       if not (List.mem NotInDocs flags) then (
9953         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9954         let doc =
9955           match fst style with
9956           | RErr | RInt _ | RInt64 _ | RBool _
9957           | RConstOptString _ | RConstString _
9958           | RString _ | RBufferOut _ -> doc
9959           | RStringList _ ->
9960               doc ^ "\n\nThis function returns a list of strings."
9961           | RStruct (_, typ) ->
9962               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9963           | RStructList (_, typ) ->
9964               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9965           | RHashtable _ ->
9966               doc ^ "\n\nThis function returns a dictionary." in
9967         let doc =
9968           if List.mem ProtocolLimitWarning flags then
9969             doc ^ "\n\n" ^ protocol_limit_warning
9970           else doc in
9971         let doc =
9972           if List.mem DangerWillRobinson flags then
9973             doc ^ "\n\n" ^ danger_will_robinson
9974           else doc in
9975         let doc =
9976           match deprecation_notice flags with
9977           | None -> doc
9978           | Some txt -> doc ^ "\n\n" ^ txt in
9979         let doc = pod2text ~width:60 name doc in
9980         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9981         let doc = String.concat "\n        " doc in
9982         pr "        u\"\"\"%s\"\"\"\n" doc;
9983       );
9984       pr "        return libguestfsmod.%s " name;
9985       generate_py_call_args ~handle:"self._o" (snd style);
9986       pr "\n";
9987       pr "\n";
9988   ) all_functions
9989
9990 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9991 and generate_py_call_args ~handle args =
9992   pr "(%s" handle;
9993   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9994   pr ")"
9995
9996 (* Useful if you need the longdesc POD text as plain text.  Returns a
9997  * list of lines.
9998  *
9999  * Because this is very slow (the slowest part of autogeneration),
10000  * we memoize the results.
10001  *)
10002 and pod2text ~width name longdesc =
10003   let key = width, name, longdesc in
10004   try Hashtbl.find pod2text_memo key
10005   with Not_found ->
10006     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
10007     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
10008     close_out chan;
10009     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
10010     let chan = open_process_in cmd in
10011     let lines = ref [] in
10012     let rec loop i =
10013       let line = input_line chan in
10014       if i = 1 then             (* discard the first line of output *)
10015         loop (i+1)
10016       else (
10017         let line = triml line in
10018         lines := line :: !lines;
10019         loop (i+1)
10020       ) in
10021     let lines = try loop 1 with End_of_file -> List.rev !lines in
10022     unlink filename;
10023     (match close_process_in chan with
10024      | WEXITED 0 -> ()
10025      | WEXITED i ->
10026          failwithf "pod2text: process exited with non-zero status (%d)" i
10027      | WSIGNALED i | WSTOPPED i ->
10028          failwithf "pod2text: process signalled or stopped by signal %d" i
10029     );
10030     Hashtbl.add pod2text_memo key lines;
10031     pod2text_memo_updated ();
10032     lines
10033
10034 (* Generate ruby bindings. *)
10035 and generate_ruby_c () =
10036   generate_header CStyle LGPLv2plus;
10037
10038   pr "\
10039 #include <stdio.h>
10040 #include <stdlib.h>
10041
10042 #include <ruby.h>
10043
10044 #include \"guestfs.h\"
10045
10046 #include \"extconf.h\"
10047
10048 /* For Ruby < 1.9 */
10049 #ifndef RARRAY_LEN
10050 #define RARRAY_LEN(r) (RARRAY((r))->len)
10051 #endif
10052
10053 static VALUE m_guestfs;                 /* guestfs module */
10054 static VALUE c_guestfs;                 /* guestfs_h handle */
10055 static VALUE e_Error;                   /* used for all errors */
10056
10057 static void ruby_guestfs_free (void *p)
10058 {
10059   if (!p) return;
10060   guestfs_close ((guestfs_h *) p);
10061 }
10062
10063 static VALUE ruby_guestfs_create (VALUE m)
10064 {
10065   guestfs_h *g;
10066
10067   g = guestfs_create ();
10068   if (!g)
10069     rb_raise (e_Error, \"failed to create guestfs handle\");
10070
10071   /* Don't print error messages to stderr by default. */
10072   guestfs_set_error_handler (g, NULL, NULL);
10073
10074   /* Wrap it, and make sure the close function is called when the
10075    * handle goes away.
10076    */
10077   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
10078 }
10079
10080 static VALUE ruby_guestfs_close (VALUE gv)
10081 {
10082   guestfs_h *g;
10083   Data_Get_Struct (gv, guestfs_h, g);
10084
10085   ruby_guestfs_free (g);
10086   DATA_PTR (gv) = NULL;
10087
10088   return Qnil;
10089 }
10090
10091 ";
10092
10093   List.iter (
10094     fun (name, style, _, _, _, _, _) ->
10095       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
10096       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
10097       pr ")\n";
10098       pr "{\n";
10099       pr "  guestfs_h *g;\n";
10100       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
10101       pr "  if (!g)\n";
10102       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
10103         name;
10104       pr "\n";
10105
10106       List.iter (
10107         function
10108         | Pathname n | Device n | Dev_or_Path n | String n | Key n
10109         | FileIn n | FileOut n ->
10110             pr "  Check_Type (%sv, T_STRING);\n" n;
10111             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
10112             pr "  if (!%s)\n" n;
10113             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
10114             pr "              \"%s\", \"%s\");\n" n name
10115         | BufferIn n ->
10116             pr "  Check_Type (%sv, T_STRING);\n" n;
10117             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
10118             pr "  if (!%s)\n" n;
10119             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
10120             pr "              \"%s\", \"%s\");\n" n name;
10121             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
10122         | OptString n ->
10123             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
10124         | StringList n | DeviceList n ->
10125             pr "  char **%s;\n" n;
10126             pr "  Check_Type (%sv, T_ARRAY);\n" n;
10127             pr "  {\n";
10128             pr "    size_t i, len;\n";
10129             pr "    len = RARRAY_LEN (%sv);\n" n;
10130             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
10131               n;
10132             pr "    for (i = 0; i < len; ++i) {\n";
10133             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
10134             pr "      %s[i] = StringValueCStr (v);\n" n;
10135             pr "    }\n";
10136             pr "    %s[len] = NULL;\n" n;
10137             pr "  }\n";
10138         | Bool n ->
10139             pr "  int %s = RTEST (%sv);\n" n n
10140         | Int n ->
10141             pr "  int %s = NUM2INT (%sv);\n" n n
10142         | Int64 n ->
10143             pr "  long long %s = NUM2LL (%sv);\n" n n
10144       ) (snd style);
10145       pr "\n";
10146
10147       let error_code =
10148         match fst style with
10149         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
10150         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
10151         | RConstString _ | RConstOptString _ ->
10152             pr "  const char *r;\n"; "NULL"
10153         | RString _ -> pr "  char *r;\n"; "NULL"
10154         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
10155         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
10156         | RStructList (_, typ) ->
10157             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
10158         | RBufferOut _ ->
10159             pr "  char *r;\n";
10160             pr "  size_t size;\n";
10161             "NULL" in
10162       pr "\n";
10163
10164       pr "  r = guestfs_%s " name;
10165       generate_c_call_args ~handle:"g" style;
10166       pr ";\n";
10167
10168       List.iter (
10169         function
10170         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
10171         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
10172         | BufferIn _ -> ()
10173         | StringList n | DeviceList n ->
10174             pr "  free (%s);\n" n
10175       ) (snd style);
10176
10177       pr "  if (r == %s)\n" error_code;
10178       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
10179       pr "\n";
10180
10181       (match fst style with
10182        | RErr ->
10183            pr "  return Qnil;\n"
10184        | RInt _ | RBool _ ->
10185            pr "  return INT2NUM (r);\n"
10186        | RInt64 _ ->
10187            pr "  return ULL2NUM (r);\n"
10188        | RConstString _ ->
10189            pr "  return rb_str_new2 (r);\n";
10190        | RConstOptString _ ->
10191            pr "  if (r)\n";
10192            pr "    return rb_str_new2 (r);\n";
10193            pr "  else\n";
10194            pr "    return Qnil;\n";
10195        | RString _ ->
10196            pr "  VALUE rv = rb_str_new2 (r);\n";
10197            pr "  free (r);\n";
10198            pr "  return rv;\n";
10199        | RStringList _ ->
10200            pr "  size_t i, len = 0;\n";
10201            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
10202            pr "  VALUE rv = rb_ary_new2 (len);\n";
10203            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
10204            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
10205            pr "    free (r[i]);\n";
10206            pr "  }\n";
10207            pr "  free (r);\n";
10208            pr "  return rv;\n"
10209        | RStruct (_, typ) ->
10210            let cols = cols_of_struct typ in
10211            generate_ruby_struct_code typ cols
10212        | RStructList (_, typ) ->
10213            let cols = cols_of_struct typ in
10214            generate_ruby_struct_list_code typ cols
10215        | RHashtable _ ->
10216            pr "  VALUE rv = rb_hash_new ();\n";
10217            pr "  size_t i;\n";
10218            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
10219            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
10220            pr "    free (r[i]);\n";
10221            pr "    free (r[i+1]);\n";
10222            pr "  }\n";
10223            pr "  free (r);\n";
10224            pr "  return rv;\n"
10225        | RBufferOut _ ->
10226            pr "  VALUE rv = rb_str_new (r, size);\n";
10227            pr "  free (r);\n";
10228            pr "  return rv;\n";
10229       );
10230
10231       pr "}\n";
10232       pr "\n"
10233   ) all_functions;
10234
10235   pr "\
10236 /* Initialize the module. */
10237 void Init__guestfs ()
10238 {
10239   m_guestfs = rb_define_module (\"Guestfs\");
10240   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
10241   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
10242
10243   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
10244   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
10245
10246 ";
10247   (* Define the rest of the methods. *)
10248   List.iter (
10249     fun (name, style, _, _, _, _, _) ->
10250       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
10251       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
10252   ) all_functions;
10253
10254   pr "}\n"
10255
10256 (* Ruby code to return a struct. *)
10257 and generate_ruby_struct_code typ cols =
10258   pr "  VALUE rv = rb_hash_new ();\n";
10259   List.iter (
10260     function
10261     | name, FString ->
10262         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
10263     | name, FBuffer ->
10264         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
10265     | name, FUUID ->
10266         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
10267     | name, (FBytes|FUInt64) ->
10268         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10269     | name, FInt64 ->
10270         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
10271     | name, FUInt32 ->
10272         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
10273     | name, FInt32 ->
10274         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
10275     | name, FOptPercent ->
10276         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
10277     | name, FChar -> (* XXX wrong? *)
10278         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10279   ) cols;
10280   pr "  guestfs_free_%s (r);\n" typ;
10281   pr "  return rv;\n"
10282
10283 (* Ruby code to return a struct list. *)
10284 and generate_ruby_struct_list_code typ cols =
10285   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
10286   pr "  size_t i;\n";
10287   pr "  for (i = 0; i < r->len; ++i) {\n";
10288   pr "    VALUE hv = rb_hash_new ();\n";
10289   List.iter (
10290     function
10291     | name, FString ->
10292         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
10293     | name, FBuffer ->
10294         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
10295     | name, FUUID ->
10296         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
10297     | name, (FBytes|FUInt64) ->
10298         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10299     | name, FInt64 ->
10300         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10301     | name, FUInt32 ->
10302         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10303     | name, FInt32 ->
10304         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10305     | name, FOptPercent ->
10306         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10307     | name, FChar -> (* XXX wrong? *)
10308         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10309   ) cols;
10310   pr "    rb_ary_push (rv, hv);\n";
10311   pr "  }\n";
10312   pr "  guestfs_free_%s_list (r);\n" typ;
10313   pr "  return rv;\n"
10314
10315 (* Generate Java bindings GuestFS.java file. *)
10316 and generate_java_java () =
10317   generate_header CStyle LGPLv2plus;
10318
10319   pr "\
10320 package com.redhat.et.libguestfs;
10321
10322 import java.util.HashMap;
10323 import com.redhat.et.libguestfs.LibGuestFSException;
10324 import com.redhat.et.libguestfs.PV;
10325 import com.redhat.et.libguestfs.VG;
10326 import com.redhat.et.libguestfs.LV;
10327 import com.redhat.et.libguestfs.Stat;
10328 import com.redhat.et.libguestfs.StatVFS;
10329 import com.redhat.et.libguestfs.IntBool;
10330 import com.redhat.et.libguestfs.Dirent;
10331
10332 /**
10333  * The GuestFS object is a libguestfs handle.
10334  *
10335  * @author rjones
10336  */
10337 public class GuestFS {
10338   // Load the native code.
10339   static {
10340     System.loadLibrary (\"guestfs_jni\");
10341   }
10342
10343   /**
10344    * The native guestfs_h pointer.
10345    */
10346   long g;
10347
10348   /**
10349    * Create a libguestfs handle.
10350    *
10351    * @throws LibGuestFSException
10352    */
10353   public GuestFS () throws LibGuestFSException
10354   {
10355     g = _create ();
10356   }
10357   private native long _create () throws LibGuestFSException;
10358
10359   /**
10360    * Close a libguestfs handle.
10361    *
10362    * You can also leave handles to be collected by the garbage
10363    * collector, but this method ensures that the resources used
10364    * by the handle are freed up immediately.  If you call any
10365    * other methods after closing the handle, you will get an
10366    * exception.
10367    *
10368    * @throws LibGuestFSException
10369    */
10370   public void close () throws LibGuestFSException
10371   {
10372     if (g != 0)
10373       _close (g);
10374     g = 0;
10375   }
10376   private native void _close (long g) throws LibGuestFSException;
10377
10378   public void finalize () throws LibGuestFSException
10379   {
10380     close ();
10381   }
10382
10383 ";
10384
10385   List.iter (
10386     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10387       if not (List.mem NotInDocs flags); then (
10388         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10389         let doc =
10390           if List.mem ProtocolLimitWarning flags then
10391             doc ^ "\n\n" ^ protocol_limit_warning
10392           else doc in
10393         let doc =
10394           if List.mem DangerWillRobinson flags then
10395             doc ^ "\n\n" ^ danger_will_robinson
10396           else doc in
10397         let doc =
10398           match deprecation_notice flags with
10399           | None -> doc
10400           | Some txt -> doc ^ "\n\n" ^ txt in
10401         let doc = pod2text ~width:60 name doc in
10402         let doc = List.map (            (* RHBZ#501883 *)
10403           function
10404           | "" -> "<p>"
10405           | nonempty -> nonempty
10406         ) doc in
10407         let doc = String.concat "\n   * " doc in
10408
10409         pr "  /**\n";
10410         pr "   * %s\n" shortdesc;
10411         pr "   * <p>\n";
10412         pr "   * %s\n" doc;
10413         pr "   * @throws LibGuestFSException\n";
10414         pr "   */\n";
10415         pr "  ";
10416       );
10417       generate_java_prototype ~public:true ~semicolon:false name style;
10418       pr "\n";
10419       pr "  {\n";
10420       pr "    if (g == 0)\n";
10421       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10422         name;
10423       pr "    ";
10424       if fst style <> RErr then pr "return ";
10425       pr "_%s " name;
10426       generate_java_call_args ~handle:"g" (snd style);
10427       pr ";\n";
10428       pr "  }\n";
10429       pr "  ";
10430       generate_java_prototype ~privat:true ~native:true name style;
10431       pr "\n";
10432       pr "\n";
10433   ) all_functions;
10434
10435   pr "}\n"
10436
10437 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10438 and generate_java_call_args ~handle args =
10439   pr "(%s" handle;
10440   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10441   pr ")"
10442
10443 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10444     ?(semicolon=true) name style =
10445   if privat then pr "private ";
10446   if public then pr "public ";
10447   if native then pr "native ";
10448
10449   (* return type *)
10450   (match fst style with
10451    | RErr -> pr "void ";
10452    | RInt _ -> pr "int ";
10453    | RInt64 _ -> pr "long ";
10454    | RBool _ -> pr "boolean ";
10455    | RConstString _ | RConstOptString _ | RString _
10456    | RBufferOut _ -> pr "String ";
10457    | RStringList _ -> pr "String[] ";
10458    | RStruct (_, typ) ->
10459        let name = java_name_of_struct typ in
10460        pr "%s " name;
10461    | RStructList (_, typ) ->
10462        let name = java_name_of_struct typ in
10463        pr "%s[] " name;
10464    | RHashtable _ -> pr "HashMap<String,String> ";
10465   );
10466
10467   if native then pr "_%s " name else pr "%s " name;
10468   pr "(";
10469   let needs_comma = ref false in
10470   if native then (
10471     pr "long g";
10472     needs_comma := true
10473   );
10474
10475   (* args *)
10476   List.iter (
10477     fun arg ->
10478       if !needs_comma then pr ", ";
10479       needs_comma := true;
10480
10481       match arg with
10482       | Pathname n
10483       | Device n | Dev_or_Path n
10484       | String n
10485       | OptString n
10486       | FileIn n
10487       | FileOut n
10488       | Key n ->
10489           pr "String %s" n
10490       | BufferIn n ->
10491           pr "byte[] %s" n
10492       | StringList n | DeviceList n ->
10493           pr "String[] %s" n
10494       | Bool n ->
10495           pr "boolean %s" n
10496       | Int n ->
10497           pr "int %s" n
10498       | Int64 n ->
10499           pr "long %s" n
10500   ) (snd style);
10501
10502   pr ")\n";
10503   pr "    throws LibGuestFSException";
10504   if semicolon then pr ";"
10505
10506 and generate_java_struct jtyp cols () =
10507   generate_header CStyle LGPLv2plus;
10508
10509   pr "\
10510 package com.redhat.et.libguestfs;
10511
10512 /**
10513  * Libguestfs %s structure.
10514  *
10515  * @author rjones
10516  * @see GuestFS
10517  */
10518 public class %s {
10519 " jtyp jtyp;
10520
10521   List.iter (
10522     function
10523     | name, FString
10524     | name, FUUID
10525     | name, FBuffer -> pr "  public String %s;\n" name
10526     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10527     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10528     | name, FChar -> pr "  public char %s;\n" name
10529     | name, FOptPercent ->
10530         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10531         pr "  public float %s;\n" name
10532   ) cols;
10533
10534   pr "}\n"
10535
10536 and generate_java_c () =
10537   generate_header CStyle LGPLv2plus;
10538
10539   pr "\
10540 #include <stdio.h>
10541 #include <stdlib.h>
10542 #include <string.h>
10543
10544 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10545 #include \"guestfs.h\"
10546
10547 /* Note that this function returns.  The exception is not thrown
10548  * until after the wrapper function returns.
10549  */
10550 static void
10551 throw_exception (JNIEnv *env, const char *msg)
10552 {
10553   jclass cl;
10554   cl = (*env)->FindClass (env,
10555                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10556   (*env)->ThrowNew (env, cl, msg);
10557 }
10558
10559 JNIEXPORT jlong JNICALL
10560 Java_com_redhat_et_libguestfs_GuestFS__1create
10561   (JNIEnv *env, jobject obj)
10562 {
10563   guestfs_h *g;
10564
10565   g = guestfs_create ();
10566   if (g == NULL) {
10567     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10568     return 0;
10569   }
10570   guestfs_set_error_handler (g, NULL, NULL);
10571   return (jlong) (long) g;
10572 }
10573
10574 JNIEXPORT void JNICALL
10575 Java_com_redhat_et_libguestfs_GuestFS__1close
10576   (JNIEnv *env, jobject obj, jlong jg)
10577 {
10578   guestfs_h *g = (guestfs_h *) (long) jg;
10579   guestfs_close (g);
10580 }
10581
10582 ";
10583
10584   List.iter (
10585     fun (name, style, _, _, _, _, _) ->
10586       pr "JNIEXPORT ";
10587       (match fst style with
10588        | RErr -> pr "void ";
10589        | RInt _ -> pr "jint ";
10590        | RInt64 _ -> pr "jlong ";
10591        | RBool _ -> pr "jboolean ";
10592        | RConstString _ | RConstOptString _ | RString _
10593        | RBufferOut _ -> pr "jstring ";
10594        | RStruct _ | RHashtable _ ->
10595            pr "jobject ";
10596        | RStringList _ | RStructList _ ->
10597            pr "jobjectArray ";
10598       );
10599       pr "JNICALL\n";
10600       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10601       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10602       pr "\n";
10603       pr "  (JNIEnv *env, jobject obj, jlong jg";
10604       List.iter (
10605         function
10606         | Pathname n
10607         | Device n | Dev_or_Path n
10608         | String n
10609         | OptString n
10610         | FileIn n
10611         | FileOut n
10612         | Key n ->
10613             pr ", jstring j%s" n
10614         | BufferIn n ->
10615             pr ", jbyteArray j%s" n
10616         | StringList n | DeviceList n ->
10617             pr ", jobjectArray j%s" n
10618         | Bool n ->
10619             pr ", jboolean j%s" n
10620         | Int n ->
10621             pr ", jint j%s" n
10622         | Int64 n ->
10623             pr ", jlong j%s" n
10624       ) (snd style);
10625       pr ")\n";
10626       pr "{\n";
10627       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10628       let error_code, no_ret =
10629         match fst style with
10630         | RErr -> pr "  int r;\n"; "-1", ""
10631         | RBool _
10632         | RInt _ -> pr "  int r;\n"; "-1", "0"
10633         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10634         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10635         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10636         | RString _ ->
10637             pr "  jstring jr;\n";
10638             pr "  char *r;\n"; "NULL", "NULL"
10639         | RStringList _ ->
10640             pr "  jobjectArray jr;\n";
10641             pr "  int r_len;\n";
10642             pr "  jclass cl;\n";
10643             pr "  jstring jstr;\n";
10644             pr "  char **r;\n"; "NULL", "NULL"
10645         | RStruct (_, typ) ->
10646             pr "  jobject jr;\n";
10647             pr "  jclass cl;\n";
10648             pr "  jfieldID fl;\n";
10649             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10650         | RStructList (_, typ) ->
10651             pr "  jobjectArray jr;\n";
10652             pr "  jclass cl;\n";
10653             pr "  jfieldID fl;\n";
10654             pr "  jobject jfl;\n";
10655             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10656         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10657         | RBufferOut _ ->
10658             pr "  jstring jr;\n";
10659             pr "  char *r;\n";
10660             pr "  size_t size;\n";
10661             "NULL", "NULL" in
10662       List.iter (
10663         function
10664         | Pathname n
10665         | Device n | Dev_or_Path n
10666         | String n
10667         | OptString n
10668         | FileIn n
10669         | FileOut n
10670         | Key n ->
10671             pr "  const char *%s;\n" n
10672         | BufferIn n ->
10673             pr "  jbyte *%s;\n" n;
10674             pr "  size_t %s_size;\n" n
10675         | StringList n | DeviceList n ->
10676             pr "  int %s_len;\n" n;
10677             pr "  const char **%s;\n" n
10678         | Bool n
10679         | Int n ->
10680             pr "  int %s;\n" n
10681         | Int64 n ->
10682             pr "  int64_t %s;\n" n
10683       ) (snd style);
10684
10685       let needs_i =
10686         (match fst style with
10687          | RStringList _ | RStructList _ -> true
10688          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10689          | RConstOptString _
10690          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10691           List.exists (function
10692                        | StringList _ -> true
10693                        | DeviceList _ -> true
10694                        | _ -> false) (snd style) in
10695       if needs_i then
10696         pr "  size_t i;\n";
10697
10698       pr "\n";
10699
10700       (* Get the parameters. *)
10701       List.iter (
10702         function
10703         | Pathname n
10704         | Device n | Dev_or_Path n
10705         | String n
10706         | FileIn n
10707         | FileOut n
10708         | Key n ->
10709             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10710         | OptString n ->
10711             (* This is completely undocumented, but Java null becomes
10712              * a NULL parameter.
10713              *)
10714             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10715         | BufferIn n ->
10716             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10717             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10718         | StringList n | DeviceList n ->
10719             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10720             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10721             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10722             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10723               n;
10724             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10725             pr "  }\n";
10726             pr "  %s[%s_len] = NULL;\n" n n;
10727         | Bool n
10728         | Int n
10729         | Int64 n ->
10730             pr "  %s = j%s;\n" n n
10731       ) (snd style);
10732
10733       (* Make the call. *)
10734       pr "  r = guestfs_%s " name;
10735       generate_c_call_args ~handle:"g" style;
10736       pr ";\n";
10737
10738       (* Release the parameters. *)
10739       List.iter (
10740         function
10741         | Pathname n
10742         | Device n | Dev_or_Path n
10743         | String n
10744         | FileIn n
10745         | FileOut n
10746         | Key n ->
10747             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10748         | OptString n ->
10749             pr "  if (j%s)\n" n;
10750             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10751         | BufferIn n ->
10752             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10753         | StringList n | DeviceList n ->
10754             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10755             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10756               n;
10757             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10758             pr "  }\n";
10759             pr "  free (%s);\n" n
10760         | Bool n
10761         | Int n
10762         | Int64 n -> ()
10763       ) (snd style);
10764
10765       (* Check for errors. *)
10766       pr "  if (r == %s) {\n" error_code;
10767       pr "    throw_exception (env, guestfs_last_error (g));\n";
10768       pr "    return %s;\n" no_ret;
10769       pr "  }\n";
10770
10771       (* Return value. *)
10772       (match fst style with
10773        | RErr -> ()
10774        | RInt _ -> pr "  return (jint) r;\n"
10775        | RBool _ -> pr "  return (jboolean) r;\n"
10776        | RInt64 _ -> pr "  return (jlong) r;\n"
10777        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10778        | RConstOptString _ ->
10779            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10780        | RString _ ->
10781            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10782            pr "  free (r);\n";
10783            pr "  return jr;\n"
10784        | RStringList _ ->
10785            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10786            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10787            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10788            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10789            pr "  for (i = 0; i < r_len; ++i) {\n";
10790            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10791            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10792            pr "    free (r[i]);\n";
10793            pr "  }\n";
10794            pr "  free (r);\n";
10795            pr "  return jr;\n"
10796        | RStruct (_, typ) ->
10797            let jtyp = java_name_of_struct typ in
10798            let cols = cols_of_struct typ in
10799            generate_java_struct_return typ jtyp cols
10800        | RStructList (_, typ) ->
10801            let jtyp = java_name_of_struct typ in
10802            let cols = cols_of_struct typ in
10803            generate_java_struct_list_return typ jtyp cols
10804        | RHashtable _ ->
10805            (* XXX *)
10806            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10807            pr "  return NULL;\n"
10808        | RBufferOut _ ->
10809            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10810            pr "  free (r);\n";
10811            pr "  return jr;\n"
10812       );
10813
10814       pr "}\n";
10815       pr "\n"
10816   ) all_functions
10817
10818 and generate_java_struct_return typ jtyp cols =
10819   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10820   pr "  jr = (*env)->AllocObject (env, cl);\n";
10821   List.iter (
10822     function
10823     | name, FString ->
10824         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10825         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10826     | name, FUUID ->
10827         pr "  {\n";
10828         pr "    char s[33];\n";
10829         pr "    memcpy (s, r->%s, 32);\n" name;
10830         pr "    s[32] = 0;\n";
10831         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10832         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10833         pr "  }\n";
10834     | name, FBuffer ->
10835         pr "  {\n";
10836         pr "    int len = r->%s_len;\n" name;
10837         pr "    char s[len+1];\n";
10838         pr "    memcpy (s, r->%s, len);\n" name;
10839         pr "    s[len] = 0;\n";
10840         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10841         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10842         pr "  }\n";
10843     | name, (FBytes|FUInt64|FInt64) ->
10844         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10845         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10846     | name, (FUInt32|FInt32) ->
10847         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10848         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10849     | name, FOptPercent ->
10850         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10851         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10852     | name, FChar ->
10853         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10854         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10855   ) cols;
10856   pr "  free (r);\n";
10857   pr "  return jr;\n"
10858
10859 and generate_java_struct_list_return typ jtyp cols =
10860   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10861   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10862   pr "  for (i = 0; i < r->len; ++i) {\n";
10863   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10864   List.iter (
10865     function
10866     | name, FString ->
10867         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10868         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10869     | name, FUUID ->
10870         pr "    {\n";
10871         pr "      char s[33];\n";
10872         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10873         pr "      s[32] = 0;\n";
10874         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10875         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10876         pr "    }\n";
10877     | name, FBuffer ->
10878         pr "    {\n";
10879         pr "      int len = r->val[i].%s_len;\n" name;
10880         pr "      char s[len+1];\n";
10881         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10882         pr "      s[len] = 0;\n";
10883         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10884         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10885         pr "    }\n";
10886     | name, (FBytes|FUInt64|FInt64) ->
10887         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10888         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10889     | name, (FUInt32|FInt32) ->
10890         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10891         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10892     | name, FOptPercent ->
10893         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10894         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10895     | name, FChar ->
10896         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10897         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10898   ) cols;
10899   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10900   pr "  }\n";
10901   pr "  guestfs_free_%s_list (r);\n" typ;
10902   pr "  return jr;\n"
10903
10904 and generate_java_makefile_inc () =
10905   generate_header HashStyle GPLv2plus;
10906
10907   pr "java_built_sources = \\\n";
10908   List.iter (
10909     fun (typ, jtyp) ->
10910         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10911   ) java_structs;
10912   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10913
10914 and generate_haskell_hs () =
10915   generate_header HaskellStyle LGPLv2plus;
10916
10917   (* XXX We only know how to generate partial FFI for Haskell
10918    * at the moment.  Please help out!
10919    *)
10920   let can_generate style =
10921     match style with
10922     | RErr, _
10923     | RInt _, _
10924     | RInt64 _, _ -> true
10925     | RBool _, _
10926     | RConstString _, _
10927     | RConstOptString _, _
10928     | RString _, _
10929     | RStringList _, _
10930     | RStruct _, _
10931     | RStructList _, _
10932     | RHashtable _, _
10933     | RBufferOut _, _ -> false in
10934
10935   pr "\
10936 {-# INCLUDE <guestfs.h> #-}
10937 {-# LANGUAGE ForeignFunctionInterface #-}
10938
10939 module Guestfs (
10940   create";
10941
10942   (* List out the names of the actions we want to export. *)
10943   List.iter (
10944     fun (name, style, _, _, _, _, _) ->
10945       if can_generate style then pr ",\n  %s" name
10946   ) all_functions;
10947
10948   pr "
10949   ) where
10950
10951 -- Unfortunately some symbols duplicate ones already present
10952 -- in Prelude.  We don't know which, so we hard-code a list
10953 -- here.
10954 import Prelude hiding (truncate)
10955
10956 import Foreign
10957 import Foreign.C
10958 import Foreign.C.Types
10959 import IO
10960 import Control.Exception
10961 import Data.Typeable
10962
10963 data GuestfsS = GuestfsS            -- represents the opaque C struct
10964 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10965 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10966
10967 -- XXX define properly later XXX
10968 data PV = PV
10969 data VG = VG
10970 data LV = LV
10971 data IntBool = IntBool
10972 data Stat = Stat
10973 data StatVFS = StatVFS
10974 data Hashtable = Hashtable
10975
10976 foreign import ccall unsafe \"guestfs_create\" c_create
10977   :: IO GuestfsP
10978 foreign import ccall unsafe \"&guestfs_close\" c_close
10979   :: FunPtr (GuestfsP -> IO ())
10980 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10981   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10982
10983 create :: IO GuestfsH
10984 create = do
10985   p <- c_create
10986   c_set_error_handler p nullPtr nullPtr
10987   h <- newForeignPtr c_close p
10988   return h
10989
10990 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10991   :: GuestfsP -> IO CString
10992
10993 -- last_error :: GuestfsH -> IO (Maybe String)
10994 -- last_error h = do
10995 --   str <- withForeignPtr h (\\p -> c_last_error p)
10996 --   maybePeek peekCString str
10997
10998 last_error :: GuestfsH -> IO (String)
10999 last_error h = do
11000   str <- withForeignPtr h (\\p -> c_last_error p)
11001   if (str == nullPtr)
11002     then return \"no error\"
11003     else peekCString str
11004
11005 ";
11006
11007   (* Generate wrappers for each foreign function. *)
11008   List.iter (
11009     fun (name, style, _, _, _, _, _) ->
11010       if can_generate style then (
11011         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
11012         pr "  :: ";
11013         generate_haskell_prototype ~handle:"GuestfsP" style;
11014         pr "\n";
11015         pr "\n";
11016         pr "%s :: " name;
11017         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
11018         pr "\n";
11019         pr "%s %s = do\n" name
11020           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
11021         pr "  r <- ";
11022         (* Convert pointer arguments using with* functions. *)
11023         List.iter (
11024           function
11025           | FileIn n
11026           | FileOut n
11027           | Pathname n | Device n | Dev_or_Path n | String n | Key n ->
11028               pr "withCString %s $ \\%s -> " n n
11029           | BufferIn n ->
11030               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
11031           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
11032           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
11033           | Bool _ | Int _ | Int64 _ -> ()
11034         ) (snd style);
11035         (* Convert integer arguments. *)
11036         let args =
11037           List.map (
11038             function
11039             | Bool n -> sprintf "(fromBool %s)" n
11040             | Int n -> sprintf "(fromIntegral %s)" n
11041             | Int64 n -> sprintf "(fromIntegral %s)" n
11042             | FileIn n | FileOut n
11043             | Pathname n | Device n | Dev_or_Path n
11044             | String n | OptString n
11045             | StringList n | DeviceList n
11046             | Key n -> n
11047             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
11048           ) (snd style) in
11049         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
11050           (String.concat " " ("p" :: args));
11051         (match fst style with
11052          | RErr | RInt _ | RInt64 _ | RBool _ ->
11053              pr "  if (r == -1)\n";
11054              pr "    then do\n";
11055              pr "      err <- last_error h\n";
11056              pr "      fail err\n";
11057          | RConstString _ | RConstOptString _ | RString _
11058          | RStringList _ | RStruct _
11059          | RStructList _ | RHashtable _ | RBufferOut _ ->
11060              pr "  if (r == nullPtr)\n";
11061              pr "    then do\n";
11062              pr "      err <- last_error h\n";
11063              pr "      fail err\n";
11064         );
11065         (match fst style with
11066          | RErr ->
11067              pr "    else return ()\n"
11068          | RInt _ ->
11069              pr "    else return (fromIntegral r)\n"
11070          | RInt64 _ ->
11071              pr "    else return (fromIntegral r)\n"
11072          | RBool _ ->
11073              pr "    else return (toBool r)\n"
11074          | RConstString _
11075          | RConstOptString _
11076          | RString _
11077          | RStringList _
11078          | RStruct _
11079          | RStructList _
11080          | RHashtable _
11081          | RBufferOut _ ->
11082              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
11083         );
11084         pr "\n";
11085       )
11086   ) all_functions
11087
11088 and generate_haskell_prototype ~handle ?(hs = false) style =
11089   pr "%s -> " handle;
11090   let string = if hs then "String" else "CString" in
11091   let int = if hs then "Int" else "CInt" in
11092   let bool = if hs then "Bool" else "CInt" in
11093   let int64 = if hs then "Integer" else "Int64" in
11094   List.iter (
11095     fun arg ->
11096       (match arg with
11097        | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _ ->
11098            pr "%s" string
11099        | BufferIn _ ->
11100            if hs then pr "String"
11101            else pr "CString -> CInt"
11102        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
11103        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
11104        | Bool _ -> pr "%s" bool
11105        | Int _ -> pr "%s" int
11106        | Int64 _ -> pr "%s" int
11107        | FileIn _ -> pr "%s" string
11108        | FileOut _ -> pr "%s" string
11109       );
11110       pr " -> ";
11111   ) (snd style);
11112   pr "IO (";
11113   (match fst style with
11114    | RErr -> if not hs then pr "CInt"
11115    | RInt _ -> pr "%s" int
11116    | RInt64 _ -> pr "%s" int64
11117    | RBool _ -> pr "%s" bool
11118    | RConstString _ -> pr "%s" string
11119    | RConstOptString _ -> pr "Maybe %s" string
11120    | RString _ -> pr "%s" string
11121    | RStringList _ -> pr "[%s]" string
11122    | RStruct (_, typ) ->
11123        let name = java_name_of_struct typ in
11124        pr "%s" name
11125    | RStructList (_, typ) ->
11126        let name = java_name_of_struct typ in
11127        pr "[%s]" name
11128    | RHashtable _ -> pr "Hashtable"
11129    | RBufferOut _ -> pr "%s" string
11130   );
11131   pr ")"
11132
11133 and generate_csharp () =
11134   generate_header CPlusPlusStyle LGPLv2plus;
11135
11136   (* XXX Make this configurable by the C# assembly users. *)
11137   let library = "libguestfs.so.0" in
11138
11139   pr "\
11140 // These C# bindings are highly experimental at present.
11141 //
11142 // Firstly they only work on Linux (ie. Mono).  In order to get them
11143 // to work on Windows (ie. .Net) you would need to port the library
11144 // itself to Windows first.
11145 //
11146 // The second issue is that some calls are known to be incorrect and
11147 // can cause Mono to segfault.  Particularly: calls which pass or
11148 // return string[], or return any structure value.  This is because
11149 // we haven't worked out the correct way to do this from C#.
11150 //
11151 // The third issue is that when compiling you get a lot of warnings.
11152 // We are not sure whether the warnings are important or not.
11153 //
11154 // Fourthly we do not routinely build or test these bindings as part
11155 // of the make && make check cycle, which means that regressions might
11156 // go unnoticed.
11157 //
11158 // Suggestions and patches are welcome.
11159
11160 // To compile:
11161 //
11162 // gmcs Libguestfs.cs
11163 // mono Libguestfs.exe
11164 //
11165 // (You'll probably want to add a Test class / static main function
11166 // otherwise this won't do anything useful).
11167
11168 using System;
11169 using System.IO;
11170 using System.Runtime.InteropServices;
11171 using System.Runtime.Serialization;
11172 using System.Collections;
11173
11174 namespace Guestfs
11175 {
11176   class Error : System.ApplicationException
11177   {
11178     public Error (string message) : base (message) {}
11179     protected Error (SerializationInfo info, StreamingContext context) {}
11180   }
11181
11182   class Guestfs
11183   {
11184     IntPtr _handle;
11185
11186     [DllImport (\"%s\")]
11187     static extern IntPtr guestfs_create ();
11188
11189     public Guestfs ()
11190     {
11191       _handle = guestfs_create ();
11192       if (_handle == IntPtr.Zero)
11193         throw new Error (\"could not create guestfs handle\");
11194     }
11195
11196     [DllImport (\"%s\")]
11197     static extern void guestfs_close (IntPtr h);
11198
11199     ~Guestfs ()
11200     {
11201       guestfs_close (_handle);
11202     }
11203
11204     [DllImport (\"%s\")]
11205     static extern string guestfs_last_error (IntPtr h);
11206
11207 " library library library;
11208
11209   (* Generate C# structure bindings.  We prefix struct names with
11210    * underscore because C# cannot have conflicting struct names and
11211    * method names (eg. "class stat" and "stat").
11212    *)
11213   List.iter (
11214     fun (typ, cols) ->
11215       pr "    [StructLayout (LayoutKind.Sequential)]\n";
11216       pr "    public class _%s {\n" typ;
11217       List.iter (
11218         function
11219         | name, FChar -> pr "      char %s;\n" name
11220         | name, FString -> pr "      string %s;\n" name
11221         | name, FBuffer ->
11222             pr "      uint %s_len;\n" name;
11223             pr "      string %s;\n" name
11224         | name, FUUID ->
11225             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
11226             pr "      string %s;\n" name
11227         | name, FUInt32 -> pr "      uint %s;\n" name
11228         | name, FInt32 -> pr "      int %s;\n" name
11229         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
11230         | name, FInt64 -> pr "      long %s;\n" name
11231         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
11232       ) cols;
11233       pr "    }\n";
11234       pr "\n"
11235   ) structs;
11236
11237   (* Generate C# function bindings. *)
11238   List.iter (
11239     fun (name, style, _, _, _, shortdesc, _) ->
11240       let rec csharp_return_type () =
11241         match fst style with
11242         | RErr -> "void"
11243         | RBool n -> "bool"
11244         | RInt n -> "int"
11245         | RInt64 n -> "long"
11246         | RConstString n
11247         | RConstOptString n
11248         | RString n
11249         | RBufferOut n -> "string"
11250         | RStruct (_,n) -> "_" ^ n
11251         | RHashtable n -> "Hashtable"
11252         | RStringList n -> "string[]"
11253         | RStructList (_,n) -> sprintf "_%s[]" n
11254
11255       and c_return_type () =
11256         match fst style with
11257         | RErr
11258         | RBool _
11259         | RInt _ -> "int"
11260         | RInt64 _ -> "long"
11261         | RConstString _
11262         | RConstOptString _
11263         | RString _
11264         | RBufferOut _ -> "string"
11265         | RStruct (_,n) -> "_" ^ n
11266         | RHashtable _
11267         | RStringList _ -> "string[]"
11268         | RStructList (_,n) -> sprintf "_%s[]" n
11269
11270       and c_error_comparison () =
11271         match fst style with
11272         | RErr
11273         | RBool _
11274         | RInt _
11275         | RInt64 _ -> "== -1"
11276         | RConstString _
11277         | RConstOptString _
11278         | RString _
11279         | RBufferOut _
11280         | RStruct (_,_)
11281         | RHashtable _
11282         | RStringList _
11283         | RStructList (_,_) -> "== null"
11284
11285       and generate_extern_prototype () =
11286         pr "    static extern %s guestfs_%s (IntPtr h"
11287           (c_return_type ()) name;
11288         List.iter (
11289           function
11290           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11291           | FileIn n | FileOut n
11292           | Key n
11293           | BufferIn n ->
11294               pr ", [In] string %s" n
11295           | StringList n | DeviceList n ->
11296               pr ", [In] string[] %s" n
11297           | Bool n ->
11298               pr ", bool %s" n
11299           | Int n ->
11300               pr ", int %s" n
11301           | Int64 n ->
11302               pr ", long %s" n
11303         ) (snd style);
11304         pr ");\n"
11305
11306       and generate_public_prototype () =
11307         pr "    public %s %s (" (csharp_return_type ()) name;
11308         let comma = ref false in
11309         let next () =
11310           if !comma then pr ", ";
11311           comma := true
11312         in
11313         List.iter (
11314           function
11315           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11316           | FileIn n | FileOut n
11317           | Key n
11318           | BufferIn n ->
11319               next (); pr "string %s" n
11320           | StringList n | DeviceList n ->
11321               next (); pr "string[] %s" n
11322           | Bool n ->
11323               next (); pr "bool %s" n
11324           | Int n ->
11325               next (); pr "int %s" n
11326           | Int64 n ->
11327               next (); pr "long %s" n
11328         ) (snd style);
11329         pr ")\n"
11330
11331       and generate_call () =
11332         pr "guestfs_%s (_handle" name;
11333         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11334         pr ");\n";
11335       in
11336
11337       pr "    [DllImport (\"%s\")]\n" library;
11338       generate_extern_prototype ();
11339       pr "\n";
11340       pr "    /// <summary>\n";
11341       pr "    /// %s\n" shortdesc;
11342       pr "    /// </summary>\n";
11343       generate_public_prototype ();
11344       pr "    {\n";
11345       pr "      %s r;\n" (c_return_type ());
11346       pr "      r = ";
11347       generate_call ();
11348       pr "      if (r %s)\n" (c_error_comparison ());
11349       pr "        throw new Error (guestfs_last_error (_handle));\n";
11350       (match fst style with
11351        | RErr -> ()
11352        | RBool _ ->
11353            pr "      return r != 0 ? true : false;\n"
11354        | RHashtable _ ->
11355            pr "      Hashtable rr = new Hashtable ();\n";
11356            pr "      for (size_t i = 0; i < r.Length; i += 2)\n";
11357            pr "        rr.Add (r[i], r[i+1]);\n";
11358            pr "      return rr;\n"
11359        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11360        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11361        | RStructList _ ->
11362            pr "      return r;\n"
11363       );
11364       pr "    }\n";
11365       pr "\n";
11366   ) all_functions_sorted;
11367
11368   pr "  }
11369 }
11370 "
11371
11372 and generate_bindtests () =
11373   generate_header CStyle LGPLv2plus;
11374
11375   pr "\
11376 #include <stdio.h>
11377 #include <stdlib.h>
11378 #include <inttypes.h>
11379 #include <string.h>
11380
11381 #include \"guestfs.h\"
11382 #include \"guestfs-internal.h\"
11383 #include \"guestfs-internal-actions.h\"
11384 #include \"guestfs_protocol.h\"
11385
11386 #define error guestfs_error
11387 #define safe_calloc guestfs_safe_calloc
11388 #define safe_malloc guestfs_safe_malloc
11389
11390 static void
11391 print_strings (char *const *argv)
11392 {
11393   size_t argc;
11394
11395   printf (\"[\");
11396   for (argc = 0; argv[argc] != NULL; ++argc) {
11397     if (argc > 0) printf (\", \");
11398     printf (\"\\\"%%s\\\"\", argv[argc]);
11399   }
11400   printf (\"]\\n\");
11401 }
11402
11403 /* The test0 function prints its parameters to stdout. */
11404 ";
11405
11406   let test0, tests =
11407     match test_functions with
11408     | [] -> assert false
11409     | test0 :: tests -> test0, tests in
11410
11411   let () =
11412     let (name, style, _, _, _, _, _) = test0 in
11413     generate_prototype ~extern:false ~semicolon:false ~newline:true
11414       ~handle:"g" ~prefix:"guestfs__" name style;
11415     pr "{\n";
11416     List.iter (
11417       function
11418       | Pathname n
11419       | Device n | Dev_or_Path n
11420       | String n
11421       | FileIn n
11422       | FileOut n
11423       | Key n -> pr "  printf (\"%%s\\n\", %s);\n" n
11424       | BufferIn n ->
11425           pr "  {\n";
11426           pr "    size_t i;\n";
11427           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11428           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11429           pr "    printf (\"\\n\");\n";
11430           pr "  }\n";
11431       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11432       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11433       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11434       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11435       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11436     ) (snd style);
11437     pr "  /* Java changes stdout line buffering so we need this: */\n";
11438     pr "  fflush (stdout);\n";
11439     pr "  return 0;\n";
11440     pr "}\n";
11441     pr "\n" in
11442
11443   List.iter (
11444     fun (name, style, _, _, _, _, _) ->
11445       if String.sub name (String.length name - 3) 3 <> "err" then (
11446         pr "/* Test normal return. */\n";
11447         generate_prototype ~extern:false ~semicolon:false ~newline:true
11448           ~handle:"g" ~prefix:"guestfs__" name style;
11449         pr "{\n";
11450         (match fst style with
11451          | RErr ->
11452              pr "  return 0;\n"
11453          | RInt _ ->
11454              pr "  int r;\n";
11455              pr "  sscanf (val, \"%%d\", &r);\n";
11456              pr "  return r;\n"
11457          | RInt64 _ ->
11458              pr "  int64_t r;\n";
11459              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11460              pr "  return r;\n"
11461          | RBool _ ->
11462              pr "  return STREQ (val, \"true\");\n"
11463          | RConstString _
11464          | RConstOptString _ ->
11465              (* Can't return the input string here.  Return a static
11466               * string so we ensure we get a segfault if the caller
11467               * tries to free it.
11468               *)
11469              pr "  return \"static string\";\n"
11470          | RString _ ->
11471              pr "  return strdup (val);\n"
11472          | RStringList _ ->
11473              pr "  char **strs;\n";
11474              pr "  int n, i;\n";
11475              pr "  sscanf (val, \"%%d\", &n);\n";
11476              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11477              pr "  for (i = 0; i < n; ++i) {\n";
11478              pr "    strs[i] = safe_malloc (g, 16);\n";
11479              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11480              pr "  }\n";
11481              pr "  strs[n] = NULL;\n";
11482              pr "  return strs;\n"
11483          | RStruct (_, typ) ->
11484              pr "  struct guestfs_%s *r;\n" typ;
11485              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11486              pr "  return r;\n"
11487          | RStructList (_, typ) ->
11488              pr "  struct guestfs_%s_list *r;\n" typ;
11489              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11490              pr "  sscanf (val, \"%%d\", &r->len);\n";
11491              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11492              pr "  return r;\n"
11493          | RHashtable _ ->
11494              pr "  char **strs;\n";
11495              pr "  int n, i;\n";
11496              pr "  sscanf (val, \"%%d\", &n);\n";
11497              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11498              pr "  for (i = 0; i < n; ++i) {\n";
11499              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11500              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11501              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11502              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11503              pr "  }\n";
11504              pr "  strs[n*2] = NULL;\n";
11505              pr "  return strs;\n"
11506          | RBufferOut _ ->
11507              pr "  return strdup (val);\n"
11508         );
11509         pr "}\n";
11510         pr "\n"
11511       ) else (
11512         pr "/* Test error return. */\n";
11513         generate_prototype ~extern:false ~semicolon:false ~newline:true
11514           ~handle:"g" ~prefix:"guestfs__" name style;
11515         pr "{\n";
11516         pr "  error (g, \"error\");\n";
11517         (match fst style with
11518          | RErr | RInt _ | RInt64 _ | RBool _ ->
11519              pr "  return -1;\n"
11520          | RConstString _ | RConstOptString _
11521          | RString _ | RStringList _ | RStruct _
11522          | RStructList _
11523          | RHashtable _
11524          | RBufferOut _ ->
11525              pr "  return NULL;\n"
11526         );
11527         pr "}\n";
11528         pr "\n"
11529       )
11530   ) tests
11531
11532 and generate_ocaml_bindtests () =
11533   generate_header OCamlStyle GPLv2plus;
11534
11535   pr "\
11536 let () =
11537   let g = Guestfs.create () in
11538 ";
11539
11540   let mkargs args =
11541     String.concat " " (
11542       List.map (
11543         function
11544         | CallString s -> "\"" ^ s ^ "\""
11545         | CallOptString None -> "None"
11546         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11547         | CallStringList xs ->
11548             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11549         | CallInt i when i >= 0 -> string_of_int i
11550         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11551         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11552         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11553         | CallBool b -> string_of_bool b
11554         | CallBuffer s -> sprintf "%S" s
11555       ) args
11556     )
11557   in
11558
11559   generate_lang_bindtests (
11560     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11561   );
11562
11563   pr "print_endline \"EOF\"\n"
11564
11565 and generate_perl_bindtests () =
11566   pr "#!/usr/bin/perl -w\n";
11567   generate_header HashStyle GPLv2plus;
11568
11569   pr "\
11570 use strict;
11571
11572 use Sys::Guestfs;
11573
11574 my $g = Sys::Guestfs->new ();
11575 ";
11576
11577   let mkargs args =
11578     String.concat ", " (
11579       List.map (
11580         function
11581         | CallString s -> "\"" ^ s ^ "\""
11582         | CallOptString None -> "undef"
11583         | CallOptString (Some s) -> sprintf "\"%s\"" s
11584         | CallStringList xs ->
11585             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11586         | CallInt i -> string_of_int i
11587         | CallInt64 i -> Int64.to_string i
11588         | CallBool b -> if b then "1" else "0"
11589         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11590       ) args
11591     )
11592   in
11593
11594   generate_lang_bindtests (
11595     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11596   );
11597
11598   pr "print \"EOF\\n\"\n"
11599
11600 and generate_python_bindtests () =
11601   generate_header HashStyle GPLv2plus;
11602
11603   pr "\
11604 import guestfs
11605
11606 g = guestfs.GuestFS ()
11607 ";
11608
11609   let mkargs args =
11610     String.concat ", " (
11611       List.map (
11612         function
11613         | CallString s -> "\"" ^ s ^ "\""
11614         | CallOptString None -> "None"
11615         | CallOptString (Some s) -> sprintf "\"%s\"" s
11616         | CallStringList xs ->
11617             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11618         | CallInt i -> string_of_int i
11619         | CallInt64 i -> Int64.to_string i
11620         | CallBool b -> if b then "1" else "0"
11621         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11622       ) args
11623     )
11624   in
11625
11626   generate_lang_bindtests (
11627     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11628   );
11629
11630   pr "print \"EOF\"\n"
11631
11632 and generate_ruby_bindtests () =
11633   generate_header HashStyle GPLv2plus;
11634
11635   pr "\
11636 require 'guestfs'
11637
11638 g = Guestfs::create()
11639 ";
11640
11641   let mkargs args =
11642     String.concat ", " (
11643       List.map (
11644         function
11645         | CallString s -> "\"" ^ s ^ "\""
11646         | CallOptString None -> "nil"
11647         | CallOptString (Some s) -> sprintf "\"%s\"" s
11648         | CallStringList xs ->
11649             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11650         | CallInt i -> string_of_int i
11651         | CallInt64 i -> Int64.to_string i
11652         | CallBool b -> string_of_bool b
11653         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11654       ) args
11655     )
11656   in
11657
11658   generate_lang_bindtests (
11659     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11660   );
11661
11662   pr "print \"EOF\\n\"\n"
11663
11664 and generate_java_bindtests () =
11665   generate_header CStyle GPLv2plus;
11666
11667   pr "\
11668 import com.redhat.et.libguestfs.*;
11669
11670 public class Bindtests {
11671     public static void main (String[] argv)
11672     {
11673         try {
11674             GuestFS g = new GuestFS ();
11675 ";
11676
11677   let mkargs args =
11678     String.concat ", " (
11679       List.map (
11680         function
11681         | CallString s -> "\"" ^ s ^ "\""
11682         | CallOptString None -> "null"
11683         | CallOptString (Some s) -> sprintf "\"%s\"" s
11684         | CallStringList xs ->
11685             "new String[]{" ^
11686               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11687         | CallInt i -> string_of_int i
11688         | CallInt64 i -> Int64.to_string i
11689         | CallBool b -> string_of_bool b
11690         | CallBuffer s ->
11691             "new byte[] { " ^ String.concat "," (
11692               map_chars (fun c -> string_of_int (Char.code c)) s
11693             ) ^ " }"
11694       ) args
11695     )
11696   in
11697
11698   generate_lang_bindtests (
11699     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11700   );
11701
11702   pr "
11703             System.out.println (\"EOF\");
11704         }
11705         catch (Exception exn) {
11706             System.err.println (exn);
11707             System.exit (1);
11708         }
11709     }
11710 }
11711 "
11712
11713 and generate_haskell_bindtests () =
11714   generate_header HaskellStyle GPLv2plus;
11715
11716   pr "\
11717 module Bindtests where
11718 import qualified Guestfs
11719
11720 main = do
11721   g <- Guestfs.create
11722 ";
11723
11724   let mkargs args =
11725     String.concat " " (
11726       List.map (
11727         function
11728         | CallString s -> "\"" ^ s ^ "\""
11729         | CallOptString None -> "Nothing"
11730         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11731         | CallStringList xs ->
11732             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11733         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11734         | CallInt i -> string_of_int i
11735         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11736         | CallInt64 i -> Int64.to_string i
11737         | CallBool true -> "True"
11738         | CallBool false -> "False"
11739         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11740       ) args
11741     )
11742   in
11743
11744   generate_lang_bindtests (
11745     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11746   );
11747
11748   pr "  putStrLn \"EOF\"\n"
11749
11750 (* Language-independent bindings tests - we do it this way to
11751  * ensure there is parity in testing bindings across all languages.
11752  *)
11753 and generate_lang_bindtests call =
11754   call "test0" [CallString "abc"; CallOptString (Some "def");
11755                 CallStringList []; CallBool false;
11756                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11757                 CallBuffer "abc\000abc"];
11758   call "test0" [CallString "abc"; CallOptString None;
11759                 CallStringList []; CallBool false;
11760                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11761                 CallBuffer "abc\000abc"];
11762   call "test0" [CallString ""; CallOptString (Some "def");
11763                 CallStringList []; CallBool false;
11764                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11765                 CallBuffer "abc\000abc"];
11766   call "test0" [CallString ""; CallOptString (Some "");
11767                 CallStringList []; CallBool false;
11768                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11769                 CallBuffer "abc\000abc"];
11770   call "test0" [CallString "abc"; CallOptString (Some "def");
11771                 CallStringList ["1"]; CallBool false;
11772                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11773                 CallBuffer "abc\000abc"];
11774   call "test0" [CallString "abc"; CallOptString (Some "def");
11775                 CallStringList ["1"; "2"]; CallBool false;
11776                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11777                 CallBuffer "abc\000abc"];
11778   call "test0" [CallString "abc"; CallOptString (Some "def");
11779                 CallStringList ["1"]; CallBool true;
11780                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11781                 CallBuffer "abc\000abc"];
11782   call "test0" [CallString "abc"; CallOptString (Some "def");
11783                 CallStringList ["1"]; CallBool false;
11784                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11785                 CallBuffer "abc\000abc"];
11786   call "test0" [CallString "abc"; CallOptString (Some "def");
11787                 CallStringList ["1"]; CallBool false;
11788                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11789                 CallBuffer "abc\000abc"];
11790   call "test0" [CallString "abc"; CallOptString (Some "def");
11791                 CallStringList ["1"]; CallBool false;
11792                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11793                 CallBuffer "abc\000abc"];
11794   call "test0" [CallString "abc"; CallOptString (Some "def");
11795                 CallStringList ["1"]; CallBool false;
11796                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11797                 CallBuffer "abc\000abc"];
11798   call "test0" [CallString "abc"; CallOptString (Some "def");
11799                 CallStringList ["1"]; CallBool false;
11800                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11801                 CallBuffer "abc\000abc"];
11802   call "test0" [CallString "abc"; CallOptString (Some "def");
11803                 CallStringList ["1"]; CallBool false;
11804                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11805                 CallBuffer "abc\000abc"]
11806
11807 (* XXX Add here tests of the return and error functions. *)
11808
11809 (* Code to generator bindings for virt-inspector.  Currently only
11810  * implemented for OCaml code (for virt-p2v 2.0).
11811  *)
11812 let rng_input = "inspector/virt-inspector.rng"
11813
11814 (* Read the input file and parse it into internal structures.  This is
11815  * by no means a complete RELAX NG parser, but is just enough to be
11816  * able to parse the specific input file.
11817  *)
11818 type rng =
11819   | Element of string * rng list        (* <element name=name/> *)
11820   | Attribute of string * rng list        (* <attribute name=name/> *)
11821   | Interleave of rng list                (* <interleave/> *)
11822   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11823   | OneOrMore of rng                        (* <oneOrMore/> *)
11824   | Optional of rng                        (* <optional/> *)
11825   | Choice of string list                (* <choice><value/>*</choice> *)
11826   | Value of string                        (* <value>str</value> *)
11827   | Text                                (* <text/> *)
11828
11829 let rec string_of_rng = function
11830   | Element (name, xs) ->
11831       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11832   | Attribute (name, xs) ->
11833       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11834   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11835   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11836   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11837   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11838   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11839   | Value value -> "Value \"" ^ value ^ "\""
11840   | Text -> "Text"
11841
11842 and string_of_rng_list xs =
11843   String.concat ", " (List.map string_of_rng xs)
11844
11845 let rec parse_rng ?defines context = function
11846   | [] -> []
11847   | Xml.Element ("element", ["name", name], children) :: rest ->
11848       Element (name, parse_rng ?defines context children)
11849       :: parse_rng ?defines context rest
11850   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11851       Attribute (name, parse_rng ?defines context children)
11852       :: parse_rng ?defines context rest
11853   | Xml.Element ("interleave", [], children) :: rest ->
11854       Interleave (parse_rng ?defines context children)
11855       :: parse_rng ?defines context rest
11856   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11857       let rng = parse_rng ?defines context [child] in
11858       (match rng with
11859        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11860        | _ ->
11861            failwithf "%s: <zeroOrMore> contains more than one child element"
11862              context
11863       )
11864   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11865       let rng = parse_rng ?defines context [child] in
11866       (match rng with
11867        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11868        | _ ->
11869            failwithf "%s: <oneOrMore> contains more than one child element"
11870              context
11871       )
11872   | Xml.Element ("optional", [], [child]) :: rest ->
11873       let rng = parse_rng ?defines context [child] in
11874       (match rng with
11875        | [child] -> Optional child :: parse_rng ?defines context rest
11876        | _ ->
11877            failwithf "%s: <optional> contains more than one child element"
11878              context
11879       )
11880   | Xml.Element ("choice", [], children) :: rest ->
11881       let values = List.map (
11882         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11883         | _ ->
11884             failwithf "%s: can't handle anything except <value> in <choice>"
11885               context
11886       ) children in
11887       Choice values
11888       :: parse_rng ?defines context rest
11889   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11890       Value value :: parse_rng ?defines context rest
11891   | Xml.Element ("text", [], []) :: rest ->
11892       Text :: parse_rng ?defines context rest
11893   | Xml.Element ("ref", ["name", name], []) :: rest ->
11894       (* Look up the reference.  Because of limitations in this parser,
11895        * we can't handle arbitrarily nested <ref> yet.  You can only
11896        * use <ref> from inside <start>.
11897        *)
11898       (match defines with
11899        | None ->
11900            failwithf "%s: contains <ref>, but no refs are defined yet" context
11901        | Some map ->
11902            let rng = StringMap.find name map in
11903            rng @ parse_rng ?defines context rest
11904       )
11905   | x :: _ ->
11906       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11907
11908 let grammar =
11909   let xml = Xml.parse_file rng_input in
11910   match xml with
11911   | Xml.Element ("grammar", _,
11912                  Xml.Element ("start", _, gram) :: defines) ->
11913       (* The <define/> elements are referenced in the <start> section,
11914        * so build a map of those first.
11915        *)
11916       let defines = List.fold_left (
11917         fun map ->
11918           function Xml.Element ("define", ["name", name], defn) ->
11919             StringMap.add name defn map
11920           | _ ->
11921               failwithf "%s: expected <define name=name/>" rng_input
11922       ) StringMap.empty defines in
11923       let defines = StringMap.mapi parse_rng defines in
11924
11925       (* Parse the <start> clause, passing the defines. *)
11926       parse_rng ~defines "<start>" gram
11927   | _ ->
11928       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11929         rng_input
11930
11931 let name_of_field = function
11932   | Element (name, _) | Attribute (name, _)
11933   | ZeroOrMore (Element (name, _))
11934   | OneOrMore (Element (name, _))
11935   | Optional (Element (name, _)) -> name
11936   | Optional (Attribute (name, _)) -> name
11937   | Text -> (* an unnamed field in an element *)
11938       "data"
11939   | rng ->
11940       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11941
11942 (* At the moment this function only generates OCaml types.  However we
11943  * should parameterize it later so it can generate types/structs in a
11944  * variety of languages.
11945  *)
11946 let generate_types xs =
11947   (* A simple type is one that can be printed out directly, eg.
11948    * "string option".  A complex type is one which has a name and has
11949    * to be defined via another toplevel definition, eg. a struct.
11950    *
11951    * generate_type generates code for either simple or complex types.
11952    * In the simple case, it returns the string ("string option").  In
11953    * the complex case, it returns the name ("mountpoint").  In the
11954    * complex case it has to print out the definition before returning,
11955    * so it should only be called when we are at the beginning of a
11956    * new line (BOL context).
11957    *)
11958   let rec generate_type = function
11959     | Text ->                                (* string *)
11960         "string", true
11961     | Choice values ->                        (* [`val1|`val2|...] *)
11962         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11963     | ZeroOrMore rng ->                        (* <rng> list *)
11964         let t, is_simple = generate_type rng in
11965         t ^ " list (* 0 or more *)", is_simple
11966     | OneOrMore rng ->                        (* <rng> list *)
11967         let t, is_simple = generate_type rng in
11968         t ^ " list (* 1 or more *)", is_simple
11969                                         (* virt-inspector hack: bool *)
11970     | Optional (Attribute (name, [Value "1"])) ->
11971         "bool", true
11972     | Optional rng ->                        (* <rng> list *)
11973         let t, is_simple = generate_type rng in
11974         t ^ " option", is_simple
11975                                         (* type name = { fields ... } *)
11976     | Element (name, fields) when is_attrs_interleave fields ->
11977         generate_type_struct name (get_attrs_interleave fields)
11978     | Element (name, [field])                (* type name = field *)
11979     | Attribute (name, [field]) ->
11980         let t, is_simple = generate_type field in
11981         if is_simple then (t, true)
11982         else (
11983           pr "type %s = %s\n" name t;
11984           name, false
11985         )
11986     | Element (name, fields) ->              (* type name = { fields ... } *)
11987         generate_type_struct name fields
11988     | rng ->
11989         failwithf "generate_type failed at: %s" (string_of_rng rng)
11990
11991   and is_attrs_interleave = function
11992     | [Interleave _] -> true
11993     | Attribute _ :: fields -> is_attrs_interleave fields
11994     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11995     | _ -> false
11996
11997   and get_attrs_interleave = function
11998     | [Interleave fields] -> fields
11999     | ((Attribute _) as field) :: fields
12000     | ((Optional (Attribute _)) as field) :: fields ->
12001         field :: get_attrs_interleave fields
12002     | _ -> assert false
12003
12004   and generate_types xs =
12005     List.iter (fun x -> ignore (generate_type x)) xs
12006
12007   and generate_type_struct name fields =
12008     (* Calculate the types of the fields first.  We have to do this
12009      * before printing anything so we are still in BOL context.
12010      *)
12011     let types = List.map fst (List.map generate_type fields) in
12012
12013     (* Special case of a struct containing just a string and another
12014      * field.  Turn it into an assoc list.
12015      *)
12016     match types with
12017     | ["string"; other] ->
12018         let fname1, fname2 =
12019           match fields with
12020           | [f1; f2] -> name_of_field f1, name_of_field f2
12021           | _ -> assert false in
12022         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
12023         name, false
12024
12025     | types ->
12026         pr "type %s = {\n" name;
12027         List.iter (
12028           fun (field, ftype) ->
12029             let fname = name_of_field field in
12030             pr "  %s_%s : %s;\n" name fname ftype
12031         ) (List.combine fields types);
12032         pr "}\n";
12033         (* Return the name of this type, and
12034          * false because it's not a simple type.
12035          *)
12036         name, false
12037   in
12038
12039   generate_types xs
12040
12041 let generate_parsers xs =
12042   (* As for generate_type above, generate_parser makes a parser for
12043    * some type, and returns the name of the parser it has generated.
12044    * Because it (may) need to print something, it should always be
12045    * called in BOL context.
12046    *)
12047   let rec generate_parser = function
12048     | Text ->                                (* string *)
12049         "string_child_or_empty"
12050     | Choice values ->                        (* [`val1|`val2|...] *)
12051         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
12052           (String.concat "|"
12053              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
12054     | ZeroOrMore rng ->                        (* <rng> list *)
12055         let pa = generate_parser rng in
12056         sprintf "(fun x -> List.map %s (Xml.children x))" pa
12057     | OneOrMore rng ->                        (* <rng> list *)
12058         let pa = generate_parser rng in
12059         sprintf "(fun x -> List.map %s (Xml.children x))" pa
12060                                         (* virt-inspector hack: bool *)
12061     | Optional (Attribute (name, [Value "1"])) ->
12062         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
12063     | Optional rng ->                        (* <rng> list *)
12064         let pa = generate_parser rng in
12065         sprintf "(function None -> None | Some x -> Some (%s x))" pa
12066                                         (* type name = { fields ... } *)
12067     | Element (name, fields) when is_attrs_interleave fields ->
12068         generate_parser_struct name (get_attrs_interleave fields)
12069     | Element (name, [field]) ->        (* type name = field *)
12070         let pa = generate_parser field in
12071         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
12072         pr "let %s =\n" parser_name;
12073         pr "  %s\n" pa;
12074         pr "let parse_%s = %s\n" name parser_name;
12075         parser_name
12076     | Attribute (name, [field]) ->
12077         let pa = generate_parser field in
12078         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
12079         pr "let %s =\n" parser_name;
12080         pr "  %s\n" pa;
12081         pr "let parse_%s = %s\n" name parser_name;
12082         parser_name
12083     | Element (name, fields) ->              (* type name = { fields ... } *)
12084         generate_parser_struct name ([], fields)
12085     | rng ->
12086         failwithf "generate_parser failed at: %s" (string_of_rng rng)
12087
12088   and is_attrs_interleave = function
12089     | [Interleave _] -> true
12090     | Attribute _ :: fields -> is_attrs_interleave fields
12091     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
12092     | _ -> false
12093
12094   and get_attrs_interleave = function
12095     | [Interleave fields] -> [], fields
12096     | ((Attribute _) as field) :: fields
12097     | ((Optional (Attribute _)) as field) :: fields ->
12098         let attrs, interleaves = get_attrs_interleave fields in
12099         (field :: attrs), interleaves
12100     | _ -> assert false
12101
12102   and generate_parsers xs =
12103     List.iter (fun x -> ignore (generate_parser x)) xs
12104
12105   and generate_parser_struct name (attrs, interleaves) =
12106     (* Generate parsers for the fields first.  We have to do this
12107      * before printing anything so we are still in BOL context.
12108      *)
12109     let fields = attrs @ interleaves in
12110     let pas = List.map generate_parser fields in
12111
12112     (* Generate an intermediate tuple from all the fields first.
12113      * If the type is just a string + another field, then we will
12114      * return this directly, otherwise it is turned into a record.
12115      *
12116      * RELAX NG note: This code treats <interleave> and plain lists of
12117      * fields the same.  In other words, it doesn't bother enforcing
12118      * any ordering of fields in the XML.
12119      *)
12120     pr "let parse_%s x =\n" name;
12121     pr "  let t = (\n    ";
12122     let comma = ref false in
12123     List.iter (
12124       fun x ->
12125         if !comma then pr ",\n    ";
12126         comma := true;
12127         match x with
12128         | Optional (Attribute (fname, [field])), pa ->
12129             pr "%s x" pa
12130         | Optional (Element (fname, [field])), pa ->
12131             pr "%s (optional_child %S x)" pa fname
12132         | Attribute (fname, [Text]), _ ->
12133             pr "attribute %S x" fname
12134         | (ZeroOrMore _ | OneOrMore _), pa ->
12135             pr "%s x" pa
12136         | Text, pa ->
12137             pr "%s x" pa
12138         | (field, pa) ->
12139             let fname = name_of_field field in
12140             pr "%s (child %S x)" pa fname
12141     ) (List.combine fields pas);
12142     pr "\n  ) in\n";
12143
12144     (match fields with
12145      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
12146          pr "  t\n"
12147
12148      | _ ->
12149          pr "  (Obj.magic t : %s)\n" name
12150 (*
12151          List.iter (
12152            function
12153            | (Optional (Attribute (fname, [field])), pa) ->
12154                pr "  %s_%s =\n" name fname;
12155                pr "    %s x;\n" pa
12156            | (Optional (Element (fname, [field])), pa) ->
12157                pr "  %s_%s =\n" name fname;
12158                pr "    (let x = optional_child %S x in\n" fname;
12159                pr "     %s x);\n" pa
12160            | (field, pa) ->
12161                let fname = name_of_field field in
12162                pr "  %s_%s =\n" name fname;
12163                pr "    (let x = child %S x in\n" fname;
12164                pr "     %s x);\n" pa
12165          ) (List.combine fields pas);
12166          pr "}\n"
12167 *)
12168     );
12169     sprintf "parse_%s" name
12170   in
12171
12172   generate_parsers xs
12173
12174 (* Generate ocaml/guestfs_inspector.mli. *)
12175 let generate_ocaml_inspector_mli () =
12176   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12177
12178   pr "\
12179 (** This is an OCaml language binding to the external [virt-inspector]
12180     program.
12181
12182     For more information, please read the man page [virt-inspector(1)].
12183 *)
12184
12185 ";
12186
12187   generate_types grammar;
12188   pr "(** The nested information returned from the {!inspect} function. *)\n";
12189   pr "\n";
12190
12191   pr "\
12192 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
12193 (** To inspect a libvirt domain called [name], pass a singleton
12194     list: [inspect [name]].  When using libvirt only, you may
12195     optionally pass a libvirt URI using [inspect ~connect:uri ...].
12196
12197     To inspect a disk image or images, pass a list of the filenames
12198     of the disk images: [inspect filenames]
12199
12200     This function inspects the given guest or disk images and
12201     returns a list of operating system(s) found and a large amount
12202     of information about them.  In the vast majority of cases,
12203     a virtual machine only contains a single operating system.
12204
12205     If the optional [~xml] parameter is given, then this function
12206     skips running the external virt-inspector program and just
12207     parses the given XML directly (which is expected to be XML
12208     produced from a previous run of virt-inspector).  The list of
12209     names and connect URI are ignored in this case.
12210
12211     This function can throw a wide variety of exceptions, for example
12212     if the external virt-inspector program cannot be found, or if
12213     it doesn't generate valid XML.
12214 *)
12215 "
12216
12217 (* Generate ocaml/guestfs_inspector.ml. *)
12218 let generate_ocaml_inspector_ml () =
12219   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12220
12221   pr "open Unix\n";
12222   pr "\n";
12223
12224   generate_types grammar;
12225   pr "\n";
12226
12227   pr "\
12228 (* Misc functions which are used by the parser code below. *)
12229 let first_child = function
12230   | Xml.Element (_, _, c::_) -> c
12231   | Xml.Element (name, _, []) ->
12232       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
12233   | Xml.PCData str ->
12234       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12235
12236 let string_child_or_empty = function
12237   | Xml.Element (_, _, [Xml.PCData s]) -> s
12238   | Xml.Element (_, _, []) -> \"\"
12239   | Xml.Element (x, _, _) ->
12240       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
12241                 x ^ \" instead\")
12242   | Xml.PCData str ->
12243       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12244
12245 let optional_child name xml =
12246   let children = Xml.children xml in
12247   try
12248     Some (List.find (function
12249                      | Xml.Element (n, _, _) when n = name -> true
12250                      | _ -> false) children)
12251   with
12252     Not_found -> None
12253
12254 let child name xml =
12255   match optional_child name xml with
12256   | Some c -> c
12257   | None ->
12258       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
12259
12260 let attribute name xml =
12261   try Xml.attrib xml name
12262   with Xml.No_attribute _ ->
12263     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
12264
12265 ";
12266
12267   generate_parsers grammar;
12268   pr "\n";
12269
12270   pr "\
12271 (* Run external virt-inspector, then use parser to parse the XML. *)
12272 let inspect ?connect ?xml names =
12273   let xml =
12274     match xml with
12275     | None ->
12276         if names = [] then invalid_arg \"inspect: no names given\";
12277         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
12278           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
12279           names in
12280         let cmd = List.map Filename.quote cmd in
12281         let cmd = String.concat \" \" cmd in
12282         let chan = open_process_in cmd in
12283         let xml = Xml.parse_in chan in
12284         (match close_process_in chan with
12285          | WEXITED 0 -> ()
12286          | WEXITED _ -> failwith \"external virt-inspector command failed\"
12287          | WSIGNALED i | WSTOPPED i ->
12288              failwith (\"external virt-inspector command died or stopped on sig \" ^
12289                        string_of_int i)
12290         );
12291         xml
12292     | Some doc ->
12293         Xml.parse_string doc in
12294   parse_operatingsystems xml
12295 "
12296
12297 and generate_max_proc_nr () =
12298   pr "%d\n" max_proc_nr
12299
12300 let output_to filename k =
12301   let filename_new = filename ^ ".new" in
12302   chan := open_out filename_new;
12303   k ();
12304   close_out !chan;
12305   chan := Pervasives.stdout;
12306
12307   (* Is the new file different from the current file? *)
12308   if Sys.file_exists filename && files_equal filename filename_new then
12309     unlink filename_new                 (* same, so skip it *)
12310   else (
12311     (* different, overwrite old one *)
12312     (try chmod filename 0o644 with Unix_error _ -> ());
12313     rename filename_new filename;
12314     chmod filename 0o444;
12315     printf "written %s\n%!" filename;
12316   )
12317
12318 let perror msg = function
12319   | Unix_error (err, _, _) ->
12320       eprintf "%s: %s\n" msg (error_message err)
12321   | exn ->
12322       eprintf "%s: %s\n" msg (Printexc.to_string exn)
12323
12324 (* Main program. *)
12325 let () =
12326   let lock_fd =
12327     try openfile "HACKING" [O_RDWR] 0
12328     with
12329     | Unix_error (ENOENT, _, _) ->
12330         eprintf "\
12331 You are probably running this from the wrong directory.
12332 Run it from the top source directory using the command
12333   src/generator.ml
12334 ";
12335         exit 1
12336     | exn ->
12337         perror "open: HACKING" exn;
12338         exit 1 in
12339
12340   (* Acquire a lock so parallel builds won't try to run the generator
12341    * twice at the same time.  Subsequent builds will wait for the first
12342    * one to finish.  Note the lock is released implicitly when the
12343    * program exits.
12344    *)
12345   (try lockf lock_fd F_LOCK 1
12346    with exn ->
12347      perror "lock: HACKING" exn;
12348      exit 1);
12349
12350   check_functions ();
12351
12352   output_to "src/guestfs_protocol.x" generate_xdr;
12353   output_to "src/guestfs-structs.h" generate_structs_h;
12354   output_to "src/guestfs-actions.h" generate_actions_h;
12355   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12356   output_to "src/actions.c" generate_client_actions;
12357   output_to "src/bindtests.c" generate_bindtests;
12358   output_to "src/guestfs-structs.pod" generate_structs_pod;
12359   output_to "src/guestfs-actions.pod" generate_actions_pod;
12360   output_to "src/guestfs-availability.pod" generate_availability_pod;
12361   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12362   output_to "src/libguestfs.syms" generate_linker_script;
12363   output_to "daemon/actions.h" generate_daemon_actions_h;
12364   output_to "daemon/stubs.c" generate_daemon_actions;
12365   output_to "daemon/names.c" generate_daemon_names;
12366   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12367   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12368   output_to "capitests/tests.c" generate_tests;
12369   output_to "fish/cmds.c" generate_fish_cmds;
12370   output_to "fish/completion.c" generate_fish_completion;
12371   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12372   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12373   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12374   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12375   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12376   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12377   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12378   output_to "perl/Guestfs.xs" generate_perl_xs;
12379   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12380   output_to "perl/bindtests.pl" generate_perl_bindtests;
12381   output_to "python/guestfs-py.c" generate_python_c;
12382   output_to "python/guestfs.py" generate_python_py;
12383   output_to "python/bindtests.py" generate_python_bindtests;
12384   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12385   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12386   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12387
12388   List.iter (
12389     fun (typ, jtyp) ->
12390       let cols = cols_of_struct typ in
12391       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12392       output_to filename (generate_java_struct jtyp cols);
12393   ) java_structs;
12394
12395   output_to "java/Makefile.inc" generate_java_makefile_inc;
12396   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12397   output_to "java/Bindtests.java" generate_java_bindtests;
12398   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12399   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12400   output_to "csharp/Libguestfs.cs" generate_csharp;
12401
12402   (* Always generate this file last, and unconditionally.  It's used
12403    * by the Makefile to know when we must re-run the generator.
12404    *)
12405   let chan = open_out "src/stamp-generator" in
12406   fprintf chan "1\n";
12407   close_out chan;
12408
12409   printf "generated %d lines of code\n" !lines