ccadbfd5ba2bccefa5f674de1f2fa3849f297525
[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
178 type flags =
179   | ProtocolLimitWarning  (* display warning about protocol size limits *)
180   | DangerWillRobinson    (* flags particularly dangerous commands *)
181   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
182   | FishOutput of fish_output_t (* how to display output in guestfish *)
183   | NotInFish             (* do not export via guestfish *)
184   | NotInDocs             (* do not add this function to documentation *)
185   | DeprecatedBy of string (* function is deprecated, use .. instead *)
186   | Optional of string    (* function is part of an optional group *)
187
188 and fish_output_t =
189   | FishOutputOctal       (* for int return, print in octal *)
190   | FishOutputHexadecimal (* for int return, print in hex *)
191
192 (* You can supply zero or as many tests as you want per API call.
193  *
194  * Note that the test environment has 3 block devices, of size 500MB,
195  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
196  * a fourth ISO block device with some known files on it (/dev/sdd).
197  *
198  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
199  * Number of cylinders was 63 for IDE emulated disks with precisely
200  * the same size.  How exactly this is calculated is a mystery.
201  *
202  * The ISO block device (/dev/sdd) comes from images/test.iso.
203  *
204  * To be able to run the tests in a reasonable amount of time,
205  * the virtual machine and block devices are reused between tests.
206  * So don't try testing kill_subprocess :-x
207  *
208  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
209  *
210  * Don't assume anything about the previous contents of the block
211  * devices.  Use 'Init*' to create some initial scenarios.
212  *
213  * You can add a prerequisite clause to any individual test.  This
214  * is a run-time check, which, if it fails, causes the test to be
215  * skipped.  Useful if testing a command which might not work on
216  * all variations of libguestfs builds.  A test that has prerequisite
217  * of 'Always' is run unconditionally.
218  *
219  * In addition, packagers can skip individual tests by setting the
220  * environment variables:     eg:
221  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
222  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
223  *)
224 type tests = (test_init * test_prereq * test) list
225 and test =
226     (* Run the command sequence and just expect nothing to fail. *)
227   | TestRun of seq
228
229     (* Run the command sequence and expect the output of the final
230      * command to be the string.
231      *)
232   | TestOutput of seq * string
233
234     (* Run the command sequence and expect the output of the final
235      * command to be the list of strings.
236      *)
237   | TestOutputList of seq * string list
238
239     (* Run the command sequence and expect the output of the final
240      * command to be the list of block devices (could be either
241      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
242      * character of each string).
243      *)
244   | TestOutputListOfDevices of seq * string list
245
246     (* Run the command sequence and expect the output of the final
247      * command to be the integer.
248      *)
249   | TestOutputInt of seq * int
250
251     (* Run the command sequence and expect the output of the final
252      * command to be <op> <int>, eg. ">=", "1".
253      *)
254   | TestOutputIntOp of seq * string * int
255
256     (* Run the command sequence and expect the output of the final
257      * command to be a true value (!= 0 or != NULL).
258      *)
259   | TestOutputTrue of seq
260
261     (* Run the command sequence and expect the output of the final
262      * command to be a false value (== 0 or == NULL, but not an error).
263      *)
264   | TestOutputFalse of seq
265
266     (* Run the command sequence and expect the output of the final
267      * command to be a list of the given length (but don't care about
268      * content).
269      *)
270   | TestOutputLength of seq * int
271
272     (* Run the command sequence and expect the output of the final
273      * command to be a buffer (RBufferOut), ie. string + size.
274      *)
275   | TestOutputBuffer of seq * string
276
277     (* Run the command sequence and expect the output of the final
278      * command to be a structure.
279      *)
280   | TestOutputStruct of seq * test_field_compare list
281
282     (* Run the command sequence and expect the final command (only)
283      * to fail.
284      *)
285   | TestLastFail of seq
286
287 and test_field_compare =
288   | CompareWithInt of string * int
289   | CompareWithIntOp of string * string * int
290   | CompareWithString of string * string
291   | CompareFieldsIntEq of string * string
292   | CompareFieldsStrEq of string * string
293
294 (* Test prerequisites. *)
295 and test_prereq =
296     (* Test always runs. *)
297   | Always
298
299     (* Test is currently disabled - eg. it fails, or it tests some
300      * unimplemented feature.
301      *)
302   | Disabled
303
304     (* 'string' is some C code (a function body) that should return
305      * true or false.  The test will run if the code returns true.
306      *)
307   | If of string
308
309     (* As for 'If' but the test runs _unless_ the code returns true. *)
310   | Unless of string
311
312 (* Some initial scenarios for testing. *)
313 and test_init =
314     (* Do nothing, block devices could contain random stuff including
315      * LVM PVs, and some filesystems might be mounted.  This is usually
316      * a bad idea.
317      *)
318   | InitNone
319
320     (* Block devices are empty and no filesystems are mounted. *)
321   | InitEmpty
322
323     (* /dev/sda contains a single partition /dev/sda1, with random
324      * content.  /dev/sdb and /dev/sdc may have random content.
325      * No LVM.
326      *)
327   | InitPartition
328
329     (* /dev/sda contains a single partition /dev/sda1, which is formatted
330      * as ext2, empty [except for lost+found] and mounted on /.
331      * /dev/sdb and /dev/sdc may have random content.
332      * No LVM.
333      *)
334   | InitBasicFS
335
336     (* /dev/sda:
337      *   /dev/sda1 (is a PV):
338      *     /dev/VG/LV (size 8MB):
339      *       formatted as ext2, empty [except for lost+found], mounted on /
340      * /dev/sdb and /dev/sdc may have random content.
341      *)
342   | InitBasicFSonLVM
343
344     (* /dev/sdd (the ISO, see images/ directory in source)
345      * is mounted on /
346      *)
347   | InitISOFS
348
349 (* Sequence of commands for testing. *)
350 and seq = cmd list
351 and cmd = string list
352
353 (* Note about long descriptions: When referring to another
354  * action, use the format C<guestfs_other> (ie. the full name of
355  * the C function).  This will be replaced as appropriate in other
356  * language bindings.
357  *
358  * Apart from that, long descriptions are just perldoc paragraphs.
359  *)
360
361 (* Generate a random UUID (used in tests). *)
362 let uuidgen () =
363   let chan = open_process_in "uuidgen" in
364   let uuid = input_line chan in
365   (match close_process_in chan with
366    | WEXITED 0 -> ()
367    | WEXITED _ ->
368        failwith "uuidgen: process exited with non-zero status"
369    | WSIGNALED _ | WSTOPPED _ ->
370        failwith "uuidgen: process signalled or stopped by signal"
371   );
372   uuid
373
374 (* These test functions are used in the language binding tests. *)
375
376 let test_all_args = [
377   String "str";
378   OptString "optstr";
379   StringList "strlist";
380   Bool "b";
381   Int "integer";
382   Int64 "integer64";
383   FileIn "filein";
384   FileOut "fileout";
385   BufferIn "bufferin";
386 ]
387
388 let test_all_rets = [
389   (* except for RErr, which is tested thoroughly elsewhere *)
390   "test0rint",         RInt "valout";
391   "test0rint64",       RInt64 "valout";
392   "test0rbool",        RBool "valout";
393   "test0rconststring", RConstString "valout";
394   "test0rconstoptstring", RConstOptString "valout";
395   "test0rstring",      RString "valout";
396   "test0rstringlist",  RStringList "valout";
397   "test0rstruct",      RStruct ("valout", "lvm_pv");
398   "test0rstructlist",  RStructList ("valout", "lvm_pv");
399   "test0rhashtable",   RHashtable "valout";
400 ]
401
402 let test_functions = [
403   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
404    [],
405    "internal test function - do not use",
406    "\
407 This is an internal test function which is used to test whether
408 the automatically generated bindings can handle every possible
409 parameter type correctly.
410
411 It echos the contents of each parameter to stdout.
412
413 You probably don't want to call this function.");
414 ] @ List.flatten (
415   List.map (
416     fun (name, ret) ->
417       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
418         [],
419         "internal test function - do not use",
420         "\
421 This is an internal test function which is used to test whether
422 the automatically generated bindings can handle every possible
423 return type correctly.
424
425 It converts string C<val> to the return type.
426
427 You probably don't want to call this function.");
428        (name ^ "err", (ret, []), -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 This function always returns an error.
437
438 You probably don't want to call this function.")]
439   ) test_all_rets
440 )
441
442 (* non_daemon_functions are any functions which don't get processed
443  * in the daemon, eg. functions for setting and getting local
444  * configuration values.
445  *)
446
447 let non_daemon_functions = test_functions @ [
448   ("launch", (RErr, []), -1, [FishAlias "run"],
449    [],
450    "launch the qemu subprocess",
451    "\
452 Internally libguestfs is implemented by running a virtual machine
453 using L<qemu(1)>.
454
455 You should call this after configuring the handle
456 (eg. adding drives) but before performing any actions.");
457
458   ("wait_ready", (RErr, []), -1, [NotInFish],
459    [],
460    "wait until the qemu subprocess launches (no op)",
461    "\
462 This function is a no op.
463
464 In versions of the API E<lt> 1.0.71 you had to call this function
465 just after calling C<guestfs_launch> to wait for the launch
466 to complete.  However this is no longer necessary because
467 C<guestfs_launch> now does the waiting.
468
469 If you see any calls to this function in code then you can just
470 remove them, unless you want to retain compatibility with older
471 versions of the API.");
472
473   ("kill_subprocess", (RErr, []), -1, [],
474    [],
475    "kill the qemu subprocess",
476    "\
477 This kills the qemu subprocess.  You should never need to call this.");
478
479   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
480    [],
481    "add an image to examine or modify",
482    "\
483 This function adds a virtual machine disk image C<filename> to the
484 guest.  The first time you call this function, the disk appears as IDE
485 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
486 so on.
487
488 You don't necessarily need to be root when using libguestfs.  However
489 you obviously do need sufficient permissions to access the filename
490 for whatever operations you want to perform (ie. read access if you
491 just want to read the image or write access if you want to modify the
492 image).
493
494 This is equivalent to the qemu parameter
495 C<-drive file=filename,cache=off,if=...>.
496
497 C<cache=off> is omitted in cases where it is not supported by
498 the underlying filesystem.
499
500 C<if=...> is set at compile time by the configuration option
501 C<./configure --with-drive-if=...>.  In the rare case where you
502 might need to change this at run time, use C<guestfs_add_drive_with_if>
503 or C<guestfs_add_drive_ro_with_if>.
504
505 Note that this call checks for the existence of C<filename>.  This
506 stops you from specifying other types of drive which are supported
507 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
508 the general C<guestfs_config> call instead.");
509
510   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
511    [],
512    "add a CD-ROM disk image to examine",
513    "\
514 This function adds a virtual CD-ROM disk image to the guest.
515
516 This is equivalent to the qemu parameter C<-cdrom filename>.
517
518 Notes:
519
520 =over 4
521
522 =item *
523
524 This call checks for the existence of C<filename>.  This
525 stops you from specifying other types of drive which are supported
526 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
527 the general C<guestfs_config> call instead.
528
529 =item *
530
531 If you just want to add an ISO file (often you use this as an
532 efficient way to transfer large files into the guest), then you
533 should probably use C<guestfs_add_drive_ro> instead.
534
535 =back");
536
537   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
538    [],
539    "add a drive in snapshot mode (read-only)",
540    "\
541 This adds a drive in snapshot mode, making it effectively
542 read-only.
543
544 Note that writes to the device are allowed, and will be seen for
545 the duration of the guestfs handle, but they are written
546 to a temporary file which is discarded as soon as the guestfs
547 handle is closed.  We don't currently have any method to enable
548 changes to be committed, although qemu can support this.
549
550 This is equivalent to the qemu parameter
551 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
552
553 C<if=...> is set at compile time by the configuration option
554 C<./configure --with-drive-if=...>.  In the rare case where you
555 might need to change this at run time, use C<guestfs_add_drive_with_if>
556 or C<guestfs_add_drive_ro_with_if>.
557
558 C<readonly=on> is only added where qemu supports this option.
559
560 Note that this call checks for the existence of C<filename>.  This
561 stops you from specifying other types of drive which are supported
562 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
563 the general C<guestfs_config> call instead.");
564
565   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
566    [],
567    "add qemu parameters",
568    "\
569 This can be used to add arbitrary qemu command line parameters
570 of the form C<-param value>.  Actually it's not quite arbitrary - we
571 prevent you from setting some parameters which would interfere with
572 parameters that we use.
573
574 The first character of C<param> string must be a C<-> (dash).
575
576 C<value> can be NULL.");
577
578   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
579    [],
580    "set the qemu binary",
581    "\
582 Set the qemu binary that we will use.
583
584 The default is chosen when the library was compiled by the
585 configure script.
586
587 You can also override this by setting the C<LIBGUESTFS_QEMU>
588 environment variable.
589
590 Setting C<qemu> to C<NULL> restores the default qemu binary.
591
592 Note that you should call this function as early as possible
593 after creating the handle.  This is because some pre-launch
594 operations depend on testing qemu features (by running C<qemu -help>).
595 If the qemu binary changes, we don't retest features, and
596 so you might see inconsistent results.  Using the environment
597 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
598 the qemu binary at the same time as the handle is created.");
599
600   ("get_qemu", (RConstString "qemu", []), -1, [],
601    [InitNone, Always, TestRun (
602       [["get_qemu"]])],
603    "get the qemu binary",
604    "\
605 Return the current qemu binary.
606
607 This is always non-NULL.  If it wasn't set already, then this will
608 return the default qemu binary name.");
609
610   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
611    [],
612    "set the search path",
613    "\
614 Set the path that libguestfs searches for kernel and initrd.img.
615
616 The default is C<$libdir/guestfs> unless overridden by setting
617 C<LIBGUESTFS_PATH> environment variable.
618
619 Setting C<path> to C<NULL> restores the default path.");
620
621   ("get_path", (RConstString "path", []), -1, [],
622    [InitNone, Always, TestRun (
623       [["get_path"]])],
624    "get the search path",
625    "\
626 Return the current search path.
627
628 This is always non-NULL.  If it wasn't set already, then this will
629 return the default path.");
630
631   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
632    [],
633    "add options to kernel command line",
634    "\
635 This function is used to add additional options to the
636 guest kernel command line.
637
638 The default is C<NULL> unless overridden by setting
639 C<LIBGUESTFS_APPEND> environment variable.
640
641 Setting C<append> to C<NULL> means I<no> additional options
642 are passed (libguestfs always adds a few of its own).");
643
644   ("get_append", (RConstOptString "append", []), -1, [],
645    (* This cannot be tested with the current framework.  The
646     * function can return NULL in normal operations, which the
647     * test framework interprets as an error.
648     *)
649    [],
650    "get the additional kernel options",
651    "\
652 Return the additional kernel options which are added to the
653 guest kernel command line.
654
655 If C<NULL> then no options are added.");
656
657   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
658    [],
659    "set autosync mode",
660    "\
661 If C<autosync> is true, this enables autosync.  Libguestfs will make a
662 best effort attempt to run C<guestfs_umount_all> followed by
663 C<guestfs_sync> when the handle is closed
664 (also if the program exits without closing handles).
665
666 This is disabled by default (except in guestfish where it is
667 enabled by default).");
668
669   ("get_autosync", (RBool "autosync", []), -1, [],
670    [InitNone, Always, TestRun (
671       [["get_autosync"]])],
672    "get autosync mode",
673    "\
674 Get the autosync flag.");
675
676   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
677    [],
678    "set verbose mode",
679    "\
680 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
681
682 Verbose messages are disabled unless the environment variable
683 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
684
685   ("get_verbose", (RBool "verbose", []), -1, [],
686    [],
687    "get verbose mode",
688    "\
689 This returns the verbose messages flag.");
690
691   ("is_ready", (RBool "ready", []), -1, [],
692    [InitNone, Always, TestOutputTrue (
693       [["is_ready"]])],
694    "is ready to accept commands",
695    "\
696 This returns true iff this handle is ready to accept commands
697 (in the C<READY> state).
698
699 For more information on states, see L<guestfs(3)>.");
700
701   ("is_config", (RBool "config", []), -1, [],
702    [InitNone, Always, TestOutputFalse (
703       [["is_config"]])],
704    "is in configuration state",
705    "\
706 This returns true iff this handle is being configured
707 (in the C<CONFIG> state).
708
709 For more information on states, see L<guestfs(3)>.");
710
711   ("is_launching", (RBool "launching", []), -1, [],
712    [InitNone, Always, TestOutputFalse (
713       [["is_launching"]])],
714    "is launching subprocess",
715    "\
716 This returns true iff this handle is launching the subprocess
717 (in the C<LAUNCHING> state).
718
719 For more information on states, see L<guestfs(3)>.");
720
721   ("is_busy", (RBool "busy", []), -1, [],
722    [InitNone, Always, TestOutputFalse (
723       [["is_busy"]])],
724    "is busy processing a command",
725    "\
726 This returns true iff this handle is busy processing a command
727 (in the C<BUSY> state).
728
729 For more information on states, see L<guestfs(3)>.");
730
731   ("get_state", (RInt "state", []), -1, [],
732    [],
733    "get the current state",
734    "\
735 This returns the current state as an opaque integer.  This is
736 only useful for printing debug and internal error messages.
737
738 For more information on states, see L<guestfs(3)>.");
739
740   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
741    [InitNone, Always, TestOutputInt (
742       [["set_memsize"; "500"];
743        ["get_memsize"]], 500)],
744    "set memory allocated to the qemu subprocess",
745    "\
746 This sets the memory size in megabytes allocated to the
747 qemu subprocess.  This only has any effect if called before
748 C<guestfs_launch>.
749
750 You can also change this by setting the environment
751 variable C<LIBGUESTFS_MEMSIZE> before the handle is
752 created.
753
754 For more information on the architecture of libguestfs,
755 see L<guestfs(3)>.");
756
757   ("get_memsize", (RInt "memsize", []), -1, [],
758    [InitNone, Always, TestOutputIntOp (
759       [["get_memsize"]], ">=", 256)],
760    "get memory allocated to the qemu subprocess",
761    "\
762 This gets the memory size in megabytes allocated to the
763 qemu subprocess.
764
765 If C<guestfs_set_memsize> was not called
766 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
767 then this returns the compiled-in default value for memsize.
768
769 For more information on the architecture of libguestfs,
770 see L<guestfs(3)>.");
771
772   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
773    [InitNone, Always, TestOutputIntOp (
774       [["get_pid"]], ">=", 1)],
775    "get PID of qemu subprocess",
776    "\
777 Return the process ID of the qemu subprocess.  If there is no
778 qemu subprocess, then this will return an error.
779
780 This is an internal call used for debugging and testing.");
781
782   ("version", (RStruct ("version", "version"), []), -1, [],
783    [InitNone, Always, TestOutputStruct (
784       [["version"]], [CompareWithInt ("major", 1)])],
785    "get the library version number",
786    "\
787 Return the libguestfs version number that the program is linked
788 against.
789
790 Note that because of dynamic linking this is not necessarily
791 the version of libguestfs that you compiled against.  You can
792 compile the program, and then at runtime dynamically link
793 against a completely different C<libguestfs.so> library.
794
795 This call was added in version C<1.0.58>.  In previous
796 versions of libguestfs there was no way to get the version
797 number.  From C code you can use dynamic linker functions
798 to find out if this symbol exists (if it doesn't, then
799 it's an earlier version).
800
801 The call returns a structure with four elements.  The first
802 three (C<major>, C<minor> and C<release>) are numbers and
803 correspond to the usual version triplet.  The fourth element
804 (C<extra>) is a string and is normally empty, but may be
805 used for distro-specific information.
806
807 To construct the original version string:
808 C<$major.$minor.$release$extra>
809
810 I<Note:> Don't use this call to test for availability
811 of features.  Distro backports makes this unreliable.  Use
812 C<guestfs_available> instead.");
813
814   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
815    [InitNone, Always, TestOutputTrue (
816       [["set_selinux"; "true"];
817        ["get_selinux"]])],
818    "set SELinux enabled or disabled at appliance boot",
819    "\
820 This sets the selinux flag that is passed to the appliance
821 at boot time.  The default is C<selinux=0> (disabled).
822
823 Note that if SELinux is enabled, it is always in
824 Permissive mode (C<enforcing=0>).
825
826 For more information on the architecture of libguestfs,
827 see L<guestfs(3)>.");
828
829   ("get_selinux", (RBool "selinux", []), -1, [],
830    [],
831    "get SELinux enabled flag",
832    "\
833 This returns the current setting of the selinux flag which
834 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
835
836 For more information on the architecture of libguestfs,
837 see L<guestfs(3)>.");
838
839   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
840    [InitNone, Always, TestOutputFalse (
841       [["set_trace"; "false"];
842        ["get_trace"]])],
843    "enable or disable command traces",
844    "\
845 If the command trace flag is set to 1, then commands are
846 printed on stdout before they are executed in a format
847 which is very similar to the one used by guestfish.  In
848 other words, you can run a program with this enabled, and
849 you will get out a script which you can feed to guestfish
850 to perform the same set of actions.
851
852 If you want to trace C API calls into libguestfs (and
853 other libraries) then possibly a better way is to use
854 the external ltrace(1) command.
855
856 Command traces are disabled unless the environment variable
857 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
858
859   ("get_trace", (RBool "trace", []), -1, [],
860    [],
861    "get command trace enabled flag",
862    "\
863 Return the command trace flag.");
864
865   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
866    [InitNone, Always, TestOutputFalse (
867       [["set_direct"; "false"];
868        ["get_direct"]])],
869    "enable or disable direct appliance mode",
870    "\
871 If the direct appliance mode flag is enabled, then stdin and
872 stdout are passed directly through to the appliance once it
873 is launched.
874
875 One consequence of this is that log messages aren't caught
876 by the library and handled by C<guestfs_set_log_message_callback>,
877 but go straight to stdout.
878
879 You probably don't want to use this unless you know what you
880 are doing.
881
882 The default is disabled.");
883
884   ("get_direct", (RBool "direct", []), -1, [],
885    [],
886    "get direct appliance mode flag",
887    "\
888 Return the direct appliance mode flag.");
889
890   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
891    [InitNone, Always, TestOutputTrue (
892       [["set_recovery_proc"; "true"];
893        ["get_recovery_proc"]])],
894    "enable or disable the recovery process",
895    "\
896 If this is called with the parameter C<false> then
897 C<guestfs_launch> does not create a recovery process.  The
898 purpose of the recovery process is to stop runaway qemu
899 processes in the case where the main program aborts abruptly.
900
901 This only has any effect if called before C<guestfs_launch>,
902 and the default is true.
903
904 About the only time when you would want to disable this is
905 if the main process will fork itself into the background
906 (\"daemonize\" itself).  In this case the recovery process
907 thinks that the main program has disappeared and so kills
908 qemu, which is not very helpful.");
909
910   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
911    [],
912    "get recovery process enabled flag",
913    "\
914 Return the recovery process enabled flag.");
915
916   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
917    [],
918    "add a drive specifying the QEMU block emulation to use",
919    "\
920 This is the same as C<guestfs_add_drive> but it allows you
921 to specify the QEMU interface emulation to use at run time.");
922
923   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
924    [],
925    "add a drive read-only specifying the QEMU block emulation to use",
926    "\
927 This is the same as C<guestfs_add_drive_ro> but it allows you
928 to specify the QEMU interface emulation to use at run time.");
929
930 ]
931
932 (* daemon_functions are any functions which cause some action
933  * to take place in the daemon.
934  *)
935
936 let daemon_functions = [
937   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
938    [InitEmpty, Always, TestOutput (
939       [["part_disk"; "/dev/sda"; "mbr"];
940        ["mkfs"; "ext2"; "/dev/sda1"];
941        ["mount"; "/dev/sda1"; "/"];
942        ["write"; "/new"; "new file contents"];
943        ["cat"; "/new"]], "new file contents")],
944    "mount a guest disk at a position in the filesystem",
945    "\
946 Mount a guest disk at a position in the filesystem.  Block devices
947 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
948 the guest.  If those block devices contain partitions, they will have
949 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
950 names can be used.
951
952 The rules are the same as for L<mount(2)>:  A filesystem must
953 first be mounted on C</> before others can be mounted.  Other
954 filesystems can only be mounted on directories which already
955 exist.
956
957 The mounted filesystem is writable, if we have sufficient permissions
958 on the underlying device.
959
960 B<Important note:>
961 When you use this call, the filesystem options C<sync> and C<noatime>
962 are set implicitly.  This was originally done because we thought it
963 would improve reliability, but it turns out that I<-o sync> has a
964 very large negative performance impact and negligible effect on
965 reliability.  Therefore we recommend that you avoid using
966 C<guestfs_mount> in any code that needs performance, and instead
967 use C<guestfs_mount_options> (use an empty string for the first
968 parameter if you don't want any options).");
969
970   ("sync", (RErr, []), 2, [],
971    [ InitEmpty, Always, TestRun [["sync"]]],
972    "sync disks, writes are flushed through to the disk image",
973    "\
974 This syncs the disk, so that any writes are flushed through to the
975 underlying disk image.
976
977 You should always call this if you have modified a disk image, before
978 closing the handle.");
979
980   ("touch", (RErr, [Pathname "path"]), 3, [],
981    [InitBasicFS, Always, TestOutputTrue (
982       [["touch"; "/new"];
983        ["exists"; "/new"]])],
984    "update file timestamps or create a new file",
985    "\
986 Touch acts like the L<touch(1)> command.  It can be used to
987 update the timestamps on a file, or, if the file does not exist,
988 to create a new zero-length file.");
989
990   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
991    [InitISOFS, Always, TestOutput (
992       [["cat"; "/known-2"]], "abcdef\n")],
993    "list the contents of a file",
994    "\
995 Return the contents of the file named C<path>.
996
997 Note that this function cannot correctly handle binary files
998 (specifically, files containing C<\\0> character which is treated
999 as end of string).  For those you need to use the C<guestfs_read_file>
1000 or C<guestfs_download> functions which have a more complex interface.");
1001
1002   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1003    [], (* XXX Tricky to test because it depends on the exact format
1004         * of the 'ls -l' command, which changes between F10 and F11.
1005         *)
1006    "list the files in a directory (long format)",
1007    "\
1008 List the files in C<directory> (relative to the root directory,
1009 there is no cwd) in the format of 'ls -la'.
1010
1011 This command is mostly useful for interactive sessions.  It
1012 is I<not> intended that you try to parse the output string.");
1013
1014   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1015    [InitBasicFS, Always, TestOutputList (
1016       [["touch"; "/new"];
1017        ["touch"; "/newer"];
1018        ["touch"; "/newest"];
1019        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1020    "list the files in a directory",
1021    "\
1022 List the files in C<directory> (relative to the root directory,
1023 there is no cwd).  The '.' and '..' entries are not returned, but
1024 hidden files are shown.
1025
1026 This command is mostly useful for interactive sessions.  Programs
1027 should probably use C<guestfs_readdir> instead.");
1028
1029   ("list_devices", (RStringList "devices", []), 7, [],
1030    [InitEmpty, Always, TestOutputListOfDevices (
1031       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1032    "list the block devices",
1033    "\
1034 List all the block devices.
1035
1036 The full block device names are returned, eg. C</dev/sda>");
1037
1038   ("list_partitions", (RStringList "partitions", []), 8, [],
1039    [InitBasicFS, Always, TestOutputListOfDevices (
1040       [["list_partitions"]], ["/dev/sda1"]);
1041     InitEmpty, Always, TestOutputListOfDevices (
1042       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1043        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1044    "list the partitions",
1045    "\
1046 List all the partitions detected on all block devices.
1047
1048 The full partition device names are returned, eg. C</dev/sda1>
1049
1050 This does not return logical volumes.  For that you will need to
1051 call C<guestfs_lvs>.");
1052
1053   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1054    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1055       [["pvs"]], ["/dev/sda1"]);
1056     InitEmpty, Always, TestOutputListOfDevices (
1057       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1058        ["pvcreate"; "/dev/sda1"];
1059        ["pvcreate"; "/dev/sda2"];
1060        ["pvcreate"; "/dev/sda3"];
1061        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1062    "list the LVM physical volumes (PVs)",
1063    "\
1064 List all the physical volumes detected.  This is the equivalent
1065 of the L<pvs(8)> command.
1066
1067 This returns a list of just the device names that contain
1068 PVs (eg. C</dev/sda2>).
1069
1070 See also C<guestfs_pvs_full>.");
1071
1072   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1073    [InitBasicFSonLVM, Always, TestOutputList (
1074       [["vgs"]], ["VG"]);
1075     InitEmpty, Always, TestOutputList (
1076       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1077        ["pvcreate"; "/dev/sda1"];
1078        ["pvcreate"; "/dev/sda2"];
1079        ["pvcreate"; "/dev/sda3"];
1080        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1081        ["vgcreate"; "VG2"; "/dev/sda3"];
1082        ["vgs"]], ["VG1"; "VG2"])],
1083    "list the LVM volume groups (VGs)",
1084    "\
1085 List all the volumes groups detected.  This is the equivalent
1086 of the L<vgs(8)> command.
1087
1088 This returns a list of just the volume group names that were
1089 detected (eg. C<VolGroup00>).
1090
1091 See also C<guestfs_vgs_full>.");
1092
1093   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1094    [InitBasicFSonLVM, Always, TestOutputList (
1095       [["lvs"]], ["/dev/VG/LV"]);
1096     InitEmpty, Always, TestOutputList (
1097       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1098        ["pvcreate"; "/dev/sda1"];
1099        ["pvcreate"; "/dev/sda2"];
1100        ["pvcreate"; "/dev/sda3"];
1101        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1102        ["vgcreate"; "VG2"; "/dev/sda3"];
1103        ["lvcreate"; "LV1"; "VG1"; "50"];
1104        ["lvcreate"; "LV2"; "VG1"; "50"];
1105        ["lvcreate"; "LV3"; "VG2"; "50"];
1106        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1107    "list the LVM logical volumes (LVs)",
1108    "\
1109 List all the logical volumes detected.  This is the equivalent
1110 of the L<lvs(8)> command.
1111
1112 This returns a list of the logical volume device names
1113 (eg. C</dev/VolGroup00/LogVol00>).
1114
1115 See also C<guestfs_lvs_full>.");
1116
1117   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1118    [], (* XXX how to test? *)
1119    "list the LVM physical volumes (PVs)",
1120    "\
1121 List all the physical volumes detected.  This is the equivalent
1122 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1123
1124   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1125    [], (* XXX how to test? *)
1126    "list the LVM volume groups (VGs)",
1127    "\
1128 List all the volumes groups detected.  This is the equivalent
1129 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1130
1131   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1132    [], (* XXX how to test? *)
1133    "list the LVM logical volumes (LVs)",
1134    "\
1135 List all the logical volumes detected.  This is the equivalent
1136 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1137
1138   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1139    [InitISOFS, Always, TestOutputList (
1140       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1141     InitISOFS, Always, TestOutputList (
1142       [["read_lines"; "/empty"]], [])],
1143    "read file as lines",
1144    "\
1145 Return the contents of the file named C<path>.
1146
1147 The file contents are returned as a list of lines.  Trailing
1148 C<LF> and C<CRLF> character sequences are I<not> returned.
1149
1150 Note that this function cannot correctly handle binary files
1151 (specifically, files containing C<\\0> character which is treated
1152 as end of line).  For those you need to use the C<guestfs_read_file>
1153 function which has a more complex interface.");
1154
1155   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1156    [], (* XXX Augeas code needs tests. *)
1157    "create a new Augeas handle",
1158    "\
1159 Create a new Augeas handle for editing configuration files.
1160 If there was any previous Augeas handle associated with this
1161 guestfs session, then it is closed.
1162
1163 You must call this before using any other C<guestfs_aug_*>
1164 commands.
1165
1166 C<root> is the filesystem root.  C<root> must not be NULL,
1167 use C</> instead.
1168
1169 The flags are the same as the flags defined in
1170 E<lt>augeas.hE<gt>, the logical I<or> of the following
1171 integers:
1172
1173 =over 4
1174
1175 =item C<AUG_SAVE_BACKUP> = 1
1176
1177 Keep the original file with a C<.augsave> extension.
1178
1179 =item C<AUG_SAVE_NEWFILE> = 2
1180
1181 Save changes into a file with extension C<.augnew>, and
1182 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1183
1184 =item C<AUG_TYPE_CHECK> = 4
1185
1186 Typecheck lenses (can be expensive).
1187
1188 =item C<AUG_NO_STDINC> = 8
1189
1190 Do not use standard load path for modules.
1191
1192 =item C<AUG_SAVE_NOOP> = 16
1193
1194 Make save a no-op, just record what would have been changed.
1195
1196 =item C<AUG_NO_LOAD> = 32
1197
1198 Do not load the tree in C<guestfs_aug_init>.
1199
1200 =back
1201
1202 To close the handle, you can call C<guestfs_aug_close>.
1203
1204 To find out more about Augeas, see L<http://augeas.net/>.");
1205
1206   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1207    [], (* XXX Augeas code needs tests. *)
1208    "close the current Augeas handle",
1209    "\
1210 Close the current Augeas handle and free up any resources
1211 used by it.  After calling this, you have to call
1212 C<guestfs_aug_init> again before you can use any other
1213 Augeas functions.");
1214
1215   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas variable",
1218    "\
1219 Defines an Augeas variable C<name> whose value is the result
1220 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1221 undefined.
1222
1223 On success this returns the number of nodes in C<expr>, or
1224 C<0> if C<expr> evaluates to something which is not a nodeset.");
1225
1226   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1227    [], (* XXX Augeas code needs tests. *)
1228    "define an Augeas node",
1229    "\
1230 Defines a variable C<name> whose value is the result of
1231 evaluating C<expr>.
1232
1233 If C<expr> evaluates to an empty nodeset, a node is created,
1234 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1235 C<name> will be the nodeset containing that single node.
1236
1237 On success this returns a pair containing the
1238 number of nodes in the nodeset, and a boolean flag
1239 if a node was created.");
1240
1241   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1242    [], (* XXX Augeas code needs tests. *)
1243    "look up the value of an Augeas path",
1244    "\
1245 Look up the value associated with C<path>.  If C<path>
1246 matches exactly one node, the C<value> is returned.");
1247
1248   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1249    [], (* XXX Augeas code needs tests. *)
1250    "set Augeas path to value",
1251    "\
1252 Set the value associated with C<path> to C<val>.
1253
1254 In the Augeas API, it is possible to clear a node by setting
1255 the value to NULL.  Due to an oversight in the libguestfs API
1256 you cannot do that with this call.  Instead you must use the
1257 C<guestfs_aug_clear> call.");
1258
1259   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1260    [], (* XXX Augeas code needs tests. *)
1261    "insert a sibling Augeas node",
1262    "\
1263 Create a new sibling C<label> for C<path>, inserting it into
1264 the tree before or after C<path> (depending on the boolean
1265 flag C<before>).
1266
1267 C<path> must match exactly one existing node in the tree, and
1268 C<label> must be a label, ie. not contain C</>, C<*> or end
1269 with a bracketed index C<[N]>.");
1270
1271   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1272    [], (* XXX Augeas code needs tests. *)
1273    "remove an Augeas path",
1274    "\
1275 Remove C<path> and all of its children.
1276
1277 On success this returns the number of entries which were removed.");
1278
1279   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1280    [], (* XXX Augeas code needs tests. *)
1281    "move Augeas node",
1282    "\
1283 Move the node C<src> to C<dest>.  C<src> must match exactly
1284 one node.  C<dest> is overwritten if it exists.");
1285
1286   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1287    [], (* XXX Augeas code needs tests. *)
1288    "return Augeas nodes which match augpath",
1289    "\
1290 Returns a list of paths which match the path expression C<path>.
1291 The returned paths are sufficiently qualified so that they match
1292 exactly one node in the current tree.");
1293
1294   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1295    [], (* XXX Augeas code needs tests. *)
1296    "write all pending Augeas changes to disk",
1297    "\
1298 This writes all pending changes to disk.
1299
1300 The flags which were passed to C<guestfs_aug_init> affect exactly
1301 how files are saved.");
1302
1303   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1304    [], (* XXX Augeas code needs tests. *)
1305    "load files into the tree",
1306    "\
1307 Load files into the tree.
1308
1309 See C<aug_load> in the Augeas documentation for the full gory
1310 details.");
1311
1312   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1313    [], (* XXX Augeas code needs tests. *)
1314    "list Augeas nodes under augpath",
1315    "\
1316 This is just a shortcut for listing C<guestfs_aug_match>
1317 C<path/*> and sorting the resulting nodes into alphabetical order.");
1318
1319   ("rm", (RErr, [Pathname "path"]), 29, [],
1320    [InitBasicFS, Always, TestRun
1321       [["touch"; "/new"];
1322        ["rm"; "/new"]];
1323     InitBasicFS, Always, TestLastFail
1324       [["rm"; "/new"]];
1325     InitBasicFS, Always, TestLastFail
1326       [["mkdir"; "/new"];
1327        ["rm"; "/new"]]],
1328    "remove a file",
1329    "\
1330 Remove the single file C<path>.");
1331
1332   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1333    [InitBasicFS, Always, TestRun
1334       [["mkdir"; "/new"];
1335        ["rmdir"; "/new"]];
1336     InitBasicFS, Always, TestLastFail
1337       [["rmdir"; "/new"]];
1338     InitBasicFS, Always, TestLastFail
1339       [["touch"; "/new"];
1340        ["rmdir"; "/new"]]],
1341    "remove a directory",
1342    "\
1343 Remove the single directory C<path>.");
1344
1345   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1346    [InitBasicFS, Always, TestOutputFalse
1347       [["mkdir"; "/new"];
1348        ["mkdir"; "/new/foo"];
1349        ["touch"; "/new/foo/bar"];
1350        ["rm_rf"; "/new"];
1351        ["exists"; "/new"]]],
1352    "remove a file or directory recursively",
1353    "\
1354 Remove the file or directory C<path>, recursively removing the
1355 contents if its a directory.  This is like the C<rm -rf> shell
1356 command.");
1357
1358   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1359    [InitBasicFS, Always, TestOutputTrue
1360       [["mkdir"; "/new"];
1361        ["is_dir"; "/new"]];
1362     InitBasicFS, Always, TestLastFail
1363       [["mkdir"; "/new/foo/bar"]]],
1364    "create a directory",
1365    "\
1366 Create a directory named C<path>.");
1367
1368   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1369    [InitBasicFS, Always, TestOutputTrue
1370       [["mkdir_p"; "/new/foo/bar"];
1371        ["is_dir"; "/new/foo/bar"]];
1372     InitBasicFS, Always, TestOutputTrue
1373       [["mkdir_p"; "/new/foo/bar"];
1374        ["is_dir"; "/new/foo"]];
1375     InitBasicFS, Always, TestOutputTrue
1376       [["mkdir_p"; "/new/foo/bar"];
1377        ["is_dir"; "/new"]];
1378     (* Regression tests for RHBZ#503133: *)
1379     InitBasicFS, Always, TestRun
1380       [["mkdir"; "/new"];
1381        ["mkdir_p"; "/new"]];
1382     InitBasicFS, Always, TestLastFail
1383       [["touch"; "/new"];
1384        ["mkdir_p"; "/new"]]],
1385    "create a directory and parents",
1386    "\
1387 Create a directory named C<path>, creating any parent directories
1388 as necessary.  This is like the C<mkdir -p> shell command.");
1389
1390   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1391    [], (* XXX Need stat command to test *)
1392    "change file mode",
1393    "\
1394 Change the mode (permissions) of C<path> to C<mode>.  Only
1395 numeric modes are supported.
1396
1397 I<Note>: When using this command from guestfish, C<mode>
1398 by default would be decimal, unless you prefix it with
1399 C<0> to get octal, ie. use C<0700> not C<700>.
1400
1401 The mode actually set is affected by the umask.");
1402
1403   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1404    [], (* XXX Need stat command to test *)
1405    "change file owner and group",
1406    "\
1407 Change the file owner to C<owner> and group to C<group>.
1408
1409 Only numeric uid and gid are supported.  If you want to use
1410 names, you will need to locate and parse the password file
1411 yourself (Augeas support makes this relatively easy).");
1412
1413   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1414    [InitISOFS, Always, TestOutputTrue (
1415       [["exists"; "/empty"]]);
1416     InitISOFS, Always, TestOutputTrue (
1417       [["exists"; "/directory"]])],
1418    "test if file or directory exists",
1419    "\
1420 This returns C<true> if and only if there is a file, directory
1421 (or anything) with the given C<path> name.
1422
1423 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1424
1425   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1426    [InitISOFS, Always, TestOutputTrue (
1427       [["is_file"; "/known-1"]]);
1428     InitISOFS, Always, TestOutputFalse (
1429       [["is_file"; "/directory"]])],
1430    "test if file exists",
1431    "\
1432 This returns C<true> if and only if there is a file
1433 with the given C<path> name.  Note that it returns false for
1434 other objects like directories.
1435
1436 See also C<guestfs_stat>.");
1437
1438   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1439    [InitISOFS, Always, TestOutputFalse (
1440       [["is_dir"; "/known-3"]]);
1441     InitISOFS, Always, TestOutputTrue (
1442       [["is_dir"; "/directory"]])],
1443    "test if file exists",
1444    "\
1445 This returns C<true> if and only if there is a directory
1446 with the given C<path> name.  Note that it returns false for
1447 other objects like files.
1448
1449 See also C<guestfs_stat>.");
1450
1451   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1452    [InitEmpty, Always, TestOutputListOfDevices (
1453       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1454        ["pvcreate"; "/dev/sda1"];
1455        ["pvcreate"; "/dev/sda2"];
1456        ["pvcreate"; "/dev/sda3"];
1457        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1458    "create an LVM physical volume",
1459    "\
1460 This creates an LVM physical volume on the named C<device>,
1461 where C<device> should usually be a partition name such
1462 as C</dev/sda1>.");
1463
1464   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1465    [InitEmpty, Always, TestOutputList (
1466       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1467        ["pvcreate"; "/dev/sda1"];
1468        ["pvcreate"; "/dev/sda2"];
1469        ["pvcreate"; "/dev/sda3"];
1470        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1471        ["vgcreate"; "VG2"; "/dev/sda3"];
1472        ["vgs"]], ["VG1"; "VG2"])],
1473    "create an LVM volume group",
1474    "\
1475 This creates an LVM volume group called C<volgroup>
1476 from the non-empty list of physical volumes C<physvols>.");
1477
1478   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1479    [InitEmpty, Always, TestOutputList (
1480       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1481        ["pvcreate"; "/dev/sda1"];
1482        ["pvcreate"; "/dev/sda2"];
1483        ["pvcreate"; "/dev/sda3"];
1484        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1485        ["vgcreate"; "VG2"; "/dev/sda3"];
1486        ["lvcreate"; "LV1"; "VG1"; "50"];
1487        ["lvcreate"; "LV2"; "VG1"; "50"];
1488        ["lvcreate"; "LV3"; "VG2"; "50"];
1489        ["lvcreate"; "LV4"; "VG2"; "50"];
1490        ["lvcreate"; "LV5"; "VG2"; "50"];
1491        ["lvs"]],
1492       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1493        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1494    "create an LVM logical volume",
1495    "\
1496 This creates an LVM logical volume called C<logvol>
1497 on the volume group C<volgroup>, with C<size> megabytes.");
1498
1499   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1500    [InitEmpty, Always, TestOutput (
1501       [["part_disk"; "/dev/sda"; "mbr"];
1502        ["mkfs"; "ext2"; "/dev/sda1"];
1503        ["mount_options"; ""; "/dev/sda1"; "/"];
1504        ["write"; "/new"; "new file contents"];
1505        ["cat"; "/new"]], "new file contents")],
1506    "make a filesystem",
1507    "\
1508 This creates a filesystem on C<device> (usually a partition
1509 or LVM logical volume).  The filesystem type is C<fstype>, for
1510 example C<ext3>.");
1511
1512   ("sfdisk", (RErr, [Device "device";
1513                      Int "cyls"; Int "heads"; Int "sectors";
1514                      StringList "lines"]), 43, [DangerWillRobinson],
1515    [],
1516    "create partitions on a block device",
1517    "\
1518 This is a direct interface to the L<sfdisk(8)> program for creating
1519 partitions on block devices.
1520
1521 C<device> should be a block device, for example C</dev/sda>.
1522
1523 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1524 and sectors on the device, which are passed directly to sfdisk as
1525 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1526 of these, then the corresponding parameter is omitted.  Usually for
1527 'large' disks, you can just pass C<0> for these, but for small
1528 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1529 out the right geometry and you will need to tell it.
1530
1531 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1532 information refer to the L<sfdisk(8)> manpage.
1533
1534 To create a single partition occupying the whole disk, you would
1535 pass C<lines> as a single element list, when the single element being
1536 the string C<,> (comma).
1537
1538 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1539 C<guestfs_part_init>");
1540
1541   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1542    [],
1543    "create a file",
1544    "\
1545 This call creates a file called C<path>.  The contents of the
1546 file is the string C<content> (which can contain any 8 bit data),
1547 with length C<size>.
1548
1549 As a special case, if C<size> is C<0>
1550 then the length is calculated using C<strlen> (so in this case
1551 the content cannot contain embedded ASCII NULs).
1552
1553 I<NB.> Owing to a bug, writing content containing ASCII NUL
1554 characters does I<not> work, even if the length is specified.");
1555
1556   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1557    [InitEmpty, Always, TestOutputListOfDevices (
1558       [["part_disk"; "/dev/sda"; "mbr"];
1559        ["mkfs"; "ext2"; "/dev/sda1"];
1560        ["mount_options"; ""; "/dev/sda1"; "/"];
1561        ["mounts"]], ["/dev/sda1"]);
1562     InitEmpty, Always, TestOutputList (
1563       [["part_disk"; "/dev/sda"; "mbr"];
1564        ["mkfs"; "ext2"; "/dev/sda1"];
1565        ["mount_options"; ""; "/dev/sda1"; "/"];
1566        ["umount"; "/"];
1567        ["mounts"]], [])],
1568    "unmount a filesystem",
1569    "\
1570 This unmounts the given filesystem.  The filesystem may be
1571 specified either by its mountpoint (path) or the device which
1572 contains the filesystem.");
1573
1574   ("mounts", (RStringList "devices", []), 46, [],
1575    [InitBasicFS, Always, TestOutputListOfDevices (
1576       [["mounts"]], ["/dev/sda1"])],
1577    "show mounted filesystems",
1578    "\
1579 This returns the list of currently mounted filesystems.  It returns
1580 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1581
1582 Some internal mounts are not shown.
1583
1584 See also: C<guestfs_mountpoints>");
1585
1586   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1587    [InitBasicFS, Always, TestOutputList (
1588       [["umount_all"];
1589        ["mounts"]], []);
1590     (* check that umount_all can unmount nested mounts correctly: *)
1591     InitEmpty, Always, TestOutputList (
1592       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1593        ["mkfs"; "ext2"; "/dev/sda1"];
1594        ["mkfs"; "ext2"; "/dev/sda2"];
1595        ["mkfs"; "ext2"; "/dev/sda3"];
1596        ["mount_options"; ""; "/dev/sda1"; "/"];
1597        ["mkdir"; "/mp1"];
1598        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1599        ["mkdir"; "/mp1/mp2"];
1600        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1601        ["mkdir"; "/mp1/mp2/mp3"];
1602        ["umount_all"];
1603        ["mounts"]], [])],
1604    "unmount all filesystems",
1605    "\
1606 This unmounts all mounted filesystems.
1607
1608 Some internal mounts are not unmounted by this call.");
1609
1610   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1611    [],
1612    "remove all LVM LVs, VGs and PVs",
1613    "\
1614 This command removes all LVM logical volumes, volume groups
1615 and physical volumes.");
1616
1617   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1618    [InitISOFS, Always, TestOutput (
1619       [["file"; "/empty"]], "empty");
1620     InitISOFS, Always, TestOutput (
1621       [["file"; "/known-1"]], "ASCII text");
1622     InitISOFS, Always, TestLastFail (
1623       [["file"; "/notexists"]])],
1624    "determine file type",
1625    "\
1626 This call uses the standard L<file(1)> command to determine
1627 the type or contents of the file.  This also works on devices,
1628 for example to find out whether a partition contains a filesystem.
1629
1630 This call will also transparently look inside various types
1631 of compressed file.
1632
1633 The exact command which runs is C<file -zbsL path>.  Note in
1634 particular that the filename is not prepended to the output
1635 (the C<-b> option).");
1636
1637   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1638    [InitBasicFS, Always, TestOutput (
1639       [["upload"; "test-command"; "/test-command"];
1640        ["chmod"; "0o755"; "/test-command"];
1641        ["command"; "/test-command 1"]], "Result1");
1642     InitBasicFS, Always, TestOutput (
1643       [["upload"; "test-command"; "/test-command"];
1644        ["chmod"; "0o755"; "/test-command"];
1645        ["command"; "/test-command 2"]], "Result2\n");
1646     InitBasicFS, Always, TestOutput (
1647       [["upload"; "test-command"; "/test-command"];
1648        ["chmod"; "0o755"; "/test-command"];
1649        ["command"; "/test-command 3"]], "\nResult3");
1650     InitBasicFS, Always, TestOutput (
1651       [["upload"; "test-command"; "/test-command"];
1652        ["chmod"; "0o755"; "/test-command"];
1653        ["command"; "/test-command 4"]], "\nResult4\n");
1654     InitBasicFS, Always, TestOutput (
1655       [["upload"; "test-command"; "/test-command"];
1656        ["chmod"; "0o755"; "/test-command"];
1657        ["command"; "/test-command 5"]], "\nResult5\n\n");
1658     InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 7"]], "");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 8"]], "\n");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 9"]], "\n\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1682     InitBasicFS, Always, TestLastFail (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command"]])],
1686    "run a command from the guest filesystem",
1687    "\
1688 This call runs a command from the guest filesystem.  The
1689 filesystem must be mounted, and must contain a compatible
1690 operating system (ie. something Linux, with the same
1691 or compatible processor architecture).
1692
1693 The single parameter is an argv-style list of arguments.
1694 The first element is the name of the program to run.
1695 Subsequent elements are parameters.  The list must be
1696 non-empty (ie. must contain a program name).  Note that
1697 the command runs directly, and is I<not> invoked via
1698 the shell (see C<guestfs_sh>).
1699
1700 The return value is anything printed to I<stdout> by
1701 the command.
1702
1703 If the command returns a non-zero exit status, then
1704 this function returns an error message.  The error message
1705 string is the content of I<stderr> from the command.
1706
1707 The C<$PATH> environment variable will contain at least
1708 C</usr/bin> and C</bin>.  If you require a program from
1709 another location, you should provide the full path in the
1710 first parameter.
1711
1712 Shared libraries and data files required by the program
1713 must be available on filesystems which are mounted in the
1714 correct places.  It is the caller's responsibility to ensure
1715 all filesystems that are needed are mounted at the right
1716 locations.");
1717
1718   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1719    [InitBasicFS, Always, TestOutputList (
1720       [["upload"; "test-command"; "/test-command"];
1721        ["chmod"; "0o755"; "/test-command"];
1722        ["command_lines"; "/test-command 1"]], ["Result1"]);
1723     InitBasicFS, Always, TestOutputList (
1724       [["upload"; "test-command"; "/test-command"];
1725        ["chmod"; "0o755"; "/test-command"];
1726        ["command_lines"; "/test-command 2"]], ["Result2"]);
1727     InitBasicFS, Always, TestOutputList (
1728       [["upload"; "test-command"; "/test-command"];
1729        ["chmod"; "0o755"; "/test-command"];
1730        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1731     InitBasicFS, Always, TestOutputList (
1732       [["upload"; "test-command"; "/test-command"];
1733        ["chmod"; "0o755"; "/test-command"];
1734        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1735     InitBasicFS, Always, TestOutputList (
1736       [["upload"; "test-command"; "/test-command"];
1737        ["chmod"; "0o755"; "/test-command"];
1738        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1739     InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 7"]], []);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 8"]], [""]);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 9"]], ["";""]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1763    "run a command, returning lines",
1764    "\
1765 This is the same as C<guestfs_command>, but splits the
1766 result into a list of lines.
1767
1768 See also: C<guestfs_sh_lines>");
1769
1770   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1771    [InitISOFS, Always, TestOutputStruct (
1772       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1773    "get file information",
1774    "\
1775 Returns file information for the given C<path>.
1776
1777 This is the same as the C<stat(2)> system call.");
1778
1779   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1780    [InitISOFS, Always, TestOutputStruct (
1781       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1782    "get file information for a symbolic link",
1783    "\
1784 Returns file information for the given C<path>.
1785
1786 This is the same as C<guestfs_stat> except that if C<path>
1787 is a symbolic link, then the link is stat-ed, not the file it
1788 refers to.
1789
1790 This is the same as the C<lstat(2)> system call.");
1791
1792   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1793    [InitISOFS, Always, TestOutputStruct (
1794       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1795    "get file system statistics",
1796    "\
1797 Returns file system statistics for any mounted file system.
1798 C<path> should be a file or directory in the mounted file system
1799 (typically it is the mount point itself, but it doesn't need to be).
1800
1801 This is the same as the C<statvfs(2)> system call.");
1802
1803   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1804    [], (* XXX test *)
1805    "get ext2/ext3/ext4 superblock details",
1806    "\
1807 This returns the contents of the ext2, ext3 or ext4 filesystem
1808 superblock on C<device>.
1809
1810 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1811 manpage for more details.  The list of fields returned isn't
1812 clearly defined, and depends on both the version of C<tune2fs>
1813 that libguestfs was built against, and the filesystem itself.");
1814
1815   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1816    [InitEmpty, Always, TestOutputTrue (
1817       [["blockdev_setro"; "/dev/sda"];
1818        ["blockdev_getro"; "/dev/sda"]])],
1819    "set block device to read-only",
1820    "\
1821 Sets the block device named C<device> to read-only.
1822
1823 This uses the L<blockdev(8)> command.");
1824
1825   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1826    [InitEmpty, Always, TestOutputFalse (
1827       [["blockdev_setrw"; "/dev/sda"];
1828        ["blockdev_getro"; "/dev/sda"]])],
1829    "set block device to read-write",
1830    "\
1831 Sets the block device named C<device> to read-write.
1832
1833 This uses the L<blockdev(8)> command.");
1834
1835   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1836    [InitEmpty, Always, TestOutputTrue (
1837       [["blockdev_setro"; "/dev/sda"];
1838        ["blockdev_getro"; "/dev/sda"]])],
1839    "is block device set to read-only",
1840    "\
1841 Returns a boolean indicating if the block device is read-only
1842 (true if read-only, false if not).
1843
1844 This uses the L<blockdev(8)> command.");
1845
1846   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1847    [InitEmpty, Always, TestOutputInt (
1848       [["blockdev_getss"; "/dev/sda"]], 512)],
1849    "get sectorsize of block device",
1850    "\
1851 This returns the size of sectors on a block device.
1852 Usually 512, but can be larger for modern devices.
1853
1854 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1855 for that).
1856
1857 This uses the L<blockdev(8)> command.");
1858
1859   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1860    [InitEmpty, Always, TestOutputInt (
1861       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1862    "get blocksize of block device",
1863    "\
1864 This returns the block size of a device.
1865
1866 (Note this is different from both I<size in blocks> and
1867 I<filesystem block size>).
1868
1869 This uses the L<blockdev(8)> command.");
1870
1871   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1872    [], (* XXX test *)
1873    "set blocksize of block device",
1874    "\
1875 This sets the block size of a device.
1876
1877 (Note this is different from both I<size in blocks> and
1878 I<filesystem block size>).
1879
1880 This uses the L<blockdev(8)> command.");
1881
1882   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1883    [InitEmpty, Always, TestOutputInt (
1884       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1885    "get total size of device in 512-byte sectors",
1886    "\
1887 This returns the size of the device in units of 512-byte sectors
1888 (even if the sectorsize isn't 512 bytes ... weird).
1889
1890 See also C<guestfs_blockdev_getss> for the real sector size of
1891 the device, and C<guestfs_blockdev_getsize64> for the more
1892 useful I<size in bytes>.
1893
1894 This uses the L<blockdev(8)> command.");
1895
1896   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1897    [InitEmpty, Always, TestOutputInt (
1898       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1899    "get total size of device in bytes",
1900    "\
1901 This returns the size of the device in bytes.
1902
1903 See also C<guestfs_blockdev_getsz>.
1904
1905 This uses the L<blockdev(8)> command.");
1906
1907   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1908    [InitEmpty, Always, TestRun
1909       [["blockdev_flushbufs"; "/dev/sda"]]],
1910    "flush device buffers",
1911    "\
1912 This tells the kernel to flush internal buffers associated
1913 with C<device>.
1914
1915 This uses the L<blockdev(8)> command.");
1916
1917   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1918    [InitEmpty, Always, TestRun
1919       [["blockdev_rereadpt"; "/dev/sda"]]],
1920    "reread partition table",
1921    "\
1922 Reread the partition table on C<device>.
1923
1924 This uses the L<blockdev(8)> command.");
1925
1926   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1927    [InitBasicFS, Always, TestOutput (
1928       (* Pick a file from cwd which isn't likely to change. *)
1929       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1930        ["checksum"; "md5"; "/COPYING.LIB"]],
1931       Digest.to_hex (Digest.file "COPYING.LIB"))],
1932    "upload a file from the local machine",
1933    "\
1934 Upload local file C<filename> to C<remotefilename> on the
1935 filesystem.
1936
1937 C<filename> can also be a named pipe.
1938
1939 See also C<guestfs_download>.");
1940
1941   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1942    [InitBasicFS, Always, TestOutput (
1943       (* Pick a file from cwd which isn't likely to change. *)
1944       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1945        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1946        ["upload"; "testdownload.tmp"; "/upload"];
1947        ["checksum"; "md5"; "/upload"]],
1948       Digest.to_hex (Digest.file "COPYING.LIB"))],
1949    "download a file to the local machine",
1950    "\
1951 Download file C<remotefilename> and save it as C<filename>
1952 on the local machine.
1953
1954 C<filename> can also be a named pipe.
1955
1956 See also C<guestfs_upload>, C<guestfs_cat>.");
1957
1958   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1959    [InitISOFS, Always, TestOutput (
1960       [["checksum"; "crc"; "/known-3"]], "2891671662");
1961     InitISOFS, Always, TestLastFail (
1962       [["checksum"; "crc"; "/notexists"]]);
1963     InitISOFS, Always, TestOutput (
1964       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1965     InitISOFS, Always, TestOutput (
1966       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1967     InitISOFS, Always, TestOutput (
1968       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1969     InitISOFS, Always, TestOutput (
1970       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1971     InitISOFS, Always, TestOutput (
1972       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1973     InitISOFS, Always, TestOutput (
1974       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1975     (* Test for RHBZ#579608, absolute symbolic links. *)
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1978    "compute MD5, SHAx or CRC checksum of file",
1979    "\
1980 This call computes the MD5, SHAx or CRC checksum of the
1981 file named C<path>.
1982
1983 The type of checksum to compute is given by the C<csumtype>
1984 parameter which must have one of the following values:
1985
1986 =over 4
1987
1988 =item C<crc>
1989
1990 Compute the cyclic redundancy check (CRC) specified by POSIX
1991 for the C<cksum> command.
1992
1993 =item C<md5>
1994
1995 Compute the MD5 hash (using the C<md5sum> program).
1996
1997 =item C<sha1>
1998
1999 Compute the SHA1 hash (using the C<sha1sum> program).
2000
2001 =item C<sha224>
2002
2003 Compute the SHA224 hash (using the C<sha224sum> program).
2004
2005 =item C<sha256>
2006
2007 Compute the SHA256 hash (using the C<sha256sum> program).
2008
2009 =item C<sha384>
2010
2011 Compute the SHA384 hash (using the C<sha384sum> program).
2012
2013 =item C<sha512>
2014
2015 Compute the SHA512 hash (using the C<sha512sum> program).
2016
2017 =back
2018
2019 The checksum is returned as a printable string.
2020
2021 To get the checksum for a device, use C<guestfs_checksum_device>.
2022
2023 To get the checksums for many files, use C<guestfs_checksums_out>.");
2024
2025   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2026    [InitBasicFS, Always, TestOutput (
2027       [["tar_in"; "../images/helloworld.tar"; "/"];
2028        ["cat"; "/hello"]], "hello\n")],
2029    "unpack tarfile to directory",
2030    "\
2031 This command uploads and unpacks local file C<tarfile> (an
2032 I<uncompressed> tar file) into C<directory>.
2033
2034 To upload a compressed tarball, use C<guestfs_tgz_in>
2035 or C<guestfs_txz_in>.");
2036
2037   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2038    [],
2039    "pack directory into tarfile",
2040    "\
2041 This command packs the contents of C<directory> and downloads
2042 it to local file C<tarfile>.
2043
2044 To download a compressed tarball, use C<guestfs_tgz_out>
2045 or C<guestfs_txz_out>.");
2046
2047   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2048    [InitBasicFS, Always, TestOutput (
2049       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2050        ["cat"; "/hello"]], "hello\n")],
2051    "unpack compressed tarball to directory",
2052    "\
2053 This command uploads and unpacks local file C<tarball> (a
2054 I<gzip compressed> tar file) into C<directory>.
2055
2056 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2057
2058   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2059    [],
2060    "pack directory into compressed tarball",
2061    "\
2062 This command packs the contents of C<directory> and downloads
2063 it to local file C<tarball>.
2064
2065 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2066
2067   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2068    [InitBasicFS, Always, TestLastFail (
2069       [["umount"; "/"];
2070        ["mount_ro"; "/dev/sda1"; "/"];
2071        ["touch"; "/new"]]);
2072     InitBasicFS, Always, TestOutput (
2073       [["write"; "/new"; "data"];
2074        ["umount"; "/"];
2075        ["mount_ro"; "/dev/sda1"; "/"];
2076        ["cat"; "/new"]], "data")],
2077    "mount a guest disk, read-only",
2078    "\
2079 This is the same as the C<guestfs_mount> command, but it
2080 mounts the filesystem with the read-only (I<-o ro>) flag.");
2081
2082   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2083    [],
2084    "mount a guest disk with mount options",
2085    "\
2086 This is the same as the C<guestfs_mount> command, but it
2087 allows you to set the mount options as for the
2088 L<mount(8)> I<-o> flag.
2089
2090 If the C<options> parameter is an empty string, then
2091 no options are passed (all options default to whatever
2092 the filesystem uses).");
2093
2094   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2095    [],
2096    "mount a guest disk with mount options and vfstype",
2097    "\
2098 This is the same as the C<guestfs_mount> command, but it
2099 allows you to set both the mount options and the vfstype
2100 as for the L<mount(8)> I<-o> and I<-t> flags.");
2101
2102   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2103    [],
2104    "debugging and internals",
2105    "\
2106 The C<guestfs_debug> command exposes some internals of
2107 C<guestfsd> (the guestfs daemon) that runs inside the
2108 qemu subprocess.
2109
2110 There is no comprehensive help for this command.  You have
2111 to look at the file C<daemon/debug.c> in the libguestfs source
2112 to find out what you can do.");
2113
2114   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2115    [InitEmpty, Always, TestOutputList (
2116       [["part_disk"; "/dev/sda"; "mbr"];
2117        ["pvcreate"; "/dev/sda1"];
2118        ["vgcreate"; "VG"; "/dev/sda1"];
2119        ["lvcreate"; "LV1"; "VG"; "50"];
2120        ["lvcreate"; "LV2"; "VG"; "50"];
2121        ["lvremove"; "/dev/VG/LV1"];
2122        ["lvs"]], ["/dev/VG/LV2"]);
2123     InitEmpty, Always, TestOutputList (
2124       [["part_disk"; "/dev/sda"; "mbr"];
2125        ["pvcreate"; "/dev/sda1"];
2126        ["vgcreate"; "VG"; "/dev/sda1"];
2127        ["lvcreate"; "LV1"; "VG"; "50"];
2128        ["lvcreate"; "LV2"; "VG"; "50"];
2129        ["lvremove"; "/dev/VG"];
2130        ["lvs"]], []);
2131     InitEmpty, Always, TestOutputList (
2132       [["part_disk"; "/dev/sda"; "mbr"];
2133        ["pvcreate"; "/dev/sda1"];
2134        ["vgcreate"; "VG"; "/dev/sda1"];
2135        ["lvcreate"; "LV1"; "VG"; "50"];
2136        ["lvcreate"; "LV2"; "VG"; "50"];
2137        ["lvremove"; "/dev/VG"];
2138        ["vgs"]], ["VG"])],
2139    "remove an LVM logical volume",
2140    "\
2141 Remove an LVM logical volume C<device>, where C<device> is
2142 the path to the LV, such as C</dev/VG/LV>.
2143
2144 You can also remove all LVs in a volume group by specifying
2145 the VG name, C</dev/VG>.");
2146
2147   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2148    [InitEmpty, Always, TestOutputList (
2149       [["part_disk"; "/dev/sda"; "mbr"];
2150        ["pvcreate"; "/dev/sda1"];
2151        ["vgcreate"; "VG"; "/dev/sda1"];
2152        ["lvcreate"; "LV1"; "VG"; "50"];
2153        ["lvcreate"; "LV2"; "VG"; "50"];
2154        ["vgremove"; "VG"];
2155        ["lvs"]], []);
2156     InitEmpty, Always, TestOutputList (
2157       [["part_disk"; "/dev/sda"; "mbr"];
2158        ["pvcreate"; "/dev/sda1"];
2159        ["vgcreate"; "VG"; "/dev/sda1"];
2160        ["lvcreate"; "LV1"; "VG"; "50"];
2161        ["lvcreate"; "LV2"; "VG"; "50"];
2162        ["vgremove"; "VG"];
2163        ["vgs"]], [])],
2164    "remove an LVM volume group",
2165    "\
2166 Remove an LVM volume group C<vgname>, (for example C<VG>).
2167
2168 This also forcibly removes all logical volumes in the volume
2169 group (if any).");
2170
2171   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2172    [InitEmpty, Always, TestOutputListOfDevices (
2173       [["part_disk"; "/dev/sda"; "mbr"];
2174        ["pvcreate"; "/dev/sda1"];
2175        ["vgcreate"; "VG"; "/dev/sda1"];
2176        ["lvcreate"; "LV1"; "VG"; "50"];
2177        ["lvcreate"; "LV2"; "VG"; "50"];
2178        ["vgremove"; "VG"];
2179        ["pvremove"; "/dev/sda1"];
2180        ["lvs"]], []);
2181     InitEmpty, Always, TestOutputListOfDevices (
2182       [["part_disk"; "/dev/sda"; "mbr"];
2183        ["pvcreate"; "/dev/sda1"];
2184        ["vgcreate"; "VG"; "/dev/sda1"];
2185        ["lvcreate"; "LV1"; "VG"; "50"];
2186        ["lvcreate"; "LV2"; "VG"; "50"];
2187        ["vgremove"; "VG"];
2188        ["pvremove"; "/dev/sda1"];
2189        ["vgs"]], []);
2190     InitEmpty, Always, TestOutputListOfDevices (
2191       [["part_disk"; "/dev/sda"; "mbr"];
2192        ["pvcreate"; "/dev/sda1"];
2193        ["vgcreate"; "VG"; "/dev/sda1"];
2194        ["lvcreate"; "LV1"; "VG"; "50"];
2195        ["lvcreate"; "LV2"; "VG"; "50"];
2196        ["vgremove"; "VG"];
2197        ["pvremove"; "/dev/sda1"];
2198        ["pvs"]], [])],
2199    "remove an LVM physical volume",
2200    "\
2201 This wipes a physical volume C<device> so that LVM will no longer
2202 recognise it.
2203
2204 The implementation uses the C<pvremove> command which refuses to
2205 wipe physical volumes that contain any volume groups, so you have
2206 to remove those first.");
2207
2208   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2209    [InitBasicFS, Always, TestOutput (
2210       [["set_e2label"; "/dev/sda1"; "testlabel"];
2211        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2212    "set the ext2/3/4 filesystem label",
2213    "\
2214 This sets the ext2/3/4 filesystem label of the filesystem on
2215 C<device> to C<label>.  Filesystem labels are limited to
2216 16 characters.
2217
2218 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2219 to return the existing label on a filesystem.");
2220
2221   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2222    [],
2223    "get the ext2/3/4 filesystem label",
2224    "\
2225 This returns the ext2/3/4 filesystem label of the filesystem on
2226 C<device>.");
2227
2228   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2229    (let uuid = uuidgen () in
2230     [InitBasicFS, Always, TestOutput (
2231        [["set_e2uuid"; "/dev/sda1"; uuid];
2232         ["get_e2uuid"; "/dev/sda1"]], uuid);
2233      InitBasicFS, Always, TestOutput (
2234        [["set_e2uuid"; "/dev/sda1"; "clear"];
2235         ["get_e2uuid"; "/dev/sda1"]], "");
2236      (* We can't predict what UUIDs will be, so just check the commands run. *)
2237      InitBasicFS, Always, TestRun (
2238        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2239      InitBasicFS, Always, TestRun (
2240        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2241    "set the ext2/3/4 filesystem UUID",
2242    "\
2243 This sets the ext2/3/4 filesystem UUID of the filesystem on
2244 C<device> to C<uuid>.  The format of the UUID and alternatives
2245 such as C<clear>, C<random> and C<time> are described in the
2246 L<tune2fs(8)> manpage.
2247
2248 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2249 to return the existing UUID of a filesystem.");
2250
2251   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2252    [],
2253    "get the ext2/3/4 filesystem UUID",
2254    "\
2255 This returns the ext2/3/4 filesystem UUID of the filesystem on
2256 C<device>.");
2257
2258   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2259    [InitBasicFS, Always, TestOutputInt (
2260       [["umount"; "/dev/sda1"];
2261        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2262     InitBasicFS, Always, TestOutputInt (
2263       [["umount"; "/dev/sda1"];
2264        ["zero"; "/dev/sda1"];
2265        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2266    "run the filesystem checker",
2267    "\
2268 This runs the filesystem checker (fsck) on C<device> which
2269 should have filesystem type C<fstype>.
2270
2271 The returned integer is the status.  See L<fsck(8)> for the
2272 list of status codes from C<fsck>.
2273
2274 Notes:
2275
2276 =over 4
2277
2278 =item *
2279
2280 Multiple status codes can be summed together.
2281
2282 =item *
2283
2284 A non-zero return code can mean \"success\", for example if
2285 errors have been corrected on the filesystem.
2286
2287 =item *
2288
2289 Checking or repairing NTFS volumes is not supported
2290 (by linux-ntfs).
2291
2292 =back
2293
2294 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2295
2296   ("zero", (RErr, [Device "device"]), 85, [],
2297    [InitBasicFS, Always, TestOutput (
2298       [["umount"; "/dev/sda1"];
2299        ["zero"; "/dev/sda1"];
2300        ["file"; "/dev/sda1"]], "data")],
2301    "write zeroes to the device",
2302    "\
2303 This command writes zeroes over the first few blocks of C<device>.
2304
2305 How many blocks are zeroed isn't specified (but it's I<not> enough
2306 to securely wipe the device).  It should be sufficient to remove
2307 any partition tables, filesystem superblocks and so on.
2308
2309 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2310
2311   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2312    (* Test disabled because grub-install incompatible with virtio-blk driver.
2313     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2314     *)
2315    [InitBasicFS, Disabled, TestOutputTrue (
2316       [["grub_install"; "/"; "/dev/sda1"];
2317        ["is_dir"; "/boot"]])],
2318    "install GRUB",
2319    "\
2320 This command installs GRUB (the Grand Unified Bootloader) on
2321 C<device>, with the root directory being C<root>.");
2322
2323   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2324    [InitBasicFS, Always, TestOutput (
2325       [["write"; "/old"; "file content"];
2326        ["cp"; "/old"; "/new"];
2327        ["cat"; "/new"]], "file content");
2328     InitBasicFS, Always, TestOutputTrue (
2329       [["write"; "/old"; "file content"];
2330        ["cp"; "/old"; "/new"];
2331        ["is_file"; "/old"]]);
2332     InitBasicFS, Always, TestOutput (
2333       [["write"; "/old"; "file content"];
2334        ["mkdir"; "/dir"];
2335        ["cp"; "/old"; "/dir/new"];
2336        ["cat"; "/dir/new"]], "file content")],
2337    "copy a file",
2338    "\
2339 This copies a file from C<src> to C<dest> where C<dest> is
2340 either a destination filename or destination directory.");
2341
2342   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2343    [InitBasicFS, Always, TestOutput (
2344       [["mkdir"; "/olddir"];
2345        ["mkdir"; "/newdir"];
2346        ["write"; "/olddir/file"; "file content"];
2347        ["cp_a"; "/olddir"; "/newdir"];
2348        ["cat"; "/newdir/olddir/file"]], "file content")],
2349    "copy a file or directory recursively",
2350    "\
2351 This copies a file or directory from C<src> to C<dest>
2352 recursively using the C<cp -a> command.");
2353
2354   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2355    [InitBasicFS, Always, TestOutput (
2356       [["write"; "/old"; "file content"];
2357        ["mv"; "/old"; "/new"];
2358        ["cat"; "/new"]], "file content");
2359     InitBasicFS, Always, TestOutputFalse (
2360       [["write"; "/old"; "file content"];
2361        ["mv"; "/old"; "/new"];
2362        ["is_file"; "/old"]])],
2363    "move a file",
2364    "\
2365 This moves a file from C<src> to C<dest> where C<dest> is
2366 either a destination filename or destination directory.");
2367
2368   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2369    [InitEmpty, Always, TestRun (
2370       [["drop_caches"; "3"]])],
2371    "drop kernel page cache, dentries and inodes",
2372    "\
2373 This instructs the guest kernel to drop its page cache,
2374 and/or dentries and inode caches.  The parameter C<whattodrop>
2375 tells the kernel what precisely to drop, see
2376 L<http://linux-mm.org/Drop_Caches>
2377
2378 Setting C<whattodrop> to 3 should drop everything.
2379
2380 This automatically calls L<sync(2)> before the operation,
2381 so that the maximum guest memory is freed.");
2382
2383   ("dmesg", (RString "kmsgs", []), 91, [],
2384    [InitEmpty, Always, TestRun (
2385       [["dmesg"]])],
2386    "return kernel messages",
2387    "\
2388 This returns the kernel messages (C<dmesg> output) from
2389 the guest kernel.  This is sometimes useful for extended
2390 debugging of problems.
2391
2392 Another way to get the same information is to enable
2393 verbose messages with C<guestfs_set_verbose> or by setting
2394 the environment variable C<LIBGUESTFS_DEBUG=1> before
2395 running the program.");
2396
2397   ("ping_daemon", (RErr, []), 92, [],
2398    [InitEmpty, Always, TestRun (
2399       [["ping_daemon"]])],
2400    "ping the guest daemon",
2401    "\
2402 This is a test probe into the guestfs daemon running inside
2403 the qemu subprocess.  Calling this function checks that the
2404 daemon responds to the ping message, without affecting the daemon
2405 or attached block device(s) in any other way.");
2406
2407   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2408    [InitBasicFS, Always, TestOutputTrue (
2409       [["write"; "/file1"; "contents of a file"];
2410        ["cp"; "/file1"; "/file2"];
2411        ["equal"; "/file1"; "/file2"]]);
2412     InitBasicFS, Always, TestOutputFalse (
2413       [["write"; "/file1"; "contents of a file"];
2414        ["write"; "/file2"; "contents of another file"];
2415        ["equal"; "/file1"; "/file2"]]);
2416     InitBasicFS, Always, TestLastFail (
2417       [["equal"; "/file1"; "/file2"]])],
2418    "test if two files have equal contents",
2419    "\
2420 This compares the two files C<file1> and C<file2> and returns
2421 true if their content is exactly equal, or false otherwise.
2422
2423 The external L<cmp(1)> program is used for the comparison.");
2424
2425   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2426    [InitISOFS, Always, TestOutputList (
2427       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2428     InitISOFS, Always, TestOutputList (
2429       [["strings"; "/empty"]], []);
2430     (* Test for RHBZ#579608, absolute symbolic links. *)
2431     InitISOFS, Always, TestRun (
2432       [["strings"; "/abssymlink"]])],
2433    "print the printable strings in a file",
2434    "\
2435 This runs the L<strings(1)> command on a file and returns
2436 the list of printable strings found.");
2437
2438   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2439    [InitISOFS, Always, TestOutputList (
2440       [["strings_e"; "b"; "/known-5"]], []);
2441     InitBasicFS, Always, TestOutputList (
2442       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2443        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2444    "print the printable strings in a file",
2445    "\
2446 This is like the C<guestfs_strings> command, but allows you to
2447 specify the encoding of strings that are looked for in
2448 the source file C<path>.
2449
2450 Allowed encodings are:
2451
2452 =over 4
2453
2454 =item s
2455
2456 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2457 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2458
2459 =item S
2460
2461 Single 8-bit-byte characters.
2462
2463 =item b
2464
2465 16-bit big endian strings such as those encoded in
2466 UTF-16BE or UCS-2BE.
2467
2468 =item l (lower case letter L)
2469
2470 16-bit little endian such as UTF-16LE and UCS-2LE.
2471 This is useful for examining binaries in Windows guests.
2472
2473 =item B
2474
2475 32-bit big endian such as UCS-4BE.
2476
2477 =item L
2478
2479 32-bit little endian such as UCS-4LE.
2480
2481 =back
2482
2483 The returned strings are transcoded to UTF-8.");
2484
2485   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2486    [InitISOFS, Always, TestOutput (
2487       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2488     (* Test for RHBZ#501888c2 regression which caused large hexdump
2489      * commands to segfault.
2490      *)
2491     InitISOFS, Always, TestRun (
2492       [["hexdump"; "/100krandom"]]);
2493     (* Test for RHBZ#579608, absolute symbolic links. *)
2494     InitISOFS, Always, TestRun (
2495       [["hexdump"; "/abssymlink"]])],
2496    "dump a file in hexadecimal",
2497    "\
2498 This runs C<hexdump -C> on the given C<path>.  The result is
2499 the human-readable, canonical hex dump of the file.");
2500
2501   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2502    [InitNone, Always, TestOutput (
2503       [["part_disk"; "/dev/sda"; "mbr"];
2504        ["mkfs"; "ext3"; "/dev/sda1"];
2505        ["mount_options"; ""; "/dev/sda1"; "/"];
2506        ["write"; "/new"; "test file"];
2507        ["umount"; "/dev/sda1"];
2508        ["zerofree"; "/dev/sda1"];
2509        ["mount_options"; ""; "/dev/sda1"; "/"];
2510        ["cat"; "/new"]], "test file")],
2511    "zero unused inodes and disk blocks on ext2/3 filesystem",
2512    "\
2513 This runs the I<zerofree> program on C<device>.  This program
2514 claims to zero unused inodes and disk blocks on an ext2/3
2515 filesystem, thus making it possible to compress the filesystem
2516 more effectively.
2517
2518 You should B<not> run this program if the filesystem is
2519 mounted.
2520
2521 It is possible that using this program can damage the filesystem
2522 or data on the filesystem.");
2523
2524   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2525    [],
2526    "resize an LVM physical volume",
2527    "\
2528 This resizes (expands or shrinks) an existing LVM physical
2529 volume to match the new size of the underlying device.");
2530
2531   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2532                        Int "cyls"; Int "heads"; Int "sectors";
2533                        String "line"]), 99, [DangerWillRobinson],
2534    [],
2535    "modify a single partition on a block device",
2536    "\
2537 This runs L<sfdisk(8)> option to modify just the single
2538 partition C<n> (note: C<n> counts from 1).
2539
2540 For other parameters, see C<guestfs_sfdisk>.  You should usually
2541 pass C<0> for the cyls/heads/sectors parameters.
2542
2543 See also: C<guestfs_part_add>");
2544
2545   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2546    [],
2547    "display the partition table",
2548    "\
2549 This displays the partition table on C<device>, in the
2550 human-readable output of the L<sfdisk(8)> command.  It is
2551 not intended to be parsed.
2552
2553 See also: C<guestfs_part_list>");
2554
2555   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2556    [],
2557    "display the kernel geometry",
2558    "\
2559 This displays the kernel's idea of the geometry of C<device>.
2560
2561 The result is in human-readable format, and not designed to
2562 be parsed.");
2563
2564   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2565    [],
2566    "display the disk geometry from the partition table",
2567    "\
2568 This displays the disk geometry of C<device> read from the
2569 partition table.  Especially in the case where the underlying
2570 block device has been resized, this can be different from the
2571 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2572
2573 The result is in human-readable format, and not designed to
2574 be parsed.");
2575
2576   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2577    [],
2578    "activate or deactivate all volume groups",
2579    "\
2580 This command activates or (if C<activate> is false) deactivates
2581 all logical volumes in all volume groups.
2582 If activated, then they are made known to the
2583 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2584 then those devices disappear.
2585
2586 This command is the same as running C<vgchange -a y|n>");
2587
2588   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2589    [],
2590    "activate or deactivate some volume groups",
2591    "\
2592 This command activates or (if C<activate> is false) deactivates
2593 all logical volumes in the listed volume groups C<volgroups>.
2594 If activated, then they are made known to the
2595 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2596 then those devices disappear.
2597
2598 This command is the same as running C<vgchange -a y|n volgroups...>
2599
2600 Note that if C<volgroups> is an empty list then B<all> volume groups
2601 are activated or deactivated.");
2602
2603   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2604    [InitNone, Always, TestOutput (
2605       [["part_disk"; "/dev/sda"; "mbr"];
2606        ["pvcreate"; "/dev/sda1"];
2607        ["vgcreate"; "VG"; "/dev/sda1"];
2608        ["lvcreate"; "LV"; "VG"; "10"];
2609        ["mkfs"; "ext2"; "/dev/VG/LV"];
2610        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2611        ["write"; "/new"; "test content"];
2612        ["umount"; "/"];
2613        ["lvresize"; "/dev/VG/LV"; "20"];
2614        ["e2fsck_f"; "/dev/VG/LV"];
2615        ["resize2fs"; "/dev/VG/LV"];
2616        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2617        ["cat"; "/new"]], "test content");
2618     InitNone, Always, TestRun (
2619       (* Make an LV smaller to test RHBZ#587484. *)
2620       [["part_disk"; "/dev/sda"; "mbr"];
2621        ["pvcreate"; "/dev/sda1"];
2622        ["vgcreate"; "VG"; "/dev/sda1"];
2623        ["lvcreate"; "LV"; "VG"; "20"];
2624        ["lvresize"; "/dev/VG/LV"; "10"]])],
2625    "resize an LVM logical volume",
2626    "\
2627 This resizes (expands or shrinks) an existing LVM logical
2628 volume to C<mbytes>.  When reducing, data in the reduced part
2629 is lost.");
2630
2631   ("resize2fs", (RErr, [Device "device"]), 106, [],
2632    [], (* lvresize tests this *)
2633    "resize an ext2/ext3 filesystem",
2634    "\
2635 This resizes an ext2 or ext3 filesystem to match the size of
2636 the underlying device.
2637
2638 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2639 on the C<device> before calling this command.  For unknown reasons
2640 C<resize2fs> sometimes gives an error about this and sometimes not.
2641 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2642 calling this function.");
2643
2644   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2645    [InitBasicFS, Always, TestOutputList (
2646       [["find"; "/"]], ["lost+found"]);
2647     InitBasicFS, Always, TestOutputList (
2648       [["touch"; "/a"];
2649        ["mkdir"; "/b"];
2650        ["touch"; "/b/c"];
2651        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2652     InitBasicFS, Always, TestOutputList (
2653       [["mkdir_p"; "/a/b/c"];
2654        ["touch"; "/a/b/c/d"];
2655        ["find"; "/a/b/"]], ["c"; "c/d"])],
2656    "find all files and directories",
2657    "\
2658 This command lists out all files and directories, recursively,
2659 starting at C<directory>.  It is essentially equivalent to
2660 running the shell command C<find directory -print> but some
2661 post-processing happens on the output, described below.
2662
2663 This returns a list of strings I<without any prefix>.  Thus
2664 if the directory structure was:
2665
2666  /tmp/a
2667  /tmp/b
2668  /tmp/c/d
2669
2670 then the returned list from C<guestfs_find> C</tmp> would be
2671 4 elements:
2672
2673  a
2674  b
2675  c
2676  c/d
2677
2678 If C<directory> is not a directory, then this command returns
2679 an error.
2680
2681 The returned list is sorted.
2682
2683 See also C<guestfs_find0>.");
2684
2685   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2686    [], (* lvresize tests this *)
2687    "check an ext2/ext3 filesystem",
2688    "\
2689 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2690 filesystem checker on C<device>, noninteractively (C<-p>),
2691 even if the filesystem appears to be clean (C<-f>).
2692
2693 This command is only needed because of C<guestfs_resize2fs>
2694 (q.v.).  Normally you should use C<guestfs_fsck>.");
2695
2696   ("sleep", (RErr, [Int "secs"]), 109, [],
2697    [InitNone, Always, TestRun (
2698       [["sleep"; "1"]])],
2699    "sleep for some seconds",
2700    "\
2701 Sleep for C<secs> seconds.");
2702
2703   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2704    [InitNone, Always, TestOutputInt (
2705       [["part_disk"; "/dev/sda"; "mbr"];
2706        ["mkfs"; "ntfs"; "/dev/sda1"];
2707        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2708     InitNone, Always, TestOutputInt (
2709       [["part_disk"; "/dev/sda"; "mbr"];
2710        ["mkfs"; "ext2"; "/dev/sda1"];
2711        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2712    "probe NTFS volume",
2713    "\
2714 This command runs the L<ntfs-3g.probe(8)> command which probes
2715 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2716 be mounted read-write, and some cannot be mounted at all).
2717
2718 C<rw> is a boolean flag.  Set it to true if you want to test
2719 if the volume can be mounted read-write.  Set it to false if
2720 you want to test if the volume can be mounted read-only.
2721
2722 The return value is an integer which C<0> if the operation
2723 would succeed, or some non-zero value documented in the
2724 L<ntfs-3g.probe(8)> manual page.");
2725
2726   ("sh", (RString "output", [String "command"]), 111, [],
2727    [], (* XXX needs tests *)
2728    "run a command via the shell",
2729    "\
2730 This call runs a command from the guest filesystem via the
2731 guest's C</bin/sh>.
2732
2733 This is like C<guestfs_command>, but passes the command to:
2734
2735  /bin/sh -c \"command\"
2736
2737 Depending on the guest's shell, this usually results in
2738 wildcards being expanded, shell expressions being interpolated
2739 and so on.
2740
2741 All the provisos about C<guestfs_command> apply to this call.");
2742
2743   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2744    [], (* XXX needs tests *)
2745    "run a command via the shell returning lines",
2746    "\
2747 This is the same as C<guestfs_sh>, but splits the result
2748 into a list of lines.
2749
2750 See also: C<guestfs_command_lines>");
2751
2752   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2753    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2754     * code in stubs.c, since all valid glob patterns must start with "/".
2755     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2756     *)
2757    [InitBasicFS, Always, TestOutputList (
2758       [["mkdir_p"; "/a/b/c"];
2759        ["touch"; "/a/b/c/d"];
2760        ["touch"; "/a/b/c/e"];
2761        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2762     InitBasicFS, Always, TestOutputList (
2763       [["mkdir_p"; "/a/b/c"];
2764        ["touch"; "/a/b/c/d"];
2765        ["touch"; "/a/b/c/e"];
2766        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2767     InitBasicFS, Always, TestOutputList (
2768       [["mkdir_p"; "/a/b/c"];
2769        ["touch"; "/a/b/c/d"];
2770        ["touch"; "/a/b/c/e"];
2771        ["glob_expand"; "/a/*/x/*"]], [])],
2772    "expand a wildcard path",
2773    "\
2774 This command searches for all the pathnames matching
2775 C<pattern> according to the wildcard expansion rules
2776 used by the shell.
2777
2778 If no paths match, then this returns an empty list
2779 (note: not an error).
2780
2781 It is just a wrapper around the C L<glob(3)> function
2782 with flags C<GLOB_MARK|GLOB_BRACE>.
2783 See that manual page for more details.");
2784
2785   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2786    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2787       [["scrub_device"; "/dev/sdc"]])],
2788    "scrub (securely wipe) a device",
2789    "\
2790 This command writes patterns over C<device> to make data retrieval
2791 more difficult.
2792
2793 It is an interface to the L<scrub(1)> program.  See that
2794 manual page for more details.");
2795
2796   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2797    [InitBasicFS, Always, TestRun (
2798       [["write"; "/file"; "content"];
2799        ["scrub_file"; "/file"]])],
2800    "scrub (securely wipe) a file",
2801    "\
2802 This command writes patterns over a file to make data retrieval
2803 more difficult.
2804
2805 The file is I<removed> after scrubbing.
2806
2807 It is an interface to the L<scrub(1)> program.  See that
2808 manual page for more details.");
2809
2810   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2811    [], (* XXX needs testing *)
2812    "scrub (securely wipe) free space",
2813    "\
2814 This command creates the directory C<dir> and then fills it
2815 with files until the filesystem is full, and scrubs the files
2816 as for C<guestfs_scrub_file>, and deletes them.
2817 The intention is to scrub any free space on the partition
2818 containing C<dir>.
2819
2820 It is an interface to the L<scrub(1)> program.  See that
2821 manual page for more details.");
2822
2823   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2824    [InitBasicFS, Always, TestRun (
2825       [["mkdir"; "/tmp"];
2826        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2827    "create a temporary directory",
2828    "\
2829 This command creates a temporary directory.  The
2830 C<template> parameter should be a full pathname for the
2831 temporary directory name with the final six characters being
2832 \"XXXXXX\".
2833
2834 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2835 the second one being suitable for Windows filesystems.
2836
2837 The name of the temporary directory that was created
2838 is returned.
2839
2840 The temporary directory is created with mode 0700
2841 and is owned by root.
2842
2843 The caller is responsible for deleting the temporary
2844 directory and its contents after use.
2845
2846 See also: L<mkdtemp(3)>");
2847
2848   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2849    [InitISOFS, Always, TestOutputInt (
2850       [["wc_l"; "/10klines"]], 10000);
2851     (* Test for RHBZ#579608, absolute symbolic links. *)
2852     InitISOFS, Always, TestOutputInt (
2853       [["wc_l"; "/abssymlink"]], 10000)],
2854    "count lines in a file",
2855    "\
2856 This command counts the lines in a file, using the
2857 C<wc -l> external command.");
2858
2859   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2860    [InitISOFS, Always, TestOutputInt (
2861       [["wc_w"; "/10klines"]], 10000)],
2862    "count words in a file",
2863    "\
2864 This command counts the words in a file, using the
2865 C<wc -w> external command.");
2866
2867   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2868    [InitISOFS, Always, TestOutputInt (
2869       [["wc_c"; "/100kallspaces"]], 102400)],
2870    "count characters in a file",
2871    "\
2872 This command counts the characters in a file, using the
2873 C<wc -c> external command.");
2874
2875   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2876    [InitISOFS, Always, TestOutputList (
2877       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2878     (* Test for RHBZ#579608, absolute symbolic links. *)
2879     InitISOFS, Always, TestOutputList (
2880       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2881    "return first 10 lines of a file",
2882    "\
2883 This command returns up to the first 10 lines of a file as
2884 a list of strings.");
2885
2886   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2887    [InitISOFS, Always, TestOutputList (
2888       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2889     InitISOFS, Always, TestOutputList (
2890       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2891     InitISOFS, Always, TestOutputList (
2892       [["head_n"; "0"; "/10klines"]], [])],
2893    "return first N lines of a file",
2894    "\
2895 If the parameter C<nrlines> is a positive number, this returns the first
2896 C<nrlines> lines of the file C<path>.
2897
2898 If the parameter C<nrlines> is a negative number, this returns lines
2899 from the file C<path>, excluding the last C<nrlines> lines.
2900
2901 If the parameter C<nrlines> is zero, this returns an empty list.");
2902
2903   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2904    [InitISOFS, Always, TestOutputList (
2905       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2906    "return last 10 lines of a file",
2907    "\
2908 This command returns up to the last 10 lines of a file as
2909 a list of strings.");
2910
2911   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2912    [InitISOFS, Always, TestOutputList (
2913       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2914     InitISOFS, Always, TestOutputList (
2915       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2916     InitISOFS, Always, TestOutputList (
2917       [["tail_n"; "0"; "/10klines"]], [])],
2918    "return last N lines of a file",
2919    "\
2920 If the parameter C<nrlines> is a positive number, this returns the last
2921 C<nrlines> lines of the file C<path>.
2922
2923 If the parameter C<nrlines> is a negative number, this returns lines
2924 from the file C<path>, starting with the C<-nrlines>th line.
2925
2926 If the parameter C<nrlines> is zero, this returns an empty list.");
2927
2928   ("df", (RString "output", []), 125, [],
2929    [], (* XXX Tricky to test because it depends on the exact format
2930         * of the 'df' command and other imponderables.
2931         *)
2932    "report file system disk space usage",
2933    "\
2934 This command runs the C<df> command to report disk space used.
2935
2936 This command is mostly useful for interactive sessions.  It
2937 is I<not> intended that you try to parse the output string.
2938 Use C<statvfs> from programs.");
2939
2940   ("df_h", (RString "output", []), 126, [],
2941    [], (* XXX Tricky to test because it depends on the exact format
2942         * of the 'df' command and other imponderables.
2943         *)
2944    "report file system disk space usage (human readable)",
2945    "\
2946 This command runs the C<df -h> command to report disk space used
2947 in human-readable format.
2948
2949 This command is mostly useful for interactive sessions.  It
2950 is I<not> intended that you try to parse the output string.
2951 Use C<statvfs> from programs.");
2952
2953   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2954    [InitISOFS, Always, TestOutputInt (
2955       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2956    "estimate file space usage",
2957    "\
2958 This command runs the C<du -s> command to estimate file space
2959 usage for C<path>.
2960
2961 C<path> can be a file or a directory.  If C<path> is a directory
2962 then the estimate includes the contents of the directory and all
2963 subdirectories (recursively).
2964
2965 The result is the estimated size in I<kilobytes>
2966 (ie. units of 1024 bytes).");
2967
2968   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2969    [InitISOFS, Always, TestOutputList (
2970       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2971    "list files in an initrd",
2972    "\
2973 This command lists out files contained in an initrd.
2974
2975 The files are listed without any initial C</> character.  The
2976 files are listed in the order they appear (not necessarily
2977 alphabetical).  Directory names are listed as separate items.
2978
2979 Old Linux kernels (2.4 and earlier) used a compressed ext2
2980 filesystem as initrd.  We I<only> support the newer initramfs
2981 format (compressed cpio files).");
2982
2983   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2984    [],
2985    "mount a file using the loop device",
2986    "\
2987 This command lets you mount C<file> (a filesystem image
2988 in a file) on a mount point.  It is entirely equivalent to
2989 the command C<mount -o loop file mountpoint>.");
2990
2991   ("mkswap", (RErr, [Device "device"]), 130, [],
2992    [InitEmpty, Always, TestRun (
2993       [["part_disk"; "/dev/sda"; "mbr"];
2994        ["mkswap"; "/dev/sda1"]])],
2995    "create a swap partition",
2996    "\
2997 Create a swap partition on C<device>.");
2998
2999   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3000    [InitEmpty, Always, TestRun (
3001       [["part_disk"; "/dev/sda"; "mbr"];
3002        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3003    "create a swap partition with a label",
3004    "\
3005 Create a swap partition on C<device> with label C<label>.
3006
3007 Note that you cannot attach a swap label to a block device
3008 (eg. C</dev/sda>), just to a partition.  This appears to be
3009 a limitation of the kernel or swap tools.");
3010
3011   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3012    (let uuid = uuidgen () in
3013     [InitEmpty, Always, TestRun (
3014        [["part_disk"; "/dev/sda"; "mbr"];
3015         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3016    "create a swap partition with an explicit UUID",
3017    "\
3018 Create a swap partition on C<device> with UUID C<uuid>.");
3019
3020   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3021    [InitBasicFS, Always, TestOutputStruct (
3022       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3023        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3024        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3025     InitBasicFS, Always, TestOutputStruct (
3026       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3027        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3028    "make block, character or FIFO devices",
3029    "\
3030 This call creates block or character special devices, or
3031 named pipes (FIFOs).
3032
3033 The C<mode> parameter should be the mode, using the standard
3034 constants.  C<devmajor> and C<devminor> are the
3035 device major and minor numbers, only used when creating block
3036 and character special devices.
3037
3038 Note that, just like L<mknod(2)>, the mode must be bitwise
3039 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3040 just creates a regular file).  These constants are
3041 available in the standard Linux header files, or you can use
3042 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3043 which are wrappers around this command which bitwise OR
3044 in the appropriate constant for you.
3045
3046 The mode actually set is affected by the umask.");
3047
3048   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3049    [InitBasicFS, Always, TestOutputStruct (
3050       [["mkfifo"; "0o777"; "/node"];
3051        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3052    "make FIFO (named pipe)",
3053    "\
3054 This call creates a FIFO (named pipe) called C<path> with
3055 mode C<mode>.  It is just a convenient wrapper around
3056 C<guestfs_mknod>.
3057
3058 The mode actually set is affected by the umask.");
3059
3060   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3061    [InitBasicFS, Always, TestOutputStruct (
3062       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3063        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3064    "make block device node",
3065    "\
3066 This call creates a block device node called C<path> with
3067 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3068 It is just a convenient wrapper around C<guestfs_mknod>.
3069
3070 The mode actually set is affected by the umask.");
3071
3072   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3073    [InitBasicFS, Always, TestOutputStruct (
3074       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3075        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3076    "make char device node",
3077    "\
3078 This call creates a char device node called C<path> with
3079 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3080 It is just a convenient wrapper around C<guestfs_mknod>.
3081
3082 The mode actually set is affected by the umask.");
3083
3084   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3085    [InitEmpty, Always, TestOutputInt (
3086       [["umask"; "0o22"]], 0o22)],
3087    "set file mode creation mask (umask)",
3088    "\
3089 This function sets the mask used for creating new files and
3090 device nodes to C<mask & 0777>.
3091
3092 Typical umask values would be C<022> which creates new files
3093 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3094 C<002> which creates new files with permissions like
3095 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3096
3097 The default umask is C<022>.  This is important because it
3098 means that directories and device nodes will be created with
3099 C<0644> or C<0755> mode even if you specify C<0777>.
3100
3101 See also C<guestfs_get_umask>,
3102 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3103
3104 This call returns the previous umask.");
3105
3106   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3107    [],
3108    "read directories entries",
3109    "\
3110 This returns the list of directory entries in directory C<dir>.
3111
3112 All entries in the directory are returned, including C<.> and
3113 C<..>.  The entries are I<not> sorted, but returned in the same
3114 order as the underlying filesystem.
3115
3116 Also this call returns basic file type information about each
3117 file.  The C<ftyp> field will contain one of the following characters:
3118
3119 =over 4
3120
3121 =item 'b'
3122
3123 Block special
3124
3125 =item 'c'
3126
3127 Char special
3128
3129 =item 'd'
3130
3131 Directory
3132
3133 =item 'f'
3134
3135 FIFO (named pipe)
3136
3137 =item 'l'
3138
3139 Symbolic link
3140
3141 =item 'r'
3142
3143 Regular file
3144
3145 =item 's'
3146
3147 Socket
3148
3149 =item 'u'
3150
3151 Unknown file type
3152
3153 =item '?'
3154
3155 The L<readdir(3)> returned a C<d_type> field with an
3156 unexpected value
3157
3158 =back
3159
3160 This function is primarily intended for use by programs.  To
3161 get a simple list of names, use C<guestfs_ls>.  To get a printable
3162 directory for human consumption, use C<guestfs_ll>.");
3163
3164   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3165    [],
3166    "create partitions on a block device",
3167    "\
3168 This is a simplified interface to the C<guestfs_sfdisk>
3169 command, where partition sizes are specified in megabytes
3170 only (rounded to the nearest cylinder) and you don't need
3171 to specify the cyls, heads and sectors parameters which
3172 were rarely if ever used anyway.
3173
3174 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3175 and C<guestfs_part_disk>");
3176
3177   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3178    [],
3179    "determine file type inside a compressed file",
3180    "\
3181 This command runs C<file> after first decompressing C<path>
3182 using C<method>.
3183
3184 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3185
3186 Since 1.0.63, use C<guestfs_file> instead which can now
3187 process compressed files.");
3188
3189   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3190    [],
3191    "list extended attributes of a file or directory",
3192    "\
3193 This call lists the extended attributes of the file or directory
3194 C<path>.
3195
3196 At the system call level, this is a combination of the
3197 L<listxattr(2)> and L<getxattr(2)> calls.
3198
3199 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3200
3201   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3202    [],
3203    "list extended attributes of a file or directory",
3204    "\
3205 This is the same as C<guestfs_getxattrs>, but if C<path>
3206 is a symbolic link, then it returns the extended attributes
3207 of the link itself.");
3208
3209   ("setxattr", (RErr, [String "xattr";
3210                        String "val"; Int "vallen"; (* will be BufferIn *)
3211                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3212    [],
3213    "set extended attribute of a file or directory",
3214    "\
3215 This call sets the extended attribute named C<xattr>
3216 of the file C<path> to the value C<val> (of length C<vallen>).
3217 The value is arbitrary 8 bit data.
3218
3219 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3220
3221   ("lsetxattr", (RErr, [String "xattr";
3222                         String "val"; Int "vallen"; (* will be BufferIn *)
3223                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3224    [],
3225    "set extended attribute of a file or directory",
3226    "\
3227 This is the same as C<guestfs_setxattr>, but if C<path>
3228 is a symbolic link, then it sets an extended attribute
3229 of the link itself.");
3230
3231   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3232    [],
3233    "remove extended attribute of a file or directory",
3234    "\
3235 This call removes the extended attribute named C<xattr>
3236 of the file C<path>.
3237
3238 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3239
3240   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3241    [],
3242    "remove extended attribute of a file or directory",
3243    "\
3244 This is the same as C<guestfs_removexattr>, but if C<path>
3245 is a symbolic link, then it removes an extended attribute
3246 of the link itself.");
3247
3248   ("mountpoints", (RHashtable "mps", []), 147, [],
3249    [],
3250    "show mountpoints",
3251    "\
3252 This call is similar to C<guestfs_mounts>.  That call returns
3253 a list of devices.  This one returns a hash table (map) of
3254 device name to directory where the device is mounted.");
3255
3256   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3257    (* This is a special case: while you would expect a parameter
3258     * of type "Pathname", that doesn't work, because it implies
3259     * NEED_ROOT in the generated calling code in stubs.c, and
3260     * this function cannot use NEED_ROOT.
3261     *)
3262    [],
3263    "create a mountpoint",
3264    "\
3265 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3266 specialized calls that can be used to create extra mountpoints
3267 before mounting the first filesystem.
3268
3269 These calls are I<only> necessary in some very limited circumstances,
3270 mainly the case where you want to mount a mix of unrelated and/or
3271 read-only filesystems together.
3272
3273 For example, live CDs often contain a \"Russian doll\" nest of
3274 filesystems, an ISO outer layer, with a squashfs image inside, with
3275 an ext2/3 image inside that.  You can unpack this as follows
3276 in guestfish:
3277
3278  add-ro Fedora-11-i686-Live.iso
3279  run
3280  mkmountpoint /cd
3281  mkmountpoint /squash
3282  mkmountpoint /ext3
3283  mount /dev/sda /cd
3284  mount-loop /cd/LiveOS/squashfs.img /squash
3285  mount-loop /squash/LiveOS/ext3fs.img /ext3
3286
3287 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3288
3289   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3290    [],
3291    "remove a mountpoint",
3292    "\
3293 This calls removes a mountpoint that was previously created
3294 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3295 for full details.");
3296
3297   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3298    [InitISOFS, Always, TestOutputBuffer (
3299       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3300     (* Test various near large, large and too large files (RHBZ#589039). *)
3301     InitBasicFS, Always, TestLastFail (
3302       [["touch"; "/a"];
3303        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3304        ["read_file"; "/a"]]);
3305     InitBasicFS, Always, TestLastFail (
3306       [["touch"; "/a"];
3307        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3308        ["read_file"; "/a"]]);
3309     InitBasicFS, Always, TestLastFail (
3310       [["touch"; "/a"];
3311        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3312        ["read_file"; "/a"]])],
3313    "read a file",
3314    "\
3315 This calls returns the contents of the file C<path> as a
3316 buffer.
3317
3318 Unlike C<guestfs_cat>, this function can correctly
3319 handle files that contain embedded ASCII NUL characters.
3320 However unlike C<guestfs_download>, this function is limited
3321 in the total size of file that can be handled.");
3322
3323   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3324    [InitISOFS, Always, TestOutputList (
3325       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3326     InitISOFS, Always, TestOutputList (
3327       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3328     (* Test for RHBZ#579608, absolute symbolic links. *)
3329     InitISOFS, Always, TestOutputList (
3330       [["grep"; "nomatch"; "/abssymlink"]], [])],
3331    "return lines matching a pattern",
3332    "\
3333 This calls the external C<grep> program and returns the
3334 matching lines.");
3335
3336   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3337    [InitISOFS, Always, TestOutputList (
3338       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3339    "return lines matching a pattern",
3340    "\
3341 This calls the external C<egrep> program and returns the
3342 matching lines.");
3343
3344   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3345    [InitISOFS, Always, TestOutputList (
3346       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3347    "return lines matching a pattern",
3348    "\
3349 This calls the external C<fgrep> program and returns the
3350 matching lines.");
3351
3352   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3353    [InitISOFS, Always, TestOutputList (
3354       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3355    "return lines matching a pattern",
3356    "\
3357 This calls the external C<grep -i> program and returns the
3358 matching lines.");
3359
3360   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3361    [InitISOFS, Always, TestOutputList (
3362       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3363    "return lines matching a pattern",
3364    "\
3365 This calls the external C<egrep -i> program and returns the
3366 matching lines.");
3367
3368   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3369    [InitISOFS, Always, TestOutputList (
3370       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3371    "return lines matching a pattern",
3372    "\
3373 This calls the external C<fgrep -i> program and returns the
3374 matching lines.");
3375
3376   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3377    [InitISOFS, Always, TestOutputList (
3378       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3379    "return lines matching a pattern",
3380    "\
3381 This calls the external C<zgrep> program and returns the
3382 matching lines.");
3383
3384   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3385    [InitISOFS, Always, TestOutputList (
3386       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3387    "return lines matching a pattern",
3388    "\
3389 This calls the external C<zegrep> program and returns the
3390 matching lines.");
3391
3392   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3393    [InitISOFS, Always, TestOutputList (
3394       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3395    "return lines matching a pattern",
3396    "\
3397 This calls the external C<zfgrep> program and returns the
3398 matching lines.");
3399
3400   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3401    [InitISOFS, Always, TestOutputList (
3402       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3403    "return lines matching a pattern",
3404    "\
3405 This calls the external C<zgrep -i> program and returns the
3406 matching lines.");
3407
3408   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3409    [InitISOFS, Always, TestOutputList (
3410       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3411    "return lines matching a pattern",
3412    "\
3413 This calls the external C<zegrep -i> program and returns the
3414 matching lines.");
3415
3416   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3417    [InitISOFS, Always, TestOutputList (
3418       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3419    "return lines matching a pattern",
3420    "\
3421 This calls the external C<zfgrep -i> program and returns the
3422 matching lines.");
3423
3424   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3425    [InitISOFS, Always, TestOutput (
3426       [["realpath"; "/../directory"]], "/directory")],
3427    "canonicalized absolute pathname",
3428    "\
3429 Return the canonicalized absolute pathname of C<path>.  The
3430 returned path has no C<.>, C<..> or symbolic link path elements.");
3431
3432   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3433    [InitBasicFS, Always, TestOutputStruct (
3434       [["touch"; "/a"];
3435        ["ln"; "/a"; "/b"];
3436        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3437    "create a hard link",
3438    "\
3439 This command creates a hard link using the C<ln> command.");
3440
3441   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3442    [InitBasicFS, Always, TestOutputStruct (
3443       [["touch"; "/a"];
3444        ["touch"; "/b"];
3445        ["ln_f"; "/a"; "/b"];
3446        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3447    "create a hard link",
3448    "\
3449 This command creates a hard link using the C<ln -f> command.
3450 The C<-f> option removes the link (C<linkname>) if it exists already.");
3451
3452   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3453    [InitBasicFS, Always, TestOutputStruct (
3454       [["touch"; "/a"];
3455        ["ln_s"; "a"; "/b"];
3456        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3457    "create a symbolic link",
3458    "\
3459 This command creates a symbolic link using the C<ln -s> command.");
3460
3461   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3462    [InitBasicFS, Always, TestOutput (
3463       [["mkdir_p"; "/a/b"];
3464        ["touch"; "/a/b/c"];
3465        ["ln_sf"; "../d"; "/a/b/c"];
3466        ["readlink"; "/a/b/c"]], "../d")],
3467    "create a symbolic link",
3468    "\
3469 This command creates a symbolic link using the C<ln -sf> command,
3470 The C<-f> option removes the link (C<linkname>) if it exists already.");
3471
3472   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3473    [] (* XXX tested above *),
3474    "read the target of a symbolic link",
3475    "\
3476 This command reads the target of a symbolic link.");
3477
3478   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3479    [InitBasicFS, Always, TestOutputStruct (
3480       [["fallocate"; "/a"; "1000000"];
3481        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3482    "preallocate a file in the guest filesystem",
3483    "\
3484 This command preallocates a file (containing zero bytes) named
3485 C<path> of size C<len> bytes.  If the file exists already, it
3486 is overwritten.
3487
3488 Do not confuse this with the guestfish-specific
3489 C<alloc> command which allocates a file in the host and
3490 attaches it as a device.");
3491
3492   ("swapon_device", (RErr, [Device "device"]), 170, [],
3493    [InitPartition, Always, TestRun (
3494       [["mkswap"; "/dev/sda1"];
3495        ["swapon_device"; "/dev/sda1"];
3496        ["swapoff_device"; "/dev/sda1"]])],
3497    "enable swap on device",
3498    "\
3499 This command enables the libguestfs appliance to use the
3500 swap device or partition named C<device>.  The increased
3501 memory is made available for all commands, for example
3502 those run using C<guestfs_command> or C<guestfs_sh>.
3503
3504 Note that you should not swap to existing guest swap
3505 partitions unless you know what you are doing.  They may
3506 contain hibernation information, or other information that
3507 the guest doesn't want you to trash.  You also risk leaking
3508 information about the host to the guest this way.  Instead,
3509 attach a new host device to the guest and swap on that.");
3510
3511   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3512    [], (* XXX tested by swapon_device *)
3513    "disable swap on device",
3514    "\
3515 This command disables the libguestfs appliance swap
3516 device or partition named C<device>.
3517 See C<guestfs_swapon_device>.");
3518
3519   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3520    [InitBasicFS, Always, TestRun (
3521       [["fallocate"; "/swap"; "8388608"];
3522        ["mkswap_file"; "/swap"];
3523        ["swapon_file"; "/swap"];
3524        ["swapoff_file"; "/swap"]])],
3525    "enable swap on file",
3526    "\
3527 This command enables swap to a file.
3528 See C<guestfs_swapon_device> for other notes.");
3529
3530   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3531    [], (* XXX tested by swapon_file *)
3532    "disable swap on file",
3533    "\
3534 This command disables the libguestfs appliance swap on file.");
3535
3536   ("swapon_label", (RErr, [String "label"]), 174, [],
3537    [InitEmpty, Always, TestRun (
3538       [["part_disk"; "/dev/sdb"; "mbr"];
3539        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3540        ["swapon_label"; "swapit"];
3541        ["swapoff_label"; "swapit"];
3542        ["zero"; "/dev/sdb"];
3543        ["blockdev_rereadpt"; "/dev/sdb"]])],
3544    "enable swap on labeled swap partition",
3545    "\
3546 This command enables swap to a labeled swap partition.
3547 See C<guestfs_swapon_device> for other notes.");
3548
3549   ("swapoff_label", (RErr, [String "label"]), 175, [],
3550    [], (* XXX tested by swapon_label *)
3551    "disable swap on labeled swap partition",
3552    "\
3553 This command disables the libguestfs appliance swap on
3554 labeled swap partition.");
3555
3556   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3557    (let uuid = uuidgen () in
3558     [InitEmpty, Always, TestRun (
3559        [["mkswap_U"; uuid; "/dev/sdb"];
3560         ["swapon_uuid"; uuid];
3561         ["swapoff_uuid"; uuid]])]),
3562    "enable swap on swap partition by UUID",
3563    "\
3564 This command enables swap to a swap partition with the given UUID.
3565 See C<guestfs_swapon_device> for other notes.");
3566
3567   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3568    [], (* XXX tested by swapon_uuid *)
3569    "disable swap on swap partition by UUID",
3570    "\
3571 This command disables the libguestfs appliance swap partition
3572 with the given UUID.");
3573
3574   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3575    [InitBasicFS, Always, TestRun (
3576       [["fallocate"; "/swap"; "8388608"];
3577        ["mkswap_file"; "/swap"]])],
3578    "create a swap file",
3579    "\
3580 Create a swap file.
3581
3582 This command just writes a swap file signature to an existing
3583 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3584
3585   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3586    [InitISOFS, Always, TestRun (
3587       [["inotify_init"; "0"]])],
3588    "create an inotify handle",
3589    "\
3590 This command creates a new inotify handle.
3591 The inotify subsystem can be used to notify events which happen to
3592 objects in the guest filesystem.
3593
3594 C<maxevents> is the maximum number of events which will be
3595 queued up between calls to C<guestfs_inotify_read> or
3596 C<guestfs_inotify_files>.
3597 If this is passed as C<0>, then the kernel (or previously set)
3598 default is used.  For Linux 2.6.29 the default was 16384 events.
3599 Beyond this limit, the kernel throws away events, but records
3600 the fact that it threw them away by setting a flag
3601 C<IN_Q_OVERFLOW> in the returned structure list (see
3602 C<guestfs_inotify_read>).
3603
3604 Before any events are generated, you have to add some
3605 watches to the internal watch list.  See:
3606 C<guestfs_inotify_add_watch>,
3607 C<guestfs_inotify_rm_watch> and
3608 C<guestfs_inotify_watch_all>.
3609
3610 Queued up events should be read periodically by calling
3611 C<guestfs_inotify_read>
3612 (or C<guestfs_inotify_files> which is just a helpful
3613 wrapper around C<guestfs_inotify_read>).  If you don't
3614 read the events out often enough then you risk the internal
3615 queue overflowing.
3616
3617 The handle should be closed after use by calling
3618 C<guestfs_inotify_close>.  This also removes any
3619 watches automatically.
3620
3621 See also L<inotify(7)> for an overview of the inotify interface
3622 as exposed by the Linux kernel, which is roughly what we expose
3623 via libguestfs.  Note that there is one global inotify handle
3624 per libguestfs instance.");
3625
3626   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3627    [InitBasicFS, Always, TestOutputList (
3628       [["inotify_init"; "0"];
3629        ["inotify_add_watch"; "/"; "1073741823"];
3630        ["touch"; "/a"];
3631        ["touch"; "/b"];
3632        ["inotify_files"]], ["a"; "b"])],
3633    "add an inotify watch",
3634    "\
3635 Watch C<path> for the events listed in C<mask>.
3636
3637 Note that if C<path> is a directory then events within that
3638 directory are watched, but this does I<not> happen recursively
3639 (in subdirectories).
3640
3641 Note for non-C or non-Linux callers: the inotify events are
3642 defined by the Linux kernel ABI and are listed in
3643 C</usr/include/sys/inotify.h>.");
3644
3645   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3646    [],
3647    "remove an inotify watch",
3648    "\
3649 Remove a previously defined inotify watch.
3650 See C<guestfs_inotify_add_watch>.");
3651
3652   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3653    [],
3654    "return list of inotify events",
3655    "\
3656 Return the complete queue of events that have happened
3657 since the previous read call.
3658
3659 If no events have happened, this returns an empty list.
3660
3661 I<Note>: In order to make sure that all events have been
3662 read, you must call this function repeatedly until it
3663 returns an empty list.  The reason is that the call will
3664 read events up to the maximum appliance-to-host message
3665 size and leave remaining events in the queue.");
3666
3667   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3668    [],
3669    "return list of watched files that had events",
3670    "\
3671 This function is a helpful wrapper around C<guestfs_inotify_read>
3672 which just returns a list of pathnames of objects that were
3673 touched.  The returned pathnames are sorted and deduplicated.");
3674
3675   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3676    [],
3677    "close the inotify handle",
3678    "\
3679 This closes the inotify handle which was previously
3680 opened by inotify_init.  It removes all watches, throws
3681 away any pending events, and deallocates all resources.");
3682
3683   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3684    [],
3685    "set SELinux security context",
3686    "\
3687 This sets the SELinux security context of the daemon
3688 to the string C<context>.
3689
3690 See the documentation about SELINUX in L<guestfs(3)>.");
3691
3692   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3693    [],
3694    "get SELinux security context",
3695    "\
3696 This gets the SELinux security context of the daemon.
3697
3698 See the documentation about SELINUX in L<guestfs(3)>,
3699 and C<guestfs_setcon>");
3700
3701   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3702    [InitEmpty, Always, TestOutput (
3703       [["part_disk"; "/dev/sda"; "mbr"];
3704        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3705        ["mount_options"; ""; "/dev/sda1"; "/"];
3706        ["write"; "/new"; "new file contents"];
3707        ["cat"; "/new"]], "new file contents")],
3708    "make a filesystem with block size",
3709    "\
3710 This call is similar to C<guestfs_mkfs>, but it allows you to
3711 control the block size of the resulting filesystem.  Supported
3712 block sizes depend on the filesystem type, but typically they
3713 are C<1024>, C<2048> or C<4096> only.");
3714
3715   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3716    [InitEmpty, Always, TestOutput (
3717       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3718        ["mke2journal"; "4096"; "/dev/sda1"];
3719        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3720        ["mount_options"; ""; "/dev/sda2"; "/"];
3721        ["write"; "/new"; "new file contents"];
3722        ["cat"; "/new"]], "new file contents")],
3723    "make ext2/3/4 external journal",
3724    "\
3725 This creates an ext2 external journal on C<device>.  It is equivalent
3726 to the command:
3727
3728  mke2fs -O journal_dev -b blocksize device");
3729
3730   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3731    [InitEmpty, Always, TestOutput (
3732       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3733        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3734        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3735        ["mount_options"; ""; "/dev/sda2"; "/"];
3736        ["write"; "/new"; "new file contents"];
3737        ["cat"; "/new"]], "new file contents")],
3738    "make ext2/3/4 external journal with label",
3739    "\
3740 This creates an ext2 external journal on C<device> with label C<label>.");
3741
3742   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3743    (let uuid = uuidgen () in
3744     [InitEmpty, Always, TestOutput (
3745        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3746         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3747         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3748         ["mount_options"; ""; "/dev/sda2"; "/"];
3749         ["write"; "/new"; "new file contents"];
3750         ["cat"; "/new"]], "new file contents")]),
3751    "make ext2/3/4 external journal with UUID",
3752    "\
3753 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3754
3755   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3756    [],
3757    "make ext2/3/4 filesystem with external journal",
3758    "\
3759 This creates an ext2/3/4 filesystem on C<device> with
3760 an external journal on C<journal>.  It is equivalent
3761 to the command:
3762
3763  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3764
3765 See also C<guestfs_mke2journal>.");
3766
3767   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3768    [],
3769    "make ext2/3/4 filesystem with external journal",
3770    "\
3771 This creates an ext2/3/4 filesystem on C<device> with
3772 an external journal on the journal labeled C<label>.
3773
3774 See also C<guestfs_mke2journal_L>.");
3775
3776   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3777    [],
3778    "make ext2/3/4 filesystem with external journal",
3779    "\
3780 This creates an ext2/3/4 filesystem on C<device> with
3781 an external journal on the journal with UUID C<uuid>.
3782
3783 See also C<guestfs_mke2journal_U>.");
3784
3785   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3786    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3787    "load a kernel module",
3788    "\
3789 This loads a kernel module in the appliance.
3790
3791 The kernel module must have been whitelisted when libguestfs
3792 was built (see C<appliance/kmod.whitelist.in> in the source).");
3793
3794   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3795    [InitNone, Always, TestOutput (
3796       [["echo_daemon"; "This is a test"]], "This is a test"
3797     )],
3798    "echo arguments back to the client",
3799    "\
3800 This command concatenate the list of C<words> passed with single spaces between
3801 them and returns the resulting string.
3802
3803 You can use this command to test the connection through to the daemon.
3804
3805 See also C<guestfs_ping_daemon>.");
3806
3807   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3808    [], (* There is a regression test for this. *)
3809    "find all files and directories, returning NUL-separated list",
3810    "\
3811 This command lists out all files and directories, recursively,
3812 starting at C<directory>, placing the resulting list in the
3813 external file called C<files>.
3814
3815 This command works the same way as C<guestfs_find> with the
3816 following exceptions:
3817
3818 =over 4
3819
3820 =item *
3821
3822 The resulting list is written to an external file.
3823
3824 =item *
3825
3826 Items (filenames) in the result are separated
3827 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3828
3829 =item *
3830
3831 This command is not limited in the number of names that it
3832 can return.
3833
3834 =item *
3835
3836 The result list is not sorted.
3837
3838 =back");
3839
3840   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3841    [InitISOFS, Always, TestOutput (
3842       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3843     InitISOFS, Always, TestOutput (
3844       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3845     InitISOFS, Always, TestOutput (
3846       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3847     InitISOFS, Always, TestLastFail (
3848       [["case_sensitive_path"; "/Known-1/"]]);
3849     InitBasicFS, Always, TestOutput (
3850       [["mkdir"; "/a"];
3851        ["mkdir"; "/a/bbb"];
3852        ["touch"; "/a/bbb/c"];
3853        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3854     InitBasicFS, Always, TestOutput (
3855       [["mkdir"; "/a"];
3856        ["mkdir"; "/a/bbb"];
3857        ["touch"; "/a/bbb/c"];
3858        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3859     InitBasicFS, Always, TestLastFail (
3860       [["mkdir"; "/a"];
3861        ["mkdir"; "/a/bbb"];
3862        ["touch"; "/a/bbb/c"];
3863        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3864    "return true path on case-insensitive filesystem",
3865    "\
3866 This can be used to resolve case insensitive paths on
3867 a filesystem which is case sensitive.  The use case is
3868 to resolve paths which you have read from Windows configuration
3869 files or the Windows Registry, to the true path.
3870
3871 The command handles a peculiarity of the Linux ntfs-3g
3872 filesystem driver (and probably others), which is that although
3873 the underlying filesystem is case-insensitive, the driver
3874 exports the filesystem to Linux as case-sensitive.
3875
3876 One consequence of this is that special directories such
3877 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3878 (or other things) depending on the precise details of how
3879 they were created.  In Windows itself this would not be
3880 a problem.
3881
3882 Bug or feature?  You decide:
3883 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3884
3885 This function resolves the true case of each element in the
3886 path and returns the case-sensitive path.
3887
3888 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3889 might return C<\"/WINDOWS/system32\"> (the exact return value
3890 would depend on details of how the directories were originally
3891 created under Windows).
3892
3893 I<Note>:
3894 This function does not handle drive names, backslashes etc.
3895
3896 See also C<guestfs_realpath>.");
3897
3898   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3899    [InitBasicFS, Always, TestOutput (
3900       [["vfs_type"; "/dev/sda1"]], "ext2")],
3901    "get the Linux VFS type corresponding to a mounted device",
3902    "\
3903 This command gets the block device type corresponding to
3904 a mounted device called C<device>.
3905
3906 Usually the result is the name of the Linux VFS module that
3907 is used to mount this device (probably determined automatically
3908 if you used the C<guestfs_mount> call).");
3909
3910   ("truncate", (RErr, [Pathname "path"]), 199, [],
3911    [InitBasicFS, Always, TestOutputStruct (
3912       [["write"; "/test"; "some stuff so size is not zero"];
3913        ["truncate"; "/test"];
3914        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3915    "truncate a file to zero size",
3916    "\
3917 This command truncates C<path> to a zero-length file.  The
3918 file must exist already.");
3919
3920   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3921    [InitBasicFS, Always, TestOutputStruct (
3922       [["touch"; "/test"];
3923        ["truncate_size"; "/test"; "1000"];
3924        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3925    "truncate a file to a particular size",
3926    "\
3927 This command truncates C<path> to size C<size> bytes.  The file
3928 must exist already.  If the file is smaller than C<size> then
3929 the file is extended to the required size with null bytes.");
3930
3931   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3932    [InitBasicFS, Always, TestOutputStruct (
3933       [["touch"; "/test"];
3934        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3935        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3936    "set timestamp of a file with nanosecond precision",
3937    "\
3938 This command sets the timestamps of a file with nanosecond
3939 precision.
3940
3941 C<atsecs, atnsecs> are the last access time (atime) in secs and
3942 nanoseconds from the epoch.
3943
3944 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3945 secs and nanoseconds from the epoch.
3946
3947 If the C<*nsecs> field contains the special value C<-1> then
3948 the corresponding timestamp is set to the current time.  (The
3949 C<*secs> field is ignored in this case).
3950
3951 If the C<*nsecs> field contains the special value C<-2> then
3952 the corresponding timestamp is left unchanged.  (The
3953 C<*secs> field is ignored in this case).");
3954
3955   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3956    [InitBasicFS, Always, TestOutputStruct (
3957       [["mkdir_mode"; "/test"; "0o111"];
3958        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3959    "create a directory with a particular mode",
3960    "\
3961 This command creates a directory, setting the initial permissions
3962 of the directory to C<mode>.
3963
3964 For common Linux filesystems, the actual mode which is set will
3965 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3966 interpret the mode in other ways.
3967
3968 See also C<guestfs_mkdir>, C<guestfs_umask>");
3969
3970   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3971    [], (* XXX *)
3972    "change file owner and group",
3973    "\
3974 Change the file owner to C<owner> and group to C<group>.
3975 This is like C<guestfs_chown> but if C<path> is a symlink then
3976 the link itself is changed, not the target.
3977
3978 Only numeric uid and gid are supported.  If you want to use
3979 names, you will need to locate and parse the password file
3980 yourself (Augeas support makes this relatively easy).");
3981
3982   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3983    [], (* XXX *)
3984    "lstat on multiple files",
3985    "\
3986 This call allows you to perform the C<guestfs_lstat> operation
3987 on multiple files, where all files are in the directory C<path>.
3988 C<names> is the list of files from this directory.
3989
3990 On return you get a list of stat structs, with a one-to-one
3991 correspondence to the C<names> list.  If any name did not exist
3992 or could not be lstat'd, then the C<ino> field of that structure
3993 is set to C<-1>.
3994
3995 This call is intended for programs that want to efficiently
3996 list a directory contents without making many round-trips.
3997 See also C<guestfs_lxattrlist> for a similarly efficient call
3998 for getting extended attributes.  Very long directory listings
3999 might cause the protocol message size to be exceeded, causing
4000 this call to fail.  The caller must split up such requests
4001 into smaller groups of names.");
4002
4003   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4004    [], (* XXX *)
4005    "lgetxattr on multiple files",
4006    "\
4007 This call allows you to get the extended attributes
4008 of multiple files, where all files are in the directory C<path>.
4009 C<names> is the list of files from this directory.
4010
4011 On return you get a flat list of xattr structs which must be
4012 interpreted sequentially.  The first xattr struct always has a zero-length
4013 C<attrname>.  C<attrval> in this struct is zero-length
4014 to indicate there was an error doing C<lgetxattr> for this
4015 file, I<or> is a C string which is a decimal number
4016 (the number of following attributes for this file, which could
4017 be C<\"0\">).  Then after the first xattr struct are the
4018 zero or more attributes for the first named file.
4019 This repeats for the second and subsequent files.
4020
4021 This call is intended for programs that want to efficiently
4022 list a directory contents without making many round-trips.
4023 See also C<guestfs_lstatlist> for a similarly efficient call
4024 for getting standard stats.  Very long directory listings
4025 might cause the protocol message size to be exceeded, causing
4026 this call to fail.  The caller must split up such requests
4027 into smaller groups of names.");
4028
4029   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4030    [], (* XXX *)
4031    "readlink on multiple files",
4032    "\
4033 This call allows you to do a C<readlink> operation
4034 on multiple files, where all files are in the directory C<path>.
4035 C<names> is the list of files from this directory.
4036
4037 On return you get a list of strings, with a one-to-one
4038 correspondence to the C<names> list.  Each string is the
4039 value of the symbol link.
4040
4041 If the C<readlink(2)> operation fails on any name, then
4042 the corresponding result string is the empty string C<\"\">.
4043 However the whole operation is completed even if there
4044 were C<readlink(2)> errors, and so you can call this
4045 function with names where you don't know if they are
4046 symbolic links already (albeit slightly less efficient).
4047
4048 This call is intended for programs that want to efficiently
4049 list a directory contents without making many round-trips.
4050 Very long directory listings might cause the protocol
4051 message size to be exceeded, causing
4052 this call to fail.  The caller must split up such requests
4053 into smaller groups of names.");
4054
4055   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4056    [InitISOFS, Always, TestOutputBuffer (
4057       [["pread"; "/known-4"; "1"; "3"]], "\n");
4058     InitISOFS, Always, TestOutputBuffer (
4059       [["pread"; "/empty"; "0"; "100"]], "")],
4060    "read part of a file",
4061    "\
4062 This command lets you read part of a file.  It reads C<count>
4063 bytes of the file, starting at C<offset>, from file C<path>.
4064
4065 This may read fewer bytes than requested.  For further details
4066 see the L<pread(2)> system call.
4067
4068 See also C<guestfs_pwrite>.");
4069
4070   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4071    [InitEmpty, Always, TestRun (
4072       [["part_init"; "/dev/sda"; "gpt"]])],
4073    "create an empty partition table",
4074    "\
4075 This creates an empty partition table on C<device> of one of the
4076 partition types listed below.  Usually C<parttype> should be
4077 either C<msdos> or C<gpt> (for large disks).
4078
4079 Initially there are no partitions.  Following this, you should
4080 call C<guestfs_part_add> for each partition required.
4081
4082 Possible values for C<parttype> are:
4083
4084 =over 4
4085
4086 =item B<efi> | B<gpt>
4087
4088 Intel EFI / GPT partition table.
4089
4090 This is recommended for >= 2 TB partitions that will be accessed
4091 from Linux and Intel-based Mac OS X.  It also has limited backwards
4092 compatibility with the C<mbr> format.
4093
4094 =item B<mbr> | B<msdos>
4095
4096 The standard PC \"Master Boot Record\" (MBR) format used
4097 by MS-DOS and Windows.  This partition type will B<only> work
4098 for device sizes up to 2 TB.  For large disks we recommend
4099 using C<gpt>.
4100
4101 =back
4102
4103 Other partition table types that may work but are not
4104 supported include:
4105
4106 =over 4
4107
4108 =item B<aix>
4109
4110 AIX disk labels.
4111
4112 =item B<amiga> | B<rdb>
4113
4114 Amiga \"Rigid Disk Block\" format.
4115
4116 =item B<bsd>
4117
4118 BSD disk labels.
4119
4120 =item B<dasd>
4121
4122 DASD, used on IBM mainframes.
4123
4124 =item B<dvh>
4125
4126 MIPS/SGI volumes.
4127
4128 =item B<mac>
4129
4130 Old Mac partition format.  Modern Macs use C<gpt>.
4131
4132 =item B<pc98>
4133
4134 NEC PC-98 format, common in Japan apparently.
4135
4136 =item B<sun>
4137
4138 Sun disk labels.
4139
4140 =back");
4141
4142   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4143    [InitEmpty, Always, TestRun (
4144       [["part_init"; "/dev/sda"; "mbr"];
4145        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4146     InitEmpty, Always, TestRun (
4147       [["part_init"; "/dev/sda"; "gpt"];
4148        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4149        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4150     InitEmpty, Always, TestRun (
4151       [["part_init"; "/dev/sda"; "mbr"];
4152        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4153        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4154        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4155        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4156    "add a partition to the device",
4157    "\
4158 This command adds a partition to C<device>.  If there is no partition
4159 table on the device, call C<guestfs_part_init> first.
4160
4161 The C<prlogex> parameter is the type of partition.  Normally you
4162 should pass C<p> or C<primary> here, but MBR partition tables also
4163 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4164 types.
4165
4166 C<startsect> and C<endsect> are the start and end of the partition
4167 in I<sectors>.  C<endsect> may be negative, which means it counts
4168 backwards from the end of the disk (C<-1> is the last sector).
4169
4170 Creating a partition which covers the whole disk is not so easy.
4171 Use C<guestfs_part_disk> to do that.");
4172
4173   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4174    [InitEmpty, Always, TestRun (
4175       [["part_disk"; "/dev/sda"; "mbr"]]);
4176     InitEmpty, Always, TestRun (
4177       [["part_disk"; "/dev/sda"; "gpt"]])],
4178    "partition whole disk with a single primary partition",
4179    "\
4180 This command is simply a combination of C<guestfs_part_init>
4181 followed by C<guestfs_part_add> to create a single primary partition
4182 covering the whole disk.
4183
4184 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4185 but other possible values are described in C<guestfs_part_init>.");
4186
4187   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4188    [InitEmpty, Always, TestRun (
4189       [["part_disk"; "/dev/sda"; "mbr"];
4190        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4191    "make a partition bootable",
4192    "\
4193 This sets the bootable flag on partition numbered C<partnum> on
4194 device C<device>.  Note that partitions are numbered from 1.
4195
4196 The bootable flag is used by some operating systems (notably
4197 Windows) to determine which partition to boot from.  It is by
4198 no means universally recognized.");
4199
4200   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4201    [InitEmpty, Always, TestRun (
4202       [["part_disk"; "/dev/sda"; "gpt"];
4203        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4204    "set partition name",
4205    "\
4206 This sets the partition name on partition numbered C<partnum> on
4207 device C<device>.  Note that partitions are numbered from 1.
4208
4209 The partition name can only be set on certain types of partition
4210 table.  This works on C<gpt> but not on C<mbr> partitions.");
4211
4212   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4213    [], (* XXX Add a regression test for this. *)
4214    "list partitions on a device",
4215    "\
4216 This command parses the partition table on C<device> and
4217 returns the list of partitions found.
4218
4219 The fields in the returned structure are:
4220
4221 =over 4
4222
4223 =item B<part_num>
4224
4225 Partition number, counting from 1.
4226
4227 =item B<part_start>
4228
4229 Start of the partition I<in bytes>.  To get sectors you have to
4230 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4231
4232 =item B<part_end>
4233
4234 End of the partition in bytes.
4235
4236 =item B<part_size>
4237
4238 Size of the partition in bytes.
4239
4240 =back");
4241
4242   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4243    [InitEmpty, Always, TestOutput (
4244       [["part_disk"; "/dev/sda"; "gpt"];
4245        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4246    "get the partition table type",
4247    "\
4248 This command examines the partition table on C<device> and
4249 returns the partition table type (format) being used.
4250
4251 Common return values include: C<msdos> (a DOS/Windows style MBR
4252 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4253 values are possible, although unusual.  See C<guestfs_part_init>
4254 for a full list.");
4255
4256   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4257    [InitBasicFS, Always, TestOutputBuffer (
4258       [["fill"; "0x63"; "10"; "/test"];
4259        ["read_file"; "/test"]], "cccccccccc")],
4260    "fill a file with octets",
4261    "\
4262 This command creates a new file called C<path>.  The initial
4263 content of the file is C<len> octets of C<c>, where C<c>
4264 must be a number in the range C<[0..255]>.
4265
4266 To fill a file with zero bytes (sparsely), it is
4267 much more efficient to use C<guestfs_truncate_size>.
4268 To create a file with a pattern of repeating bytes
4269 use C<guestfs_fill_pattern>.");
4270
4271   ("available", (RErr, [StringList "groups"]), 216, [],
4272    [InitNone, Always, TestRun [["available"; ""]]],
4273    "test availability of some parts of the API",
4274    "\
4275 This command is used to check the availability of some
4276 groups of functionality in the appliance, which not all builds of
4277 the libguestfs appliance will be able to provide.
4278
4279 The libguestfs groups, and the functions that those
4280 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4281
4282 The argument C<groups> is a list of group names, eg:
4283 C<[\"inotify\", \"augeas\"]> would check for the availability of
4284 the Linux inotify functions and Augeas (configuration file
4285 editing) functions.
4286
4287 The command returns no error if I<all> requested groups are available.
4288
4289 It fails with an error if one or more of the requested
4290 groups is unavailable in the appliance.
4291
4292 If an unknown group name is included in the
4293 list of groups then an error is always returned.
4294
4295 I<Notes:>
4296
4297 =over 4
4298
4299 =item *
4300
4301 You must call C<guestfs_launch> before calling this function.
4302
4303 The reason is because we don't know what groups are
4304 supported by the appliance/daemon until it is running and can
4305 be queried.
4306
4307 =item *
4308
4309 If a group of functions is available, this does not necessarily
4310 mean that they will work.  You still have to check for errors
4311 when calling individual API functions even if they are
4312 available.
4313
4314 =item *
4315
4316 It is usually the job of distro packagers to build
4317 complete functionality into the libguestfs appliance.
4318 Upstream libguestfs, if built from source with all
4319 requirements satisfied, will support everything.
4320
4321 =item *
4322
4323 This call was added in version C<1.0.80>.  In previous
4324 versions of libguestfs all you could do would be to speculatively
4325 execute a command to find out if the daemon implemented it.
4326 See also C<guestfs_version>.
4327
4328 =back");
4329
4330   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4331    [InitBasicFS, Always, TestOutputBuffer (
4332       [["write"; "/src"; "hello, world"];
4333        ["dd"; "/src"; "/dest"];
4334        ["read_file"; "/dest"]], "hello, world")],
4335    "copy from source to destination using dd",
4336    "\
4337 This command copies from one source device or file C<src>
4338 to another destination device or file C<dest>.  Normally you
4339 would use this to copy to or from a device or partition, for
4340 example to duplicate a filesystem.
4341
4342 If the destination is a device, it must be as large or larger
4343 than the source file or device, otherwise the copy will fail.
4344 This command cannot do partial copies (see C<guestfs_copy_size>).");
4345
4346   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4347    [InitBasicFS, Always, TestOutputInt (
4348       [["write"; "/file"; "hello, world"];
4349        ["filesize"; "/file"]], 12)],
4350    "return the size of the file in bytes",
4351    "\
4352 This command returns the size of C<file> in bytes.
4353
4354 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4355 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4356 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4357
4358   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4359    [InitBasicFSonLVM, Always, TestOutputList (
4360       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4361        ["lvs"]], ["/dev/VG/LV2"])],
4362    "rename an LVM logical volume",
4363    "\
4364 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4365
4366   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4367    [InitBasicFSonLVM, Always, TestOutputList (
4368       [["umount"; "/"];
4369        ["vg_activate"; "false"; "VG"];
4370        ["vgrename"; "VG"; "VG2"];
4371        ["vg_activate"; "true"; "VG2"];
4372        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4373        ["vgs"]], ["VG2"])],
4374    "rename an LVM volume group",
4375    "\
4376 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4377
4378   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4379    [InitISOFS, Always, TestOutputBuffer (
4380       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4381    "list the contents of a single file in an initrd",
4382    "\
4383 This command unpacks the file C<filename> from the initrd file
4384 called C<initrdpath>.  The filename must be given I<without> the
4385 initial C</> character.
4386
4387 For example, in guestfish you could use the following command
4388 to examine the boot script (usually called C</init>)
4389 contained in a Linux initrd or initramfs image:
4390
4391  initrd-cat /boot/initrd-<version>.img init
4392
4393 See also C<guestfs_initrd_list>.");
4394
4395   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4396    [],
4397    "get the UUID of a physical volume",
4398    "\
4399 This command returns the UUID of the LVM PV C<device>.");
4400
4401   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4402    [],
4403    "get the UUID of a volume group",
4404    "\
4405 This command returns the UUID of the LVM VG named C<vgname>.");
4406
4407   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4408    [],
4409    "get the UUID of a logical volume",
4410    "\
4411 This command returns the UUID of the LVM LV C<device>.");
4412
4413   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4414    [],
4415    "get the PV UUIDs containing the volume group",
4416    "\
4417 Given a VG called C<vgname>, this returns the UUIDs of all
4418 the physical volumes that this volume group resides on.
4419
4420 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4421 calls to associate physical volumes and volume groups.
4422
4423 See also C<guestfs_vglvuuids>.");
4424
4425   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4426    [],
4427    "get the LV UUIDs of all LVs in the volume group",
4428    "\
4429 Given a VG called C<vgname>, this returns the UUIDs of all
4430 the logical volumes created in this volume group.
4431
4432 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4433 calls to associate logical volumes and volume groups.
4434
4435 See also C<guestfs_vgpvuuids>.");
4436
4437   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4438    [InitBasicFS, Always, TestOutputBuffer (
4439       [["write"; "/src"; "hello, world"];
4440        ["copy_size"; "/src"; "/dest"; "5"];
4441        ["read_file"; "/dest"]], "hello")],
4442    "copy size bytes from source to destination using dd",
4443    "\
4444 This command copies exactly C<size> bytes from one source device
4445 or file C<src> to another destination device or file C<dest>.
4446
4447 Note this will fail if the source is too short or if the destination
4448 is not large enough.");
4449
4450   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4451    [InitBasicFSonLVM, Always, TestRun (
4452       [["zero_device"; "/dev/VG/LV"]])],
4453    "write zeroes to an entire device",
4454    "\
4455 This command writes zeroes over the entire C<device>.  Compare
4456 with C<guestfs_zero> which just zeroes the first few blocks of
4457 a device.");
4458
4459   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4460    [InitBasicFS, Always, TestOutput (
4461       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4462        ["cat"; "/hello"]], "hello\n")],
4463    "unpack compressed tarball to directory",
4464    "\
4465 This command uploads and unpacks local file C<tarball> (an
4466 I<xz compressed> tar file) into C<directory>.");
4467
4468   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4469    [],
4470    "pack directory into compressed tarball",
4471    "\
4472 This command packs the contents of C<directory> and downloads
4473 it to local file C<tarball> (as an xz compressed tar archive).");
4474
4475   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4476    [],
4477    "resize an NTFS filesystem",
4478    "\
4479 This command resizes an NTFS filesystem, expanding or
4480 shrinking it to the size of the underlying device.
4481 See also L<ntfsresize(8)>.");
4482
4483   ("vgscan", (RErr, []), 232, [],
4484    [InitEmpty, Always, TestRun (
4485       [["vgscan"]])],
4486    "rescan for LVM physical volumes, volume groups and logical volumes",
4487    "\
4488 This rescans all block devices and rebuilds the list of LVM
4489 physical volumes, volume groups and logical volumes.");
4490
4491   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4492    [InitEmpty, Always, TestRun (
4493       [["part_init"; "/dev/sda"; "mbr"];
4494        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4495        ["part_del"; "/dev/sda"; "1"]])],
4496    "delete a partition",
4497    "\
4498 This command deletes the partition numbered C<partnum> on C<device>.
4499
4500 Note that in the case of MBR partitioning, deleting an
4501 extended partition also deletes any logical partitions
4502 it contains.");
4503
4504   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4505    [InitEmpty, Always, TestOutputTrue (
4506       [["part_init"; "/dev/sda"; "mbr"];
4507        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4508        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4509        ["part_get_bootable"; "/dev/sda"; "1"]])],
4510    "return true if a partition is bootable",
4511    "\
4512 This command returns true if the partition C<partnum> on
4513 C<device> has the bootable flag set.
4514
4515 See also C<guestfs_part_set_bootable>.");
4516
4517   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4518    [InitEmpty, Always, TestOutputInt (
4519       [["part_init"; "/dev/sda"; "mbr"];
4520        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4521        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4522        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4523    "get the MBR type byte (ID byte) from a partition",
4524    "\
4525 Returns the MBR type byte (also known as the ID byte) from
4526 the numbered partition C<partnum>.
4527
4528 Note that only MBR (old DOS-style) partitions have type bytes.
4529 You will get undefined results for other partition table
4530 types (see C<guestfs_part_get_parttype>).");
4531
4532   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4533    [], (* tested by part_get_mbr_id *)
4534    "set the MBR type byte (ID byte) of a partition",
4535    "\
4536 Sets the MBR type byte (also known as the ID byte) of
4537 the numbered partition C<partnum> to C<idbyte>.  Note
4538 that the type bytes quoted in most documentation are
4539 in fact hexadecimal numbers, but usually documented
4540 without any leading \"0x\" which might be confusing.
4541
4542 Note that only MBR (old DOS-style) partitions have type bytes.
4543 You will get undefined results for other partition table
4544 types (see C<guestfs_part_get_parttype>).");
4545
4546   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4547    [InitISOFS, Always, TestOutput (
4548       [["checksum_device"; "md5"; "/dev/sdd"]],
4549       (Digest.to_hex (Digest.file "images/test.iso")))],
4550    "compute MD5, SHAx or CRC checksum of the contents of a device",
4551    "\
4552 This call computes the MD5, SHAx or CRC checksum of the
4553 contents of the device named C<device>.  For the types of
4554 checksums supported see the C<guestfs_checksum> command.");
4555
4556   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4557    [InitNone, Always, TestRun (
4558       [["part_disk"; "/dev/sda"; "mbr"];
4559        ["pvcreate"; "/dev/sda1"];
4560        ["vgcreate"; "VG"; "/dev/sda1"];
4561        ["lvcreate"; "LV"; "VG"; "10"];
4562        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4563    "expand an LV to fill free space",
4564    "\
4565 This expands an existing logical volume C<lv> so that it fills
4566 C<pc>% of the remaining free space in the volume group.  Commonly
4567 you would call this with pc = 100 which expands the logical volume
4568 as much as possible, using all remaining free space in the volume
4569 group.");
4570
4571   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4572    [], (* XXX Augeas code needs tests. *)
4573    "clear Augeas path",
4574    "\
4575 Set the value associated with C<path> to C<NULL>.  This
4576 is the same as the L<augtool(1)> C<clear> command.");
4577
4578   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4579    [InitEmpty, Always, TestOutputInt (
4580       [["get_umask"]], 0o22)],
4581    "get the current umask",
4582    "\
4583 Return the current umask.  By default the umask is C<022>
4584 unless it has been set by calling C<guestfs_umask>.");
4585
4586   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4587    [],
4588    "upload a file to the appliance (internal use only)",
4589    "\
4590 The C<guestfs_debug_upload> command uploads a file to
4591 the libguestfs appliance.
4592
4593 There is no comprehensive help for this command.  You have
4594 to look at the file C<daemon/debug.c> in the libguestfs source
4595 to find out what it is for.");
4596
4597   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4598    [InitBasicFS, Always, TestOutput (
4599       [["base64_in"; "../images/hello.b64"; "/hello"];
4600        ["cat"; "/hello"]], "hello\n")],
4601    "upload base64-encoded data to file",
4602    "\
4603 This command uploads base64-encoded data from C<base64file>
4604 to C<filename>.");
4605
4606   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4607    [],
4608    "download file and encode as base64",
4609    "\
4610 This command downloads the contents of C<filename>, writing
4611 it out to local file C<base64file> encoded as base64.");
4612
4613   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4614    [],
4615    "compute MD5, SHAx or CRC checksum of files in a directory",
4616    "\
4617 This command computes the checksums of all regular files in
4618 C<directory> and then emits a list of those checksums to
4619 the local output file C<sumsfile>.
4620
4621 This can be used for verifying the integrity of a virtual
4622 machine.  However to be properly secure you should pay
4623 attention to the output of the checksum command (it uses
4624 the ones from GNU coreutils).  In particular when the
4625 filename is not printable, coreutils uses a special
4626 backslash syntax.  For more information, see the GNU
4627 coreutils info file.");
4628
4629   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4630    [InitBasicFS, Always, TestOutputBuffer (
4631       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4632        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4633    "fill a file with a repeating pattern of bytes",
4634    "\
4635 This function is like C<guestfs_fill> except that it creates
4636 a new file of length C<len> containing the repeating pattern
4637 of bytes in C<pattern>.  The pattern is truncated if necessary
4638 to ensure the length of the file is exactly C<len> bytes.");
4639
4640   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4641    [InitBasicFS, Always, TestOutput (
4642       [["write"; "/new"; "new file contents"];
4643        ["cat"; "/new"]], "new file contents");
4644     InitBasicFS, Always, TestOutput (
4645       [["write"; "/new"; "\nnew file contents\n"];
4646        ["cat"; "/new"]], "\nnew file contents\n");
4647     InitBasicFS, Always, TestOutput (
4648       [["write"; "/new"; "\n\n"];
4649        ["cat"; "/new"]], "\n\n");
4650     InitBasicFS, Always, TestOutput (
4651       [["write"; "/new"; ""];
4652        ["cat"; "/new"]], "");
4653     InitBasicFS, Always, TestOutput (
4654       [["write"; "/new"; "\n\n\n"];
4655        ["cat"; "/new"]], "\n\n\n");
4656     InitBasicFS, Always, TestOutput (
4657       [["write"; "/new"; "\n"];
4658        ["cat"; "/new"]], "\n")],
4659    "create a new file",
4660    "\
4661 This call creates a file called C<path>.  The content of the
4662 file is the string C<content> (which can contain any 8 bit data).");
4663
4664   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4665    [InitBasicFS, Always, TestOutput (
4666       [["write"; "/new"; "new file contents"];
4667        ["pwrite"; "/new"; "data"; "4"];
4668        ["cat"; "/new"]], "new data contents");
4669     InitBasicFS, Always, TestOutput (
4670       [["write"; "/new"; "new file contents"];
4671        ["pwrite"; "/new"; "is extended"; "9"];
4672        ["cat"; "/new"]], "new file is extended");
4673     InitBasicFS, Always, TestOutput (
4674       [["write"; "/new"; "new file contents"];
4675        ["pwrite"; "/new"; ""; "4"];
4676        ["cat"; "/new"]], "new file contents")],
4677    "write to part of a file",
4678    "\
4679 This command writes to part of a file.  It writes the data
4680 buffer C<content> to the file C<path> starting at offset C<offset>.
4681
4682 This command implements the L<pwrite(2)> system call, and like
4683 that system call it may not write the full data requested.  The
4684 return value is the number of bytes that were actually written
4685 to the file.  This could even be 0, although short writes are
4686 unlikely for regular files in ordinary circumstances.
4687
4688 See also C<guestfs_pread>.");
4689
4690   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4691    [],
4692    "resize an ext2/ext3 filesystem (with size)",
4693    "\
4694 This command is the same as C<guestfs_resize2fs> except that it
4695 allows you to specify the new size (in bytes) explicitly.");
4696
4697   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4698    [],
4699    "resize an LVM physical volume (with size)",
4700    "\
4701 This command is the same as C<guestfs_pvresize> except that it
4702 allows you to specify the new size (in bytes) explicitly.");
4703
4704   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4705    [],
4706    "resize an NTFS filesystem (with size)",
4707    "\
4708 This command is the same as C<guestfs_ntfsresize> except that it
4709 allows you to specify the new size (in bytes) explicitly.");
4710
4711 ]
4712
4713 let all_functions = non_daemon_functions @ daemon_functions
4714
4715 (* In some places we want the functions to be displayed sorted
4716  * alphabetically, so this is useful:
4717  *)
4718 let all_functions_sorted =
4719   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4720                compare n1 n2) all_functions
4721
4722 (* This is used to generate the src/MAX_PROC_NR file which
4723  * contains the maximum procedure number, a surrogate for the
4724  * ABI version number.  See src/Makefile.am for the details.
4725  *)
4726 let max_proc_nr =
4727   let proc_nrs = List.map (
4728     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4729   ) daemon_functions in
4730   List.fold_left max 0 proc_nrs
4731
4732 (* Field types for structures. *)
4733 type field =
4734   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4735   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4736   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4737   | FUInt32
4738   | FInt32
4739   | FUInt64
4740   | FInt64
4741   | FBytes                      (* Any int measure that counts bytes. *)
4742   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4743   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4744
4745 (* Because we generate extra parsing code for LVM command line tools,
4746  * we have to pull out the LVM columns separately here.
4747  *)
4748 let lvm_pv_cols = [
4749   "pv_name", FString;
4750   "pv_uuid", FUUID;
4751   "pv_fmt", FString;
4752   "pv_size", FBytes;
4753   "dev_size", FBytes;
4754   "pv_free", FBytes;
4755   "pv_used", FBytes;
4756   "pv_attr", FString (* XXX *);
4757   "pv_pe_count", FInt64;
4758   "pv_pe_alloc_count", FInt64;
4759   "pv_tags", FString;
4760   "pe_start", FBytes;
4761   "pv_mda_count", FInt64;
4762   "pv_mda_free", FBytes;
4763   (* Not in Fedora 10:
4764      "pv_mda_size", FBytes;
4765   *)
4766 ]
4767 let lvm_vg_cols = [
4768   "vg_name", FString;
4769   "vg_uuid", FUUID;
4770   "vg_fmt", FString;
4771   "vg_attr", FString (* XXX *);
4772   "vg_size", FBytes;
4773   "vg_free", FBytes;
4774   "vg_sysid", FString;
4775   "vg_extent_size", FBytes;
4776   "vg_extent_count", FInt64;
4777   "vg_free_count", FInt64;
4778   "max_lv", FInt64;
4779   "max_pv", FInt64;
4780   "pv_count", FInt64;
4781   "lv_count", FInt64;
4782   "snap_count", FInt64;
4783   "vg_seqno", FInt64;
4784   "vg_tags", FString;
4785   "vg_mda_count", FInt64;
4786   "vg_mda_free", FBytes;
4787   (* Not in Fedora 10:
4788      "vg_mda_size", FBytes;
4789   *)
4790 ]
4791 let lvm_lv_cols = [
4792   "lv_name", FString;
4793   "lv_uuid", FUUID;
4794   "lv_attr", FString (* XXX *);
4795   "lv_major", FInt64;
4796   "lv_minor", FInt64;
4797   "lv_kernel_major", FInt64;
4798   "lv_kernel_minor", FInt64;
4799   "lv_size", FBytes;
4800   "seg_count", FInt64;
4801   "origin", FString;
4802   "snap_percent", FOptPercent;
4803   "copy_percent", FOptPercent;
4804   "move_pv", FString;
4805   "lv_tags", FString;
4806   "mirror_log", FString;
4807   "modules", FString;
4808 ]
4809
4810 (* Names and fields in all structures (in RStruct and RStructList)
4811  * that we support.
4812  *)
4813 let structs = [
4814   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4815    * not use this struct in any new code.
4816    *)
4817   "int_bool", [
4818     "i", FInt32;                (* for historical compatibility *)
4819     "b", FInt32;                (* for historical compatibility *)
4820   ];
4821
4822   (* LVM PVs, VGs, LVs. *)
4823   "lvm_pv", lvm_pv_cols;
4824   "lvm_vg", lvm_vg_cols;
4825   "lvm_lv", lvm_lv_cols;
4826
4827   (* Column names and types from stat structures.
4828    * NB. Can't use things like 'st_atime' because glibc header files
4829    * define some of these as macros.  Ugh.
4830    *)
4831   "stat", [
4832     "dev", FInt64;
4833     "ino", FInt64;
4834     "mode", FInt64;
4835     "nlink", FInt64;
4836     "uid", FInt64;
4837     "gid", FInt64;
4838     "rdev", FInt64;
4839     "size", FInt64;
4840     "blksize", FInt64;
4841     "blocks", FInt64;
4842     "atime", FInt64;
4843     "mtime", FInt64;
4844     "ctime", FInt64;
4845   ];
4846   "statvfs", [
4847     "bsize", FInt64;
4848     "frsize", FInt64;
4849     "blocks", FInt64;
4850     "bfree", FInt64;
4851     "bavail", FInt64;
4852     "files", FInt64;
4853     "ffree", FInt64;
4854     "favail", FInt64;
4855     "fsid", FInt64;
4856     "flag", FInt64;
4857     "namemax", FInt64;
4858   ];
4859
4860   (* Column names in dirent structure. *)
4861   "dirent", [
4862     "ino", FInt64;
4863     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4864     "ftyp", FChar;
4865     "name", FString;
4866   ];
4867
4868   (* Version numbers. *)
4869   "version", [
4870     "major", FInt64;
4871     "minor", FInt64;
4872     "release", FInt64;
4873     "extra", FString;
4874   ];
4875
4876   (* Extended attribute. *)
4877   "xattr", [
4878     "attrname", FString;
4879     "attrval", FBuffer;
4880   ];
4881
4882   (* Inotify events. *)
4883   "inotify_event", [
4884     "in_wd", FInt64;
4885     "in_mask", FUInt32;
4886     "in_cookie", FUInt32;
4887     "in_name", FString;
4888   ];
4889
4890   (* Partition table entry. *)
4891   "partition", [
4892     "part_num", FInt32;
4893     "part_start", FBytes;
4894     "part_end", FBytes;
4895     "part_size", FBytes;
4896   ];
4897 ] (* end of structs *)
4898
4899 (* Ugh, Java has to be different ..
4900  * These names are also used by the Haskell bindings.
4901  *)
4902 let java_structs = [
4903   "int_bool", "IntBool";
4904   "lvm_pv", "PV";
4905   "lvm_vg", "VG";
4906   "lvm_lv", "LV";
4907   "stat", "Stat";
4908   "statvfs", "StatVFS";
4909   "dirent", "Dirent";
4910   "version", "Version";
4911   "xattr", "XAttr";
4912   "inotify_event", "INotifyEvent";
4913   "partition", "Partition";
4914 ]
4915
4916 (* What structs are actually returned. *)
4917 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4918
4919 (* Returns a list of RStruct/RStructList structs that are returned
4920  * by any function.  Each element of returned list is a pair:
4921  *
4922  * (structname, RStructOnly)
4923  *    == there exists function which returns RStruct (_, structname)
4924  * (structname, RStructListOnly)
4925  *    == there exists function which returns RStructList (_, structname)
4926  * (structname, RStructAndList)
4927  *    == there are functions returning both RStruct (_, structname)
4928  *                                      and RStructList (_, structname)
4929  *)
4930 let rstructs_used_by functions =
4931   (* ||| is a "logical OR" for rstructs_used_t *)
4932   let (|||) a b =
4933     match a, b with
4934     | RStructAndList, _
4935     | _, RStructAndList -> RStructAndList
4936     | RStructOnly, RStructListOnly
4937     | RStructListOnly, RStructOnly -> RStructAndList
4938     | RStructOnly, RStructOnly -> RStructOnly
4939     | RStructListOnly, RStructListOnly -> RStructListOnly
4940   in
4941
4942   let h = Hashtbl.create 13 in
4943
4944   (* if elem->oldv exists, update entry using ||| operator,
4945    * else just add elem->newv to the hash
4946    *)
4947   let update elem newv =
4948     try  let oldv = Hashtbl.find h elem in
4949          Hashtbl.replace h elem (newv ||| oldv)
4950     with Not_found -> Hashtbl.add h elem newv
4951   in
4952
4953   List.iter (
4954     fun (_, style, _, _, _, _, _) ->
4955       match fst style with
4956       | RStruct (_, structname) -> update structname RStructOnly
4957       | RStructList (_, structname) -> update structname RStructListOnly
4958       | _ -> ()
4959   ) functions;
4960
4961   (* return key->values as a list of (key,value) *)
4962   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4963
4964 (* Used for testing language bindings. *)
4965 type callt =
4966   | CallString of string
4967   | CallOptString of string option
4968   | CallStringList of string list
4969   | CallInt of int
4970   | CallInt64 of int64
4971   | CallBool of bool
4972   | CallBuffer of string
4973
4974 (* Used to memoize the result of pod2text. *)
4975 let pod2text_memo_filename = "src/.pod2text.data"
4976 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4977   try
4978     let chan = open_in pod2text_memo_filename in
4979     let v = input_value chan in
4980     close_in chan;
4981     v
4982   with
4983     _ -> Hashtbl.create 13
4984 let pod2text_memo_updated () =
4985   let chan = open_out pod2text_memo_filename in
4986   output_value chan pod2text_memo;
4987   close_out chan
4988
4989 (* Useful functions.
4990  * Note we don't want to use any external OCaml libraries which
4991  * makes this a bit harder than it should be.
4992  *)
4993 module StringMap = Map.Make (String)
4994
4995 let failwithf fs = ksprintf failwith fs
4996
4997 let unique = let i = ref 0 in fun () -> incr i; !i
4998
4999 let replace_char s c1 c2 =
5000   let s2 = String.copy s in
5001   let r = ref false in
5002   for i = 0 to String.length s2 - 1 do
5003     if String.unsafe_get s2 i = c1 then (
5004       String.unsafe_set s2 i c2;
5005       r := true
5006     )
5007   done;
5008   if not !r then s else s2
5009
5010 let isspace c =
5011   c = ' '
5012   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5013
5014 let triml ?(test = isspace) str =
5015   let i = ref 0 in
5016   let n = ref (String.length str) in
5017   while !n > 0 && test str.[!i]; do
5018     decr n;
5019     incr i
5020   done;
5021   if !i = 0 then str
5022   else String.sub str !i !n
5023
5024 let trimr ?(test = isspace) str =
5025   let n = ref (String.length str) in
5026   while !n > 0 && test str.[!n-1]; do
5027     decr n
5028   done;
5029   if !n = String.length str then str
5030   else String.sub str 0 !n
5031
5032 let trim ?(test = isspace) str =
5033   trimr ~test (triml ~test str)
5034
5035 let rec find s sub =
5036   let len = String.length s in
5037   let sublen = String.length sub in
5038   let rec loop i =
5039     if i <= len-sublen then (
5040       let rec loop2 j =
5041         if j < sublen then (
5042           if s.[i+j] = sub.[j] then loop2 (j+1)
5043           else -1
5044         ) else
5045           i (* found *)
5046       in
5047       let r = loop2 0 in
5048       if r = -1 then loop (i+1) else r
5049     ) else
5050       -1 (* not found *)
5051   in
5052   loop 0
5053
5054 let rec replace_str s s1 s2 =
5055   let len = String.length s in
5056   let sublen = String.length s1 in
5057   let i = find s s1 in
5058   if i = -1 then s
5059   else (
5060     let s' = String.sub s 0 i in
5061     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5062     s' ^ s2 ^ replace_str s'' s1 s2
5063   )
5064
5065 let rec string_split sep str =
5066   let len = String.length str in
5067   let seplen = String.length sep in
5068   let i = find str sep in
5069   if i = -1 then [str]
5070   else (
5071     let s' = String.sub str 0 i in
5072     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5073     s' :: string_split sep s''
5074   )
5075
5076 let files_equal n1 n2 =
5077   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5078   match Sys.command cmd with
5079   | 0 -> true
5080   | 1 -> false
5081   | i -> failwithf "%s: failed with error code %d" cmd i
5082
5083 let rec filter_map f = function
5084   | [] -> []
5085   | x :: xs ->
5086       match f x with
5087       | Some y -> y :: filter_map f xs
5088       | None -> filter_map f xs
5089
5090 let rec find_map f = function
5091   | [] -> raise Not_found
5092   | x :: xs ->
5093       match f x with
5094       | Some y -> y
5095       | None -> find_map f xs
5096
5097 let iteri f xs =
5098   let rec loop i = function
5099     | [] -> ()
5100     | x :: xs -> f i x; loop (i+1) xs
5101   in
5102   loop 0 xs
5103
5104 let mapi f xs =
5105   let rec loop i = function
5106     | [] -> []
5107     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5108   in
5109   loop 0 xs
5110
5111 let count_chars c str =
5112   let count = ref 0 in
5113   for i = 0 to String.length str - 1 do
5114     if c = String.unsafe_get str i then incr count
5115   done;
5116   !count
5117
5118 let explode str =
5119   let r = ref [] in
5120   for i = 0 to String.length str - 1 do
5121     let c = String.unsafe_get str i in
5122     r := c :: !r;
5123   done;
5124   List.rev !r
5125
5126 let map_chars f str =
5127   List.map f (explode str)
5128
5129 let name_of_argt = function
5130   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5131   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5132   | FileIn n | FileOut n | BufferIn n -> n
5133
5134 let java_name_of_struct typ =
5135   try List.assoc typ java_structs
5136   with Not_found ->
5137     failwithf
5138       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5139
5140 let cols_of_struct typ =
5141   try List.assoc typ structs
5142   with Not_found ->
5143     failwithf "cols_of_struct: unknown struct %s" typ
5144
5145 let seq_of_test = function
5146   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5147   | TestOutputListOfDevices (s, _)
5148   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5149   | TestOutputTrue s | TestOutputFalse s
5150   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5151   | TestOutputStruct (s, _)
5152   | TestLastFail s -> s
5153
5154 (* Handling for function flags. *)
5155 let protocol_limit_warning =
5156   "Because of the message protocol, there is a transfer limit
5157 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5158
5159 let danger_will_robinson =
5160   "B<This command is dangerous.  Without careful use you
5161 can easily destroy all your data>."
5162
5163 let deprecation_notice flags =
5164   try
5165     let alt =
5166       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5167     let txt =
5168       sprintf "This function is deprecated.
5169 In new code, use the C<%s> call instead.
5170
5171 Deprecated functions will not be removed from the API, but the
5172 fact that they are deprecated indicates that there are problems
5173 with correct use of these functions." alt in
5174     Some txt
5175   with
5176     Not_found -> None
5177
5178 (* Create list of optional groups. *)
5179 let optgroups =
5180   let h = Hashtbl.create 13 in
5181   List.iter (
5182     fun (name, _, _, flags, _, _, _) ->
5183       List.iter (
5184         function
5185         | Optional group ->
5186             let names = try Hashtbl.find h group with Not_found -> [] in
5187             Hashtbl.replace h group (name :: names)
5188         | _ -> ()
5189       ) flags
5190   ) daemon_functions;
5191   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5192   let groups =
5193     List.map (
5194       fun group -> group, List.sort compare (Hashtbl.find h group)
5195     ) groups in
5196   List.sort (fun x y -> compare (fst x) (fst y)) groups
5197
5198 (* Check function names etc. for consistency. *)
5199 let check_functions () =
5200   let contains_uppercase str =
5201     let len = String.length str in
5202     let rec loop i =
5203       if i >= len then false
5204       else (
5205         let c = str.[i] in
5206         if c >= 'A' && c <= 'Z' then true
5207         else loop (i+1)
5208       )
5209     in
5210     loop 0
5211   in
5212
5213   (* Check function names. *)
5214   List.iter (
5215     fun (name, _, _, _, _, _, _) ->
5216       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5217         failwithf "function name %s does not need 'guestfs' prefix" name;
5218       if name = "" then
5219         failwithf "function name is empty";
5220       if name.[0] < 'a' || name.[0] > 'z' then
5221         failwithf "function name %s must start with lowercase a-z" name;
5222       if String.contains name '-' then
5223         failwithf "function name %s should not contain '-', use '_' instead."
5224           name
5225   ) all_functions;
5226
5227   (* Check function parameter/return names. *)
5228   List.iter (
5229     fun (name, style, _, _, _, _, _) ->
5230       let check_arg_ret_name n =
5231         if contains_uppercase n then
5232           failwithf "%s param/ret %s should not contain uppercase chars"
5233             name n;
5234         if String.contains n '-' || String.contains n '_' then
5235           failwithf "%s param/ret %s should not contain '-' or '_'"
5236             name n;
5237         if n = "value" then
5238           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;
5239         if n = "int" || n = "char" || n = "short" || n = "long" then
5240           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5241         if n = "i" || n = "n" then
5242           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5243         if n = "argv" || n = "args" then
5244           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5245
5246         (* List Haskell, OCaml and C keywords here.
5247          * http://www.haskell.org/haskellwiki/Keywords
5248          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5249          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5250          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5251          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5252          * Omitting _-containing words, since they're handled above.
5253          * Omitting the OCaml reserved word, "val", is ok,
5254          * and saves us from renaming several parameters.
5255          *)
5256         let reserved = [
5257           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5258           "char"; "class"; "const"; "constraint"; "continue"; "data";
5259           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5260           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5261           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5262           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5263           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5264           "interface";
5265           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5266           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5267           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5268           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5269           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5270           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5271           "volatile"; "when"; "where"; "while";
5272           ] in
5273         if List.mem n reserved then
5274           failwithf "%s has param/ret using reserved word %s" name n;
5275       in
5276
5277       (match fst style with
5278        | RErr -> ()
5279        | RInt n | RInt64 n | RBool n
5280        | RConstString n | RConstOptString n | RString n
5281        | RStringList n | RStruct (n, _) | RStructList (n, _)
5282        | RHashtable n | RBufferOut n ->
5283            check_arg_ret_name n
5284       );
5285       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5286   ) all_functions;
5287
5288   (* Check short descriptions. *)
5289   List.iter (
5290     fun (name, _, _, _, _, shortdesc, _) ->
5291       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5292         failwithf "short description of %s should begin with lowercase." name;
5293       let c = shortdesc.[String.length shortdesc-1] in
5294       if c = '\n' || c = '.' then
5295         failwithf "short description of %s should not end with . or \\n." name
5296   ) all_functions;
5297
5298   (* Check long descriptions. *)
5299   List.iter (
5300     fun (name, _, _, _, _, _, longdesc) ->
5301       if longdesc.[String.length longdesc-1] = '\n' then
5302         failwithf "long description of %s should not end with \\n." name
5303   ) all_functions;
5304
5305   (* Check proc_nrs. *)
5306   List.iter (
5307     fun (name, _, proc_nr, _, _, _, _) ->
5308       if proc_nr <= 0 then
5309         failwithf "daemon function %s should have proc_nr > 0" name
5310   ) daemon_functions;
5311
5312   List.iter (
5313     fun (name, _, proc_nr, _, _, _, _) ->
5314       if proc_nr <> -1 then
5315         failwithf "non-daemon function %s should have proc_nr -1" name
5316   ) non_daemon_functions;
5317
5318   let proc_nrs =
5319     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5320       daemon_functions in
5321   let proc_nrs =
5322     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5323   let rec loop = function
5324     | [] -> ()
5325     | [_] -> ()
5326     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5327         loop rest
5328     | (name1,nr1) :: (name2,nr2) :: _ ->
5329         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5330           name1 name2 nr1 nr2
5331   in
5332   loop proc_nrs;
5333
5334   (* Check tests. *)
5335   List.iter (
5336     function
5337       (* Ignore functions that have no tests.  We generate a
5338        * warning when the user does 'make check' instead.
5339        *)
5340     | name, _, _, _, [], _, _ -> ()
5341     | name, _, _, _, tests, _, _ ->
5342         let funcs =
5343           List.map (
5344             fun (_, _, test) ->
5345               match seq_of_test test with
5346               | [] ->
5347                   failwithf "%s has a test containing an empty sequence" name
5348               | cmds -> List.map List.hd cmds
5349           ) tests in
5350         let funcs = List.flatten funcs in
5351
5352         let tested = List.mem name funcs in
5353
5354         if not tested then
5355           failwithf "function %s has tests but does not test itself" name
5356   ) all_functions
5357
5358 (* 'pr' prints to the current output file. *)
5359 let chan = ref Pervasives.stdout
5360 let lines = ref 0
5361 let pr fs =
5362   ksprintf
5363     (fun str ->
5364        let i = count_chars '\n' str in
5365        lines := !lines + i;
5366        output_string !chan str
5367     ) fs
5368
5369 let copyright_years =
5370   let this_year = 1900 + (localtime (time ())).tm_year in
5371   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5372
5373 (* Generate a header block in a number of standard styles. *)
5374 type comment_style =
5375     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5376 type license = GPLv2plus | LGPLv2plus
5377
5378 let generate_header ?(extra_inputs = []) comment license =
5379   let inputs = "src/generator.ml" :: extra_inputs in
5380   let c = match comment with
5381     | CStyle ->         pr "/* "; " *"
5382     | CPlusPlusStyle -> pr "// "; "//"
5383     | HashStyle ->      pr "# ";  "#"
5384     | OCamlStyle ->     pr "(* "; " *"
5385     | HaskellStyle ->   pr "{- "; "  " in
5386   pr "libguestfs generated file\n";
5387   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5388   List.iter (pr "%s   %s\n" c) inputs;
5389   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5390   pr "%s\n" c;
5391   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5392   pr "%s\n" c;
5393   (match license with
5394    | GPLv2plus ->
5395        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5396        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5397        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5398        pr "%s (at your option) any later version.\n" c;
5399        pr "%s\n" c;
5400        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5401        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5402        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5403        pr "%s GNU General Public License for more details.\n" c;
5404        pr "%s\n" c;
5405        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5406        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5407        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5408
5409    | LGPLv2plus ->
5410        pr "%s This library is free software; you can redistribute it and/or\n" c;
5411        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5412        pr "%s License as published by the Free Software Foundation; either\n" c;
5413        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5414        pr "%s\n" c;
5415        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5416        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5417        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5418        pr "%s Lesser General Public License for more details.\n" c;
5419        pr "%s\n" c;
5420        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5421        pr "%s License along with this library; if not, write to the Free Software\n" c;
5422        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5423   );
5424   (match comment with
5425    | CStyle -> pr " */\n"
5426    | CPlusPlusStyle
5427    | HashStyle -> ()
5428    | OCamlStyle -> pr " *)\n"
5429    | HaskellStyle -> pr "-}\n"
5430   );
5431   pr "\n"
5432
5433 (* Start of main code generation functions below this line. *)
5434
5435 (* Generate the pod documentation for the C API. *)
5436 let rec generate_actions_pod () =
5437   List.iter (
5438     fun (shortname, style, _, flags, _, _, longdesc) ->
5439       if not (List.mem NotInDocs flags) then (
5440         let name = "guestfs_" ^ shortname in
5441         pr "=head2 %s\n\n" name;
5442         pr " ";
5443         generate_prototype ~extern:false ~handle:"g" name style;
5444         pr "\n\n";
5445         pr "%s\n\n" longdesc;
5446         (match fst style with
5447          | RErr ->
5448              pr "This function returns 0 on success or -1 on error.\n\n"
5449          | RInt _ ->
5450              pr "On error this function returns -1.\n\n"
5451          | RInt64 _ ->
5452              pr "On error this function returns -1.\n\n"
5453          | RBool _ ->
5454              pr "This function returns a C truth value on success or -1 on error.\n\n"
5455          | RConstString _ ->
5456              pr "This function returns a string, or NULL on error.
5457 The string is owned by the guest handle and must I<not> be freed.\n\n"
5458          | RConstOptString _ ->
5459              pr "This function returns a string which may be NULL.
5460 There is way to return an error from this function.
5461 The string is owned by the guest handle and must I<not> be freed.\n\n"
5462          | RString _ ->
5463              pr "This function returns a string, or NULL on error.
5464 I<The caller must free the returned string after use>.\n\n"
5465          | RStringList _ ->
5466              pr "This function returns a NULL-terminated array of strings
5467 (like L<environ(3)>), or NULL if there was an error.
5468 I<The caller must free the strings and the array after use>.\n\n"
5469          | RStruct (_, typ) ->
5470              pr "This function returns a C<struct guestfs_%s *>,
5471 or NULL if there was an error.
5472 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5473          | RStructList (_, typ) ->
5474              pr "This function returns a C<struct guestfs_%s_list *>
5475 (see E<lt>guestfs-structs.hE<gt>),
5476 or NULL if there was an error.
5477 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5478          | RHashtable _ ->
5479              pr "This function returns a NULL-terminated array of
5480 strings, or NULL if there was an error.
5481 The array of strings will always have length C<2n+1>, where
5482 C<n> keys and values alternate, followed by the trailing NULL entry.
5483 I<The caller must free the strings and the array after use>.\n\n"
5484          | RBufferOut _ ->
5485              pr "This function returns a buffer, or NULL on error.
5486 The size of the returned buffer is written to C<*size_r>.
5487 I<The caller must free the returned buffer after use>.\n\n"
5488         );
5489         if List.mem ProtocolLimitWarning flags then
5490           pr "%s\n\n" protocol_limit_warning;
5491         if List.mem DangerWillRobinson flags then
5492           pr "%s\n\n" danger_will_robinson;
5493         match deprecation_notice flags with
5494         | None -> ()
5495         | Some txt -> pr "%s\n\n" txt
5496       )
5497   ) all_functions_sorted
5498
5499 and generate_structs_pod () =
5500   (* Structs documentation. *)
5501   List.iter (
5502     fun (typ, cols) ->
5503       pr "=head2 guestfs_%s\n" typ;
5504       pr "\n";
5505       pr " struct guestfs_%s {\n" typ;
5506       List.iter (
5507         function
5508         | name, FChar -> pr "   char %s;\n" name
5509         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5510         | name, FInt32 -> pr "   int32_t %s;\n" name
5511         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5512         | name, FInt64 -> pr "   int64_t %s;\n" name
5513         | name, FString -> pr "   char *%s;\n" name
5514         | name, FBuffer ->
5515             pr "   /* The next two fields describe a byte array. */\n";
5516             pr "   uint32_t %s_len;\n" name;
5517             pr "   char *%s;\n" name
5518         | name, FUUID ->
5519             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5520             pr "   char %s[32];\n" name
5521         | name, FOptPercent ->
5522             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5523             pr "   float %s;\n" name
5524       ) cols;
5525       pr " };\n";
5526       pr " \n";
5527       pr " struct guestfs_%s_list {\n" typ;
5528       pr "   uint32_t len; /* Number of elements in list. */\n";
5529       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5530       pr " };\n";
5531       pr " \n";
5532       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5533       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5534         typ typ;
5535       pr "\n"
5536   ) structs
5537
5538 and generate_availability_pod () =
5539   (* Availability documentation. *)
5540   pr "=over 4\n";
5541   pr "\n";
5542   List.iter (
5543     fun (group, functions) ->
5544       pr "=item B<%s>\n" group;
5545       pr "\n";
5546       pr "The following functions:\n";
5547       List.iter (pr "L</guestfs_%s>\n") functions;
5548       pr "\n"
5549   ) optgroups;
5550   pr "=back\n";
5551   pr "\n"
5552
5553 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5554  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5555  *
5556  * We have to use an underscore instead of a dash because otherwise
5557  * rpcgen generates incorrect code.
5558  *
5559  * This header is NOT exported to clients, but see also generate_structs_h.
5560  *)
5561 and generate_xdr () =
5562   generate_header CStyle LGPLv2plus;
5563
5564   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5565   pr "typedef string str<>;\n";
5566   pr "\n";
5567
5568   (* Internal structures. *)
5569   List.iter (
5570     function
5571     | typ, cols ->
5572         pr "struct guestfs_int_%s {\n" typ;
5573         List.iter (function
5574                    | name, FChar -> pr "  char %s;\n" name
5575                    | name, FString -> pr "  string %s<>;\n" name
5576                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5577                    | name, FUUID -> pr "  opaque %s[32];\n" name
5578                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5579                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5580                    | name, FOptPercent -> pr "  float %s;\n" name
5581                   ) cols;
5582         pr "};\n";
5583         pr "\n";
5584         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5585         pr "\n";
5586   ) structs;
5587
5588   List.iter (
5589     fun (shortname, style, _, _, _, _, _) ->
5590       let name = "guestfs_" ^ shortname in
5591
5592       (match snd style with
5593        | [] -> ()
5594        | args ->
5595            pr "struct %s_args {\n" name;
5596            List.iter (
5597              function
5598              | Pathname n | Device n | Dev_or_Path n | String n ->
5599                  pr "  string %s<>;\n" n
5600              | OptString n -> pr "  str *%s;\n" n
5601              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5602              | Bool n -> pr "  bool %s;\n" n
5603              | Int n -> pr "  int %s;\n" n
5604              | Int64 n -> pr "  hyper %s;\n" n
5605              | BufferIn n ->
5606                  pr "  opaque %s<>;\n" n
5607              | FileIn _ | FileOut _ -> ()
5608            ) args;
5609            pr "};\n\n"
5610       );
5611       (match fst style with
5612        | RErr -> ()
5613        | RInt n ->
5614            pr "struct %s_ret {\n" name;
5615            pr "  int %s;\n" n;
5616            pr "};\n\n"
5617        | RInt64 n ->
5618            pr "struct %s_ret {\n" name;
5619            pr "  hyper %s;\n" n;
5620            pr "};\n\n"
5621        | RBool n ->
5622            pr "struct %s_ret {\n" name;
5623            pr "  bool %s;\n" n;
5624            pr "};\n\n"
5625        | RConstString _ | RConstOptString _ ->
5626            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5627        | RString n ->
5628            pr "struct %s_ret {\n" name;
5629            pr "  string %s<>;\n" n;
5630            pr "};\n\n"
5631        | RStringList n ->
5632            pr "struct %s_ret {\n" name;
5633            pr "  str %s<>;\n" n;
5634            pr "};\n\n"
5635        | RStruct (n, typ) ->
5636            pr "struct %s_ret {\n" name;
5637            pr "  guestfs_int_%s %s;\n" typ n;
5638            pr "};\n\n"
5639        | RStructList (n, typ) ->
5640            pr "struct %s_ret {\n" name;
5641            pr "  guestfs_int_%s_list %s;\n" typ n;
5642            pr "};\n\n"
5643        | RHashtable n ->
5644            pr "struct %s_ret {\n" name;
5645            pr "  str %s<>;\n" n;
5646            pr "};\n\n"
5647        | RBufferOut n ->
5648            pr "struct %s_ret {\n" name;
5649            pr "  opaque %s<>;\n" n;
5650            pr "};\n\n"
5651       );
5652   ) daemon_functions;
5653
5654   (* Table of procedure numbers. *)
5655   pr "enum guestfs_procedure {\n";
5656   List.iter (
5657     fun (shortname, _, proc_nr, _, _, _, _) ->
5658       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5659   ) daemon_functions;
5660   pr "  GUESTFS_PROC_NR_PROCS\n";
5661   pr "};\n";
5662   pr "\n";
5663
5664   (* Having to choose a maximum message size is annoying for several
5665    * reasons (it limits what we can do in the API), but it (a) makes
5666    * the protocol a lot simpler, and (b) provides a bound on the size
5667    * of the daemon which operates in limited memory space.
5668    *)
5669   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5670   pr "\n";
5671
5672   (* Message header, etc. *)
5673   pr "\
5674 /* The communication protocol is now documented in the guestfs(3)
5675  * manpage.
5676  */
5677
5678 const GUESTFS_PROGRAM = 0x2000F5F5;
5679 const GUESTFS_PROTOCOL_VERSION = 1;
5680
5681 /* These constants must be larger than any possible message length. */
5682 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5683 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5684
5685 enum guestfs_message_direction {
5686   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5687   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5688 };
5689
5690 enum guestfs_message_status {
5691   GUESTFS_STATUS_OK = 0,
5692   GUESTFS_STATUS_ERROR = 1
5693 };
5694
5695 const GUESTFS_ERROR_LEN = 256;
5696
5697 struct guestfs_message_error {
5698   string error_message<GUESTFS_ERROR_LEN>;
5699 };
5700
5701 struct guestfs_message_header {
5702   unsigned prog;                     /* GUESTFS_PROGRAM */
5703   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5704   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5705   guestfs_message_direction direction;
5706   unsigned serial;                   /* message serial number */
5707   guestfs_message_status status;
5708 };
5709
5710 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5711
5712 struct guestfs_chunk {
5713   int cancel;                        /* if non-zero, transfer is cancelled */
5714   /* data size is 0 bytes if the transfer has finished successfully */
5715   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5716 };
5717 "
5718
5719 (* Generate the guestfs-structs.h file. *)
5720 and generate_structs_h () =
5721   generate_header CStyle LGPLv2plus;
5722
5723   (* This is a public exported header file containing various
5724    * structures.  The structures are carefully written to have
5725    * exactly the same in-memory format as the XDR structures that
5726    * we use on the wire to the daemon.  The reason for creating
5727    * copies of these structures here is just so we don't have to
5728    * export the whole of guestfs_protocol.h (which includes much
5729    * unrelated and XDR-dependent stuff that we don't want to be
5730    * public, or required by clients).
5731    *
5732    * To reiterate, we will pass these structures to and from the
5733    * client with a simple assignment or memcpy, so the format
5734    * must be identical to what rpcgen / the RFC defines.
5735    *)
5736
5737   (* Public structures. *)
5738   List.iter (
5739     fun (typ, cols) ->
5740       pr "struct guestfs_%s {\n" typ;
5741       List.iter (
5742         function
5743         | name, FChar -> pr "  char %s;\n" name
5744         | name, FString -> pr "  char *%s;\n" name
5745         | name, FBuffer ->
5746             pr "  uint32_t %s_len;\n" name;
5747             pr "  char *%s;\n" name
5748         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5749         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5750         | name, FInt32 -> pr "  int32_t %s;\n" name
5751         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5752         | name, FInt64 -> pr "  int64_t %s;\n" name
5753         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5754       ) cols;
5755       pr "};\n";
5756       pr "\n";
5757       pr "struct guestfs_%s_list {\n" typ;
5758       pr "  uint32_t len;\n";
5759       pr "  struct guestfs_%s *val;\n" typ;
5760       pr "};\n";
5761       pr "\n";
5762       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5763       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5764       pr "\n"
5765   ) structs
5766
5767 (* Generate the guestfs-actions.h file. *)
5768 and generate_actions_h () =
5769   generate_header CStyle LGPLv2plus;
5770   List.iter (
5771     fun (shortname, style, _, _, _, _, _) ->
5772       let name = "guestfs_" ^ shortname in
5773       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5774         name style
5775   ) all_functions
5776
5777 (* Generate the guestfs-internal-actions.h file. *)
5778 and generate_internal_actions_h () =
5779   generate_header CStyle LGPLv2plus;
5780   List.iter (
5781     fun (shortname, style, _, _, _, _, _) ->
5782       let name = "guestfs__" ^ shortname in
5783       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5784         name style
5785   ) non_daemon_functions
5786
5787 (* Generate the client-side dispatch stubs. *)
5788 and generate_client_actions () =
5789   generate_header CStyle LGPLv2plus;
5790
5791   pr "\
5792 #include <stdio.h>
5793 #include <stdlib.h>
5794 #include <stdint.h>
5795 #include <string.h>
5796 #include <inttypes.h>
5797
5798 #include \"guestfs.h\"
5799 #include \"guestfs-internal.h\"
5800 #include \"guestfs-internal-actions.h\"
5801 #include \"guestfs_protocol.h\"
5802
5803 #define error guestfs_error
5804 //#define perrorf guestfs_perrorf
5805 #define safe_malloc guestfs_safe_malloc
5806 #define safe_realloc guestfs_safe_realloc
5807 //#define safe_strdup guestfs_safe_strdup
5808 #define safe_memdup guestfs_safe_memdup
5809
5810 /* Check the return message from a call for validity. */
5811 static int
5812 check_reply_header (guestfs_h *g,
5813                     const struct guestfs_message_header *hdr,
5814                     unsigned int proc_nr, unsigned int serial)
5815 {
5816   if (hdr->prog != GUESTFS_PROGRAM) {
5817     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5818     return -1;
5819   }
5820   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5821     error (g, \"wrong protocol version (%%d/%%d)\",
5822            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5823     return -1;
5824   }
5825   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5826     error (g, \"unexpected message direction (%%d/%%d)\",
5827            hdr->direction, GUESTFS_DIRECTION_REPLY);
5828     return -1;
5829   }
5830   if (hdr->proc != proc_nr) {
5831     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5832     return -1;
5833   }
5834   if (hdr->serial != serial) {
5835     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5836     return -1;
5837   }
5838
5839   return 0;
5840 }
5841
5842 /* Check we are in the right state to run a high-level action. */
5843 static int
5844 check_state (guestfs_h *g, const char *caller)
5845 {
5846   if (!guestfs__is_ready (g)) {
5847     if (guestfs__is_config (g) || guestfs__is_launching (g))
5848       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5849         caller);
5850     else
5851       error (g, \"%%s called from the wrong state, %%d != READY\",
5852         caller, guestfs__get_state (g));
5853     return -1;
5854   }
5855   return 0;
5856 }
5857
5858 ";
5859
5860   let error_code_of = function
5861     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5862     | RConstString _ | RConstOptString _
5863     | RString _ | RStringList _
5864     | RStruct _ | RStructList _
5865     | RHashtable _ | RBufferOut _ -> "NULL"
5866   in
5867
5868   (* Generate code to check String-like parameters are not passed in
5869    * as NULL (returning an error if they are).
5870    *)
5871   let check_null_strings shortname style =
5872     let pr_newline = ref false in
5873     List.iter (
5874       function
5875       (* parameters which should not be NULL *)
5876       | String n
5877       | Device n
5878       | Pathname n
5879       | Dev_or_Path n
5880       | FileIn n
5881       | FileOut n
5882       | BufferIn n
5883       | StringList n
5884       | DeviceList n ->
5885           pr "  if (%s == NULL) {\n" n;
5886           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
5887           pr "           \"%s\", \"%s\");\n" shortname n;
5888           pr "    return %s;\n" (error_code_of (fst style));
5889           pr "  }\n";
5890           pr_newline := true
5891
5892       (* can be NULL *)
5893       | OptString _
5894
5895       (* not applicable *)
5896       | Bool _
5897       | Int _
5898       | Int64 _ -> ()
5899     ) (snd style);
5900
5901     if !pr_newline then pr "\n";
5902   in
5903
5904   (* Generate code to generate guestfish call traces. *)
5905   let trace_call shortname style =
5906     pr "  if (guestfs__get_trace (g)) {\n";
5907
5908     let needs_i =
5909       List.exists (function
5910                    | StringList _ | DeviceList _ -> true
5911                    | _ -> false) (snd style) in
5912     if needs_i then (
5913       pr "    int i;\n";
5914       pr "\n"
5915     );
5916
5917     pr "    printf (\"%s\");\n" shortname;
5918     List.iter (
5919       function
5920       | String n                        (* strings *)
5921       | Device n
5922       | Pathname n
5923       | Dev_or_Path n
5924       | FileIn n
5925       | FileOut n
5926       | BufferIn n ->
5927           (* guestfish doesn't support string escaping, so neither do we *)
5928           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5929       | OptString n ->                  (* string option *)
5930           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5931           pr "    else printf (\" null\");\n"
5932       | StringList n
5933       | DeviceList n ->                 (* string list *)
5934           pr "    putchar (' ');\n";
5935           pr "    putchar ('\"');\n";
5936           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5937           pr "      if (i > 0) putchar (' ');\n";
5938           pr "      fputs (%s[i], stdout);\n" n;
5939           pr "    }\n";
5940           pr "    putchar ('\"');\n";
5941       | Bool n ->                       (* boolean *)
5942           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5943       | Int n ->                        (* int *)
5944           pr "    printf (\" %%d\", %s);\n" n
5945       | Int64 n ->
5946           pr "    printf (\" %%\" PRIi64, %s);\n" n
5947     ) (snd style);
5948     pr "    putchar ('\\n');\n";
5949     pr "  }\n";
5950     pr "\n";
5951   in
5952
5953   (* For non-daemon functions, generate a wrapper around each function. *)
5954   List.iter (
5955     fun (shortname, style, _, _, _, _, _) ->
5956       let name = "guestfs_" ^ shortname in
5957
5958       generate_prototype ~extern:false ~semicolon:false ~newline:true
5959         ~handle:"g" name style;
5960       pr "{\n";
5961       check_null_strings shortname style;
5962       trace_call shortname style;
5963       pr "  return guestfs__%s " shortname;
5964       generate_c_call_args ~handle:"g" style;
5965       pr ";\n";
5966       pr "}\n";
5967       pr "\n"
5968   ) non_daemon_functions;
5969
5970   (* Client-side stubs for each function. *)
5971   List.iter (
5972     fun (shortname, style, _, _, _, _, _) ->
5973       let name = "guestfs_" ^ shortname in
5974       let error_code = error_code_of (fst style) in
5975
5976       (* Generate the action stub. *)
5977       generate_prototype ~extern:false ~semicolon:false ~newline:true
5978         ~handle:"g" name style;
5979
5980       pr "{\n";
5981
5982       (match snd style with
5983        | [] -> ()
5984        | _ -> pr "  struct %s_args args;\n" name
5985       );
5986
5987       pr "  guestfs_message_header hdr;\n";
5988       pr "  guestfs_message_error err;\n";
5989       let has_ret =
5990         match fst style with
5991         | RErr -> false
5992         | RConstString _ | RConstOptString _ ->
5993             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5994         | RInt _ | RInt64 _
5995         | RBool _ | RString _ | RStringList _
5996         | RStruct _ | RStructList _
5997         | RHashtable _ | RBufferOut _ ->
5998             pr "  struct %s_ret ret;\n" name;
5999             true in
6000
6001       pr "  int serial;\n";
6002       pr "  int r;\n";
6003       pr "\n";
6004       check_null_strings shortname style;
6005       trace_call shortname style;
6006       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6007         shortname error_code;
6008       pr "  guestfs___set_busy (g);\n";
6009       pr "\n";
6010
6011       (* Send the main header and arguments. *)
6012       (match snd style with
6013        | [] ->
6014            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6015              (String.uppercase shortname)
6016        | args ->
6017            List.iter (
6018              function
6019              | Pathname n | Device n | Dev_or_Path n | String n ->
6020                  pr "  args.%s = (char *) %s;\n" n n
6021              | OptString n ->
6022                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6023              | StringList n | DeviceList n ->
6024                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6025                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6026              | Bool n ->
6027                  pr "  args.%s = %s;\n" n n
6028              | Int n ->
6029                  pr "  args.%s = %s;\n" n n
6030              | Int64 n ->
6031                  pr "  args.%s = %s;\n" n n
6032              | FileIn _ | FileOut _ -> ()
6033              | BufferIn n ->
6034                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6035                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6036                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6037                    shortname;
6038                  pr "    guestfs___end_busy (g);\n";
6039                  pr "    return %s;\n" error_code;
6040                  pr "  }\n";
6041                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6042                  pr "  args.%s.%s_len = %s_size;\n" n n n
6043            ) args;
6044            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6045              (String.uppercase shortname);
6046            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6047              name;
6048       );
6049       pr "  if (serial == -1) {\n";
6050       pr "    guestfs___end_busy (g);\n";
6051       pr "    return %s;\n" error_code;
6052       pr "  }\n";
6053       pr "\n";
6054
6055       (* Send any additional files (FileIn) requested. *)
6056       let need_read_reply_label = ref false in
6057       List.iter (
6058         function
6059         | FileIn n ->
6060             pr "  r = guestfs___send_file (g, %s);\n" n;
6061             pr "  if (r == -1) {\n";
6062             pr "    guestfs___end_busy (g);\n";
6063             pr "    return %s;\n" error_code;
6064             pr "  }\n";
6065             pr "  if (r == -2) /* daemon cancelled */\n";
6066             pr "    goto read_reply;\n";
6067             need_read_reply_label := true;
6068             pr "\n";
6069         | _ -> ()
6070       ) (snd style);
6071
6072       (* Wait for the reply from the remote end. *)
6073       if !need_read_reply_label then pr " read_reply:\n";
6074       pr "  memset (&hdr, 0, sizeof hdr);\n";
6075       pr "  memset (&err, 0, sizeof err);\n";
6076       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6077       pr "\n";
6078       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6079       if not has_ret then
6080         pr "NULL, NULL"
6081       else
6082         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6083       pr ");\n";
6084
6085       pr "  if (r == -1) {\n";
6086       pr "    guestfs___end_busy (g);\n";
6087       pr "    return %s;\n" error_code;
6088       pr "  }\n";
6089       pr "\n";
6090
6091       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6092         (String.uppercase shortname);
6093       pr "    guestfs___end_busy (g);\n";
6094       pr "    return %s;\n" error_code;
6095       pr "  }\n";
6096       pr "\n";
6097
6098       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6099       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6100       pr "    free (err.error_message);\n";
6101       pr "    guestfs___end_busy (g);\n";
6102       pr "    return %s;\n" error_code;
6103       pr "  }\n";
6104       pr "\n";
6105
6106       (* Expecting to receive further files (FileOut)? *)
6107       List.iter (
6108         function
6109         | FileOut n ->
6110             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6111             pr "    guestfs___end_busy (g);\n";
6112             pr "    return %s;\n" error_code;
6113             pr "  }\n";
6114             pr "\n";
6115         | _ -> ()
6116       ) (snd style);
6117
6118       pr "  guestfs___end_busy (g);\n";
6119
6120       (match fst style with
6121        | RErr -> pr "  return 0;\n"
6122        | RInt n | RInt64 n | RBool n ->
6123            pr "  return ret.%s;\n" n
6124        | RConstString _ | RConstOptString _ ->
6125            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6126        | RString n ->
6127            pr "  return ret.%s; /* caller will free */\n" n
6128        | RStringList n | RHashtable n ->
6129            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6130            pr "  ret.%s.%s_val =\n" n n;
6131            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6132            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6133              n n;
6134            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6135            pr "  return ret.%s.%s_val;\n" n n
6136        | RStruct (n, _) ->
6137            pr "  /* caller will free this */\n";
6138            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6139        | RStructList (n, _) ->
6140            pr "  /* caller will free this */\n";
6141            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6142        | RBufferOut n ->
6143            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6144            pr "   * _val might be NULL here.  To make the API saner for\n";
6145            pr "   * callers, we turn this case into a unique pointer (using\n";
6146            pr "   * malloc(1)).\n";
6147            pr "   */\n";
6148            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6149            pr "    *size_r = ret.%s.%s_len;\n" n n;
6150            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6151            pr "  } else {\n";
6152            pr "    free (ret.%s.%s_val);\n" n n;
6153            pr "    char *p = safe_malloc (g, 1);\n";
6154            pr "    *size_r = ret.%s.%s_len;\n" n n;
6155            pr "    return p;\n";
6156            pr "  }\n";
6157       );
6158
6159       pr "}\n\n"
6160   ) daemon_functions;
6161
6162   (* Functions to free structures. *)
6163   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6164   pr " * structure format is identical to the XDR format.  See note in\n";
6165   pr " * generator.ml.\n";
6166   pr " */\n";
6167   pr "\n";
6168
6169   List.iter (
6170     fun (typ, _) ->
6171       pr "void\n";
6172       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6173       pr "{\n";
6174       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6175       pr "  free (x);\n";
6176       pr "}\n";
6177       pr "\n";
6178
6179       pr "void\n";
6180       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6181       pr "{\n";
6182       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6183       pr "  free (x);\n";
6184       pr "}\n";
6185       pr "\n";
6186
6187   ) structs;
6188
6189 (* Generate daemon/actions.h. *)
6190 and generate_daemon_actions_h () =
6191   generate_header CStyle GPLv2plus;
6192
6193   pr "#include \"../src/guestfs_protocol.h\"\n";
6194   pr "\n";
6195
6196   List.iter (
6197     fun (name, style, _, _, _, _, _) ->
6198       generate_prototype
6199         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6200         name style;
6201   ) daemon_functions
6202
6203 (* Generate the linker script which controls the visibility of
6204  * symbols in the public ABI and ensures no other symbols get
6205  * exported accidentally.
6206  *)
6207 and generate_linker_script () =
6208   generate_header HashStyle GPLv2plus;
6209
6210   let globals = [
6211     "guestfs_create";
6212     "guestfs_close";
6213     "guestfs_get_error_handler";
6214     "guestfs_get_out_of_memory_handler";
6215     "guestfs_last_error";
6216     "guestfs_set_error_handler";
6217     "guestfs_set_launch_done_callback";
6218     "guestfs_set_log_message_callback";
6219     "guestfs_set_out_of_memory_handler";
6220     "guestfs_set_subprocess_quit_callback";
6221
6222     (* Unofficial parts of the API: the bindings code use these
6223      * functions, so it is useful to export them.
6224      *)
6225     "guestfs_safe_calloc";
6226     "guestfs_safe_malloc";
6227   ] in
6228   let functions =
6229     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6230       all_functions in
6231   let structs =
6232     List.concat (
6233       List.map (fun (typ, _) ->
6234                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6235         structs
6236     ) in
6237   let globals = List.sort compare (globals @ functions @ structs) in
6238
6239   pr "{\n";
6240   pr "    global:\n";
6241   List.iter (pr "        %s;\n") globals;
6242   pr "\n";
6243
6244   pr "    local:\n";
6245   pr "        *;\n";
6246   pr "};\n"
6247
6248 (* Generate the server-side stubs. *)
6249 and generate_daemon_actions () =
6250   generate_header CStyle GPLv2plus;
6251
6252   pr "#include <config.h>\n";
6253   pr "\n";
6254   pr "#include <stdio.h>\n";
6255   pr "#include <stdlib.h>\n";
6256   pr "#include <string.h>\n";
6257   pr "#include <inttypes.h>\n";
6258   pr "#include <rpc/types.h>\n";
6259   pr "#include <rpc/xdr.h>\n";
6260   pr "\n";
6261   pr "#include \"daemon.h\"\n";
6262   pr "#include \"c-ctype.h\"\n";
6263   pr "#include \"../src/guestfs_protocol.h\"\n";
6264   pr "#include \"actions.h\"\n";
6265   pr "\n";
6266
6267   List.iter (
6268     fun (name, style, _, _, _, _, _) ->
6269       (* Generate server-side stubs. *)
6270       pr "static void %s_stub (XDR *xdr_in)\n" name;
6271       pr "{\n";
6272       let error_code =
6273         match fst style with
6274         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6275         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6276         | RBool _ -> pr "  int r;\n"; "-1"
6277         | RConstString _ | RConstOptString _ ->
6278             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6279         | RString _ -> pr "  char *r;\n"; "NULL"
6280         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6281         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6282         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6283         | RBufferOut _ ->
6284             pr "  size_t size = 1;\n";
6285             pr "  char *r;\n";
6286             "NULL" in
6287
6288       (match snd style with
6289        | [] -> ()
6290        | args ->
6291            pr "  struct guestfs_%s_args args;\n" name;
6292            List.iter (
6293              function
6294              | Device n | Dev_or_Path n
6295              | Pathname n
6296              | String n -> ()
6297              | OptString n -> pr "  char *%s;\n" n
6298              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6299              | Bool n -> pr "  int %s;\n" n
6300              | Int n -> pr "  int %s;\n" n
6301              | Int64 n -> pr "  int64_t %s;\n" n
6302              | FileIn _ | FileOut _ -> ()
6303              | BufferIn n ->
6304                  pr "  const char *%s;\n" n;
6305                  pr "  size_t %s_size;\n" n
6306            ) args
6307       );
6308       pr "\n";
6309
6310       let is_filein =
6311         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6312
6313       (match snd style with
6314        | [] -> ()
6315        | args ->
6316            pr "  memset (&args, 0, sizeof args);\n";
6317            pr "\n";
6318            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6319            if is_filein then
6320              pr "    if (cancel_receive () != -2)\n";
6321            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6322            pr "    goto done;\n";
6323            pr "  }\n";
6324            let pr_args n =
6325              pr "  char *%s = args.%s;\n" n n
6326            in
6327            let pr_list_handling_code n =
6328              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6329              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6330              pr "  if (%s == NULL) {\n" n;
6331              if is_filein then
6332                pr "    if (cancel_receive () != -2)\n";
6333              pr "      reply_with_perror (\"realloc\");\n";
6334              pr "    goto done;\n";
6335              pr "  }\n";
6336              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6337              pr "  args.%s.%s_val = %s;\n" n n n;
6338            in
6339            List.iter (
6340              function
6341              | Pathname n ->
6342                  pr_args n;
6343                  pr "  ABS_PATH (%s, %s, goto done);\n"
6344                    n (if is_filein then "cancel_receive ()" else "0");
6345              | Device n ->
6346                  pr_args n;
6347                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6348                    n (if is_filein then "cancel_receive ()" else "0");
6349              | Dev_or_Path n ->
6350                  pr_args n;
6351                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6352                    n (if is_filein then "cancel_receive ()" else "0");
6353              | String n -> pr_args n
6354              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6355              | StringList n ->
6356                  pr_list_handling_code n;
6357              | DeviceList n ->
6358                  pr_list_handling_code n;
6359                  pr "  /* Ensure that each is a device,\n";
6360                  pr "   * and perform device name translation. */\n";
6361                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6362                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6363                    (if is_filein then "cancel_receive ()" else "0");
6364                  pr "  }\n";
6365              | Bool n -> pr "  %s = args.%s;\n" n n
6366              | Int n -> pr "  %s = args.%s;\n" n n
6367              | Int64 n -> pr "  %s = args.%s;\n" n n
6368              | FileIn _ | FileOut _ -> ()
6369              | BufferIn n ->
6370                  pr "  %s = args.%s.%s_val;\n" n n n;
6371                  pr "  %s_size = args.%s.%s_len;\n" n n n
6372            ) args;
6373            pr "\n"
6374       );
6375
6376       (* this is used at least for do_equal *)
6377       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6378         (* Emit NEED_ROOT just once, even when there are two or
6379            more Pathname args *)
6380         pr "  NEED_ROOT (%s, goto done);\n"
6381           (if is_filein then "cancel_receive ()" else "0");
6382       );
6383
6384       (* Don't want to call the impl with any FileIn or FileOut
6385        * parameters, since these go "outside" the RPC protocol.
6386        *)
6387       let args' =
6388         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6389           (snd style) in
6390       pr "  r = do_%s " name;
6391       generate_c_call_args (fst style, args');
6392       pr ";\n";
6393
6394       (match fst style with
6395        | RErr | RInt _ | RInt64 _ | RBool _
6396        | RConstString _ | RConstOptString _
6397        | RString _ | RStringList _ | RHashtable _
6398        | RStruct (_, _) | RStructList (_, _) ->
6399            pr "  if (r == %s)\n" error_code;
6400            pr "    /* do_%s has already called reply_with_error */\n" name;
6401            pr "    goto done;\n";
6402            pr "\n"
6403        | RBufferOut _ ->
6404            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6405            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6406            pr "   */\n";
6407            pr "  if (size == 1 && r == %s)\n" error_code;
6408            pr "    /* do_%s has already called reply_with_error */\n" name;
6409            pr "    goto done;\n";
6410            pr "\n"
6411       );
6412
6413       (* If there are any FileOut parameters, then the impl must
6414        * send its own reply.
6415        *)
6416       let no_reply =
6417         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6418       if no_reply then
6419         pr "  /* do_%s has already sent a reply */\n" name
6420       else (
6421         match fst style with
6422         | RErr -> pr "  reply (NULL, NULL);\n"
6423         | RInt n | RInt64 n | RBool n ->
6424             pr "  struct guestfs_%s_ret ret;\n" name;
6425             pr "  ret.%s = r;\n" n;
6426             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6427               name
6428         | RConstString _ | RConstOptString _ ->
6429             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6430         | RString n ->
6431             pr "  struct guestfs_%s_ret ret;\n" name;
6432             pr "  ret.%s = r;\n" n;
6433             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6434               name;
6435             pr "  free (r);\n"
6436         | RStringList n | RHashtable n ->
6437             pr "  struct guestfs_%s_ret ret;\n" name;
6438             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6439             pr "  ret.%s.%s_val = r;\n" n n;
6440             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6441               name;
6442             pr "  free_strings (r);\n"
6443         | RStruct (n, _) ->
6444             pr "  struct guestfs_%s_ret ret;\n" name;
6445             pr "  ret.%s = *r;\n" n;
6446             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6447               name;
6448             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6449               name
6450         | RStructList (n, _) ->
6451             pr "  struct guestfs_%s_ret ret;\n" name;
6452             pr "  ret.%s = *r;\n" n;
6453             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6454               name;
6455             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6456               name
6457         | RBufferOut n ->
6458             pr "  struct guestfs_%s_ret ret;\n" name;
6459             pr "  ret.%s.%s_val = r;\n" n n;
6460             pr "  ret.%s.%s_len = size;\n" n n;
6461             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6462               name;
6463             pr "  free (r);\n"
6464       );
6465
6466       (* Free the args. *)
6467       pr "done:\n";
6468       (match snd style with
6469        | [] -> ()
6470        | _ ->
6471            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6472              name
6473       );
6474       pr "  return;\n";
6475       pr "}\n\n";
6476   ) daemon_functions;
6477
6478   (* Dispatch function. *)
6479   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6480   pr "{\n";
6481   pr "  switch (proc_nr) {\n";
6482
6483   List.iter (
6484     fun (name, style, _, _, _, _, _) ->
6485       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6486       pr "      %s_stub (xdr_in);\n" name;
6487       pr "      break;\n"
6488   ) daemon_functions;
6489
6490   pr "    default:\n";
6491   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";
6492   pr "  }\n";
6493   pr "}\n";
6494   pr "\n";
6495
6496   (* LVM columns and tokenization functions. *)
6497   (* XXX This generates crap code.  We should rethink how we
6498    * do this parsing.
6499    *)
6500   List.iter (
6501     function
6502     | typ, cols ->
6503         pr "static const char *lvm_%s_cols = \"%s\";\n"
6504           typ (String.concat "," (List.map fst cols));
6505         pr "\n";
6506
6507         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6508         pr "{\n";
6509         pr "  char *tok, *p, *next;\n";
6510         pr "  int i, j;\n";
6511         pr "\n";
6512         (*
6513           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6514           pr "\n";
6515         *)
6516         pr "  if (!str) {\n";
6517         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6518         pr "    return -1;\n";
6519         pr "  }\n";
6520         pr "  if (!*str || c_isspace (*str)) {\n";
6521         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6522         pr "    return -1;\n";
6523         pr "  }\n";
6524         pr "  tok = str;\n";
6525         List.iter (
6526           fun (name, coltype) ->
6527             pr "  if (!tok) {\n";
6528             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6529             pr "    return -1;\n";
6530             pr "  }\n";
6531             pr "  p = strchrnul (tok, ',');\n";
6532             pr "  if (*p) next = p+1; else next = NULL;\n";
6533             pr "  *p = '\\0';\n";
6534             (match coltype with
6535              | FString ->
6536                  pr "  r->%s = strdup (tok);\n" name;
6537                  pr "  if (r->%s == NULL) {\n" name;
6538                  pr "    perror (\"strdup\");\n";
6539                  pr "    return -1;\n";
6540                  pr "  }\n"
6541              | FUUID ->
6542                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6543                  pr "    if (tok[j] == '\\0') {\n";
6544                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6545                  pr "      return -1;\n";
6546                  pr "    } else if (tok[j] != '-')\n";
6547                  pr "      r->%s[i++] = tok[j];\n" name;
6548                  pr "  }\n";
6549              | FBytes ->
6550                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6551                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6552                  pr "    return -1;\n";
6553                  pr "  }\n";
6554              | FInt64 ->
6555                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6556                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6557                  pr "    return -1;\n";
6558                  pr "  }\n";
6559              | FOptPercent ->
6560                  pr "  if (tok[0] == '\\0')\n";
6561                  pr "    r->%s = -1;\n" name;
6562                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6563                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6564                  pr "    return -1;\n";
6565                  pr "  }\n";
6566              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6567                  assert false (* can never be an LVM column *)
6568             );
6569             pr "  tok = next;\n";
6570         ) cols;
6571
6572         pr "  if (tok != NULL) {\n";
6573         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6574         pr "    return -1;\n";
6575         pr "  }\n";
6576         pr "  return 0;\n";
6577         pr "}\n";
6578         pr "\n";
6579
6580         pr "guestfs_int_lvm_%s_list *\n" typ;
6581         pr "parse_command_line_%ss (void)\n" typ;
6582         pr "{\n";
6583         pr "  char *out, *err;\n";
6584         pr "  char *p, *pend;\n";
6585         pr "  int r, i;\n";
6586         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6587         pr "  void *newp;\n";
6588         pr "\n";
6589         pr "  ret = malloc (sizeof *ret);\n";
6590         pr "  if (!ret) {\n";
6591         pr "    reply_with_perror (\"malloc\");\n";
6592         pr "    return NULL;\n";
6593         pr "  }\n";
6594         pr "\n";
6595         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6596         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6597         pr "\n";
6598         pr "  r = command (&out, &err,\n";
6599         pr "           \"lvm\", \"%ss\",\n" typ;
6600         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6601         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6602         pr "  if (r == -1) {\n";
6603         pr "    reply_with_error (\"%%s\", err);\n";
6604         pr "    free (out);\n";
6605         pr "    free (err);\n";
6606         pr "    free (ret);\n";
6607         pr "    return NULL;\n";
6608         pr "  }\n";
6609         pr "\n";
6610         pr "  free (err);\n";
6611         pr "\n";
6612         pr "  /* Tokenize each line of the output. */\n";
6613         pr "  p = out;\n";
6614         pr "  i = 0;\n";
6615         pr "  while (p) {\n";
6616         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6617         pr "    if (pend) {\n";
6618         pr "      *pend = '\\0';\n";
6619         pr "      pend++;\n";
6620         pr "    }\n";
6621         pr "\n";
6622         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6623         pr "      p++;\n";
6624         pr "\n";
6625         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6626         pr "      p = pend;\n";
6627         pr "      continue;\n";
6628         pr "    }\n";
6629         pr "\n";
6630         pr "    /* Allocate some space to store this next entry. */\n";
6631         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6632         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6633         pr "    if (newp == NULL) {\n";
6634         pr "      reply_with_perror (\"realloc\");\n";
6635         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6636         pr "      free (ret);\n";
6637         pr "      free (out);\n";
6638         pr "      return NULL;\n";
6639         pr "    }\n";
6640         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6641         pr "\n";
6642         pr "    /* Tokenize the next entry. */\n";
6643         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6644         pr "    if (r == -1) {\n";
6645         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6646         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6647         pr "      free (ret);\n";
6648         pr "      free (out);\n";
6649         pr "      return NULL;\n";
6650         pr "    }\n";
6651         pr "\n";
6652         pr "    ++i;\n";
6653         pr "    p = pend;\n";
6654         pr "  }\n";
6655         pr "\n";
6656         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6657         pr "\n";
6658         pr "  free (out);\n";
6659         pr "  return ret;\n";
6660         pr "}\n"
6661
6662   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6663
6664 (* Generate a list of function names, for debugging in the daemon.. *)
6665 and generate_daemon_names () =
6666   generate_header CStyle GPLv2plus;
6667
6668   pr "#include <config.h>\n";
6669   pr "\n";
6670   pr "#include \"daemon.h\"\n";
6671   pr "\n";
6672
6673   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6674   pr "const char *function_names[] = {\n";
6675   List.iter (
6676     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6677   ) daemon_functions;
6678   pr "};\n";
6679
6680 (* Generate the optional groups for the daemon to implement
6681  * guestfs_available.
6682  *)
6683 and generate_daemon_optgroups_c () =
6684   generate_header CStyle GPLv2plus;
6685
6686   pr "#include <config.h>\n";
6687   pr "\n";
6688   pr "#include \"daemon.h\"\n";
6689   pr "#include \"optgroups.h\"\n";
6690   pr "\n";
6691
6692   pr "struct optgroup optgroups[] = {\n";
6693   List.iter (
6694     fun (group, _) ->
6695       pr "  { \"%s\", optgroup_%s_available },\n" group group
6696   ) optgroups;
6697   pr "  { NULL, NULL }\n";
6698   pr "};\n"
6699
6700 and generate_daemon_optgroups_h () =
6701   generate_header CStyle GPLv2plus;
6702
6703   List.iter (
6704     fun (group, _) ->
6705       pr "extern int optgroup_%s_available (void);\n" group
6706   ) optgroups
6707
6708 (* Generate the tests. *)
6709 and generate_tests () =
6710   generate_header CStyle GPLv2plus;
6711
6712   pr "\
6713 #include <stdio.h>
6714 #include <stdlib.h>
6715 #include <string.h>
6716 #include <unistd.h>
6717 #include <sys/types.h>
6718 #include <fcntl.h>
6719
6720 #include \"guestfs.h\"
6721 #include \"guestfs-internal.h\"
6722
6723 static guestfs_h *g;
6724 static int suppress_error = 0;
6725
6726 static void print_error (guestfs_h *g, void *data, const char *msg)
6727 {
6728   if (!suppress_error)
6729     fprintf (stderr, \"%%s\\n\", msg);
6730 }
6731
6732 /* FIXME: nearly identical code appears in fish.c */
6733 static void print_strings (char *const *argv)
6734 {
6735   int argc;
6736
6737   for (argc = 0; argv[argc] != NULL; ++argc)
6738     printf (\"\\t%%s\\n\", argv[argc]);
6739 }
6740
6741 /*
6742 static void print_table (char const *const *argv)
6743 {
6744   int i;
6745
6746   for (i = 0; argv[i] != NULL; i += 2)
6747     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6748 }
6749 */
6750
6751 ";
6752
6753   (* Generate a list of commands which are not tested anywhere. *)
6754   pr "static void no_test_warnings (void)\n";
6755   pr "{\n";
6756
6757   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6758   List.iter (
6759     fun (_, _, _, _, tests, _, _) ->
6760       let tests = filter_map (
6761         function
6762         | (_, (Always|If _|Unless _), test) -> Some test
6763         | (_, Disabled, _) -> None
6764       ) tests in
6765       let seq = List.concat (List.map seq_of_test tests) in
6766       let cmds_tested = List.map List.hd seq in
6767       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6768   ) all_functions;
6769
6770   List.iter (
6771     fun (name, _, _, _, _, _, _) ->
6772       if not (Hashtbl.mem hash name) then
6773         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6774   ) all_functions;
6775
6776   pr "}\n";
6777   pr "\n";
6778
6779   (* Generate the actual tests.  Note that we generate the tests
6780    * in reverse order, deliberately, so that (in general) the
6781    * newest tests run first.  This makes it quicker and easier to
6782    * debug them.
6783    *)
6784   let test_names =
6785     List.map (
6786       fun (name, _, _, flags, tests, _, _) ->
6787         mapi (generate_one_test name flags) tests
6788     ) (List.rev all_functions) in
6789   let test_names = List.concat test_names in
6790   let nr_tests = List.length test_names in
6791
6792   pr "\
6793 int main (int argc, char *argv[])
6794 {
6795   char c = 0;
6796   unsigned long int n_failed = 0;
6797   const char *filename;
6798   int fd;
6799   int nr_tests, test_num = 0;
6800
6801   setbuf (stdout, NULL);
6802
6803   no_test_warnings ();
6804
6805   g = guestfs_create ();
6806   if (g == NULL) {
6807     printf (\"guestfs_create FAILED\\n\");
6808     exit (EXIT_FAILURE);
6809   }
6810
6811   guestfs_set_error_handler (g, print_error, NULL);
6812
6813   guestfs_set_path (g, \"../appliance\");
6814
6815   filename = \"test1.img\";
6816   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6817   if (fd == -1) {
6818     perror (filename);
6819     exit (EXIT_FAILURE);
6820   }
6821   if (lseek (fd, %d, SEEK_SET) == -1) {
6822     perror (\"lseek\");
6823     close (fd);
6824     unlink (filename);
6825     exit (EXIT_FAILURE);
6826   }
6827   if (write (fd, &c, 1) == -1) {
6828     perror (\"write\");
6829     close (fd);
6830     unlink (filename);
6831     exit (EXIT_FAILURE);
6832   }
6833   if (close (fd) == -1) {
6834     perror (filename);
6835     unlink (filename);
6836     exit (EXIT_FAILURE);
6837   }
6838   if (guestfs_add_drive (g, filename) == -1) {
6839     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6840     exit (EXIT_FAILURE);
6841   }
6842
6843   filename = \"test2.img\";
6844   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6845   if (fd == -1) {
6846     perror (filename);
6847     exit (EXIT_FAILURE);
6848   }
6849   if (lseek (fd, %d, SEEK_SET) == -1) {
6850     perror (\"lseek\");
6851     close (fd);
6852     unlink (filename);
6853     exit (EXIT_FAILURE);
6854   }
6855   if (write (fd, &c, 1) == -1) {
6856     perror (\"write\");
6857     close (fd);
6858     unlink (filename);
6859     exit (EXIT_FAILURE);
6860   }
6861   if (close (fd) == -1) {
6862     perror (filename);
6863     unlink (filename);
6864     exit (EXIT_FAILURE);
6865   }
6866   if (guestfs_add_drive (g, filename) == -1) {
6867     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6868     exit (EXIT_FAILURE);
6869   }
6870
6871   filename = \"test3.img\";
6872   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6873   if (fd == -1) {
6874     perror (filename);
6875     exit (EXIT_FAILURE);
6876   }
6877   if (lseek (fd, %d, SEEK_SET) == -1) {
6878     perror (\"lseek\");
6879     close (fd);
6880     unlink (filename);
6881     exit (EXIT_FAILURE);
6882   }
6883   if (write (fd, &c, 1) == -1) {
6884     perror (\"write\");
6885     close (fd);
6886     unlink (filename);
6887     exit (EXIT_FAILURE);
6888   }
6889   if (close (fd) == -1) {
6890     perror (filename);
6891     unlink (filename);
6892     exit (EXIT_FAILURE);
6893   }
6894   if (guestfs_add_drive (g, filename) == -1) {
6895     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6896     exit (EXIT_FAILURE);
6897   }
6898
6899   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6900     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6901     exit (EXIT_FAILURE);
6902   }
6903
6904   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6905   alarm (600);
6906
6907   if (guestfs_launch (g) == -1) {
6908     printf (\"guestfs_launch FAILED\\n\");
6909     exit (EXIT_FAILURE);
6910   }
6911
6912   /* Cancel previous alarm. */
6913   alarm (0);
6914
6915   nr_tests = %d;
6916
6917 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6918
6919   iteri (
6920     fun i test_name ->
6921       pr "  test_num++;\n";
6922       pr "  if (guestfs_get_verbose (g))\n";
6923       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6924       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6925       pr "  if (%s () == -1) {\n" test_name;
6926       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6927       pr "    n_failed++;\n";
6928       pr "  }\n";
6929   ) test_names;
6930   pr "\n";
6931
6932   pr "  guestfs_close (g);\n";
6933   pr "  unlink (\"test1.img\");\n";
6934   pr "  unlink (\"test2.img\");\n";
6935   pr "  unlink (\"test3.img\");\n";
6936   pr "\n";
6937
6938   pr "  if (n_failed > 0) {\n";
6939   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6940   pr "    exit (EXIT_FAILURE);\n";
6941   pr "  }\n";
6942   pr "\n";
6943
6944   pr "  exit (EXIT_SUCCESS);\n";
6945   pr "}\n"
6946
6947 and generate_one_test name flags i (init, prereq, test) =
6948   let test_name = sprintf "test_%s_%d" name i in
6949
6950   pr "\
6951 static int %s_skip (void)
6952 {
6953   const char *str;
6954
6955   str = getenv (\"TEST_ONLY\");
6956   if (str)
6957     return strstr (str, \"%s\") == NULL;
6958   str = getenv (\"SKIP_%s\");
6959   if (str && STREQ (str, \"1\")) return 1;
6960   str = getenv (\"SKIP_TEST_%s\");
6961   if (str && STREQ (str, \"1\")) return 1;
6962   return 0;
6963 }
6964
6965 " test_name name (String.uppercase test_name) (String.uppercase name);
6966
6967   (match prereq with
6968    | Disabled | Always -> ()
6969    | If code | Unless code ->
6970        pr "static int %s_prereq (void)\n" test_name;
6971        pr "{\n";
6972        pr "  %s\n" code;
6973        pr "}\n";
6974        pr "\n";
6975   );
6976
6977   pr "\
6978 static int %s (void)
6979 {
6980   if (%s_skip ()) {
6981     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6982     return 0;
6983   }
6984
6985 " test_name test_name test_name;
6986
6987   (* Optional functions should only be tested if the relevant
6988    * support is available in the daemon.
6989    *)
6990   List.iter (
6991     function
6992     | Optional group ->
6993         pr "  {\n";
6994         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6995         pr "    int r;\n";
6996         pr "    suppress_error = 1;\n";
6997         pr "    r = guestfs_available (g, (char **) groups);\n";
6998         pr "    suppress_error = 0;\n";
6999         pr "    if (r == -1) {\n";
7000         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
7001         pr "      return 0;\n";
7002         pr "    }\n";
7003         pr "  }\n";
7004     | _ -> ()
7005   ) flags;
7006
7007   (match prereq with
7008    | Disabled ->
7009        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7010    | If _ ->
7011        pr "  if (! %s_prereq ()) {\n" test_name;
7012        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7013        pr "    return 0;\n";
7014        pr "  }\n";
7015        pr "\n";
7016        generate_one_test_body name i test_name init test;
7017    | Unless _ ->
7018        pr "  if (%s_prereq ()) {\n" test_name;
7019        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7020        pr "    return 0;\n";
7021        pr "  }\n";
7022        pr "\n";
7023        generate_one_test_body name i test_name init test;
7024    | Always ->
7025        generate_one_test_body name i test_name init test
7026   );
7027
7028   pr "  return 0;\n";
7029   pr "}\n";
7030   pr "\n";
7031   test_name
7032
7033 and generate_one_test_body name i test_name init test =
7034   (match init with
7035    | InitNone (* XXX at some point, InitNone and InitEmpty became
7036                * folded together as the same thing.  Really we should
7037                * make InitNone do nothing at all, but the tests may
7038                * need to be checked to make sure this is OK.
7039                *)
7040    | InitEmpty ->
7041        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7042        List.iter (generate_test_command_call test_name)
7043          [["blockdev_setrw"; "/dev/sda"];
7044           ["umount_all"];
7045           ["lvm_remove_all"]]
7046    | InitPartition ->
7047        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7048        List.iter (generate_test_command_call test_name)
7049          [["blockdev_setrw"; "/dev/sda"];
7050           ["umount_all"];
7051           ["lvm_remove_all"];
7052           ["part_disk"; "/dev/sda"; "mbr"]]
7053    | InitBasicFS ->
7054        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7055        List.iter (generate_test_command_call test_name)
7056          [["blockdev_setrw"; "/dev/sda"];
7057           ["umount_all"];
7058           ["lvm_remove_all"];
7059           ["part_disk"; "/dev/sda"; "mbr"];
7060           ["mkfs"; "ext2"; "/dev/sda1"];
7061           ["mount_options"; ""; "/dev/sda1"; "/"]]
7062    | InitBasicFSonLVM ->
7063        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7064          test_name;
7065        List.iter (generate_test_command_call test_name)
7066          [["blockdev_setrw"; "/dev/sda"];
7067           ["umount_all"];
7068           ["lvm_remove_all"];
7069           ["part_disk"; "/dev/sda"; "mbr"];
7070           ["pvcreate"; "/dev/sda1"];
7071           ["vgcreate"; "VG"; "/dev/sda1"];
7072           ["lvcreate"; "LV"; "VG"; "8"];
7073           ["mkfs"; "ext2"; "/dev/VG/LV"];
7074           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7075    | InitISOFS ->
7076        pr "  /* InitISOFS for %s */\n" test_name;
7077        List.iter (generate_test_command_call test_name)
7078          [["blockdev_setrw"; "/dev/sda"];
7079           ["umount_all"];
7080           ["lvm_remove_all"];
7081           ["mount_ro"; "/dev/sdd"; "/"]]
7082   );
7083
7084   let get_seq_last = function
7085     | [] ->
7086         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7087           test_name
7088     | seq ->
7089         let seq = List.rev seq in
7090         List.rev (List.tl seq), List.hd seq
7091   in
7092
7093   match test with
7094   | TestRun seq ->
7095       pr "  /* TestRun for %s (%d) */\n" name i;
7096       List.iter (generate_test_command_call test_name) seq
7097   | TestOutput (seq, expected) ->
7098       pr "  /* TestOutput for %s (%d) */\n" name i;
7099       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7100       let seq, last = get_seq_last seq in
7101       let test () =
7102         pr "    if (STRNEQ (r, expected)) {\n";
7103         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7104         pr "      return -1;\n";
7105         pr "    }\n"
7106       in
7107       List.iter (generate_test_command_call test_name) seq;
7108       generate_test_command_call ~test test_name last
7109   | TestOutputList (seq, expected) ->
7110       pr "  /* TestOutputList for %s (%d) */\n" name i;
7111       let seq, last = get_seq_last seq in
7112       let test () =
7113         iteri (
7114           fun i str ->
7115             pr "    if (!r[%d]) {\n" i;
7116             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7117             pr "      print_strings (r);\n";
7118             pr "      return -1;\n";
7119             pr "    }\n";
7120             pr "    {\n";
7121             pr "      const char *expected = \"%s\";\n" (c_quote str);
7122             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7123             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7124             pr "        return -1;\n";
7125             pr "      }\n";
7126             pr "    }\n"
7127         ) expected;
7128         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7129         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7130           test_name;
7131         pr "      print_strings (r);\n";
7132         pr "      return -1;\n";
7133         pr "    }\n"
7134       in
7135       List.iter (generate_test_command_call test_name) seq;
7136       generate_test_command_call ~test test_name last
7137   | TestOutputListOfDevices (seq, expected) ->
7138       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7139       let seq, last = get_seq_last seq in
7140       let test () =
7141         iteri (
7142           fun i str ->
7143             pr "    if (!r[%d]) {\n" i;
7144             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7145             pr "      print_strings (r);\n";
7146             pr "      return -1;\n";
7147             pr "    }\n";
7148             pr "    {\n";
7149             pr "      const char *expected = \"%s\";\n" (c_quote str);
7150             pr "      r[%d][5] = 's';\n" i;
7151             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7152             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7153             pr "        return -1;\n";
7154             pr "      }\n";
7155             pr "    }\n"
7156         ) expected;
7157         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7158         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7159           test_name;
7160         pr "      print_strings (r);\n";
7161         pr "      return -1;\n";
7162         pr "    }\n"
7163       in
7164       List.iter (generate_test_command_call test_name) seq;
7165       generate_test_command_call ~test test_name last
7166   | TestOutputInt (seq, expected) ->
7167       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7168       let seq, last = get_seq_last seq in
7169       let test () =
7170         pr "    if (r != %d) {\n" expected;
7171         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7172           test_name expected;
7173         pr "               (int) r);\n";
7174         pr "      return -1;\n";
7175         pr "    }\n"
7176       in
7177       List.iter (generate_test_command_call test_name) seq;
7178       generate_test_command_call ~test test_name last
7179   | TestOutputIntOp (seq, op, expected) ->
7180       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7181       let seq, last = get_seq_last seq in
7182       let test () =
7183         pr "    if (! (r %s %d)) {\n" op expected;
7184         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7185           test_name op expected;
7186         pr "               (int) r);\n";
7187         pr "      return -1;\n";
7188         pr "    }\n"
7189       in
7190       List.iter (generate_test_command_call test_name) seq;
7191       generate_test_command_call ~test test_name last
7192   | TestOutputTrue seq ->
7193       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7194       let seq, last = get_seq_last seq in
7195       let test () =
7196         pr "    if (!r) {\n";
7197         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7198           test_name;
7199         pr "      return -1;\n";
7200         pr "    }\n"
7201       in
7202       List.iter (generate_test_command_call test_name) seq;
7203       generate_test_command_call ~test test_name last
7204   | TestOutputFalse seq ->
7205       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7206       let seq, last = get_seq_last seq in
7207       let test () =
7208         pr "    if (r) {\n";
7209         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7210           test_name;
7211         pr "      return -1;\n";
7212         pr "    }\n"
7213       in
7214       List.iter (generate_test_command_call test_name) seq;
7215       generate_test_command_call ~test test_name last
7216   | TestOutputLength (seq, expected) ->
7217       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7218       let seq, last = get_seq_last seq in
7219       let test () =
7220         pr "    int j;\n";
7221         pr "    for (j = 0; j < %d; ++j)\n" expected;
7222         pr "      if (r[j] == NULL) {\n";
7223         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7224           test_name;
7225         pr "        print_strings (r);\n";
7226         pr "        return -1;\n";
7227         pr "      }\n";
7228         pr "    if (r[j] != NULL) {\n";
7229         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7230           test_name;
7231         pr "      print_strings (r);\n";
7232         pr "      return -1;\n";
7233         pr "    }\n"
7234       in
7235       List.iter (generate_test_command_call test_name) seq;
7236       generate_test_command_call ~test test_name last
7237   | TestOutputBuffer (seq, expected) ->
7238       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7239       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7240       let seq, last = get_seq_last seq in
7241       let len = String.length expected in
7242       let test () =
7243         pr "    if (size != %d) {\n" len;
7244         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7245         pr "      return -1;\n";
7246         pr "    }\n";
7247         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7248         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7249         pr "      return -1;\n";
7250         pr "    }\n"
7251       in
7252       List.iter (generate_test_command_call test_name) seq;
7253       generate_test_command_call ~test test_name last
7254   | TestOutputStruct (seq, checks) ->
7255       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7256       let seq, last = get_seq_last seq in
7257       let test () =
7258         List.iter (
7259           function
7260           | CompareWithInt (field, expected) ->
7261               pr "    if (r->%s != %d) {\n" field expected;
7262               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7263                 test_name field expected;
7264               pr "               (int) r->%s);\n" field;
7265               pr "      return -1;\n";
7266               pr "    }\n"
7267           | CompareWithIntOp (field, op, expected) ->
7268               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7269               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7270                 test_name field op expected;
7271               pr "               (int) r->%s);\n" field;
7272               pr "      return -1;\n";
7273               pr "    }\n"
7274           | CompareWithString (field, expected) ->
7275               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7276               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7277                 test_name field expected;
7278               pr "               r->%s);\n" field;
7279               pr "      return -1;\n";
7280               pr "    }\n"
7281           | CompareFieldsIntEq (field1, field2) ->
7282               pr "    if (r->%s != r->%s) {\n" field1 field2;
7283               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7284                 test_name field1 field2;
7285               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7286               pr "      return -1;\n";
7287               pr "    }\n"
7288           | CompareFieldsStrEq (field1, field2) ->
7289               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7290               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7291                 test_name field1 field2;
7292               pr "               r->%s, r->%s);\n" field1 field2;
7293               pr "      return -1;\n";
7294               pr "    }\n"
7295         ) checks
7296       in
7297       List.iter (generate_test_command_call test_name) seq;
7298       generate_test_command_call ~test test_name last
7299   | TestLastFail seq ->
7300       pr "  /* TestLastFail for %s (%d) */\n" name i;
7301       let seq, last = get_seq_last seq in
7302       List.iter (generate_test_command_call test_name) seq;
7303       generate_test_command_call test_name ~expect_error:true last
7304
7305 (* Generate the code to run a command, leaving the result in 'r'.
7306  * If you expect to get an error then you should set expect_error:true.
7307  *)
7308 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7309   match cmd with
7310   | [] -> assert false
7311   | name :: args ->
7312       (* Look up the command to find out what args/ret it has. *)
7313       let style =
7314         try
7315           let _, style, _, _, _, _, _ =
7316             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7317           style
7318         with Not_found ->
7319           failwithf "%s: in test, command %s was not found" test_name name in
7320
7321       if List.length (snd style) <> List.length args then
7322         failwithf "%s: in test, wrong number of args given to %s"
7323           test_name name;
7324
7325       pr "  {\n";
7326
7327       List.iter (
7328         function
7329         | OptString n, "NULL" -> ()
7330         | Pathname n, arg
7331         | Device n, arg
7332         | Dev_or_Path n, arg
7333         | String n, arg
7334         | OptString n, arg ->
7335             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7336         | BufferIn n, arg ->
7337             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7338             pr "    size_t %s_size = %d;\n" n (String.length arg)
7339         | Int _, _
7340         | Int64 _, _
7341         | Bool _, _
7342         | FileIn _, _ | FileOut _, _ -> ()
7343         | StringList n, "" | DeviceList n, "" ->
7344             pr "    const char *const %s[1] = { NULL };\n" n
7345         | StringList n, arg | DeviceList n, arg ->
7346             let strs = string_split " " arg in
7347             iteri (
7348               fun i str ->
7349                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7350             ) strs;
7351             pr "    const char *const %s[] = {\n" n;
7352             iteri (
7353               fun i _ -> pr "      %s_%d,\n" n i
7354             ) strs;
7355             pr "      NULL\n";
7356             pr "    };\n";
7357       ) (List.combine (snd style) args);
7358
7359       let error_code =
7360         match fst style with
7361         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7362         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7363         | RConstString _ | RConstOptString _ ->
7364             pr "    const char *r;\n"; "NULL"
7365         | RString _ -> pr "    char *r;\n"; "NULL"
7366         | RStringList _ | RHashtable _ ->
7367             pr "    char **r;\n";
7368             pr "    int i;\n";
7369             "NULL"
7370         | RStruct (_, typ) ->
7371             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7372         | RStructList (_, typ) ->
7373             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7374         | RBufferOut _ ->
7375             pr "    char *r;\n";
7376             pr "    size_t size;\n";
7377             "NULL" in
7378
7379       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7380       pr "    r = guestfs_%s (g" name;
7381
7382       (* Generate the parameters. *)
7383       List.iter (
7384         function
7385         | OptString _, "NULL" -> pr ", NULL"
7386         | Pathname n, _
7387         | Device n, _ | Dev_or_Path n, _
7388         | String n, _
7389         | OptString n, _ ->
7390             pr ", %s" n
7391         | BufferIn n, _ ->
7392             pr ", %s, %s_size" n n
7393         | FileIn _, arg | FileOut _, arg ->
7394             pr ", \"%s\"" (c_quote arg)
7395         | StringList n, _ | DeviceList n, _ ->
7396             pr ", (char **) %s" n
7397         | Int _, arg ->
7398             let i =
7399               try int_of_string arg
7400               with Failure "int_of_string" ->
7401                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7402             pr ", %d" i
7403         | Int64 _, arg ->
7404             let i =
7405               try Int64.of_string arg
7406               with Failure "int_of_string" ->
7407                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7408             pr ", %Ld" i
7409         | Bool _, arg ->
7410             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7411       ) (List.combine (snd style) args);
7412
7413       (match fst style with
7414        | RBufferOut _ -> pr ", &size"
7415        | _ -> ()
7416       );
7417
7418       pr ");\n";
7419
7420       if not expect_error then
7421         pr "    if (r == %s)\n" error_code
7422       else
7423         pr "    if (r != %s)\n" error_code;
7424       pr "      return -1;\n";
7425
7426       (* Insert the test code. *)
7427       (match test with
7428        | None -> ()
7429        | Some f -> f ()
7430       );
7431
7432       (match fst style with
7433        | RErr | RInt _ | RInt64 _ | RBool _
7434        | RConstString _ | RConstOptString _ -> ()
7435        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7436        | RStringList _ | RHashtable _ ->
7437            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7438            pr "      free (r[i]);\n";
7439            pr "    free (r);\n"
7440        | RStruct (_, typ) ->
7441            pr "    guestfs_free_%s (r);\n" typ
7442        | RStructList (_, typ) ->
7443            pr "    guestfs_free_%s_list (r);\n" typ
7444       );
7445
7446       pr "  }\n"
7447
7448 and c_quote str =
7449   let str = replace_str str "\r" "\\r" in
7450   let str = replace_str str "\n" "\\n" in
7451   let str = replace_str str "\t" "\\t" in
7452   let str = replace_str str "\000" "\\0" in
7453   str
7454
7455 (* Generate a lot of different functions for guestfish. *)
7456 and generate_fish_cmds () =
7457   generate_header CStyle GPLv2plus;
7458
7459   let all_functions =
7460     List.filter (
7461       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7462     ) all_functions in
7463   let all_functions_sorted =
7464     List.filter (
7465       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7466     ) all_functions_sorted in
7467
7468   pr "#include <config.h>\n";
7469   pr "\n";
7470   pr "#include <stdio.h>\n";
7471   pr "#include <stdlib.h>\n";
7472   pr "#include <string.h>\n";
7473   pr "#include <inttypes.h>\n";
7474   pr "\n";
7475   pr "#include <guestfs.h>\n";
7476   pr "#include \"c-ctype.h\"\n";
7477   pr "#include \"full-write.h\"\n";
7478   pr "#include \"xstrtol.h\"\n";
7479   pr "#include \"fish.h\"\n";
7480   pr "\n";
7481   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7482   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7483   pr "\n";
7484
7485   (* list_commands function, which implements guestfish -h *)
7486   pr "void list_commands (void)\n";
7487   pr "{\n";
7488   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7489   pr "  list_builtin_commands ();\n";
7490   List.iter (
7491     fun (name, _, _, flags, _, shortdesc, _) ->
7492       let name = replace_char name '_' '-' in
7493       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7494         name shortdesc
7495   ) all_functions_sorted;
7496   pr "  printf (\"    %%s\\n\",";
7497   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7498   pr "}\n";
7499   pr "\n";
7500
7501   (* display_command function, which implements guestfish -h cmd *)
7502   pr "void display_command (const char *cmd)\n";
7503   pr "{\n";
7504   List.iter (
7505     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7506       let name2 = replace_char name '_' '-' in
7507       let alias =
7508         try find_map (function FishAlias n -> Some n | _ -> None) flags
7509         with Not_found -> name in
7510       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7511       let synopsis =
7512         match snd style with
7513         | [] -> name2
7514         | args ->
7515             sprintf "%s %s"
7516               name2 (String.concat " " (List.map name_of_argt args)) in
7517
7518       let warnings =
7519         if List.mem ProtocolLimitWarning flags then
7520           ("\n\n" ^ protocol_limit_warning)
7521         else "" in
7522
7523       (* For DangerWillRobinson commands, we should probably have
7524        * guestfish prompt before allowing you to use them (especially
7525        * in interactive mode). XXX
7526        *)
7527       let warnings =
7528         warnings ^
7529           if List.mem DangerWillRobinson flags then
7530             ("\n\n" ^ danger_will_robinson)
7531           else "" in
7532
7533       let warnings =
7534         warnings ^
7535           match deprecation_notice flags with
7536           | None -> ""
7537           | Some txt -> "\n\n" ^ txt in
7538
7539       let describe_alias =
7540         if name <> alias then
7541           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7542         else "" in
7543
7544       pr "  if (";
7545       pr "STRCASEEQ (cmd, \"%s\")" name;
7546       if name <> name2 then
7547         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7548       if name <> alias then
7549         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7550       pr ")\n";
7551       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7552         name2 shortdesc
7553         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7554          "=head1 DESCRIPTION\n\n" ^
7555          longdesc ^ warnings ^ describe_alias);
7556       pr "  else\n"
7557   ) all_functions;
7558   pr "    display_builtin_command (cmd);\n";
7559   pr "}\n";
7560   pr "\n";
7561
7562   let emit_print_list_function typ =
7563     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7564       typ typ typ;
7565     pr "{\n";
7566     pr "  unsigned int i;\n";
7567     pr "\n";
7568     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7569     pr "    printf (\"[%%d] = {\\n\", i);\n";
7570     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7571     pr "    printf (\"}\\n\");\n";
7572     pr "  }\n";
7573     pr "}\n";
7574     pr "\n";
7575   in
7576
7577   (* print_* functions *)
7578   List.iter (
7579     fun (typ, cols) ->
7580       let needs_i =
7581         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7582
7583       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7584       pr "{\n";
7585       if needs_i then (
7586         pr "  unsigned int i;\n";
7587         pr "\n"
7588       );
7589       List.iter (
7590         function
7591         | name, FString ->
7592             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7593         | name, FUUID ->
7594             pr "  printf (\"%%s%s: \", indent);\n" name;
7595             pr "  for (i = 0; i < 32; ++i)\n";
7596             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7597             pr "  printf (\"\\n\");\n"
7598         | name, FBuffer ->
7599             pr "  printf (\"%%s%s: \", indent);\n" name;
7600             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7601             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7602             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7603             pr "    else\n";
7604             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7605             pr "  printf (\"\\n\");\n"
7606         | name, (FUInt64|FBytes) ->
7607             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7608               name typ name
7609         | name, FInt64 ->
7610             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7611               name typ name
7612         | name, FUInt32 ->
7613             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7614               name typ name
7615         | name, FInt32 ->
7616             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7617               name typ name
7618         | name, FChar ->
7619             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7620               name typ name
7621         | name, FOptPercent ->
7622             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7623               typ name name typ name;
7624             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7625       ) cols;
7626       pr "}\n";
7627       pr "\n";
7628   ) structs;
7629
7630   (* Emit a print_TYPE_list function definition only if that function is used. *)
7631   List.iter (
7632     function
7633     | typ, (RStructListOnly | RStructAndList) ->
7634         (* generate the function for typ *)
7635         emit_print_list_function typ
7636     | typ, _ -> () (* empty *)
7637   ) (rstructs_used_by all_functions);
7638
7639   (* Emit a print_TYPE function definition only if that function is used. *)
7640   List.iter (
7641     function
7642     | typ, (RStructOnly | RStructAndList) ->
7643         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7644         pr "{\n";
7645         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7646         pr "}\n";
7647         pr "\n";
7648     | typ, _ -> () (* empty *)
7649   ) (rstructs_used_by all_functions);
7650
7651   (* run_<action> actions *)
7652   List.iter (
7653     fun (name, style, _, flags, _, _, _) ->
7654       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7655       pr "{\n";
7656       (match fst style with
7657        | RErr
7658        | RInt _
7659        | RBool _ -> pr "  int r;\n"
7660        | RInt64 _ -> pr "  int64_t r;\n"
7661        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7662        | RString _ -> pr "  char *r;\n"
7663        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7664        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7665        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7666        | RBufferOut _ ->
7667            pr "  char *r;\n";
7668            pr "  size_t size;\n";
7669       );
7670       List.iter (
7671         function
7672         | Device n
7673         | String n
7674         | OptString n -> pr "  const char *%s;\n" n
7675         | Pathname n
7676         | Dev_or_Path n
7677         | FileIn n
7678         | FileOut n -> pr "  char *%s;\n" n
7679         | BufferIn n ->
7680             pr "  const char *%s;\n" n;
7681             pr "  size_t %s_size;\n" n
7682         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7683         | Bool n -> pr "  int %s;\n" n
7684         | Int n -> pr "  int %s;\n" n
7685         | Int64 n -> pr "  int64_t %s;\n" n
7686       ) (snd style);
7687
7688       (* Check and convert parameters. *)
7689       let argc_expected = List.length (snd style) in
7690       pr "  if (argc != %d) {\n" argc_expected;
7691       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7692         argc_expected;
7693       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7694       pr "    return -1;\n";
7695       pr "  }\n";
7696
7697       let parse_integer fn fntyp rtyp range name i =
7698         pr "  {\n";
7699         pr "    strtol_error xerr;\n";
7700         pr "    %s r;\n" fntyp;
7701         pr "\n";
7702         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7703         pr "    if (xerr != LONGINT_OK) {\n";
7704         pr "      fprintf (stderr,\n";
7705         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7706         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7707         pr "      return -1;\n";
7708         pr "    }\n";
7709         (match range with
7710          | None -> ()
7711          | Some (min, max, comment) ->
7712              pr "    /* %s */\n" comment;
7713              pr "    if (r < %s || r > %s) {\n" min max;
7714              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7715                name;
7716              pr "      return -1;\n";
7717              pr "    }\n";
7718              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7719         );
7720         pr "    %s = r;\n" name;
7721         pr "  }\n";
7722       in
7723
7724       iteri (
7725         fun i ->
7726           function
7727           | Device name
7728           | String name ->
7729               pr "  %s = argv[%d];\n" name i
7730           | Pathname name
7731           | Dev_or_Path name ->
7732               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7733               pr "  if (%s == NULL) return -1;\n" name
7734           | OptString name ->
7735               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7736                 name i i
7737           | BufferIn name ->
7738               pr "  %s = argv[%d];\n" name i;
7739               pr "  %s_size = strlen (argv[%d]);\n" name i
7740           | FileIn name ->
7741               pr "  %s = file_in (argv[%d]);\n" name i;
7742               pr "  if (%s == NULL) return -1;\n" name
7743           | FileOut name ->
7744               pr "  %s = file_out (argv[%d]);\n" name i;
7745               pr "  if (%s == NULL) return -1;\n" name
7746           | StringList name | DeviceList name ->
7747               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7748               pr "  if (%s == NULL) return -1;\n" name;
7749           | Bool name ->
7750               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7751           | Int name ->
7752               let range =
7753                 let min = "(-(2LL<<30))"
7754                 and max = "((2LL<<30)-1)"
7755                 and comment =
7756                   "The Int type in the generator is a signed 31 bit int." in
7757                 Some (min, max, comment) in
7758               parse_integer "xstrtoll" "long long" "int" range name i
7759           | Int64 name ->
7760               parse_integer "xstrtoll" "long long" "int64_t" None name i
7761       ) (snd style);
7762
7763       (* Call C API function. *)
7764       pr "  r = guestfs_%s " name;
7765       generate_c_call_args ~handle:"g" style;
7766       pr ";\n";
7767
7768       List.iter (
7769         function
7770         | Device name | String name
7771         | OptString name | Bool name
7772         | Int name | Int64 name
7773         | BufferIn name -> ()
7774         | Pathname name | Dev_or_Path name | FileOut name ->
7775             pr "  free (%s);\n" name
7776         | FileIn name ->
7777             pr "  free_file_in (%s);\n" name
7778         | StringList name | DeviceList name ->
7779             pr "  free_strings (%s);\n" name
7780       ) (snd style);
7781
7782       (* Any output flags? *)
7783       let fish_output =
7784         let flags = filter_map (
7785           function FishOutput flag -> Some flag | _ -> None
7786         ) flags in
7787         match flags with
7788         | [] -> None
7789         | [f] -> Some f
7790         | _ ->
7791             failwithf "%s: more than one FishOutput flag is not allowed" name in
7792
7793       (* Check return value for errors and display command results. *)
7794       (match fst style with
7795        | RErr -> pr "  return r;\n"
7796        | RInt _ ->
7797            pr "  if (r == -1) return -1;\n";
7798            (match fish_output with
7799             | None ->
7800                 pr "  printf (\"%%d\\n\", r);\n";
7801             | Some FishOutputOctal ->
7802                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7803             | Some FishOutputHexadecimal ->
7804                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7805            pr "  return 0;\n"
7806        | RInt64 _ ->
7807            pr "  if (r == -1) return -1;\n";
7808            (match fish_output with
7809             | None ->
7810                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7811             | Some FishOutputOctal ->
7812                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7813             | Some FishOutputHexadecimal ->
7814                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7815            pr "  return 0;\n"
7816        | RBool _ ->
7817            pr "  if (r == -1) return -1;\n";
7818            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7819            pr "  return 0;\n"
7820        | RConstString _ ->
7821            pr "  if (r == NULL) return -1;\n";
7822            pr "  printf (\"%%s\\n\", r);\n";
7823            pr "  return 0;\n"
7824        | RConstOptString _ ->
7825            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7826            pr "  return 0;\n"
7827        | RString _ ->
7828            pr "  if (r == NULL) return -1;\n";
7829            pr "  printf (\"%%s\\n\", r);\n";
7830            pr "  free (r);\n";
7831            pr "  return 0;\n"
7832        | RStringList _ ->
7833            pr "  if (r == NULL) return -1;\n";
7834            pr "  print_strings (r);\n";
7835            pr "  free_strings (r);\n";
7836            pr "  return 0;\n"
7837        | RStruct (_, typ) ->
7838            pr "  if (r == NULL) return -1;\n";
7839            pr "  print_%s (r);\n" typ;
7840            pr "  guestfs_free_%s (r);\n" typ;
7841            pr "  return 0;\n"
7842        | RStructList (_, typ) ->
7843            pr "  if (r == NULL) return -1;\n";
7844            pr "  print_%s_list (r);\n" typ;
7845            pr "  guestfs_free_%s_list (r);\n" typ;
7846            pr "  return 0;\n"
7847        | RHashtable _ ->
7848            pr "  if (r == NULL) return -1;\n";
7849            pr "  print_table (r);\n";
7850            pr "  free_strings (r);\n";
7851            pr "  return 0;\n"
7852        | RBufferOut _ ->
7853            pr "  if (r == NULL) return -1;\n";
7854            pr "  if (full_write (1, r, size) != size) {\n";
7855            pr "    perror (\"write\");\n";
7856            pr "    free (r);\n";
7857            pr "    return -1;\n";
7858            pr "  }\n";
7859            pr "  free (r);\n";
7860            pr "  return 0;\n"
7861       );
7862       pr "}\n";
7863       pr "\n"
7864   ) all_functions;
7865
7866   (* run_action function *)
7867   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7868   pr "{\n";
7869   List.iter (
7870     fun (name, _, _, flags, _, _, _) ->
7871       let name2 = replace_char name '_' '-' in
7872       let alias =
7873         try find_map (function FishAlias n -> Some n | _ -> None) flags
7874         with Not_found -> name in
7875       pr "  if (";
7876       pr "STRCASEEQ (cmd, \"%s\")" name;
7877       if name <> name2 then
7878         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7879       if name <> alias then
7880         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7881       pr ")\n";
7882       pr "    return run_%s (cmd, argc, argv);\n" name;
7883       pr "  else\n";
7884   ) all_functions;
7885   pr "    {\n";
7886   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7887   pr "      if (command_num == 1)\n";
7888   pr "        extended_help_message ();\n";
7889   pr "      return -1;\n";
7890   pr "    }\n";
7891   pr "  return 0;\n";
7892   pr "}\n";
7893   pr "\n"
7894
7895 (* Readline completion for guestfish. *)
7896 and generate_fish_completion () =
7897   generate_header CStyle GPLv2plus;
7898
7899   let all_functions =
7900     List.filter (
7901       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7902     ) all_functions in
7903
7904   pr "\
7905 #include <config.h>
7906
7907 #include <stdio.h>
7908 #include <stdlib.h>
7909 #include <string.h>
7910
7911 #ifdef HAVE_LIBREADLINE
7912 #include <readline/readline.h>
7913 #endif
7914
7915 #include \"fish.h\"
7916
7917 #ifdef HAVE_LIBREADLINE
7918
7919 static const char *const commands[] = {
7920   BUILTIN_COMMANDS_FOR_COMPLETION,
7921 ";
7922
7923   (* Get the commands, including the aliases.  They don't need to be
7924    * sorted - the generator() function just does a dumb linear search.
7925    *)
7926   let commands =
7927     List.map (
7928       fun (name, _, _, flags, _, _, _) ->
7929         let name2 = replace_char name '_' '-' in
7930         let alias =
7931           try find_map (function FishAlias n -> Some n | _ -> None) flags
7932           with Not_found -> name in
7933
7934         if name <> alias then [name2; alias] else [name2]
7935     ) all_functions in
7936   let commands = List.flatten commands in
7937
7938   List.iter (pr "  \"%s\",\n") commands;
7939
7940   pr "  NULL
7941 };
7942
7943 static char *
7944 generator (const char *text, int state)
7945 {
7946   static int index, len;
7947   const char *name;
7948
7949   if (!state) {
7950     index = 0;
7951     len = strlen (text);
7952   }
7953
7954   rl_attempted_completion_over = 1;
7955
7956   while ((name = commands[index]) != NULL) {
7957     index++;
7958     if (STRCASEEQLEN (name, text, len))
7959       return strdup (name);
7960   }
7961
7962   return NULL;
7963 }
7964
7965 #endif /* HAVE_LIBREADLINE */
7966
7967 #ifdef HAVE_RL_COMPLETION_MATCHES
7968 #define RL_COMPLETION_MATCHES rl_completion_matches
7969 #else
7970 #ifdef HAVE_COMPLETION_MATCHES
7971 #define RL_COMPLETION_MATCHES completion_matches
7972 #endif
7973 #endif /* else just fail if we don't have either symbol */
7974
7975 char **
7976 do_completion (const char *text, int start, int end)
7977 {
7978   char **matches = NULL;
7979
7980 #ifdef HAVE_LIBREADLINE
7981   rl_completion_append_character = ' ';
7982
7983   if (start == 0)
7984     matches = RL_COMPLETION_MATCHES (text, generator);
7985   else if (complete_dest_paths)
7986     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7987 #endif
7988
7989   return matches;
7990 }
7991 ";
7992
7993 (* Generate the POD documentation for guestfish. *)
7994 and generate_fish_actions_pod () =
7995   let all_functions_sorted =
7996     List.filter (
7997       fun (_, _, _, flags, _, _, _) ->
7998         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7999     ) all_functions_sorted in
8000
8001   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8002
8003   List.iter (
8004     fun (name, style, _, flags, _, _, longdesc) ->
8005       let longdesc =
8006         Str.global_substitute rex (
8007           fun s ->
8008             let sub =
8009               try Str.matched_group 1 s
8010               with Not_found ->
8011                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8012             "C<" ^ replace_char sub '_' '-' ^ ">"
8013         ) longdesc in
8014       let name = replace_char name '_' '-' in
8015       let alias =
8016         try find_map (function FishAlias n -> Some n | _ -> None) flags
8017         with Not_found -> name in
8018
8019       pr "=head2 %s" name;
8020       if name <> alias then
8021         pr " | %s" alias;
8022       pr "\n";
8023       pr "\n";
8024       pr " %s" name;
8025       List.iter (
8026         function
8027         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8028         | OptString n -> pr " %s" n
8029         | StringList n | DeviceList n -> pr " '%s ...'" n
8030         | Bool _ -> pr " true|false"
8031         | Int n -> pr " %s" n
8032         | Int64 n -> pr " %s" n
8033         | FileIn n | FileOut n -> pr " (%s|-)" n
8034         | BufferIn n -> pr " %s" n
8035       ) (snd style);
8036       pr "\n";
8037       pr "\n";
8038       pr "%s\n\n" longdesc;
8039
8040       if List.exists (function FileIn _ | FileOut _ -> true
8041                       | _ -> false) (snd style) then
8042         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8043
8044       if List.mem ProtocolLimitWarning flags then
8045         pr "%s\n\n" protocol_limit_warning;
8046
8047       if List.mem DangerWillRobinson flags then
8048         pr "%s\n\n" danger_will_robinson;
8049
8050       match deprecation_notice flags with
8051       | None -> ()
8052       | Some txt -> pr "%s\n\n" txt
8053   ) all_functions_sorted
8054
8055 (* Generate a C function prototype. *)
8056 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8057     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8058     ?(prefix = "")
8059     ?handle name style =
8060   if extern then pr "extern ";
8061   if static then pr "static ";
8062   (match fst style with
8063    | RErr -> pr "int "
8064    | RInt _ -> pr "int "
8065    | RInt64 _ -> pr "int64_t "
8066    | RBool _ -> pr "int "
8067    | RConstString _ | RConstOptString _ -> pr "const char *"
8068    | RString _ | RBufferOut _ -> pr "char *"
8069    | RStringList _ | RHashtable _ -> pr "char **"
8070    | RStruct (_, typ) ->
8071        if not in_daemon then pr "struct guestfs_%s *" typ
8072        else pr "guestfs_int_%s *" typ
8073    | RStructList (_, typ) ->
8074        if not in_daemon then pr "struct guestfs_%s_list *" typ
8075        else pr "guestfs_int_%s_list *" typ
8076   );
8077   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8078   pr "%s%s (" prefix name;
8079   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8080     pr "void"
8081   else (
8082     let comma = ref false in
8083     (match handle with
8084      | None -> ()
8085      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8086     );
8087     let next () =
8088       if !comma then (
8089         if single_line then pr ", " else pr ",\n\t\t"
8090       );
8091       comma := true
8092     in
8093     List.iter (
8094       function
8095       | Pathname n
8096       | Device n | Dev_or_Path n
8097       | String n
8098       | OptString n ->
8099           next ();
8100           pr "const char *%s" n
8101       | StringList n | DeviceList n ->
8102           next ();
8103           pr "char *const *%s" n
8104       | Bool n -> next (); pr "int %s" n
8105       | Int n -> next (); pr "int %s" n
8106       | Int64 n -> next (); pr "int64_t %s" n
8107       | FileIn n
8108       | FileOut n ->
8109           if not in_daemon then (next (); pr "const char *%s" n)
8110       | BufferIn n ->
8111           next ();
8112           pr "const char *%s" n;
8113           next ();
8114           pr "size_t %s_size" n
8115     ) (snd style);
8116     if is_RBufferOut then (next (); pr "size_t *size_r");
8117   );
8118   pr ")";
8119   if semicolon then pr ";";
8120   if newline then pr "\n"
8121
8122 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8123 and generate_c_call_args ?handle ?(decl = false) style =
8124   pr "(";
8125   let comma = ref false in
8126   let next () =
8127     if !comma then pr ", ";
8128     comma := true
8129   in
8130   (match handle with
8131    | None -> ()
8132    | Some handle -> pr "%s" handle; comma := true
8133   );
8134   List.iter (
8135     function
8136     | BufferIn n ->
8137         next ();
8138         pr "%s, %s_size" n n
8139     | arg ->
8140         next ();
8141         pr "%s" (name_of_argt arg)
8142   ) (snd style);
8143   (* For RBufferOut calls, add implicit &size parameter. *)
8144   if not decl then (
8145     match fst style with
8146     | RBufferOut _ ->
8147         next ();
8148         pr "&size"
8149     | _ -> ()
8150   );
8151   pr ")"
8152
8153 (* Generate the OCaml bindings interface. *)
8154 and generate_ocaml_mli () =
8155   generate_header OCamlStyle LGPLv2plus;
8156
8157   pr "\
8158 (** For API documentation you should refer to the C API
8159     in the guestfs(3) manual page.  The OCaml API uses almost
8160     exactly the same calls. *)
8161
8162 type t
8163 (** A [guestfs_h] handle. *)
8164
8165 exception Error of string
8166 (** This exception is raised when there is an error. *)
8167
8168 exception Handle_closed of string
8169 (** This exception is raised if you use a {!Guestfs.t} handle
8170     after calling {!close} on it.  The string is the name of
8171     the function. *)
8172
8173 val create : unit -> t
8174 (** Create a {!Guestfs.t} handle. *)
8175
8176 val close : t -> unit
8177 (** Close the {!Guestfs.t} handle and free up all resources used
8178     by it immediately.
8179
8180     Handles are closed by the garbage collector when they become
8181     unreferenced, but callers can call this in order to provide
8182     predictable cleanup. *)
8183
8184 ";
8185   generate_ocaml_structure_decls ();
8186
8187   (* The actions. *)
8188   List.iter (
8189     fun (name, style, _, _, _, shortdesc, _) ->
8190       generate_ocaml_prototype name style;
8191       pr "(** %s *)\n" shortdesc;
8192       pr "\n"
8193   ) all_functions_sorted
8194
8195 (* Generate the OCaml bindings implementation. *)
8196 and generate_ocaml_ml () =
8197   generate_header OCamlStyle LGPLv2plus;
8198
8199   pr "\
8200 type t
8201
8202 exception Error of string
8203 exception Handle_closed of string
8204
8205 external create : unit -> t = \"ocaml_guestfs_create\"
8206 external close : t -> unit = \"ocaml_guestfs_close\"
8207
8208 (* Give the exceptions names, so they can be raised from the C code. *)
8209 let () =
8210   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8211   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8212
8213 ";
8214
8215   generate_ocaml_structure_decls ();
8216
8217   (* The actions. *)
8218   List.iter (
8219     fun (name, style, _, _, _, shortdesc, _) ->
8220       generate_ocaml_prototype ~is_external:true name style;
8221   ) all_functions_sorted
8222
8223 (* Generate the OCaml bindings C implementation. *)
8224 and generate_ocaml_c () =
8225   generate_header CStyle LGPLv2plus;
8226
8227   pr "\
8228 #include <stdio.h>
8229 #include <stdlib.h>
8230 #include <string.h>
8231
8232 #include <caml/config.h>
8233 #include <caml/alloc.h>
8234 #include <caml/callback.h>
8235 #include <caml/fail.h>
8236 #include <caml/memory.h>
8237 #include <caml/mlvalues.h>
8238 #include <caml/signals.h>
8239
8240 #include <guestfs.h>
8241
8242 #include \"guestfs_c.h\"
8243
8244 /* Copy a hashtable of string pairs into an assoc-list.  We return
8245  * the list in reverse order, but hashtables aren't supposed to be
8246  * ordered anyway.
8247  */
8248 static CAMLprim value
8249 copy_table (char * const * argv)
8250 {
8251   CAMLparam0 ();
8252   CAMLlocal5 (rv, pairv, kv, vv, cons);
8253   int i;
8254
8255   rv = Val_int (0);
8256   for (i = 0; argv[i] != NULL; i += 2) {
8257     kv = caml_copy_string (argv[i]);
8258     vv = caml_copy_string (argv[i+1]);
8259     pairv = caml_alloc (2, 0);
8260     Store_field (pairv, 0, kv);
8261     Store_field (pairv, 1, vv);
8262     cons = caml_alloc (2, 0);
8263     Store_field (cons, 1, rv);
8264     rv = cons;
8265     Store_field (cons, 0, pairv);
8266   }
8267
8268   CAMLreturn (rv);
8269 }
8270
8271 ";
8272
8273   (* Struct copy functions. *)
8274
8275   let emit_ocaml_copy_list_function typ =
8276     pr "static CAMLprim value\n";
8277     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8278     pr "{\n";
8279     pr "  CAMLparam0 ();\n";
8280     pr "  CAMLlocal2 (rv, v);\n";
8281     pr "  unsigned int i;\n";
8282     pr "\n";
8283     pr "  if (%ss->len == 0)\n" typ;
8284     pr "    CAMLreturn (Atom (0));\n";
8285     pr "  else {\n";
8286     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8287     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8288     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8289     pr "      caml_modify (&Field (rv, i), v);\n";
8290     pr "    }\n";
8291     pr "    CAMLreturn (rv);\n";
8292     pr "  }\n";
8293     pr "}\n";
8294     pr "\n";
8295   in
8296
8297   List.iter (
8298     fun (typ, cols) ->
8299       let has_optpercent_col =
8300         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8301
8302       pr "static CAMLprim value\n";
8303       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8304       pr "{\n";
8305       pr "  CAMLparam0 ();\n";
8306       if has_optpercent_col then
8307         pr "  CAMLlocal3 (rv, v, v2);\n"
8308       else
8309         pr "  CAMLlocal2 (rv, v);\n";
8310       pr "\n";
8311       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8312       iteri (
8313         fun i col ->
8314           (match col with
8315            | name, FString ->
8316                pr "  v = caml_copy_string (%s->%s);\n" typ name
8317            | name, FBuffer ->
8318                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8319                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8320                  typ name typ name
8321            | name, FUUID ->
8322                pr "  v = caml_alloc_string (32);\n";
8323                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8324            | name, (FBytes|FInt64|FUInt64) ->
8325                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8326            | name, (FInt32|FUInt32) ->
8327                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8328            | name, FOptPercent ->
8329                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8330                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8331                pr "    v = caml_alloc (1, 0);\n";
8332                pr "    Store_field (v, 0, v2);\n";
8333                pr "  } else /* None */\n";
8334                pr "    v = Val_int (0);\n";
8335            | name, FChar ->
8336                pr "  v = Val_int (%s->%s);\n" typ name
8337           );
8338           pr "  Store_field (rv, %d, v);\n" i
8339       ) cols;
8340       pr "  CAMLreturn (rv);\n";
8341       pr "}\n";
8342       pr "\n";
8343   ) structs;
8344
8345   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8346   List.iter (
8347     function
8348     | typ, (RStructListOnly | RStructAndList) ->
8349         (* generate the function for typ *)
8350         emit_ocaml_copy_list_function typ
8351     | typ, _ -> () (* empty *)
8352   ) (rstructs_used_by all_functions);
8353
8354   (* The wrappers. *)
8355   List.iter (
8356     fun (name, style, _, _, _, _, _) ->
8357       pr "/* Automatically generated wrapper for function\n";
8358       pr " * ";
8359       generate_ocaml_prototype name style;
8360       pr " */\n";
8361       pr "\n";
8362
8363       let params =
8364         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8365
8366       let needs_extra_vs =
8367         match fst style with RConstOptString _ -> true | _ -> false in
8368
8369       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8370       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8371       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8372       pr "\n";
8373
8374       pr "CAMLprim value\n";
8375       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8376       List.iter (pr ", value %s") (List.tl params);
8377       pr ")\n";
8378       pr "{\n";
8379
8380       (match params with
8381        | [p1; p2; p3; p4; p5] ->
8382            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8383        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8384            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8385            pr "  CAMLxparam%d (%s);\n"
8386              (List.length rest) (String.concat ", " rest)
8387        | ps ->
8388            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8389       );
8390       if not needs_extra_vs then
8391         pr "  CAMLlocal1 (rv);\n"
8392       else
8393         pr "  CAMLlocal3 (rv, v, v2);\n";
8394       pr "\n";
8395
8396       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8397       pr "  if (g == NULL)\n";
8398       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8399       pr "\n";
8400
8401       List.iter (
8402         function
8403         | Pathname n
8404         | Device n | Dev_or_Path n
8405         | String n
8406         | FileIn n
8407         | FileOut n ->
8408             pr "  const char *%s = String_val (%sv);\n" n n
8409         | OptString n ->
8410             pr "  const char *%s =\n" n;
8411             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8412               n n
8413         | BufferIn n ->
8414             pr "  const char *%s = String_val (%sv);\n" n n;
8415             pr "  size_t %s_size = caml_string_length (%sv);\n" n n
8416         | StringList n | DeviceList n ->
8417             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8418         | Bool n ->
8419             pr "  int %s = Bool_val (%sv);\n" n n
8420         | Int n ->
8421             pr "  int %s = Int_val (%sv);\n" n n
8422         | Int64 n ->
8423             pr "  int64_t %s = Int64_val (%sv);\n" n n
8424       ) (snd style);
8425       let error_code =
8426         match fst style with
8427         | RErr -> pr "  int r;\n"; "-1"
8428         | RInt _ -> pr "  int r;\n"; "-1"
8429         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8430         | RBool _ -> pr "  int r;\n"; "-1"
8431         | RConstString _ | RConstOptString _ ->
8432             pr "  const char *r;\n"; "NULL"
8433         | RString _ -> pr "  char *r;\n"; "NULL"
8434         | RStringList _ ->
8435             pr "  int i;\n";
8436             pr "  char **r;\n";
8437             "NULL"
8438         | RStruct (_, typ) ->
8439             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8440         | RStructList (_, typ) ->
8441             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8442         | RHashtable _ ->
8443             pr "  int i;\n";
8444             pr "  char **r;\n";
8445             "NULL"
8446         | RBufferOut _ ->
8447             pr "  char *r;\n";
8448             pr "  size_t size;\n";
8449             "NULL" in
8450       pr "\n";
8451
8452       pr "  caml_enter_blocking_section ();\n";
8453       pr "  r = guestfs_%s " name;
8454       generate_c_call_args ~handle:"g" style;
8455       pr ";\n";
8456       pr "  caml_leave_blocking_section ();\n";
8457
8458       List.iter (
8459         function
8460         | StringList n | DeviceList n ->
8461             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8462         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8463         | Bool _ | Int _ | Int64 _
8464         | FileIn _ | FileOut _ | BufferIn _ -> ()
8465       ) (snd style);
8466
8467       pr "  if (r == %s)\n" error_code;
8468       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8469       pr "\n";
8470
8471       (match fst style with
8472        | RErr -> pr "  rv = Val_unit;\n"
8473        | RInt _ -> pr "  rv = Val_int (r);\n"
8474        | RInt64 _ ->
8475            pr "  rv = caml_copy_int64 (r);\n"
8476        | RBool _ -> pr "  rv = Val_bool (r);\n"
8477        | RConstString _ ->
8478            pr "  rv = caml_copy_string (r);\n"
8479        | RConstOptString _ ->
8480            pr "  if (r) { /* Some string */\n";
8481            pr "    v = caml_alloc (1, 0);\n";
8482            pr "    v2 = caml_copy_string (r);\n";
8483            pr "    Store_field (v, 0, v2);\n";
8484            pr "  } else /* None */\n";
8485            pr "    v = Val_int (0);\n";
8486        | RString _ ->
8487            pr "  rv = caml_copy_string (r);\n";
8488            pr "  free (r);\n"
8489        | RStringList _ ->
8490            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8491            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8492            pr "  free (r);\n"
8493        | RStruct (_, typ) ->
8494            pr "  rv = copy_%s (r);\n" typ;
8495            pr "  guestfs_free_%s (r);\n" typ;
8496        | RStructList (_, typ) ->
8497            pr "  rv = copy_%s_list (r);\n" typ;
8498            pr "  guestfs_free_%s_list (r);\n" typ;
8499        | RHashtable _ ->
8500            pr "  rv = copy_table (r);\n";
8501            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8502            pr "  free (r);\n";
8503        | RBufferOut _ ->
8504            pr "  rv = caml_alloc_string (size);\n";
8505            pr "  memcpy (String_val (rv), r, size);\n";
8506       );
8507
8508       pr "  CAMLreturn (rv);\n";
8509       pr "}\n";
8510       pr "\n";
8511
8512       if List.length params > 5 then (
8513         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8514         pr "CAMLprim value ";
8515         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8516         pr "CAMLprim value\n";
8517         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8518         pr "{\n";
8519         pr "  return ocaml_guestfs_%s (argv[0]" name;
8520         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8521         pr ");\n";
8522         pr "}\n";
8523         pr "\n"
8524       )
8525   ) all_functions_sorted
8526
8527 and generate_ocaml_structure_decls () =
8528   List.iter (
8529     fun (typ, cols) ->
8530       pr "type %s = {\n" typ;
8531       List.iter (
8532         function
8533         | name, FString -> pr "  %s : string;\n" name
8534         | name, FBuffer -> pr "  %s : string;\n" name
8535         | name, FUUID -> pr "  %s : string;\n" name
8536         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8537         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8538         | name, FChar -> pr "  %s : char;\n" name
8539         | name, FOptPercent -> pr "  %s : float option;\n" name
8540       ) cols;
8541       pr "}\n";
8542       pr "\n"
8543   ) structs
8544
8545 and generate_ocaml_prototype ?(is_external = false) name style =
8546   if is_external then pr "external " else pr "val ";
8547   pr "%s : t -> " name;
8548   List.iter (
8549     function
8550     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8551     | BufferIn _ -> pr "string -> "
8552     | OptString _ -> pr "string option -> "
8553     | StringList _ | DeviceList _ -> pr "string array -> "
8554     | Bool _ -> pr "bool -> "
8555     | Int _ -> pr "int -> "
8556     | Int64 _ -> pr "int64 -> "
8557   ) (snd style);
8558   (match fst style with
8559    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8560    | RInt _ -> pr "int"
8561    | RInt64 _ -> pr "int64"
8562    | RBool _ -> pr "bool"
8563    | RConstString _ -> pr "string"
8564    | RConstOptString _ -> pr "string option"
8565    | RString _ | RBufferOut _ -> pr "string"
8566    | RStringList _ -> pr "string array"
8567    | RStruct (_, typ) -> pr "%s" typ
8568    | RStructList (_, typ) -> pr "%s array" typ
8569    | RHashtable _ -> pr "(string * string) list"
8570   );
8571   if is_external then (
8572     pr " = ";
8573     if List.length (snd style) + 1 > 5 then
8574       pr "\"ocaml_guestfs_%s_byte\" " name;
8575     pr "\"ocaml_guestfs_%s\"" name
8576   );
8577   pr "\n"
8578
8579 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8580 and generate_perl_xs () =
8581   generate_header CStyle LGPLv2plus;
8582
8583   pr "\
8584 #include \"EXTERN.h\"
8585 #include \"perl.h\"
8586 #include \"XSUB.h\"
8587
8588 #include <guestfs.h>
8589
8590 #ifndef PRId64
8591 #define PRId64 \"lld\"
8592 #endif
8593
8594 static SV *
8595 my_newSVll(long long val) {
8596 #ifdef USE_64_BIT_ALL
8597   return newSViv(val);
8598 #else
8599   char buf[100];
8600   int len;
8601   len = snprintf(buf, 100, \"%%\" PRId64, val);
8602   return newSVpv(buf, len);
8603 #endif
8604 }
8605
8606 #ifndef PRIu64
8607 #define PRIu64 \"llu\"
8608 #endif
8609
8610 static SV *
8611 my_newSVull(unsigned long long val) {
8612 #ifdef USE_64_BIT_ALL
8613   return newSVuv(val);
8614 #else
8615   char buf[100];
8616   int len;
8617   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8618   return newSVpv(buf, len);
8619 #endif
8620 }
8621
8622 /* http://www.perlmonks.org/?node_id=680842 */
8623 static char **
8624 XS_unpack_charPtrPtr (SV *arg) {
8625   char **ret;
8626   AV *av;
8627   I32 i;
8628
8629   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8630     croak (\"array reference expected\");
8631
8632   av = (AV *)SvRV (arg);
8633   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8634   if (!ret)
8635     croak (\"malloc failed\");
8636
8637   for (i = 0; i <= av_len (av); i++) {
8638     SV **elem = av_fetch (av, i, 0);
8639
8640     if (!elem || !*elem)
8641       croak (\"missing element in list\");
8642
8643     ret[i] = SvPV_nolen (*elem);
8644   }
8645
8646   ret[i] = NULL;
8647
8648   return ret;
8649 }
8650
8651 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8652
8653 PROTOTYPES: ENABLE
8654
8655 guestfs_h *
8656 _create ()
8657    CODE:
8658       RETVAL = guestfs_create ();
8659       if (!RETVAL)
8660         croak (\"could not create guestfs handle\");
8661       guestfs_set_error_handler (RETVAL, NULL, NULL);
8662  OUTPUT:
8663       RETVAL
8664
8665 void
8666 DESTROY (g)
8667       guestfs_h *g;
8668  PPCODE:
8669       guestfs_close (g);
8670
8671 ";
8672
8673   List.iter (
8674     fun (name, style, _, _, _, _, _) ->
8675       (match fst style with
8676        | RErr -> pr "void\n"
8677        | RInt _ -> pr "SV *\n"
8678        | RInt64 _ -> pr "SV *\n"
8679        | RBool _ -> pr "SV *\n"
8680        | RConstString _ -> pr "SV *\n"
8681        | RConstOptString _ -> pr "SV *\n"
8682        | RString _ -> pr "SV *\n"
8683        | RBufferOut _ -> pr "SV *\n"
8684        | RStringList _
8685        | RStruct _ | RStructList _
8686        | RHashtable _ ->
8687            pr "void\n" (* all lists returned implictly on the stack *)
8688       );
8689       (* Call and arguments. *)
8690       pr "%s (g" name;
8691       List.iter (
8692         fun arg -> pr ", %s" (name_of_argt arg)
8693       ) (snd style);
8694       pr ")\n";
8695       pr "      guestfs_h *g;\n";
8696       iteri (
8697         fun i ->
8698           function
8699           | Pathname n | Device n | Dev_or_Path n | String n
8700           | FileIn n | FileOut n ->
8701               pr "      char *%s;\n" n
8702           | BufferIn n ->
8703               pr "      char *%s;\n" n;
8704               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8705           | OptString n ->
8706               (* http://www.perlmonks.org/?node_id=554277
8707                * Note that the implicit handle argument means we have
8708                * to add 1 to the ST(x) operator.
8709                *)
8710               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8711           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8712           | Bool n -> pr "      int %s;\n" n
8713           | Int n -> pr "      int %s;\n" n
8714           | Int64 n -> pr "      int64_t %s;\n" n
8715       ) (snd style);
8716
8717       let do_cleanups () =
8718         List.iter (
8719           function
8720           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8721           | Bool _ | Int _ | Int64 _
8722           | FileIn _ | FileOut _
8723           | BufferIn _ -> ()
8724           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8725         ) (snd style)
8726       in
8727
8728       (* Code. *)
8729       (match fst style with
8730        | RErr ->
8731            pr "PREINIT:\n";
8732            pr "      int r;\n";
8733            pr " PPCODE:\n";
8734            pr "      r = guestfs_%s " name;
8735            generate_c_call_args ~handle:"g" style;
8736            pr ";\n";
8737            do_cleanups ();
8738            pr "      if (r == -1)\n";
8739            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8740        | RInt n
8741        | RBool n ->
8742            pr "PREINIT:\n";
8743            pr "      int %s;\n" n;
8744            pr "   CODE:\n";
8745            pr "      %s = guestfs_%s " n name;
8746            generate_c_call_args ~handle:"g" style;
8747            pr ";\n";
8748            do_cleanups ();
8749            pr "      if (%s == -1)\n" n;
8750            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8751            pr "      RETVAL = newSViv (%s);\n" n;
8752            pr " OUTPUT:\n";
8753            pr "      RETVAL\n"
8754        | RInt64 n ->
8755            pr "PREINIT:\n";
8756            pr "      int64_t %s;\n" n;
8757            pr "   CODE:\n";
8758            pr "      %s = guestfs_%s " n name;
8759            generate_c_call_args ~handle:"g" style;
8760            pr ";\n";
8761            do_cleanups ();
8762            pr "      if (%s == -1)\n" n;
8763            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8764            pr "      RETVAL = my_newSVll (%s);\n" n;
8765            pr " OUTPUT:\n";
8766            pr "      RETVAL\n"
8767        | RConstString n ->
8768            pr "PREINIT:\n";
8769            pr "      const char *%s;\n" n;
8770            pr "   CODE:\n";
8771            pr "      %s = guestfs_%s " n name;
8772            generate_c_call_args ~handle:"g" style;
8773            pr ";\n";
8774            do_cleanups ();
8775            pr "      if (%s == NULL)\n" n;
8776            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8777            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8778            pr " OUTPUT:\n";
8779            pr "      RETVAL\n"
8780        | RConstOptString n ->
8781            pr "PREINIT:\n";
8782            pr "      const char *%s;\n" n;
8783            pr "   CODE:\n";
8784            pr "      %s = guestfs_%s " n name;
8785            generate_c_call_args ~handle:"g" style;
8786            pr ";\n";
8787            do_cleanups ();
8788            pr "      if (%s == NULL)\n" n;
8789            pr "        RETVAL = &PL_sv_undef;\n";
8790            pr "      else\n";
8791            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8792            pr " OUTPUT:\n";
8793            pr "      RETVAL\n"
8794        | RString n ->
8795            pr "PREINIT:\n";
8796            pr "      char *%s;\n" n;
8797            pr "   CODE:\n";
8798            pr "      %s = guestfs_%s " n name;
8799            generate_c_call_args ~handle:"g" style;
8800            pr ";\n";
8801            do_cleanups ();
8802            pr "      if (%s == NULL)\n" n;
8803            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8804            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8805            pr "      free (%s);\n" n;
8806            pr " OUTPUT:\n";
8807            pr "      RETVAL\n"
8808        | RStringList n | RHashtable n ->
8809            pr "PREINIT:\n";
8810            pr "      char **%s;\n" n;
8811            pr "      int i, n;\n";
8812            pr " PPCODE:\n";
8813            pr "      %s = guestfs_%s " n name;
8814            generate_c_call_args ~handle:"g" style;
8815            pr ";\n";
8816            do_cleanups ();
8817            pr "      if (%s == NULL)\n" n;
8818            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8819            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8820            pr "      EXTEND (SP, n);\n";
8821            pr "      for (i = 0; i < n; ++i) {\n";
8822            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8823            pr "        free (%s[i]);\n" n;
8824            pr "      }\n";
8825            pr "      free (%s);\n" n;
8826        | RStruct (n, typ) ->
8827            let cols = cols_of_struct typ in
8828            generate_perl_struct_code typ cols name style n do_cleanups
8829        | RStructList (n, typ) ->
8830            let cols = cols_of_struct typ in
8831            generate_perl_struct_list_code typ cols name style n do_cleanups
8832        | RBufferOut n ->
8833            pr "PREINIT:\n";
8834            pr "      char *%s;\n" n;
8835            pr "      size_t size;\n";
8836            pr "   CODE:\n";
8837            pr "      %s = guestfs_%s " n name;
8838            generate_c_call_args ~handle:"g" style;
8839            pr ";\n";
8840            do_cleanups ();
8841            pr "      if (%s == NULL)\n" n;
8842            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8843            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8844            pr "      free (%s);\n" n;
8845            pr " OUTPUT:\n";
8846            pr "      RETVAL\n"
8847       );
8848
8849       pr "\n"
8850   ) all_functions
8851
8852 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8853   pr "PREINIT:\n";
8854   pr "      struct guestfs_%s_list *%s;\n" typ n;
8855   pr "      int i;\n";
8856   pr "      HV *hv;\n";
8857   pr " PPCODE:\n";
8858   pr "      %s = guestfs_%s " n name;
8859   generate_c_call_args ~handle:"g" style;
8860   pr ";\n";
8861   do_cleanups ();
8862   pr "      if (%s == NULL)\n" n;
8863   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8864   pr "      EXTEND (SP, %s->len);\n" n;
8865   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8866   pr "        hv = newHV ();\n";
8867   List.iter (
8868     function
8869     | name, FString ->
8870         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8871           name (String.length name) n name
8872     | name, FUUID ->
8873         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8874           name (String.length name) n name
8875     | name, FBuffer ->
8876         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8877           name (String.length name) n name n name
8878     | name, (FBytes|FUInt64) ->
8879         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8880           name (String.length name) n name
8881     | name, FInt64 ->
8882         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8883           name (String.length name) n name
8884     | name, (FInt32|FUInt32) ->
8885         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8886           name (String.length name) n name
8887     | name, FChar ->
8888         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8889           name (String.length name) n name
8890     | name, FOptPercent ->
8891         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8892           name (String.length name) n name
8893   ) cols;
8894   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8895   pr "      }\n";
8896   pr "      guestfs_free_%s_list (%s);\n" typ n
8897
8898 and generate_perl_struct_code typ cols name style n do_cleanups =
8899   pr "PREINIT:\n";
8900   pr "      struct guestfs_%s *%s;\n" typ n;
8901   pr " PPCODE:\n";
8902   pr "      %s = guestfs_%s " n name;
8903   generate_c_call_args ~handle:"g" style;
8904   pr ";\n";
8905   do_cleanups ();
8906   pr "      if (%s == NULL)\n" n;
8907   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8908   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8909   List.iter (
8910     fun ((name, _) as col) ->
8911       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8912
8913       match col with
8914       | name, FString ->
8915           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8916             n name
8917       | name, FBuffer ->
8918           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8919             n name n name
8920       | name, FUUID ->
8921           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8922             n name
8923       | name, (FBytes|FUInt64) ->
8924           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8925             n name
8926       | name, FInt64 ->
8927           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8928             n name
8929       | name, (FInt32|FUInt32) ->
8930           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8931             n name
8932       | name, FChar ->
8933           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8934             n name
8935       | name, FOptPercent ->
8936           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8937             n name
8938   ) cols;
8939   pr "      free (%s);\n" n
8940
8941 (* Generate Sys/Guestfs.pm. *)
8942 and generate_perl_pm () =
8943   generate_header HashStyle LGPLv2plus;
8944
8945   pr "\
8946 =pod
8947
8948 =head1 NAME
8949
8950 Sys::Guestfs - Perl bindings for libguestfs
8951
8952 =head1 SYNOPSIS
8953
8954  use Sys::Guestfs;
8955
8956  my $h = Sys::Guestfs->new ();
8957  $h->add_drive ('guest.img');
8958  $h->launch ();
8959  $h->mount ('/dev/sda1', '/');
8960  $h->touch ('/hello');
8961  $h->sync ();
8962
8963 =head1 DESCRIPTION
8964
8965 The C<Sys::Guestfs> module provides a Perl XS binding to the
8966 libguestfs API for examining and modifying virtual machine
8967 disk images.
8968
8969 Amongst the things this is good for: making batch configuration
8970 changes to guests, getting disk used/free statistics (see also:
8971 virt-df), migrating between virtualization systems (see also:
8972 virt-p2v), performing partial backups, performing partial guest
8973 clones, cloning guests and changing registry/UUID/hostname info, and
8974 much else besides.
8975
8976 Libguestfs uses Linux kernel and qemu code, and can access any type of
8977 guest filesystem that Linux and qemu can, including but not limited
8978 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8979 schemes, qcow, qcow2, vmdk.
8980
8981 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8982 LVs, what filesystem is in each LV, etc.).  It can also run commands
8983 in the context of the guest.  Also you can access filesystems over
8984 FUSE.
8985
8986 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8987 functions for using libguestfs from Perl, including integration
8988 with libvirt.
8989
8990 =head1 ERRORS
8991
8992 All errors turn into calls to C<croak> (see L<Carp(3)>).
8993
8994 =head1 METHODS
8995
8996 =over 4
8997
8998 =cut
8999
9000 package Sys::Guestfs;
9001
9002 use strict;
9003 use warnings;
9004
9005 # This version number changes whenever a new function
9006 # is added to the libguestfs API.  It is not directly
9007 # related to the libguestfs version number.
9008 use vars qw($VERSION);
9009 $VERSION = '0.%d';
9010
9011 require XSLoader;
9012 XSLoader::load ('Sys::Guestfs');
9013
9014 =item $h = Sys::Guestfs->new ();
9015
9016 Create a new guestfs handle.
9017
9018 =cut
9019
9020 sub new {
9021   my $proto = shift;
9022   my $class = ref ($proto) || $proto;
9023
9024   my $self = Sys::Guestfs::_create ();
9025   bless $self, $class;
9026   return $self;
9027 }
9028
9029 " max_proc_nr;
9030
9031   (* Actions.  We only need to print documentation for these as
9032    * they are pulled in from the XS code automatically.
9033    *)
9034   List.iter (
9035     fun (name, style, _, flags, _, _, longdesc) ->
9036       if not (List.mem NotInDocs flags) then (
9037         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9038         pr "=item ";
9039         generate_perl_prototype name style;
9040         pr "\n\n";
9041         pr "%s\n\n" longdesc;
9042         if List.mem ProtocolLimitWarning flags then
9043           pr "%s\n\n" protocol_limit_warning;
9044         if List.mem DangerWillRobinson flags then
9045           pr "%s\n\n" danger_will_robinson;
9046         match deprecation_notice flags with
9047         | None -> ()
9048         | Some txt -> pr "%s\n\n" txt
9049       )
9050   ) all_functions_sorted;
9051
9052   (* End of file. *)
9053   pr "\
9054 =cut
9055
9056 1;
9057
9058 =back
9059
9060 =head1 COPYRIGHT
9061
9062 Copyright (C) %s Red Hat Inc.
9063
9064 =head1 LICENSE
9065
9066 Please see the file COPYING.LIB for the full license.
9067
9068 =head1 SEE ALSO
9069
9070 L<guestfs(3)>,
9071 L<guestfish(1)>,
9072 L<http://libguestfs.org>,
9073 L<Sys::Guestfs::Lib(3)>.
9074
9075 =cut
9076 " copyright_years
9077
9078 and generate_perl_prototype name style =
9079   (match fst style with
9080    | RErr -> ()
9081    | RBool n
9082    | RInt n
9083    | RInt64 n
9084    | RConstString n
9085    | RConstOptString n
9086    | RString n
9087    | RBufferOut n -> pr "$%s = " n
9088    | RStruct (n,_)
9089    | RHashtable n -> pr "%%%s = " n
9090    | RStringList n
9091    | RStructList (n,_) -> pr "@%s = " n
9092   );
9093   pr "$h->%s (" name;
9094   let comma = ref false in
9095   List.iter (
9096     fun arg ->
9097       if !comma then pr ", ";
9098       comma := true;
9099       match arg with
9100       | Pathname n | Device n | Dev_or_Path n | String n
9101       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9102       | BufferIn n ->
9103           pr "$%s" n
9104       | StringList n | DeviceList n ->
9105           pr "\\@%s" n
9106   ) (snd style);
9107   pr ");"
9108
9109 (* Generate Python C module. *)
9110 and generate_python_c () =
9111   generate_header CStyle LGPLv2plus;
9112
9113   pr "\
9114 #define PY_SSIZE_T_CLEAN 1
9115 #include <Python.h>
9116
9117 #if PY_VERSION_HEX < 0x02050000
9118 typedef int Py_ssize_t;
9119 #define PY_SSIZE_T_MAX INT_MAX
9120 #define PY_SSIZE_T_MIN INT_MIN
9121 #endif
9122
9123 #include <stdio.h>
9124 #include <stdlib.h>
9125 #include <assert.h>
9126
9127 #include \"guestfs.h\"
9128
9129 typedef struct {
9130   PyObject_HEAD
9131   guestfs_h *g;
9132 } Pyguestfs_Object;
9133
9134 static guestfs_h *
9135 get_handle (PyObject *obj)
9136 {
9137   assert (obj);
9138   assert (obj != Py_None);
9139   return ((Pyguestfs_Object *) obj)->g;
9140 }
9141
9142 static PyObject *
9143 put_handle (guestfs_h *g)
9144 {
9145   assert (g);
9146   return
9147     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9148 }
9149
9150 /* This list should be freed (but not the strings) after use. */
9151 static char **
9152 get_string_list (PyObject *obj)
9153 {
9154   int i, len;
9155   char **r;
9156
9157   assert (obj);
9158
9159   if (!PyList_Check (obj)) {
9160     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9161     return NULL;
9162   }
9163
9164   len = PyList_Size (obj);
9165   r = malloc (sizeof (char *) * (len+1));
9166   if (r == NULL) {
9167     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9168     return NULL;
9169   }
9170
9171   for (i = 0; i < len; ++i)
9172     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9173   r[len] = NULL;
9174
9175   return r;
9176 }
9177
9178 static PyObject *
9179 put_string_list (char * const * const argv)
9180 {
9181   PyObject *list;
9182   int argc, i;
9183
9184   for (argc = 0; argv[argc] != NULL; ++argc)
9185     ;
9186
9187   list = PyList_New (argc);
9188   for (i = 0; i < argc; ++i)
9189     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9190
9191   return list;
9192 }
9193
9194 static PyObject *
9195 put_table (char * const * const argv)
9196 {
9197   PyObject *list, *item;
9198   int argc, i;
9199
9200   for (argc = 0; argv[argc] != NULL; ++argc)
9201     ;
9202
9203   list = PyList_New (argc >> 1);
9204   for (i = 0; i < argc; i += 2) {
9205     item = PyTuple_New (2);
9206     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9207     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9208     PyList_SetItem (list, i >> 1, item);
9209   }
9210
9211   return list;
9212 }
9213
9214 static void
9215 free_strings (char **argv)
9216 {
9217   int argc;
9218
9219   for (argc = 0; argv[argc] != NULL; ++argc)
9220     free (argv[argc]);
9221   free (argv);
9222 }
9223
9224 static PyObject *
9225 py_guestfs_create (PyObject *self, PyObject *args)
9226 {
9227   guestfs_h *g;
9228
9229   g = guestfs_create ();
9230   if (g == NULL) {
9231     PyErr_SetString (PyExc_RuntimeError,
9232                      \"guestfs.create: failed to allocate handle\");
9233     return NULL;
9234   }
9235   guestfs_set_error_handler (g, NULL, NULL);
9236   return put_handle (g);
9237 }
9238
9239 static PyObject *
9240 py_guestfs_close (PyObject *self, PyObject *args)
9241 {
9242   PyObject *py_g;
9243   guestfs_h *g;
9244
9245   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9246     return NULL;
9247   g = get_handle (py_g);
9248
9249   guestfs_close (g);
9250
9251   Py_INCREF (Py_None);
9252   return Py_None;
9253 }
9254
9255 ";
9256
9257   let emit_put_list_function typ =
9258     pr "static PyObject *\n";
9259     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9260     pr "{\n";
9261     pr "  PyObject *list;\n";
9262     pr "  int i;\n";
9263     pr "\n";
9264     pr "  list = PyList_New (%ss->len);\n" typ;
9265     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9266     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9267     pr "  return list;\n";
9268     pr "};\n";
9269     pr "\n"
9270   in
9271
9272   (* Structures, turned into Python dictionaries. *)
9273   List.iter (
9274     fun (typ, cols) ->
9275       pr "static PyObject *\n";
9276       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9277       pr "{\n";
9278       pr "  PyObject *dict;\n";
9279       pr "\n";
9280       pr "  dict = PyDict_New ();\n";
9281       List.iter (
9282         function
9283         | name, FString ->
9284             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9285             pr "                        PyString_FromString (%s->%s));\n"
9286               typ name
9287         | name, FBuffer ->
9288             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9289             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9290               typ name typ name
9291         | name, FUUID ->
9292             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9293             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9294               typ name
9295         | name, (FBytes|FUInt64) ->
9296             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9297             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9298               typ name
9299         | name, FInt64 ->
9300             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9301             pr "                        PyLong_FromLongLong (%s->%s));\n"
9302               typ name
9303         | name, FUInt32 ->
9304             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9305             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9306               typ name
9307         | name, FInt32 ->
9308             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9309             pr "                        PyLong_FromLong (%s->%s));\n"
9310               typ name
9311         | name, FOptPercent ->
9312             pr "  if (%s->%s >= 0)\n" typ name;
9313             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9314             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9315               typ name;
9316             pr "  else {\n";
9317             pr "    Py_INCREF (Py_None);\n";
9318             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9319             pr "  }\n"
9320         | name, FChar ->
9321             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9322             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9323       ) cols;
9324       pr "  return dict;\n";
9325       pr "};\n";
9326       pr "\n";
9327
9328   ) structs;
9329
9330   (* Emit a put_TYPE_list function definition only if that function is used. *)
9331   List.iter (
9332     function
9333     | typ, (RStructListOnly | RStructAndList) ->
9334         (* generate the function for typ *)
9335         emit_put_list_function typ
9336     | typ, _ -> () (* empty *)
9337   ) (rstructs_used_by all_functions);
9338
9339   (* Python wrapper functions. *)
9340   List.iter (
9341     fun (name, style, _, _, _, _, _) ->
9342       pr "static PyObject *\n";
9343       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9344       pr "{\n";
9345
9346       pr "  PyObject *py_g;\n";
9347       pr "  guestfs_h *g;\n";
9348       pr "  PyObject *py_r;\n";
9349
9350       let error_code =
9351         match fst style with
9352         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9353         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9354         | RConstString _ | RConstOptString _ ->
9355             pr "  const char *r;\n"; "NULL"
9356         | RString _ -> pr "  char *r;\n"; "NULL"
9357         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9358         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9359         | RStructList (_, typ) ->
9360             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9361         | RBufferOut _ ->
9362             pr "  char *r;\n";
9363             pr "  size_t size;\n";
9364             "NULL" in
9365
9366       List.iter (
9367         function
9368         | Pathname n | Device n | Dev_or_Path n | String n
9369         | FileIn n | FileOut n ->
9370             pr "  const char *%s;\n" n
9371         | OptString n -> pr "  const char *%s;\n" n
9372         | BufferIn n ->
9373             pr "  const char *%s;\n" n;
9374             pr "  Py_ssize_t %s_size;\n" n
9375         | StringList n | DeviceList n ->
9376             pr "  PyObject *py_%s;\n" n;
9377             pr "  char **%s;\n" n
9378         | Bool n -> pr "  int %s;\n" n
9379         | Int n -> pr "  int %s;\n" n
9380         | Int64 n -> pr "  long long %s;\n" n
9381       ) (snd style);
9382
9383       pr "\n";
9384
9385       (* Convert the parameters. *)
9386       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9387       List.iter (
9388         function
9389         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9390         | OptString _ -> pr "z"
9391         | StringList _ | DeviceList _ -> pr "O"
9392         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9393         | Int _ -> pr "i"
9394         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9395                              * emulate C's int/long/long long in Python?
9396                              *)
9397         | BufferIn _ -> pr "s#"
9398       ) (snd style);
9399       pr ":guestfs_%s\",\n" name;
9400       pr "                         &py_g";
9401       List.iter (
9402         function
9403         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9404         | OptString n -> pr ", &%s" n
9405         | StringList n | DeviceList n -> pr ", &py_%s" n
9406         | Bool n -> pr ", &%s" n
9407         | Int n -> pr ", &%s" n
9408         | Int64 n -> pr ", &%s" n
9409         | BufferIn n -> pr ", &%s, &%s_size" n n
9410       ) (snd style);
9411
9412       pr "))\n";
9413       pr "    return NULL;\n";
9414
9415       pr "  g = get_handle (py_g);\n";
9416       List.iter (
9417         function
9418         | Pathname _ | Device _ | Dev_or_Path _ | String _
9419         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9420         | BufferIn _ -> ()
9421         | StringList n | DeviceList n ->
9422             pr "  %s = get_string_list (py_%s);\n" n n;
9423             pr "  if (!%s) return NULL;\n" n
9424       ) (snd style);
9425
9426       pr "\n";
9427
9428       pr "  r = guestfs_%s " name;
9429       generate_c_call_args ~handle:"g" style;
9430       pr ";\n";
9431
9432       List.iter (
9433         function
9434         | Pathname _ | Device _ | Dev_or_Path _ | String _
9435         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9436         | BufferIn _ -> ()
9437         | StringList n | DeviceList n ->
9438             pr "  free (%s);\n" n
9439       ) (snd style);
9440
9441       pr "  if (r == %s) {\n" error_code;
9442       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9443       pr "    return NULL;\n";
9444       pr "  }\n";
9445       pr "\n";
9446
9447       (match fst style with
9448        | RErr ->
9449            pr "  Py_INCREF (Py_None);\n";
9450            pr "  py_r = Py_None;\n"
9451        | RInt _
9452        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9453        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9454        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9455        | RConstOptString _ ->
9456            pr "  if (r)\n";
9457            pr "    py_r = PyString_FromString (r);\n";
9458            pr "  else {\n";
9459            pr "    Py_INCREF (Py_None);\n";
9460            pr "    py_r = Py_None;\n";
9461            pr "  }\n"
9462        | RString _ ->
9463            pr "  py_r = PyString_FromString (r);\n";
9464            pr "  free (r);\n"
9465        | RStringList _ ->
9466            pr "  py_r = put_string_list (r);\n";
9467            pr "  free_strings (r);\n"
9468        | RStruct (_, typ) ->
9469            pr "  py_r = put_%s (r);\n" typ;
9470            pr "  guestfs_free_%s (r);\n" typ
9471        | RStructList (_, typ) ->
9472            pr "  py_r = put_%s_list (r);\n" typ;
9473            pr "  guestfs_free_%s_list (r);\n" typ
9474        | RHashtable n ->
9475            pr "  py_r = put_table (r);\n";
9476            pr "  free_strings (r);\n"
9477        | RBufferOut _ ->
9478            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9479            pr "  free (r);\n"
9480       );
9481
9482       pr "  return py_r;\n";
9483       pr "}\n";
9484       pr "\n"
9485   ) all_functions;
9486
9487   (* Table of functions. *)
9488   pr "static PyMethodDef methods[] = {\n";
9489   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9490   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9491   List.iter (
9492     fun (name, _, _, _, _, _, _) ->
9493       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9494         name name
9495   ) all_functions;
9496   pr "  { NULL, NULL, 0, NULL }\n";
9497   pr "};\n";
9498   pr "\n";
9499
9500   (* Init function. *)
9501   pr "\
9502 void
9503 initlibguestfsmod (void)
9504 {
9505   static int initialized = 0;
9506
9507   if (initialized) return;
9508   Py_InitModule ((char *) \"libguestfsmod\", methods);
9509   initialized = 1;
9510 }
9511 "
9512
9513 (* Generate Python module. *)
9514 and generate_python_py () =
9515   generate_header HashStyle LGPLv2plus;
9516
9517   pr "\
9518 u\"\"\"Python bindings for libguestfs
9519
9520 import guestfs
9521 g = guestfs.GuestFS ()
9522 g.add_drive (\"guest.img\")
9523 g.launch ()
9524 parts = g.list_partitions ()
9525
9526 The guestfs module provides a Python binding to the libguestfs API
9527 for examining and modifying virtual machine disk images.
9528
9529 Amongst the things this is good for: making batch configuration
9530 changes to guests, getting disk used/free statistics (see also:
9531 virt-df), migrating between virtualization systems (see also:
9532 virt-p2v), performing partial backups, performing partial guest
9533 clones, cloning guests and changing registry/UUID/hostname info, and
9534 much else besides.
9535
9536 Libguestfs uses Linux kernel and qemu code, and can access any type of
9537 guest filesystem that Linux and qemu can, including but not limited
9538 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9539 schemes, qcow, qcow2, vmdk.
9540
9541 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9542 LVs, what filesystem is in each LV, etc.).  It can also run commands
9543 in the context of the guest.  Also you can access filesystems over
9544 FUSE.
9545
9546 Errors which happen while using the API are turned into Python
9547 RuntimeError exceptions.
9548
9549 To create a guestfs handle you usually have to perform the following
9550 sequence of calls:
9551
9552 # Create the handle, call add_drive at least once, and possibly
9553 # several times if the guest has multiple block devices:
9554 g = guestfs.GuestFS ()
9555 g.add_drive (\"guest.img\")
9556
9557 # Launch the qemu subprocess and wait for it to become ready:
9558 g.launch ()
9559
9560 # Now you can issue commands, for example:
9561 logvols = g.lvs ()
9562
9563 \"\"\"
9564
9565 import libguestfsmod
9566
9567 class GuestFS:
9568     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9569
9570     def __init__ (self):
9571         \"\"\"Create a new libguestfs handle.\"\"\"
9572         self._o = libguestfsmod.create ()
9573
9574     def __del__ (self):
9575         libguestfsmod.close (self._o)
9576
9577 ";
9578
9579   List.iter (
9580     fun (name, style, _, flags, _, _, longdesc) ->
9581       pr "    def %s " name;
9582       generate_py_call_args ~handle:"self" (snd style);
9583       pr ":\n";
9584
9585       if not (List.mem NotInDocs flags) then (
9586         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9587         let doc =
9588           match fst style with
9589           | RErr | RInt _ | RInt64 _ | RBool _
9590           | RConstOptString _ | RConstString _
9591           | RString _ | RBufferOut _ -> doc
9592           | RStringList _ ->
9593               doc ^ "\n\nThis function returns a list of strings."
9594           | RStruct (_, typ) ->
9595               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9596           | RStructList (_, typ) ->
9597               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9598           | RHashtable _ ->
9599               doc ^ "\n\nThis function returns a dictionary." in
9600         let doc =
9601           if List.mem ProtocolLimitWarning flags then
9602             doc ^ "\n\n" ^ protocol_limit_warning
9603           else doc in
9604         let doc =
9605           if List.mem DangerWillRobinson flags then
9606             doc ^ "\n\n" ^ danger_will_robinson
9607           else doc in
9608         let doc =
9609           match deprecation_notice flags with
9610           | None -> doc
9611           | Some txt -> doc ^ "\n\n" ^ txt in
9612         let doc = pod2text ~width:60 name doc in
9613         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9614         let doc = String.concat "\n        " doc in
9615         pr "        u\"\"\"%s\"\"\"\n" doc;
9616       );
9617       pr "        return libguestfsmod.%s " name;
9618       generate_py_call_args ~handle:"self._o" (snd style);
9619       pr "\n";
9620       pr "\n";
9621   ) all_functions
9622
9623 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9624 and generate_py_call_args ~handle args =
9625   pr "(%s" handle;
9626   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9627   pr ")"
9628
9629 (* Useful if you need the longdesc POD text as plain text.  Returns a
9630  * list of lines.
9631  *
9632  * Because this is very slow (the slowest part of autogeneration),
9633  * we memoize the results.
9634  *)
9635 and pod2text ~width name longdesc =
9636   let key = width, name, longdesc in
9637   try Hashtbl.find pod2text_memo key
9638   with Not_found ->
9639     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9640     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9641     close_out chan;
9642     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9643     let chan = open_process_in cmd in
9644     let lines = ref [] in
9645     let rec loop i =
9646       let line = input_line chan in
9647       if i = 1 then             (* discard the first line of output *)
9648         loop (i+1)
9649       else (
9650         let line = triml line in
9651         lines := line :: !lines;
9652         loop (i+1)
9653       ) in
9654     let lines = try loop 1 with End_of_file -> List.rev !lines in
9655     unlink filename;
9656     (match close_process_in chan with
9657      | WEXITED 0 -> ()
9658      | WEXITED i ->
9659          failwithf "pod2text: process exited with non-zero status (%d)" i
9660      | WSIGNALED i | WSTOPPED i ->
9661          failwithf "pod2text: process signalled or stopped by signal %d" i
9662     );
9663     Hashtbl.add pod2text_memo key lines;
9664     pod2text_memo_updated ();
9665     lines
9666
9667 (* Generate ruby bindings. *)
9668 and generate_ruby_c () =
9669   generate_header CStyle LGPLv2plus;
9670
9671   pr "\
9672 #include <stdio.h>
9673 #include <stdlib.h>
9674
9675 #include <ruby.h>
9676
9677 #include \"guestfs.h\"
9678
9679 #include \"extconf.h\"
9680
9681 /* For Ruby < 1.9 */
9682 #ifndef RARRAY_LEN
9683 #define RARRAY_LEN(r) (RARRAY((r))->len)
9684 #endif
9685
9686 static VALUE m_guestfs;                 /* guestfs module */
9687 static VALUE c_guestfs;                 /* guestfs_h handle */
9688 static VALUE e_Error;                   /* used for all errors */
9689
9690 static void ruby_guestfs_free (void *p)
9691 {
9692   if (!p) return;
9693   guestfs_close ((guestfs_h *) p);
9694 }
9695
9696 static VALUE ruby_guestfs_create (VALUE m)
9697 {
9698   guestfs_h *g;
9699
9700   g = guestfs_create ();
9701   if (!g)
9702     rb_raise (e_Error, \"failed to create guestfs handle\");
9703
9704   /* Don't print error messages to stderr by default. */
9705   guestfs_set_error_handler (g, NULL, NULL);
9706
9707   /* Wrap it, and make sure the close function is called when the
9708    * handle goes away.
9709    */
9710   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9711 }
9712
9713 static VALUE ruby_guestfs_close (VALUE gv)
9714 {
9715   guestfs_h *g;
9716   Data_Get_Struct (gv, guestfs_h, g);
9717
9718   ruby_guestfs_free (g);
9719   DATA_PTR (gv) = NULL;
9720
9721   return Qnil;
9722 }
9723
9724 ";
9725
9726   List.iter (
9727     fun (name, style, _, _, _, _, _) ->
9728       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9729       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9730       pr ")\n";
9731       pr "{\n";
9732       pr "  guestfs_h *g;\n";
9733       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9734       pr "  if (!g)\n";
9735       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9736         name;
9737       pr "\n";
9738
9739       List.iter (
9740         function
9741         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9742             pr "  Check_Type (%sv, T_STRING);\n" n;
9743             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9744             pr "  if (!%s)\n" n;
9745             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9746             pr "              \"%s\", \"%s\");\n" n name
9747         | BufferIn n ->
9748             pr "  Check_Type (%sv, T_STRING);\n" n;
9749             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9750             pr "  if (!%s)\n" n;
9751             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9752             pr "              \"%s\", \"%s\");\n" n name;
9753             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9754         | OptString n ->
9755             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9756         | StringList n | DeviceList n ->
9757             pr "  char **%s;\n" n;
9758             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9759             pr "  {\n";
9760             pr "    int i, len;\n";
9761             pr "    len = RARRAY_LEN (%sv);\n" n;
9762             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9763               n;
9764             pr "    for (i = 0; i < len; ++i) {\n";
9765             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9766             pr "      %s[i] = StringValueCStr (v);\n" n;
9767             pr "    }\n";
9768             pr "    %s[len] = NULL;\n" n;
9769             pr "  }\n";
9770         | Bool n ->
9771             pr "  int %s = RTEST (%sv);\n" n n
9772         | Int n ->
9773             pr "  int %s = NUM2INT (%sv);\n" n n
9774         | Int64 n ->
9775             pr "  long long %s = NUM2LL (%sv);\n" n n
9776       ) (snd style);
9777       pr "\n";
9778
9779       let error_code =
9780         match fst style with
9781         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9782         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9783         | RConstString _ | RConstOptString _ ->
9784             pr "  const char *r;\n"; "NULL"
9785         | RString _ -> pr "  char *r;\n"; "NULL"
9786         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9787         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9788         | RStructList (_, typ) ->
9789             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9790         | RBufferOut _ ->
9791             pr "  char *r;\n";
9792             pr "  size_t size;\n";
9793             "NULL" in
9794       pr "\n";
9795
9796       pr "  r = guestfs_%s " name;
9797       generate_c_call_args ~handle:"g" style;
9798       pr ";\n";
9799
9800       List.iter (
9801         function
9802         | Pathname _ | Device _ | Dev_or_Path _ | String _
9803         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9804         | BufferIn _ -> ()
9805         | StringList n | DeviceList n ->
9806             pr "  free (%s);\n" n
9807       ) (snd style);
9808
9809       pr "  if (r == %s)\n" error_code;
9810       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9811       pr "\n";
9812
9813       (match fst style with
9814        | RErr ->
9815            pr "  return Qnil;\n"
9816        | RInt _ | RBool _ ->
9817            pr "  return INT2NUM (r);\n"
9818        | RInt64 _ ->
9819            pr "  return ULL2NUM (r);\n"
9820        | RConstString _ ->
9821            pr "  return rb_str_new2 (r);\n";
9822        | RConstOptString _ ->
9823            pr "  if (r)\n";
9824            pr "    return rb_str_new2 (r);\n";
9825            pr "  else\n";
9826            pr "    return Qnil;\n";
9827        | RString _ ->
9828            pr "  VALUE rv = rb_str_new2 (r);\n";
9829            pr "  free (r);\n";
9830            pr "  return rv;\n";
9831        | RStringList _ ->
9832            pr "  int i, len = 0;\n";
9833            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9834            pr "  VALUE rv = rb_ary_new2 (len);\n";
9835            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9836            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9837            pr "    free (r[i]);\n";
9838            pr "  }\n";
9839            pr "  free (r);\n";
9840            pr "  return rv;\n"
9841        | RStruct (_, typ) ->
9842            let cols = cols_of_struct typ in
9843            generate_ruby_struct_code typ cols
9844        | RStructList (_, typ) ->
9845            let cols = cols_of_struct typ in
9846            generate_ruby_struct_list_code typ cols
9847        | RHashtable _ ->
9848            pr "  VALUE rv = rb_hash_new ();\n";
9849            pr "  int i;\n";
9850            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9851            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9852            pr "    free (r[i]);\n";
9853            pr "    free (r[i+1]);\n";
9854            pr "  }\n";
9855            pr "  free (r);\n";
9856            pr "  return rv;\n"
9857        | RBufferOut _ ->
9858            pr "  VALUE rv = rb_str_new (r, size);\n";
9859            pr "  free (r);\n";
9860            pr "  return rv;\n";
9861       );
9862
9863       pr "}\n";
9864       pr "\n"
9865   ) all_functions;
9866
9867   pr "\
9868 /* Initialize the module. */
9869 void Init__guestfs ()
9870 {
9871   m_guestfs = rb_define_module (\"Guestfs\");
9872   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9873   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9874
9875   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9876   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9877
9878 ";
9879   (* Define the rest of the methods. *)
9880   List.iter (
9881     fun (name, style, _, _, _, _, _) ->
9882       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9883       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9884   ) all_functions;
9885
9886   pr "}\n"
9887
9888 (* Ruby code to return a struct. *)
9889 and generate_ruby_struct_code typ cols =
9890   pr "  VALUE rv = rb_hash_new ();\n";
9891   List.iter (
9892     function
9893     | name, FString ->
9894         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9895     | name, FBuffer ->
9896         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9897     | name, FUUID ->
9898         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9899     | name, (FBytes|FUInt64) ->
9900         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9901     | name, FInt64 ->
9902         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9903     | name, FUInt32 ->
9904         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9905     | name, FInt32 ->
9906         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9907     | name, FOptPercent ->
9908         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9909     | name, FChar -> (* XXX wrong? *)
9910         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9911   ) cols;
9912   pr "  guestfs_free_%s (r);\n" typ;
9913   pr "  return rv;\n"
9914
9915 (* Ruby code to return a struct list. *)
9916 and generate_ruby_struct_list_code typ cols =
9917   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9918   pr "  int i;\n";
9919   pr "  for (i = 0; i < r->len; ++i) {\n";
9920   pr "    VALUE hv = rb_hash_new ();\n";
9921   List.iter (
9922     function
9923     | name, FString ->
9924         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9925     | name, FBuffer ->
9926         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
9927     | name, FUUID ->
9928         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9929     | name, (FBytes|FUInt64) ->
9930         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9931     | name, FInt64 ->
9932         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9933     | name, FUInt32 ->
9934         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9935     | name, FInt32 ->
9936         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9937     | name, FOptPercent ->
9938         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9939     | name, FChar -> (* XXX wrong? *)
9940         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9941   ) cols;
9942   pr "    rb_ary_push (rv, hv);\n";
9943   pr "  }\n";
9944   pr "  guestfs_free_%s_list (r);\n" typ;
9945   pr "  return rv;\n"
9946
9947 (* Generate Java bindings GuestFS.java file. *)
9948 and generate_java_java () =
9949   generate_header CStyle LGPLv2plus;
9950
9951   pr "\
9952 package com.redhat.et.libguestfs;
9953
9954 import java.util.HashMap;
9955 import com.redhat.et.libguestfs.LibGuestFSException;
9956 import com.redhat.et.libguestfs.PV;
9957 import com.redhat.et.libguestfs.VG;
9958 import com.redhat.et.libguestfs.LV;
9959 import com.redhat.et.libguestfs.Stat;
9960 import com.redhat.et.libguestfs.StatVFS;
9961 import com.redhat.et.libguestfs.IntBool;
9962 import com.redhat.et.libguestfs.Dirent;
9963
9964 /**
9965  * The GuestFS object is a libguestfs handle.
9966  *
9967  * @author rjones
9968  */
9969 public class GuestFS {
9970   // Load the native code.
9971   static {
9972     System.loadLibrary (\"guestfs_jni\");
9973   }
9974
9975   /**
9976    * The native guestfs_h pointer.
9977    */
9978   long g;
9979
9980   /**
9981    * Create a libguestfs handle.
9982    *
9983    * @throws LibGuestFSException
9984    */
9985   public GuestFS () throws LibGuestFSException
9986   {
9987     g = _create ();
9988   }
9989   private native long _create () throws LibGuestFSException;
9990
9991   /**
9992    * Close a libguestfs handle.
9993    *
9994    * You can also leave handles to be collected by the garbage
9995    * collector, but this method ensures that the resources used
9996    * by the handle are freed up immediately.  If you call any
9997    * other methods after closing the handle, you will get an
9998    * exception.
9999    *
10000    * @throws LibGuestFSException
10001    */
10002   public void close () throws LibGuestFSException
10003   {
10004     if (g != 0)
10005       _close (g);
10006     g = 0;
10007   }
10008   private native void _close (long g) throws LibGuestFSException;
10009
10010   public void finalize () throws LibGuestFSException
10011   {
10012     close ();
10013   }
10014
10015 ";
10016
10017   List.iter (
10018     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10019       if not (List.mem NotInDocs flags); then (
10020         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10021         let doc =
10022           if List.mem ProtocolLimitWarning flags then
10023             doc ^ "\n\n" ^ protocol_limit_warning
10024           else doc in
10025         let doc =
10026           if List.mem DangerWillRobinson flags then
10027             doc ^ "\n\n" ^ danger_will_robinson
10028           else doc in
10029         let doc =
10030           match deprecation_notice flags with
10031           | None -> doc
10032           | Some txt -> doc ^ "\n\n" ^ txt in
10033         let doc = pod2text ~width:60 name doc in
10034         let doc = List.map (            (* RHBZ#501883 *)
10035           function
10036           | "" -> "<p>"
10037           | nonempty -> nonempty
10038         ) doc in
10039         let doc = String.concat "\n   * " doc in
10040
10041         pr "  /**\n";
10042         pr "   * %s\n" shortdesc;
10043         pr "   * <p>\n";
10044         pr "   * %s\n" doc;
10045         pr "   * @throws LibGuestFSException\n";
10046         pr "   */\n";
10047         pr "  ";
10048       );
10049       generate_java_prototype ~public:true ~semicolon:false name style;
10050       pr "\n";
10051       pr "  {\n";
10052       pr "    if (g == 0)\n";
10053       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10054         name;
10055       pr "    ";
10056       if fst style <> RErr then pr "return ";
10057       pr "_%s " name;
10058       generate_java_call_args ~handle:"g" (snd style);
10059       pr ";\n";
10060       pr "  }\n";
10061       pr "  ";
10062       generate_java_prototype ~privat:true ~native:true name style;
10063       pr "\n";
10064       pr "\n";
10065   ) all_functions;
10066
10067   pr "}\n"
10068
10069 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10070 and generate_java_call_args ~handle args =
10071   pr "(%s" handle;
10072   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10073   pr ")"
10074
10075 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10076     ?(semicolon=true) name style =
10077   if privat then pr "private ";
10078   if public then pr "public ";
10079   if native then pr "native ";
10080
10081   (* return type *)
10082   (match fst style with
10083    | RErr -> pr "void ";
10084    | RInt _ -> pr "int ";
10085    | RInt64 _ -> pr "long ";
10086    | RBool _ -> pr "boolean ";
10087    | RConstString _ | RConstOptString _ | RString _
10088    | RBufferOut _ -> pr "String ";
10089    | RStringList _ -> pr "String[] ";
10090    | RStruct (_, typ) ->
10091        let name = java_name_of_struct typ in
10092        pr "%s " name;
10093    | RStructList (_, typ) ->
10094        let name = java_name_of_struct typ in
10095        pr "%s[] " name;
10096    | RHashtable _ -> pr "HashMap<String,String> ";
10097   );
10098
10099   if native then pr "_%s " name else pr "%s " name;
10100   pr "(";
10101   let needs_comma = ref false in
10102   if native then (
10103     pr "long g";
10104     needs_comma := true
10105   );
10106
10107   (* args *)
10108   List.iter (
10109     fun arg ->
10110       if !needs_comma then pr ", ";
10111       needs_comma := true;
10112
10113       match arg with
10114       | Pathname n
10115       | Device n | Dev_or_Path n
10116       | String n
10117       | OptString n
10118       | FileIn n
10119       | FileOut n ->
10120           pr "String %s" n
10121       | BufferIn n ->
10122           pr "byte[] %s" n
10123       | StringList n | DeviceList n ->
10124           pr "String[] %s" n
10125       | Bool n ->
10126           pr "boolean %s" n
10127       | Int n ->
10128           pr "int %s" n
10129       | Int64 n ->
10130           pr "long %s" n
10131   ) (snd style);
10132
10133   pr ")\n";
10134   pr "    throws LibGuestFSException";
10135   if semicolon then pr ";"
10136
10137 and generate_java_struct jtyp cols () =
10138   generate_header CStyle LGPLv2plus;
10139
10140   pr "\
10141 package com.redhat.et.libguestfs;
10142
10143 /**
10144  * Libguestfs %s structure.
10145  *
10146  * @author rjones
10147  * @see GuestFS
10148  */
10149 public class %s {
10150 " jtyp jtyp;
10151
10152   List.iter (
10153     function
10154     | name, FString
10155     | name, FUUID
10156     | name, FBuffer -> pr "  public String %s;\n" name
10157     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10158     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10159     | name, FChar -> pr "  public char %s;\n" name
10160     | name, FOptPercent ->
10161         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10162         pr "  public float %s;\n" name
10163   ) cols;
10164
10165   pr "}\n"
10166
10167 and generate_java_c () =
10168   generate_header CStyle LGPLv2plus;
10169
10170   pr "\
10171 #include <stdio.h>
10172 #include <stdlib.h>
10173 #include <string.h>
10174
10175 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10176 #include \"guestfs.h\"
10177
10178 /* Note that this function returns.  The exception is not thrown
10179  * until after the wrapper function returns.
10180  */
10181 static void
10182 throw_exception (JNIEnv *env, const char *msg)
10183 {
10184   jclass cl;
10185   cl = (*env)->FindClass (env,
10186                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10187   (*env)->ThrowNew (env, cl, msg);
10188 }
10189
10190 JNIEXPORT jlong JNICALL
10191 Java_com_redhat_et_libguestfs_GuestFS__1create
10192   (JNIEnv *env, jobject obj)
10193 {
10194   guestfs_h *g;
10195
10196   g = guestfs_create ();
10197   if (g == NULL) {
10198     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10199     return 0;
10200   }
10201   guestfs_set_error_handler (g, NULL, NULL);
10202   return (jlong) (long) g;
10203 }
10204
10205 JNIEXPORT void JNICALL
10206 Java_com_redhat_et_libguestfs_GuestFS__1close
10207   (JNIEnv *env, jobject obj, jlong jg)
10208 {
10209   guestfs_h *g = (guestfs_h *) (long) jg;
10210   guestfs_close (g);
10211 }
10212
10213 ";
10214
10215   List.iter (
10216     fun (name, style, _, _, _, _, _) ->
10217       pr "JNIEXPORT ";
10218       (match fst style with
10219        | RErr -> pr "void ";
10220        | RInt _ -> pr "jint ";
10221        | RInt64 _ -> pr "jlong ";
10222        | RBool _ -> pr "jboolean ";
10223        | RConstString _ | RConstOptString _ | RString _
10224        | RBufferOut _ -> pr "jstring ";
10225        | RStruct _ | RHashtable _ ->
10226            pr "jobject ";
10227        | RStringList _ | RStructList _ ->
10228            pr "jobjectArray ";
10229       );
10230       pr "JNICALL\n";
10231       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10232       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10233       pr "\n";
10234       pr "  (JNIEnv *env, jobject obj, jlong jg";
10235       List.iter (
10236         function
10237         | Pathname n
10238         | Device n | Dev_or_Path n
10239         | String n
10240         | OptString n
10241         | FileIn n
10242         | FileOut n ->
10243             pr ", jstring j%s" n
10244         | BufferIn n ->
10245             pr ", jbyteArray j%s" n
10246         | StringList n | DeviceList n ->
10247             pr ", jobjectArray j%s" n
10248         | Bool n ->
10249             pr ", jboolean j%s" n
10250         | Int n ->
10251             pr ", jint j%s" n
10252         | Int64 n ->
10253             pr ", jlong j%s" n
10254       ) (snd style);
10255       pr ")\n";
10256       pr "{\n";
10257       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10258       let error_code, no_ret =
10259         match fst style with
10260         | RErr -> pr "  int r;\n"; "-1", ""
10261         | RBool _
10262         | RInt _ -> pr "  int r;\n"; "-1", "0"
10263         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10264         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10265         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10266         | RString _ ->
10267             pr "  jstring jr;\n";
10268             pr "  char *r;\n"; "NULL", "NULL"
10269         | RStringList _ ->
10270             pr "  jobjectArray jr;\n";
10271             pr "  int r_len;\n";
10272             pr "  jclass cl;\n";
10273             pr "  jstring jstr;\n";
10274             pr "  char **r;\n"; "NULL", "NULL"
10275         | RStruct (_, typ) ->
10276             pr "  jobject jr;\n";
10277             pr "  jclass cl;\n";
10278             pr "  jfieldID fl;\n";
10279             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10280         | RStructList (_, typ) ->
10281             pr "  jobjectArray jr;\n";
10282             pr "  jclass cl;\n";
10283             pr "  jfieldID fl;\n";
10284             pr "  jobject jfl;\n";
10285             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10286         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10287         | RBufferOut _ ->
10288             pr "  jstring jr;\n";
10289             pr "  char *r;\n";
10290             pr "  size_t size;\n";
10291             "NULL", "NULL" in
10292       List.iter (
10293         function
10294         | Pathname n
10295         | Device n | Dev_or_Path n
10296         | String n
10297         | OptString n
10298         | FileIn n
10299         | FileOut n ->
10300             pr "  const char *%s;\n" n
10301         | BufferIn n ->
10302             pr "  jbyte *%s;\n" n;
10303             pr "  size_t %s_size;\n" n
10304         | StringList n | DeviceList n ->
10305             pr "  int %s_len;\n" n;
10306             pr "  const char **%s;\n" n
10307         | Bool n
10308         | Int n ->
10309             pr "  int %s;\n" n
10310         | Int64 n ->
10311             pr "  int64_t %s;\n" n
10312       ) (snd style);
10313
10314       let needs_i =
10315         (match fst style with
10316          | RStringList _ | RStructList _ -> true
10317          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10318          | RConstOptString _
10319          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10320           List.exists (function
10321                        | StringList _ -> true
10322                        | DeviceList _ -> true
10323                        | _ -> false) (snd style) in
10324       if needs_i then
10325         pr "  int i;\n";
10326
10327       pr "\n";
10328
10329       (* Get the parameters. *)
10330       List.iter (
10331         function
10332         | Pathname n
10333         | Device n | Dev_or_Path n
10334         | String n
10335         | FileIn n
10336         | FileOut n ->
10337             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10338         | OptString n ->
10339             (* This is completely undocumented, but Java null becomes
10340              * a NULL parameter.
10341              *)
10342             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10343         | BufferIn n ->
10344             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10345             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10346         | StringList n | DeviceList n ->
10347             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10348             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10349             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10350             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10351               n;
10352             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10353             pr "  }\n";
10354             pr "  %s[%s_len] = NULL;\n" n n;
10355         | Bool n
10356         | Int n
10357         | Int64 n ->
10358             pr "  %s = j%s;\n" n n
10359       ) (snd style);
10360
10361       (* Make the call. *)
10362       pr "  r = guestfs_%s " name;
10363       generate_c_call_args ~handle:"g" style;
10364       pr ";\n";
10365
10366       (* Release the parameters. *)
10367       List.iter (
10368         function
10369         | Pathname n
10370         | Device n | Dev_or_Path n
10371         | String n
10372         | FileIn n
10373         | FileOut n ->
10374             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10375         | OptString n ->
10376             pr "  if (j%s)\n" n;
10377             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10378         | BufferIn n ->
10379             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10380         | StringList n | DeviceList n ->
10381             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10382             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10383               n;
10384             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10385             pr "  }\n";
10386             pr "  free (%s);\n" n
10387         | Bool n
10388         | Int n
10389         | Int64 n -> ()
10390       ) (snd style);
10391
10392       (* Check for errors. *)
10393       pr "  if (r == %s) {\n" error_code;
10394       pr "    throw_exception (env, guestfs_last_error (g));\n";
10395       pr "    return %s;\n" no_ret;
10396       pr "  }\n";
10397
10398       (* Return value. *)
10399       (match fst style with
10400        | RErr -> ()
10401        | RInt _ -> pr "  return (jint) r;\n"
10402        | RBool _ -> pr "  return (jboolean) r;\n"
10403        | RInt64 _ -> pr "  return (jlong) r;\n"
10404        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10405        | RConstOptString _ ->
10406            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10407        | RString _ ->
10408            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10409            pr "  free (r);\n";
10410            pr "  return jr;\n"
10411        | RStringList _ ->
10412            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10413            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10414            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10415            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10416            pr "  for (i = 0; i < r_len; ++i) {\n";
10417            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10418            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10419            pr "    free (r[i]);\n";
10420            pr "  }\n";
10421            pr "  free (r);\n";
10422            pr "  return jr;\n"
10423        | RStruct (_, typ) ->
10424            let jtyp = java_name_of_struct typ in
10425            let cols = cols_of_struct typ in
10426            generate_java_struct_return typ jtyp cols
10427        | RStructList (_, typ) ->
10428            let jtyp = java_name_of_struct typ in
10429            let cols = cols_of_struct typ in
10430            generate_java_struct_list_return typ jtyp cols
10431        | RHashtable _ ->
10432            (* XXX *)
10433            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10434            pr "  return NULL;\n"
10435        | RBufferOut _ ->
10436            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10437            pr "  free (r);\n";
10438            pr "  return jr;\n"
10439       );
10440
10441       pr "}\n";
10442       pr "\n"
10443   ) all_functions
10444
10445 and generate_java_struct_return typ jtyp cols =
10446   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10447   pr "  jr = (*env)->AllocObject (env, cl);\n";
10448   List.iter (
10449     function
10450     | name, FString ->
10451         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10452         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10453     | name, FUUID ->
10454         pr "  {\n";
10455         pr "    char s[33];\n";
10456         pr "    memcpy (s, r->%s, 32);\n" name;
10457         pr "    s[32] = 0;\n";
10458         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10459         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10460         pr "  }\n";
10461     | name, FBuffer ->
10462         pr "  {\n";
10463         pr "    int len = r->%s_len;\n" name;
10464         pr "    char s[len+1];\n";
10465         pr "    memcpy (s, r->%s, len);\n" name;
10466         pr "    s[len] = 0;\n";
10467         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10468         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10469         pr "  }\n";
10470     | name, (FBytes|FUInt64|FInt64) ->
10471         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10472         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10473     | name, (FUInt32|FInt32) ->
10474         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10475         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10476     | name, FOptPercent ->
10477         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10478         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10479     | name, FChar ->
10480         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10481         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10482   ) cols;
10483   pr "  free (r);\n";
10484   pr "  return jr;\n"
10485
10486 and generate_java_struct_list_return typ jtyp cols =
10487   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10488   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10489   pr "  for (i = 0; i < r->len; ++i) {\n";
10490   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10491   List.iter (
10492     function
10493     | name, FString ->
10494         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10495         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10496     | name, FUUID ->
10497         pr "    {\n";
10498         pr "      char s[33];\n";
10499         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10500         pr "      s[32] = 0;\n";
10501         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10502         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10503         pr "    }\n";
10504     | name, FBuffer ->
10505         pr "    {\n";
10506         pr "      int len = r->val[i].%s_len;\n" name;
10507         pr "      char s[len+1];\n";
10508         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10509         pr "      s[len] = 0;\n";
10510         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10511         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10512         pr "    }\n";
10513     | name, (FBytes|FUInt64|FInt64) ->
10514         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10515         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10516     | name, (FUInt32|FInt32) ->
10517         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10518         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10519     | name, FOptPercent ->
10520         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10521         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10522     | name, FChar ->
10523         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10524         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10525   ) cols;
10526   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10527   pr "  }\n";
10528   pr "  guestfs_free_%s_list (r);\n" typ;
10529   pr "  return jr;\n"
10530
10531 and generate_java_makefile_inc () =
10532   generate_header HashStyle GPLv2plus;
10533
10534   pr "java_built_sources = \\\n";
10535   List.iter (
10536     fun (typ, jtyp) ->
10537         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10538   ) java_structs;
10539   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10540
10541 and generate_haskell_hs () =
10542   generate_header HaskellStyle LGPLv2plus;
10543
10544   (* XXX We only know how to generate partial FFI for Haskell
10545    * at the moment.  Please help out!
10546    *)
10547   let can_generate style =
10548     match style with
10549     | RErr, _
10550     | RInt _, _
10551     | RInt64 _, _ -> true
10552     | RBool _, _
10553     | RConstString _, _
10554     | RConstOptString _, _
10555     | RString _, _
10556     | RStringList _, _
10557     | RStruct _, _
10558     | RStructList _, _
10559     | RHashtable _, _
10560     | RBufferOut _, _ -> false in
10561
10562   pr "\
10563 {-# INCLUDE <guestfs.h> #-}
10564 {-# LANGUAGE ForeignFunctionInterface #-}
10565
10566 module Guestfs (
10567   create";
10568
10569   (* List out the names of the actions we want to export. *)
10570   List.iter (
10571     fun (name, style, _, _, _, _, _) ->
10572       if can_generate style then pr ",\n  %s" name
10573   ) all_functions;
10574
10575   pr "
10576   ) where
10577
10578 -- Unfortunately some symbols duplicate ones already present
10579 -- in Prelude.  We don't know which, so we hard-code a list
10580 -- here.
10581 import Prelude hiding (truncate)
10582
10583 import Foreign
10584 import Foreign.C
10585 import Foreign.C.Types
10586 import IO
10587 import Control.Exception
10588 import Data.Typeable
10589
10590 data GuestfsS = GuestfsS            -- represents the opaque C struct
10591 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10592 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10593
10594 -- XXX define properly later XXX
10595 data PV = PV
10596 data VG = VG
10597 data LV = LV
10598 data IntBool = IntBool
10599 data Stat = Stat
10600 data StatVFS = StatVFS
10601 data Hashtable = Hashtable
10602
10603 foreign import ccall unsafe \"guestfs_create\" c_create
10604   :: IO GuestfsP
10605 foreign import ccall unsafe \"&guestfs_close\" c_close
10606   :: FunPtr (GuestfsP -> IO ())
10607 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10608   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10609
10610 create :: IO GuestfsH
10611 create = do
10612   p <- c_create
10613   c_set_error_handler p nullPtr nullPtr
10614   h <- newForeignPtr c_close p
10615   return h
10616
10617 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10618   :: GuestfsP -> IO CString
10619
10620 -- last_error :: GuestfsH -> IO (Maybe String)
10621 -- last_error h = do
10622 --   str <- withForeignPtr h (\\p -> c_last_error p)
10623 --   maybePeek peekCString str
10624
10625 last_error :: GuestfsH -> IO (String)
10626 last_error h = do
10627   str <- withForeignPtr h (\\p -> c_last_error p)
10628   if (str == nullPtr)
10629     then return \"no error\"
10630     else peekCString str
10631
10632 ";
10633
10634   (* Generate wrappers for each foreign function. *)
10635   List.iter (
10636     fun (name, style, _, _, _, _, _) ->
10637       if can_generate style then (
10638         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10639         pr "  :: ";
10640         generate_haskell_prototype ~handle:"GuestfsP" style;
10641         pr "\n";
10642         pr "\n";
10643         pr "%s :: " name;
10644         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10645         pr "\n";
10646         pr "%s %s = do\n" name
10647           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10648         pr "  r <- ";
10649         (* Convert pointer arguments using with* functions. *)
10650         List.iter (
10651           function
10652           | FileIn n
10653           | FileOut n
10654           | Pathname n | Device n | Dev_or_Path n | String n ->
10655               pr "withCString %s $ \\%s -> " n n
10656           | BufferIn n ->
10657               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10658           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10659           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10660           | Bool _ | Int _ | Int64 _ -> ()
10661         ) (snd style);
10662         (* Convert integer arguments. *)
10663         let args =
10664           List.map (
10665             function
10666             | Bool n -> sprintf "(fromBool %s)" n
10667             | Int n -> sprintf "(fromIntegral %s)" n
10668             | Int64 n -> sprintf "(fromIntegral %s)" n
10669             | FileIn n | FileOut n
10670             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10671             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10672           ) (snd style) in
10673         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10674           (String.concat " " ("p" :: args));
10675         (match fst style with
10676          | RErr | RInt _ | RInt64 _ | RBool _ ->
10677              pr "  if (r == -1)\n";
10678              pr "    then do\n";
10679              pr "      err <- last_error h\n";
10680              pr "      fail err\n";
10681          | RConstString _ | RConstOptString _ | RString _
10682          | RStringList _ | RStruct _
10683          | RStructList _ | RHashtable _ | RBufferOut _ ->
10684              pr "  if (r == nullPtr)\n";
10685              pr "    then do\n";
10686              pr "      err <- last_error h\n";
10687              pr "      fail err\n";
10688         );
10689         (match fst style with
10690          | RErr ->
10691              pr "    else return ()\n"
10692          | RInt _ ->
10693              pr "    else return (fromIntegral r)\n"
10694          | RInt64 _ ->
10695              pr "    else return (fromIntegral r)\n"
10696          | RBool _ ->
10697              pr "    else return (toBool r)\n"
10698          | RConstString _
10699          | RConstOptString _
10700          | RString _
10701          | RStringList _
10702          | RStruct _
10703          | RStructList _
10704          | RHashtable _
10705          | RBufferOut _ ->
10706              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10707         );
10708         pr "\n";
10709       )
10710   ) all_functions
10711
10712 and generate_haskell_prototype ~handle ?(hs = false) style =
10713   pr "%s -> " handle;
10714   let string = if hs then "String" else "CString" in
10715   let int = if hs then "Int" else "CInt" in
10716   let bool = if hs then "Bool" else "CInt" in
10717   let int64 = if hs then "Integer" else "Int64" in
10718   List.iter (
10719     fun arg ->
10720       (match arg with
10721        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10722        | BufferIn _ ->
10723            if hs then pr "String"
10724            else pr "CString -> CInt"
10725        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10726        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10727        | Bool _ -> pr "%s" bool
10728        | Int _ -> pr "%s" int
10729        | Int64 _ -> pr "%s" int
10730        | FileIn _ -> pr "%s" string
10731        | FileOut _ -> pr "%s" string
10732       );
10733       pr " -> ";
10734   ) (snd style);
10735   pr "IO (";
10736   (match fst style with
10737    | RErr -> if not hs then pr "CInt"
10738    | RInt _ -> pr "%s" int
10739    | RInt64 _ -> pr "%s" int64
10740    | RBool _ -> pr "%s" bool
10741    | RConstString _ -> pr "%s" string
10742    | RConstOptString _ -> pr "Maybe %s" string
10743    | RString _ -> pr "%s" string
10744    | RStringList _ -> pr "[%s]" string
10745    | RStruct (_, typ) ->
10746        let name = java_name_of_struct typ in
10747        pr "%s" name
10748    | RStructList (_, typ) ->
10749        let name = java_name_of_struct typ in
10750        pr "[%s]" name
10751    | RHashtable _ -> pr "Hashtable"
10752    | RBufferOut _ -> pr "%s" string
10753   );
10754   pr ")"
10755
10756 and generate_csharp () =
10757   generate_header CPlusPlusStyle LGPLv2plus;
10758
10759   (* XXX Make this configurable by the C# assembly users. *)
10760   let library = "libguestfs.so.0" in
10761
10762   pr "\
10763 // These C# bindings are highly experimental at present.
10764 //
10765 // Firstly they only work on Linux (ie. Mono).  In order to get them
10766 // to work on Windows (ie. .Net) you would need to port the library
10767 // itself to Windows first.
10768 //
10769 // The second issue is that some calls are known to be incorrect and
10770 // can cause Mono to segfault.  Particularly: calls which pass or
10771 // return string[], or return any structure value.  This is because
10772 // we haven't worked out the correct way to do this from C#.
10773 //
10774 // The third issue is that when compiling you get a lot of warnings.
10775 // We are not sure whether the warnings are important or not.
10776 //
10777 // Fourthly we do not routinely build or test these bindings as part
10778 // of the make && make check cycle, which means that regressions might
10779 // go unnoticed.
10780 //
10781 // Suggestions and patches are welcome.
10782
10783 // To compile:
10784 //
10785 // gmcs Libguestfs.cs
10786 // mono Libguestfs.exe
10787 //
10788 // (You'll probably want to add a Test class / static main function
10789 // otherwise this won't do anything useful).
10790
10791 using System;
10792 using System.IO;
10793 using System.Runtime.InteropServices;
10794 using System.Runtime.Serialization;
10795 using System.Collections;
10796
10797 namespace Guestfs
10798 {
10799   class Error : System.ApplicationException
10800   {
10801     public Error (string message) : base (message) {}
10802     protected Error (SerializationInfo info, StreamingContext context) {}
10803   }
10804
10805   class Guestfs
10806   {
10807     IntPtr _handle;
10808
10809     [DllImport (\"%s\")]
10810     static extern IntPtr guestfs_create ();
10811
10812     public Guestfs ()
10813     {
10814       _handle = guestfs_create ();
10815       if (_handle == IntPtr.Zero)
10816         throw new Error (\"could not create guestfs handle\");
10817     }
10818
10819     [DllImport (\"%s\")]
10820     static extern void guestfs_close (IntPtr h);
10821
10822     ~Guestfs ()
10823     {
10824       guestfs_close (_handle);
10825     }
10826
10827     [DllImport (\"%s\")]
10828     static extern string guestfs_last_error (IntPtr h);
10829
10830 " library library library;
10831
10832   (* Generate C# structure bindings.  We prefix struct names with
10833    * underscore because C# cannot have conflicting struct names and
10834    * method names (eg. "class stat" and "stat").
10835    *)
10836   List.iter (
10837     fun (typ, cols) ->
10838       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10839       pr "    public class _%s {\n" typ;
10840       List.iter (
10841         function
10842         | name, FChar -> pr "      char %s;\n" name
10843         | name, FString -> pr "      string %s;\n" name
10844         | name, FBuffer ->
10845             pr "      uint %s_len;\n" name;
10846             pr "      string %s;\n" name
10847         | name, FUUID ->
10848             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10849             pr "      string %s;\n" name
10850         | name, FUInt32 -> pr "      uint %s;\n" name
10851         | name, FInt32 -> pr "      int %s;\n" name
10852         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10853         | name, FInt64 -> pr "      long %s;\n" name
10854         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10855       ) cols;
10856       pr "    }\n";
10857       pr "\n"
10858   ) structs;
10859
10860   (* Generate C# function bindings. *)
10861   List.iter (
10862     fun (name, style, _, _, _, shortdesc, _) ->
10863       let rec csharp_return_type () =
10864         match fst style with
10865         | RErr -> "void"
10866         | RBool n -> "bool"
10867         | RInt n -> "int"
10868         | RInt64 n -> "long"
10869         | RConstString n
10870         | RConstOptString n
10871         | RString n
10872         | RBufferOut n -> "string"
10873         | RStruct (_,n) -> "_" ^ n
10874         | RHashtable n -> "Hashtable"
10875         | RStringList n -> "string[]"
10876         | RStructList (_,n) -> sprintf "_%s[]" n
10877
10878       and c_return_type () =
10879         match fst style with
10880         | RErr
10881         | RBool _
10882         | RInt _ -> "int"
10883         | RInt64 _ -> "long"
10884         | RConstString _
10885         | RConstOptString _
10886         | RString _
10887         | RBufferOut _ -> "string"
10888         | RStruct (_,n) -> "_" ^ n
10889         | RHashtable _
10890         | RStringList _ -> "string[]"
10891         | RStructList (_,n) -> sprintf "_%s[]" n
10892
10893       and c_error_comparison () =
10894         match fst style with
10895         | RErr
10896         | RBool _
10897         | RInt _
10898         | RInt64 _ -> "== -1"
10899         | RConstString _
10900         | RConstOptString _
10901         | RString _
10902         | RBufferOut _
10903         | RStruct (_,_)
10904         | RHashtable _
10905         | RStringList _
10906         | RStructList (_,_) -> "== null"
10907
10908       and generate_extern_prototype () =
10909         pr "    static extern %s guestfs_%s (IntPtr h"
10910           (c_return_type ()) name;
10911         List.iter (
10912           function
10913           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10914           | FileIn n | FileOut n
10915           | BufferIn n ->
10916               pr ", [In] string %s" n
10917           | StringList n | DeviceList n ->
10918               pr ", [In] string[] %s" n
10919           | Bool n ->
10920               pr ", bool %s" n
10921           | Int n ->
10922               pr ", int %s" n
10923           | Int64 n ->
10924               pr ", long %s" n
10925         ) (snd style);
10926         pr ");\n"
10927
10928       and generate_public_prototype () =
10929         pr "    public %s %s (" (csharp_return_type ()) name;
10930         let comma = ref false in
10931         let next () =
10932           if !comma then pr ", ";
10933           comma := true
10934         in
10935         List.iter (
10936           function
10937           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10938           | FileIn n | FileOut n
10939           | BufferIn n ->
10940               next (); pr "string %s" n
10941           | StringList n | DeviceList n ->
10942               next (); pr "string[] %s" n
10943           | Bool n ->
10944               next (); pr "bool %s" n
10945           | Int n ->
10946               next (); pr "int %s" n
10947           | Int64 n ->
10948               next (); pr "long %s" n
10949         ) (snd style);
10950         pr ")\n"
10951
10952       and generate_call () =
10953         pr "guestfs_%s (_handle" name;
10954         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10955         pr ");\n";
10956       in
10957
10958       pr "    [DllImport (\"%s\")]\n" library;
10959       generate_extern_prototype ();
10960       pr "\n";
10961       pr "    /// <summary>\n";
10962       pr "    /// %s\n" shortdesc;
10963       pr "    /// </summary>\n";
10964       generate_public_prototype ();
10965       pr "    {\n";
10966       pr "      %s r;\n" (c_return_type ());
10967       pr "      r = ";
10968       generate_call ();
10969       pr "      if (r %s)\n" (c_error_comparison ());
10970       pr "        throw new Error (guestfs_last_error (_handle));\n";
10971       (match fst style with
10972        | RErr -> ()
10973        | RBool _ ->
10974            pr "      return r != 0 ? true : false;\n"
10975        | RHashtable _ ->
10976            pr "      Hashtable rr = new Hashtable ();\n";
10977            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10978            pr "        rr.Add (r[i], r[i+1]);\n";
10979            pr "      return rr;\n"
10980        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10981        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10982        | RStructList _ ->
10983            pr "      return r;\n"
10984       );
10985       pr "    }\n";
10986       pr "\n";
10987   ) all_functions_sorted;
10988
10989   pr "  }
10990 }
10991 "
10992
10993 and generate_bindtests () =
10994   generate_header CStyle LGPLv2plus;
10995
10996   pr "\
10997 #include <stdio.h>
10998 #include <stdlib.h>
10999 #include <inttypes.h>
11000 #include <string.h>
11001
11002 #include \"guestfs.h\"
11003 #include \"guestfs-internal.h\"
11004 #include \"guestfs-internal-actions.h\"
11005 #include \"guestfs_protocol.h\"
11006
11007 #define error guestfs_error
11008 #define safe_calloc guestfs_safe_calloc
11009 #define safe_malloc guestfs_safe_malloc
11010
11011 static void
11012 print_strings (char *const *argv)
11013 {
11014   int argc;
11015
11016   printf (\"[\");
11017   for (argc = 0; argv[argc] != NULL; ++argc) {
11018     if (argc > 0) printf (\", \");
11019     printf (\"\\\"%%s\\\"\", argv[argc]);
11020   }
11021   printf (\"]\\n\");
11022 }
11023
11024 /* The test0 function prints its parameters to stdout. */
11025 ";
11026
11027   let test0, tests =
11028     match test_functions with
11029     | [] -> assert false
11030     | test0 :: tests -> test0, tests in
11031
11032   let () =
11033     let (name, style, _, _, _, _, _) = test0 in
11034     generate_prototype ~extern:false ~semicolon:false ~newline:true
11035       ~handle:"g" ~prefix:"guestfs__" name style;
11036     pr "{\n";
11037     List.iter (
11038       function
11039       | Pathname n
11040       | Device n | Dev_or_Path n
11041       | String n
11042       | FileIn n
11043       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11044       | BufferIn n ->
11045           pr "  {\n";
11046           pr "    size_t i;\n";
11047           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11048           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11049           pr "    printf (\"\\n\");\n";
11050           pr "  }\n";
11051       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11052       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11053       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11054       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11055       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11056     ) (snd style);
11057     pr "  /* Java changes stdout line buffering so we need this: */\n";
11058     pr "  fflush (stdout);\n";
11059     pr "  return 0;\n";
11060     pr "}\n";
11061     pr "\n" in
11062
11063   List.iter (
11064     fun (name, style, _, _, _, _, _) ->
11065       if String.sub name (String.length name - 3) 3 <> "err" then (
11066         pr "/* Test normal return. */\n";
11067         generate_prototype ~extern:false ~semicolon:false ~newline:true
11068           ~handle:"g" ~prefix:"guestfs__" name style;
11069         pr "{\n";
11070         (match fst style with
11071          | RErr ->
11072              pr "  return 0;\n"
11073          | RInt _ ->
11074              pr "  int r;\n";
11075              pr "  sscanf (val, \"%%d\", &r);\n";
11076              pr "  return r;\n"
11077          | RInt64 _ ->
11078              pr "  int64_t r;\n";
11079              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11080              pr "  return r;\n"
11081          | RBool _ ->
11082              pr "  return STREQ (val, \"true\");\n"
11083          | RConstString _
11084          | RConstOptString _ ->
11085              (* Can't return the input string here.  Return a static
11086               * string so we ensure we get a segfault if the caller
11087               * tries to free it.
11088               *)
11089              pr "  return \"static string\";\n"
11090          | RString _ ->
11091              pr "  return strdup (val);\n"
11092          | RStringList _ ->
11093              pr "  char **strs;\n";
11094              pr "  int n, i;\n";
11095              pr "  sscanf (val, \"%%d\", &n);\n";
11096              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11097              pr "  for (i = 0; i < n; ++i) {\n";
11098              pr "    strs[i] = safe_malloc (g, 16);\n";
11099              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11100              pr "  }\n";
11101              pr "  strs[n] = NULL;\n";
11102              pr "  return strs;\n"
11103          | RStruct (_, typ) ->
11104              pr "  struct guestfs_%s *r;\n" typ;
11105              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11106              pr "  return r;\n"
11107          | RStructList (_, typ) ->
11108              pr "  struct guestfs_%s_list *r;\n" typ;
11109              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11110              pr "  sscanf (val, \"%%d\", &r->len);\n";
11111              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11112              pr "  return r;\n"
11113          | RHashtable _ ->
11114              pr "  char **strs;\n";
11115              pr "  int n, i;\n";
11116              pr "  sscanf (val, \"%%d\", &n);\n";
11117              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11118              pr "  for (i = 0; i < n; ++i) {\n";
11119              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11120              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11121              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11122              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11123              pr "  }\n";
11124              pr "  strs[n*2] = NULL;\n";
11125              pr "  return strs;\n"
11126          | RBufferOut _ ->
11127              pr "  return strdup (val);\n"
11128         );
11129         pr "}\n";
11130         pr "\n"
11131       ) else (
11132         pr "/* Test error return. */\n";
11133         generate_prototype ~extern:false ~semicolon:false ~newline:true
11134           ~handle:"g" ~prefix:"guestfs__" name style;
11135         pr "{\n";
11136         pr "  error (g, \"error\");\n";
11137         (match fst style with
11138          | RErr | RInt _ | RInt64 _ | RBool _ ->
11139              pr "  return -1;\n"
11140          | RConstString _ | RConstOptString _
11141          | RString _ | RStringList _ | RStruct _
11142          | RStructList _
11143          | RHashtable _
11144          | RBufferOut _ ->
11145              pr "  return NULL;\n"
11146         );
11147         pr "}\n";
11148         pr "\n"
11149       )
11150   ) tests
11151
11152 and generate_ocaml_bindtests () =
11153   generate_header OCamlStyle GPLv2plus;
11154
11155   pr "\
11156 let () =
11157   let g = Guestfs.create () in
11158 ";
11159
11160   let mkargs args =
11161     String.concat " " (
11162       List.map (
11163         function
11164         | CallString s -> "\"" ^ s ^ "\""
11165         | CallOptString None -> "None"
11166         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11167         | CallStringList xs ->
11168             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11169         | CallInt i when i >= 0 -> string_of_int i
11170         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11171         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11172         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11173         | CallBool b -> string_of_bool b
11174         | CallBuffer s -> sprintf "%S" s
11175       ) args
11176     )
11177   in
11178
11179   generate_lang_bindtests (
11180     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11181   );
11182
11183   pr "print_endline \"EOF\"\n"
11184
11185 and generate_perl_bindtests () =
11186   pr "#!/usr/bin/perl -w\n";
11187   generate_header HashStyle GPLv2plus;
11188
11189   pr "\
11190 use strict;
11191
11192 use Sys::Guestfs;
11193
11194 my $g = Sys::Guestfs->new ();
11195 ";
11196
11197   let mkargs args =
11198     String.concat ", " (
11199       List.map (
11200         function
11201         | CallString s -> "\"" ^ s ^ "\""
11202         | CallOptString None -> "undef"
11203         | CallOptString (Some s) -> sprintf "\"%s\"" s
11204         | CallStringList xs ->
11205             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11206         | CallInt i -> string_of_int i
11207         | CallInt64 i -> Int64.to_string i
11208         | CallBool b -> if b then "1" else "0"
11209         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11210       ) args
11211     )
11212   in
11213
11214   generate_lang_bindtests (
11215     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11216   );
11217
11218   pr "print \"EOF\\n\"\n"
11219
11220 and generate_python_bindtests () =
11221   generate_header HashStyle GPLv2plus;
11222
11223   pr "\
11224 import guestfs
11225
11226 g = guestfs.GuestFS ()
11227 ";
11228
11229   let mkargs args =
11230     String.concat ", " (
11231       List.map (
11232         function
11233         | CallString s -> "\"" ^ s ^ "\""
11234         | CallOptString None -> "None"
11235         | CallOptString (Some s) -> sprintf "\"%s\"" s
11236         | CallStringList xs ->
11237             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11238         | CallInt i -> string_of_int i
11239         | CallInt64 i -> Int64.to_string i
11240         | CallBool b -> if b then "1" else "0"
11241         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11242       ) args
11243     )
11244   in
11245
11246   generate_lang_bindtests (
11247     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11248   );
11249
11250   pr "print \"EOF\"\n"
11251
11252 and generate_ruby_bindtests () =
11253   generate_header HashStyle GPLv2plus;
11254
11255   pr "\
11256 require 'guestfs'
11257
11258 g = Guestfs::create()
11259 ";
11260
11261   let mkargs args =
11262     String.concat ", " (
11263       List.map (
11264         function
11265         | CallString s -> "\"" ^ s ^ "\""
11266         | CallOptString None -> "nil"
11267         | CallOptString (Some s) -> sprintf "\"%s\"" s
11268         | CallStringList xs ->
11269             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11270         | CallInt i -> string_of_int i
11271         | CallInt64 i -> Int64.to_string i
11272         | CallBool b -> string_of_bool b
11273         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11274       ) args
11275     )
11276   in
11277
11278   generate_lang_bindtests (
11279     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11280   );
11281
11282   pr "print \"EOF\\n\"\n"
11283
11284 and generate_java_bindtests () =
11285   generate_header CStyle GPLv2plus;
11286
11287   pr "\
11288 import com.redhat.et.libguestfs.*;
11289
11290 public class Bindtests {
11291     public static void main (String[] argv)
11292     {
11293         try {
11294             GuestFS g = new GuestFS ();
11295 ";
11296
11297   let mkargs args =
11298     String.concat ", " (
11299       List.map (
11300         function
11301         | CallString s -> "\"" ^ s ^ "\""
11302         | CallOptString None -> "null"
11303         | CallOptString (Some s) -> sprintf "\"%s\"" s
11304         | CallStringList xs ->
11305             "new String[]{" ^
11306               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11307         | CallInt i -> string_of_int i
11308         | CallInt64 i -> Int64.to_string i
11309         | CallBool b -> string_of_bool b
11310         | CallBuffer s ->
11311             "new byte[] { " ^ String.concat "," (
11312               map_chars (fun c -> string_of_int (Char.code c)) s
11313             ) ^ " }"
11314       ) args
11315     )
11316   in
11317
11318   generate_lang_bindtests (
11319     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11320   );
11321
11322   pr "
11323             System.out.println (\"EOF\");
11324         }
11325         catch (Exception exn) {
11326             System.err.println (exn);
11327             System.exit (1);
11328         }
11329     }
11330 }
11331 "
11332
11333 and generate_haskell_bindtests () =
11334   generate_header HaskellStyle GPLv2plus;
11335
11336   pr "\
11337 module Bindtests where
11338 import qualified Guestfs
11339
11340 main = do
11341   g <- Guestfs.create
11342 ";
11343
11344   let mkargs args =
11345     String.concat " " (
11346       List.map (
11347         function
11348         | CallString s -> "\"" ^ s ^ "\""
11349         | CallOptString None -> "Nothing"
11350         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11351         | CallStringList xs ->
11352             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11353         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11354         | CallInt i -> string_of_int i
11355         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11356         | CallInt64 i -> Int64.to_string i
11357         | CallBool true -> "True"
11358         | CallBool false -> "False"
11359         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11360       ) args
11361     )
11362   in
11363
11364   generate_lang_bindtests (
11365     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11366   );
11367
11368   pr "  putStrLn \"EOF\"\n"
11369
11370 (* Language-independent bindings tests - we do it this way to
11371  * ensure there is parity in testing bindings across all languages.
11372  *)
11373 and generate_lang_bindtests call =
11374   call "test0" [CallString "abc"; CallOptString (Some "def");
11375                 CallStringList []; CallBool false;
11376                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11377                 CallBuffer "abc\000abc"];
11378   call "test0" [CallString "abc"; CallOptString None;
11379                 CallStringList []; CallBool false;
11380                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11381                 CallBuffer "abc\000abc"];
11382   call "test0" [CallString ""; CallOptString (Some "def");
11383                 CallStringList []; CallBool false;
11384                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11385                 CallBuffer "abc\000abc"];
11386   call "test0" [CallString ""; CallOptString (Some "");
11387                 CallStringList []; CallBool false;
11388                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11389                 CallBuffer "abc\000abc"];
11390   call "test0" [CallString "abc"; CallOptString (Some "def");
11391                 CallStringList ["1"]; CallBool false;
11392                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11393                 CallBuffer "abc\000abc"];
11394   call "test0" [CallString "abc"; CallOptString (Some "def");
11395                 CallStringList ["1"; "2"]; CallBool false;
11396                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11397                 CallBuffer "abc\000abc"];
11398   call "test0" [CallString "abc"; CallOptString (Some "def");
11399                 CallStringList ["1"]; CallBool true;
11400                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11401                 CallBuffer "abc\000abc"];
11402   call "test0" [CallString "abc"; CallOptString (Some "def");
11403                 CallStringList ["1"]; CallBool false;
11404                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11405                 CallBuffer "abc\000abc"];
11406   call "test0" [CallString "abc"; CallOptString (Some "def");
11407                 CallStringList ["1"]; CallBool false;
11408                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11409                 CallBuffer "abc\000abc"];
11410   call "test0" [CallString "abc"; CallOptString (Some "def");
11411                 CallStringList ["1"]; CallBool false;
11412                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11413                 CallBuffer "abc\000abc"];
11414   call "test0" [CallString "abc"; CallOptString (Some "def");
11415                 CallStringList ["1"]; CallBool false;
11416                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11417                 CallBuffer "abc\000abc"];
11418   call "test0" [CallString "abc"; CallOptString (Some "def");
11419                 CallStringList ["1"]; CallBool false;
11420                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11421                 CallBuffer "abc\000abc"];
11422   call "test0" [CallString "abc"; CallOptString (Some "def");
11423                 CallStringList ["1"]; CallBool false;
11424                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11425                 CallBuffer "abc\000abc"]
11426
11427 (* XXX Add here tests of the return and error functions. *)
11428
11429 (* Code to generator bindings for virt-inspector.  Currently only
11430  * implemented for OCaml code (for virt-p2v 2.0).
11431  *)
11432 let rng_input = "inspector/virt-inspector.rng"
11433
11434 (* Read the input file and parse it into internal structures.  This is
11435  * by no means a complete RELAX NG parser, but is just enough to be
11436  * able to parse the specific input file.
11437  *)
11438 type rng =
11439   | Element of string * rng list        (* <element name=name/> *)
11440   | Attribute of string * rng list        (* <attribute name=name/> *)
11441   | Interleave of rng list                (* <interleave/> *)
11442   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11443   | OneOrMore of rng                        (* <oneOrMore/> *)
11444   | Optional of rng                        (* <optional/> *)
11445   | Choice of string list                (* <choice><value/>*</choice> *)
11446   | Value of string                        (* <value>str</value> *)
11447   | Text                                (* <text/> *)
11448
11449 let rec string_of_rng = function
11450   | Element (name, xs) ->
11451       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11452   | Attribute (name, xs) ->
11453       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11454   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11455   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11456   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11457   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11458   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11459   | Value value -> "Value \"" ^ value ^ "\""
11460   | Text -> "Text"
11461
11462 and string_of_rng_list xs =
11463   String.concat ", " (List.map string_of_rng xs)
11464
11465 let rec parse_rng ?defines context = function
11466   | [] -> []
11467   | Xml.Element ("element", ["name", name], children) :: rest ->
11468       Element (name, parse_rng ?defines context children)
11469       :: parse_rng ?defines context rest
11470   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11471       Attribute (name, parse_rng ?defines context children)
11472       :: parse_rng ?defines context rest
11473   | Xml.Element ("interleave", [], children) :: rest ->
11474       Interleave (parse_rng ?defines context children)
11475       :: parse_rng ?defines context rest
11476   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11477       let rng = parse_rng ?defines context [child] in
11478       (match rng with
11479        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11480        | _ ->
11481            failwithf "%s: <zeroOrMore> contains more than one child element"
11482              context
11483       )
11484   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11485       let rng = parse_rng ?defines context [child] in
11486       (match rng with
11487        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11488        | _ ->
11489            failwithf "%s: <oneOrMore> contains more than one child element"
11490              context
11491       )
11492   | Xml.Element ("optional", [], [child]) :: rest ->
11493       let rng = parse_rng ?defines context [child] in
11494       (match rng with
11495        | [child] -> Optional child :: parse_rng ?defines context rest
11496        | _ ->
11497            failwithf "%s: <optional> contains more than one child element"
11498              context
11499       )
11500   | Xml.Element ("choice", [], children) :: rest ->
11501       let values = List.map (
11502         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11503         | _ ->
11504             failwithf "%s: can't handle anything except <value> in <choice>"
11505               context
11506       ) children in
11507       Choice values
11508       :: parse_rng ?defines context rest
11509   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11510       Value value :: parse_rng ?defines context rest
11511   | Xml.Element ("text", [], []) :: rest ->
11512       Text :: parse_rng ?defines context rest
11513   | Xml.Element ("ref", ["name", name], []) :: rest ->
11514       (* Look up the reference.  Because of limitations in this parser,
11515        * we can't handle arbitrarily nested <ref> yet.  You can only
11516        * use <ref> from inside <start>.
11517        *)
11518       (match defines with
11519        | None ->
11520            failwithf "%s: contains <ref>, but no refs are defined yet" context
11521        | Some map ->
11522            let rng = StringMap.find name map in
11523            rng @ parse_rng ?defines context rest
11524       )
11525   | x :: _ ->
11526       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11527
11528 let grammar =
11529   let xml = Xml.parse_file rng_input in
11530   match xml with
11531   | Xml.Element ("grammar", _,
11532                  Xml.Element ("start", _, gram) :: defines) ->
11533       (* The <define/> elements are referenced in the <start> section,
11534        * so build a map of those first.
11535        *)
11536       let defines = List.fold_left (
11537         fun map ->
11538           function Xml.Element ("define", ["name", name], defn) ->
11539             StringMap.add name defn map
11540           | _ ->
11541               failwithf "%s: expected <define name=name/>" rng_input
11542       ) StringMap.empty defines in
11543       let defines = StringMap.mapi parse_rng defines in
11544
11545       (* Parse the <start> clause, passing the defines. *)
11546       parse_rng ~defines "<start>" gram
11547   | _ ->
11548       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11549         rng_input
11550
11551 let name_of_field = function
11552   | Element (name, _) | Attribute (name, _)
11553   | ZeroOrMore (Element (name, _))
11554   | OneOrMore (Element (name, _))
11555   | Optional (Element (name, _)) -> name
11556   | Optional (Attribute (name, _)) -> name
11557   | Text -> (* an unnamed field in an element *)
11558       "data"
11559   | rng ->
11560       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11561
11562 (* At the moment this function only generates OCaml types.  However we
11563  * should parameterize it later so it can generate types/structs in a
11564  * variety of languages.
11565  *)
11566 let generate_types xs =
11567   (* A simple type is one that can be printed out directly, eg.
11568    * "string option".  A complex type is one which has a name and has
11569    * to be defined via another toplevel definition, eg. a struct.
11570    *
11571    * generate_type generates code for either simple or complex types.
11572    * In the simple case, it returns the string ("string option").  In
11573    * the complex case, it returns the name ("mountpoint").  In the
11574    * complex case it has to print out the definition before returning,
11575    * so it should only be called when we are at the beginning of a
11576    * new line (BOL context).
11577    *)
11578   let rec generate_type = function
11579     | Text ->                                (* string *)
11580         "string", true
11581     | Choice values ->                        (* [`val1|`val2|...] *)
11582         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11583     | ZeroOrMore rng ->                        (* <rng> list *)
11584         let t, is_simple = generate_type rng in
11585         t ^ " list (* 0 or more *)", is_simple
11586     | OneOrMore rng ->                        (* <rng> list *)
11587         let t, is_simple = generate_type rng in
11588         t ^ " list (* 1 or more *)", is_simple
11589                                         (* virt-inspector hack: bool *)
11590     | Optional (Attribute (name, [Value "1"])) ->
11591         "bool", true
11592     | Optional rng ->                        (* <rng> list *)
11593         let t, is_simple = generate_type rng in
11594         t ^ " option", is_simple
11595                                         (* type name = { fields ... } *)
11596     | Element (name, fields) when is_attrs_interleave fields ->
11597         generate_type_struct name (get_attrs_interleave fields)
11598     | Element (name, [field])                (* type name = field *)
11599     | Attribute (name, [field]) ->
11600         let t, is_simple = generate_type field in
11601         if is_simple then (t, true)
11602         else (
11603           pr "type %s = %s\n" name t;
11604           name, false
11605         )
11606     | Element (name, fields) ->              (* type name = { fields ... } *)
11607         generate_type_struct name fields
11608     | rng ->
11609         failwithf "generate_type failed at: %s" (string_of_rng rng)
11610
11611   and is_attrs_interleave = function
11612     | [Interleave _] -> true
11613     | Attribute _ :: fields -> is_attrs_interleave fields
11614     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11615     | _ -> false
11616
11617   and get_attrs_interleave = function
11618     | [Interleave fields] -> fields
11619     | ((Attribute _) as field) :: fields
11620     | ((Optional (Attribute _)) as field) :: fields ->
11621         field :: get_attrs_interleave fields
11622     | _ -> assert false
11623
11624   and generate_types xs =
11625     List.iter (fun x -> ignore (generate_type x)) xs
11626
11627   and generate_type_struct name fields =
11628     (* Calculate the types of the fields first.  We have to do this
11629      * before printing anything so we are still in BOL context.
11630      *)
11631     let types = List.map fst (List.map generate_type fields) in
11632
11633     (* Special case of a struct containing just a string and another
11634      * field.  Turn it into an assoc list.
11635      *)
11636     match types with
11637     | ["string"; other] ->
11638         let fname1, fname2 =
11639           match fields with
11640           | [f1; f2] -> name_of_field f1, name_of_field f2
11641           | _ -> assert false in
11642         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11643         name, false
11644
11645     | types ->
11646         pr "type %s = {\n" name;
11647         List.iter (
11648           fun (field, ftype) ->
11649             let fname = name_of_field field in
11650             pr "  %s_%s : %s;\n" name fname ftype
11651         ) (List.combine fields types);
11652         pr "}\n";
11653         (* Return the name of this type, and
11654          * false because it's not a simple type.
11655          *)
11656         name, false
11657   in
11658
11659   generate_types xs
11660
11661 let generate_parsers xs =
11662   (* As for generate_type above, generate_parser makes a parser for
11663    * some type, and returns the name of the parser it has generated.
11664    * Because it (may) need to print something, it should always be
11665    * called in BOL context.
11666    *)
11667   let rec generate_parser = function
11668     | Text ->                                (* string *)
11669         "string_child_or_empty"
11670     | Choice values ->                        (* [`val1|`val2|...] *)
11671         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11672           (String.concat "|"
11673              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11674     | ZeroOrMore rng ->                        (* <rng> list *)
11675         let pa = generate_parser rng in
11676         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11677     | OneOrMore rng ->                        (* <rng> list *)
11678         let pa = generate_parser rng in
11679         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11680                                         (* virt-inspector hack: bool *)
11681     | Optional (Attribute (name, [Value "1"])) ->
11682         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11683     | Optional rng ->                        (* <rng> list *)
11684         let pa = generate_parser rng in
11685         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11686                                         (* type name = { fields ... } *)
11687     | Element (name, fields) when is_attrs_interleave fields ->
11688         generate_parser_struct name (get_attrs_interleave fields)
11689     | Element (name, [field]) ->        (* type name = field *)
11690         let pa = generate_parser field in
11691         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11692         pr "let %s =\n" parser_name;
11693         pr "  %s\n" pa;
11694         pr "let parse_%s = %s\n" name parser_name;
11695         parser_name
11696     | Attribute (name, [field]) ->
11697         let pa = generate_parser field in
11698         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11699         pr "let %s =\n" parser_name;
11700         pr "  %s\n" pa;
11701         pr "let parse_%s = %s\n" name parser_name;
11702         parser_name
11703     | Element (name, fields) ->              (* type name = { fields ... } *)
11704         generate_parser_struct name ([], fields)
11705     | rng ->
11706         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11707
11708   and is_attrs_interleave = function
11709     | [Interleave _] -> true
11710     | Attribute _ :: fields -> is_attrs_interleave fields
11711     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11712     | _ -> false
11713
11714   and get_attrs_interleave = function
11715     | [Interleave fields] -> [], fields
11716     | ((Attribute _) as field) :: fields
11717     | ((Optional (Attribute _)) as field) :: fields ->
11718         let attrs, interleaves = get_attrs_interleave fields in
11719         (field :: attrs), interleaves
11720     | _ -> assert false
11721
11722   and generate_parsers xs =
11723     List.iter (fun x -> ignore (generate_parser x)) xs
11724
11725   and generate_parser_struct name (attrs, interleaves) =
11726     (* Generate parsers for the fields first.  We have to do this
11727      * before printing anything so we are still in BOL context.
11728      *)
11729     let fields = attrs @ interleaves in
11730     let pas = List.map generate_parser fields in
11731
11732     (* Generate an intermediate tuple from all the fields first.
11733      * If the type is just a string + another field, then we will
11734      * return this directly, otherwise it is turned into a record.
11735      *
11736      * RELAX NG note: This code treats <interleave> and plain lists of
11737      * fields the same.  In other words, it doesn't bother enforcing
11738      * any ordering of fields in the XML.
11739      *)
11740     pr "let parse_%s x =\n" name;
11741     pr "  let t = (\n    ";
11742     let comma = ref false in
11743     List.iter (
11744       fun x ->
11745         if !comma then pr ",\n    ";
11746         comma := true;
11747         match x with
11748         | Optional (Attribute (fname, [field])), pa ->
11749             pr "%s x" pa
11750         | Optional (Element (fname, [field])), pa ->
11751             pr "%s (optional_child %S x)" pa fname
11752         | Attribute (fname, [Text]), _ ->
11753             pr "attribute %S x" fname
11754         | (ZeroOrMore _ | OneOrMore _), pa ->
11755             pr "%s x" pa
11756         | Text, pa ->
11757             pr "%s x" pa
11758         | (field, pa) ->
11759             let fname = name_of_field field in
11760             pr "%s (child %S x)" pa fname
11761     ) (List.combine fields pas);
11762     pr "\n  ) in\n";
11763
11764     (match fields with
11765      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11766          pr "  t\n"
11767
11768      | _ ->
11769          pr "  (Obj.magic t : %s)\n" name
11770 (*
11771          List.iter (
11772            function
11773            | (Optional (Attribute (fname, [field])), pa) ->
11774                pr "  %s_%s =\n" name fname;
11775                pr "    %s x;\n" pa
11776            | (Optional (Element (fname, [field])), pa) ->
11777                pr "  %s_%s =\n" name fname;
11778                pr "    (let x = optional_child %S x in\n" fname;
11779                pr "     %s x);\n" pa
11780            | (field, pa) ->
11781                let fname = name_of_field field in
11782                pr "  %s_%s =\n" name fname;
11783                pr "    (let x = child %S x in\n" fname;
11784                pr "     %s x);\n" pa
11785          ) (List.combine fields pas);
11786          pr "}\n"
11787 *)
11788     );
11789     sprintf "parse_%s" name
11790   in
11791
11792   generate_parsers xs
11793
11794 (* Generate ocaml/guestfs_inspector.mli. *)
11795 let generate_ocaml_inspector_mli () =
11796   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11797
11798   pr "\
11799 (** This is an OCaml language binding to the external [virt-inspector]
11800     program.
11801
11802     For more information, please read the man page [virt-inspector(1)].
11803 *)
11804
11805 ";
11806
11807   generate_types grammar;
11808   pr "(** The nested information returned from the {!inspect} function. *)\n";
11809   pr "\n";
11810
11811   pr "\
11812 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11813 (** To inspect a libvirt domain called [name], pass a singleton
11814     list: [inspect [name]].  When using libvirt only, you may
11815     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11816
11817     To inspect a disk image or images, pass a list of the filenames
11818     of the disk images: [inspect filenames]
11819
11820     This function inspects the given guest or disk images and
11821     returns a list of operating system(s) found and a large amount
11822     of information about them.  In the vast majority of cases,
11823     a virtual machine only contains a single operating system.
11824
11825     If the optional [~xml] parameter is given, then this function
11826     skips running the external virt-inspector program and just
11827     parses the given XML directly (which is expected to be XML
11828     produced from a previous run of virt-inspector).  The list of
11829     names and connect URI are ignored in this case.
11830
11831     This function can throw a wide variety of exceptions, for example
11832     if the external virt-inspector program cannot be found, or if
11833     it doesn't generate valid XML.
11834 *)
11835 "
11836
11837 (* Generate ocaml/guestfs_inspector.ml. *)
11838 let generate_ocaml_inspector_ml () =
11839   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11840
11841   pr "open Unix\n";
11842   pr "\n";
11843
11844   generate_types grammar;
11845   pr "\n";
11846
11847   pr "\
11848 (* Misc functions which are used by the parser code below. *)
11849 let first_child = function
11850   | Xml.Element (_, _, c::_) -> c
11851   | Xml.Element (name, _, []) ->
11852       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11853   | Xml.PCData str ->
11854       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11855
11856 let string_child_or_empty = function
11857   | Xml.Element (_, _, [Xml.PCData s]) -> s
11858   | Xml.Element (_, _, []) -> \"\"
11859   | Xml.Element (x, _, _) ->
11860       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11861                 x ^ \" instead\")
11862   | Xml.PCData str ->
11863       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11864
11865 let optional_child name xml =
11866   let children = Xml.children xml in
11867   try
11868     Some (List.find (function
11869                      | Xml.Element (n, _, _) when n = name -> true
11870                      | _ -> false) children)
11871   with
11872     Not_found -> None
11873
11874 let child name xml =
11875   match optional_child name xml with
11876   | Some c -> c
11877   | None ->
11878       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11879
11880 let attribute name xml =
11881   try Xml.attrib xml name
11882   with Xml.No_attribute _ ->
11883     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11884
11885 ";
11886
11887   generate_parsers grammar;
11888   pr "\n";
11889
11890   pr "\
11891 (* Run external virt-inspector, then use parser to parse the XML. *)
11892 let inspect ?connect ?xml names =
11893   let xml =
11894     match xml with
11895     | None ->
11896         if names = [] then invalid_arg \"inspect: no names given\";
11897         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11898           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11899           names in
11900         let cmd = List.map Filename.quote cmd in
11901         let cmd = String.concat \" \" cmd in
11902         let chan = open_process_in cmd in
11903         let xml = Xml.parse_in chan in
11904         (match close_process_in chan with
11905          | WEXITED 0 -> ()
11906          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11907          | WSIGNALED i | WSTOPPED i ->
11908              failwith (\"external virt-inspector command died or stopped on sig \" ^
11909                        string_of_int i)
11910         );
11911         xml
11912     | Some doc ->
11913         Xml.parse_string doc in
11914   parse_operatingsystems xml
11915 "
11916
11917 and generate_max_proc_nr () =
11918   pr "%d\n" max_proc_nr
11919
11920 let output_to filename k =
11921   let filename_new = filename ^ ".new" in
11922   chan := open_out filename_new;
11923   k ();
11924   close_out !chan;
11925   chan := Pervasives.stdout;
11926
11927   (* Is the new file different from the current file? *)
11928   if Sys.file_exists filename && files_equal filename filename_new then
11929     unlink filename_new                 (* same, so skip it *)
11930   else (
11931     (* different, overwrite old one *)
11932     (try chmod filename 0o644 with Unix_error _ -> ());
11933     rename filename_new filename;
11934     chmod filename 0o444;
11935     printf "written %s\n%!" filename;
11936   )
11937
11938 let perror msg = function
11939   | Unix_error (err, _, _) ->
11940       eprintf "%s: %s\n" msg (error_message err)
11941   | exn ->
11942       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11943
11944 (* Main program. *)
11945 let () =
11946   let lock_fd =
11947     try openfile "HACKING" [O_RDWR] 0
11948     with
11949     | Unix_error (ENOENT, _, _) ->
11950         eprintf "\
11951 You are probably running this from the wrong directory.
11952 Run it from the top source directory using the command
11953   src/generator.ml
11954 ";
11955         exit 1
11956     | exn ->
11957         perror "open: HACKING" exn;
11958         exit 1 in
11959
11960   (* Acquire a lock so parallel builds won't try to run the generator
11961    * twice at the same time.  Subsequent builds will wait for the first
11962    * one to finish.  Note the lock is released implicitly when the
11963    * program exits.
11964    *)
11965   (try lockf lock_fd F_LOCK 1
11966    with exn ->
11967      perror "lock: HACKING" exn;
11968      exit 1);
11969
11970   check_functions ();
11971
11972   output_to "src/guestfs_protocol.x" generate_xdr;
11973   output_to "src/guestfs-structs.h" generate_structs_h;
11974   output_to "src/guestfs-actions.h" generate_actions_h;
11975   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11976   output_to "src/guestfs-actions.c" generate_client_actions;
11977   output_to "src/guestfs-bindtests.c" generate_bindtests;
11978   output_to "src/guestfs-structs.pod" generate_structs_pod;
11979   output_to "src/guestfs-actions.pod" generate_actions_pod;
11980   output_to "src/guestfs-availability.pod" generate_availability_pod;
11981   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11982   output_to "src/libguestfs.syms" generate_linker_script;
11983   output_to "daemon/actions.h" generate_daemon_actions_h;
11984   output_to "daemon/stubs.c" generate_daemon_actions;
11985   output_to "daemon/names.c" generate_daemon_names;
11986   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11987   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11988   output_to "capitests/tests.c" generate_tests;
11989   output_to "fish/cmds.c" generate_fish_cmds;
11990   output_to "fish/completion.c" generate_fish_completion;
11991   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11992   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11993   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11994   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11995   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11996   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11997   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11998   output_to "perl/Guestfs.xs" generate_perl_xs;
11999   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12000   output_to "perl/bindtests.pl" generate_perl_bindtests;
12001   output_to "python/guestfs-py.c" generate_python_c;
12002   output_to "python/guestfs.py" generate_python_py;
12003   output_to "python/bindtests.py" generate_python_bindtests;
12004   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12005   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12006   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12007
12008   List.iter (
12009     fun (typ, jtyp) ->
12010       let cols = cols_of_struct typ in
12011       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12012       output_to filename (generate_java_struct jtyp cols);
12013   ) java_structs;
12014
12015   output_to "java/Makefile.inc" generate_java_makefile_inc;
12016   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12017   output_to "java/Bindtests.java" generate_java_bindtests;
12018   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12019   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12020   output_to "csharp/Libguestfs.cs" generate_csharp;
12021
12022   (* Always generate this file last, and unconditionally.  It's used
12023    * by the Makefile to know when we must re-run the generator.
12024    *)
12025   let chan = open_out "src/stamp-generator" in
12026   fprintf chan "1\n";
12027   close_out chan;
12028
12029   printf "generated %d lines of code\n" !lines