58eaee45264cf70e2c41b7d4dbef4913bd8370eb
[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 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
811
812 I<Note:> Don't use this call to test for availability
813 of features.  In enterprise distributions we backport
814 features from later versions into earlier versions,
815 making this an unreliable way to test for features.
816 Use C<guestfs_available> instead.");
817
818   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
819    [InitNone, Always, TestOutputTrue (
820       [["set_selinux"; "true"];
821        ["get_selinux"]])],
822    "set SELinux enabled or disabled at appliance boot",
823    "\
824 This sets the selinux flag that is passed to the appliance
825 at boot time.  The default is C<selinux=0> (disabled).
826
827 Note that if SELinux is enabled, it is always in
828 Permissive mode (C<enforcing=0>).
829
830 For more information on the architecture of libguestfs,
831 see L<guestfs(3)>.");
832
833   ("get_selinux", (RBool "selinux", []), -1, [],
834    [],
835    "get SELinux enabled flag",
836    "\
837 This returns the current setting of the selinux flag which
838 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
839
840 For more information on the architecture of libguestfs,
841 see L<guestfs(3)>.");
842
843   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
844    [InitNone, Always, TestOutputFalse (
845       [["set_trace"; "false"];
846        ["get_trace"]])],
847    "enable or disable command traces",
848    "\
849 If the command trace flag is set to 1, then commands are
850 printed on stdout before they are executed in a format
851 which is very similar to the one used by guestfish.  In
852 other words, you can run a program with this enabled, and
853 you will get out a script which you can feed to guestfish
854 to perform the same set of actions.
855
856 If you want to trace C API calls into libguestfs (and
857 other libraries) then possibly a better way is to use
858 the external ltrace(1) command.
859
860 Command traces are disabled unless the environment variable
861 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
862
863   ("get_trace", (RBool "trace", []), -1, [],
864    [],
865    "get command trace enabled flag",
866    "\
867 Return the command trace flag.");
868
869   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
870    [InitNone, Always, TestOutputFalse (
871       [["set_direct"; "false"];
872        ["get_direct"]])],
873    "enable or disable direct appliance mode",
874    "\
875 If the direct appliance mode flag is enabled, then stdin and
876 stdout are passed directly through to the appliance once it
877 is launched.
878
879 One consequence of this is that log messages aren't caught
880 by the library and handled by C<guestfs_set_log_message_callback>,
881 but go straight to stdout.
882
883 You probably don't want to use this unless you know what you
884 are doing.
885
886 The default is disabled.");
887
888   ("get_direct", (RBool "direct", []), -1, [],
889    [],
890    "get direct appliance mode flag",
891    "\
892 Return the direct appliance mode flag.");
893
894   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
895    [InitNone, Always, TestOutputTrue (
896       [["set_recovery_proc"; "true"];
897        ["get_recovery_proc"]])],
898    "enable or disable the recovery process",
899    "\
900 If this is called with the parameter C<false> then
901 C<guestfs_launch> does not create a recovery process.  The
902 purpose of the recovery process is to stop runaway qemu
903 processes in the case where the main program aborts abruptly.
904
905 This only has any effect if called before C<guestfs_launch>,
906 and the default is true.
907
908 About the only time when you would want to disable this is
909 if the main process will fork itself into the background
910 (\"daemonize\" itself).  In this case the recovery process
911 thinks that the main program has disappeared and so kills
912 qemu, which is not very helpful.");
913
914   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
915    [],
916    "get recovery process enabled flag",
917    "\
918 Return the recovery process enabled flag.");
919
920   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
921    [],
922    "add a drive specifying the QEMU block emulation to use",
923    "\
924 This is the same as C<guestfs_add_drive> but it allows you
925 to specify the QEMU interface emulation to use at run time.");
926
927   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
928    [],
929    "add a drive read-only specifying the QEMU block emulation to use",
930    "\
931 This is the same as C<guestfs_add_drive_ro> but it allows you
932 to specify the QEMU interface emulation to use at run time.");
933
934 ]
935
936 (* daemon_functions are any functions which cause some action
937  * to take place in the daemon.
938  *)
939
940 let daemon_functions = [
941   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
942    [InitEmpty, Always, TestOutput (
943       [["part_disk"; "/dev/sda"; "mbr"];
944        ["mkfs"; "ext2"; "/dev/sda1"];
945        ["mount"; "/dev/sda1"; "/"];
946        ["write"; "/new"; "new file contents"];
947        ["cat"; "/new"]], "new file contents")],
948    "mount a guest disk at a position in the filesystem",
949    "\
950 Mount a guest disk at a position in the filesystem.  Block devices
951 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
952 the guest.  If those block devices contain partitions, they will have
953 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
954 names can be used.
955
956 The rules are the same as for L<mount(2)>:  A filesystem must
957 first be mounted on C</> before others can be mounted.  Other
958 filesystems can only be mounted on directories which already
959 exist.
960
961 The mounted filesystem is writable, if we have sufficient permissions
962 on the underlying device.
963
964 B<Important note:>
965 When you use this call, the filesystem options C<sync> and C<noatime>
966 are set implicitly.  This was originally done because we thought it
967 would improve reliability, but it turns out that I<-o sync> has a
968 very large negative performance impact and negligible effect on
969 reliability.  Therefore we recommend that you avoid using
970 C<guestfs_mount> in any code that needs performance, and instead
971 use C<guestfs_mount_options> (use an empty string for the first
972 parameter if you don't want any options).");
973
974   ("sync", (RErr, []), 2, [],
975    [ InitEmpty, Always, TestRun [["sync"]]],
976    "sync disks, writes are flushed through to the disk image",
977    "\
978 This syncs the disk, so that any writes are flushed through to the
979 underlying disk image.
980
981 You should always call this if you have modified a disk image, before
982 closing the handle.");
983
984   ("touch", (RErr, [Pathname "path"]), 3, [],
985    [InitBasicFS, Always, TestOutputTrue (
986       [["touch"; "/new"];
987        ["exists"; "/new"]])],
988    "update file timestamps or create a new file",
989    "\
990 Touch acts like the L<touch(1)> command.  It can be used to
991 update the timestamps on a file, or, if the file does not exist,
992 to create a new zero-length file.");
993
994   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
995    [InitISOFS, Always, TestOutput (
996       [["cat"; "/known-2"]], "abcdef\n")],
997    "list the contents of a file",
998    "\
999 Return the contents of the file named C<path>.
1000
1001 Note that this function cannot correctly handle binary files
1002 (specifically, files containing C<\\0> character which is treated
1003 as end of string).  For those you need to use the C<guestfs_read_file>
1004 or C<guestfs_download> functions which have a more complex interface.");
1005
1006   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1007    [], (* XXX Tricky to test because it depends on the exact format
1008         * of the 'ls -l' command, which changes between F10 and F11.
1009         *)
1010    "list the files in a directory (long format)",
1011    "\
1012 List the files in C<directory> (relative to the root directory,
1013 there is no cwd) in the format of 'ls -la'.
1014
1015 This command is mostly useful for interactive sessions.  It
1016 is I<not> intended that you try to parse the output string.");
1017
1018   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1019    [InitBasicFS, Always, TestOutputList (
1020       [["touch"; "/new"];
1021        ["touch"; "/newer"];
1022        ["touch"; "/newest"];
1023        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1024    "list the files in a directory",
1025    "\
1026 List the files in C<directory> (relative to the root directory,
1027 there is no cwd).  The '.' and '..' entries are not returned, but
1028 hidden files are shown.
1029
1030 This command is mostly useful for interactive sessions.  Programs
1031 should probably use C<guestfs_readdir> instead.");
1032
1033   ("list_devices", (RStringList "devices", []), 7, [],
1034    [InitEmpty, Always, TestOutputListOfDevices (
1035       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1036    "list the block devices",
1037    "\
1038 List all the block devices.
1039
1040 The full block device names are returned, eg. C</dev/sda>");
1041
1042   ("list_partitions", (RStringList "partitions", []), 8, [],
1043    [InitBasicFS, Always, TestOutputListOfDevices (
1044       [["list_partitions"]], ["/dev/sda1"]);
1045     InitEmpty, Always, TestOutputListOfDevices (
1046       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1048    "list the partitions",
1049    "\
1050 List all the partitions detected on all block devices.
1051
1052 The full partition device names are returned, eg. C</dev/sda1>
1053
1054 This does not return logical volumes.  For that you will need to
1055 call C<guestfs_lvs>.");
1056
1057   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1058    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1059       [["pvs"]], ["/dev/sda1"]);
1060     InitEmpty, Always, TestOutputListOfDevices (
1061       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1062        ["pvcreate"; "/dev/sda1"];
1063        ["pvcreate"; "/dev/sda2"];
1064        ["pvcreate"; "/dev/sda3"];
1065        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1066    "list the LVM physical volumes (PVs)",
1067    "\
1068 List all the physical volumes detected.  This is the equivalent
1069 of the L<pvs(8)> command.
1070
1071 This returns a list of just the device names that contain
1072 PVs (eg. C</dev/sda2>).
1073
1074 See also C<guestfs_pvs_full>.");
1075
1076   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1077    [InitBasicFSonLVM, Always, TestOutputList (
1078       [["vgs"]], ["VG"]);
1079     InitEmpty, Always, TestOutputList (
1080       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1081        ["pvcreate"; "/dev/sda1"];
1082        ["pvcreate"; "/dev/sda2"];
1083        ["pvcreate"; "/dev/sda3"];
1084        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1085        ["vgcreate"; "VG2"; "/dev/sda3"];
1086        ["vgs"]], ["VG1"; "VG2"])],
1087    "list the LVM volume groups (VGs)",
1088    "\
1089 List all the volumes groups detected.  This is the equivalent
1090 of the L<vgs(8)> command.
1091
1092 This returns a list of just the volume group names that were
1093 detected (eg. C<VolGroup00>).
1094
1095 See also C<guestfs_vgs_full>.");
1096
1097   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1098    [InitBasicFSonLVM, Always, TestOutputList (
1099       [["lvs"]], ["/dev/VG/LV"]);
1100     InitEmpty, Always, TestOutputList (
1101       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1102        ["pvcreate"; "/dev/sda1"];
1103        ["pvcreate"; "/dev/sda2"];
1104        ["pvcreate"; "/dev/sda3"];
1105        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1106        ["vgcreate"; "VG2"; "/dev/sda3"];
1107        ["lvcreate"; "LV1"; "VG1"; "50"];
1108        ["lvcreate"; "LV2"; "VG1"; "50"];
1109        ["lvcreate"; "LV3"; "VG2"; "50"];
1110        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1111    "list the LVM logical volumes (LVs)",
1112    "\
1113 List all the logical volumes detected.  This is the equivalent
1114 of the L<lvs(8)> command.
1115
1116 This returns a list of the logical volume device names
1117 (eg. C</dev/VolGroup00/LogVol00>).
1118
1119 See also C<guestfs_lvs_full>.");
1120
1121   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1122    [], (* XXX how to test? *)
1123    "list the LVM physical volumes (PVs)",
1124    "\
1125 List all the physical volumes detected.  This is the equivalent
1126 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1127
1128   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1129    [], (* XXX how to test? *)
1130    "list the LVM volume groups (VGs)",
1131    "\
1132 List all the volumes groups detected.  This is the equivalent
1133 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1134
1135   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1136    [], (* XXX how to test? *)
1137    "list the LVM logical volumes (LVs)",
1138    "\
1139 List all the logical volumes detected.  This is the equivalent
1140 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1141
1142   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1143    [InitISOFS, Always, TestOutputList (
1144       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1145     InitISOFS, Always, TestOutputList (
1146       [["read_lines"; "/empty"]], [])],
1147    "read file as lines",
1148    "\
1149 Return the contents of the file named C<path>.
1150
1151 The file contents are returned as a list of lines.  Trailing
1152 C<LF> and C<CRLF> character sequences are I<not> returned.
1153
1154 Note that this function cannot correctly handle binary files
1155 (specifically, files containing C<\\0> character which is treated
1156 as end of line).  For those you need to use the C<guestfs_read_file>
1157 function which has a more complex interface.");
1158
1159   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1160    [], (* XXX Augeas code needs tests. *)
1161    "create a new Augeas handle",
1162    "\
1163 Create a new Augeas handle for editing configuration files.
1164 If there was any previous Augeas handle associated with this
1165 guestfs session, then it is closed.
1166
1167 You must call this before using any other C<guestfs_aug_*>
1168 commands.
1169
1170 C<root> is the filesystem root.  C<root> must not be NULL,
1171 use C</> instead.
1172
1173 The flags are the same as the flags defined in
1174 E<lt>augeas.hE<gt>, the logical I<or> of the following
1175 integers:
1176
1177 =over 4
1178
1179 =item C<AUG_SAVE_BACKUP> = 1
1180
1181 Keep the original file with a C<.augsave> extension.
1182
1183 =item C<AUG_SAVE_NEWFILE> = 2
1184
1185 Save changes into a file with extension C<.augnew>, and
1186 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1187
1188 =item C<AUG_TYPE_CHECK> = 4
1189
1190 Typecheck lenses (can be expensive).
1191
1192 =item C<AUG_NO_STDINC> = 8
1193
1194 Do not use standard load path for modules.
1195
1196 =item C<AUG_SAVE_NOOP> = 16
1197
1198 Make save a no-op, just record what would have been changed.
1199
1200 =item C<AUG_NO_LOAD> = 32
1201
1202 Do not load the tree in C<guestfs_aug_init>.
1203
1204 =back
1205
1206 To close the handle, you can call C<guestfs_aug_close>.
1207
1208 To find out more about Augeas, see L<http://augeas.net/>.");
1209
1210   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1211    [], (* XXX Augeas code needs tests. *)
1212    "close the current Augeas handle",
1213    "\
1214 Close the current Augeas handle and free up any resources
1215 used by it.  After calling this, you have to call
1216 C<guestfs_aug_init> again before you can use any other
1217 Augeas functions.");
1218
1219   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1220    [], (* XXX Augeas code needs tests. *)
1221    "define an Augeas variable",
1222    "\
1223 Defines an Augeas variable C<name> whose value is the result
1224 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1225 undefined.
1226
1227 On success this returns the number of nodes in C<expr>, or
1228 C<0> if C<expr> evaluates to something which is not a nodeset.");
1229
1230   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1231    [], (* XXX Augeas code needs tests. *)
1232    "define an Augeas node",
1233    "\
1234 Defines a variable C<name> whose value is the result of
1235 evaluating C<expr>.
1236
1237 If C<expr> evaluates to an empty nodeset, a node is created,
1238 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1239 C<name> will be the nodeset containing that single node.
1240
1241 On success this returns a pair containing the
1242 number of nodes in the nodeset, and a boolean flag
1243 if a node was created.");
1244
1245   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1246    [], (* XXX Augeas code needs tests. *)
1247    "look up the value of an Augeas path",
1248    "\
1249 Look up the value associated with C<path>.  If C<path>
1250 matches exactly one node, the C<value> is returned.");
1251
1252   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1253    [], (* XXX Augeas code needs tests. *)
1254    "set Augeas path to value",
1255    "\
1256 Set the value associated with C<path> to C<val>.
1257
1258 In the Augeas API, it is possible to clear a node by setting
1259 the value to NULL.  Due to an oversight in the libguestfs API
1260 you cannot do that with this call.  Instead you must use the
1261 C<guestfs_aug_clear> call.");
1262
1263   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "insert a sibling Augeas node",
1266    "\
1267 Create a new sibling C<label> for C<path>, inserting it into
1268 the tree before or after C<path> (depending on the boolean
1269 flag C<before>).
1270
1271 C<path> must match exactly one existing node in the tree, and
1272 C<label> must be a label, ie. not contain C</>, C<*> or end
1273 with a bracketed index C<[N]>.");
1274
1275   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1276    [], (* XXX Augeas code needs tests. *)
1277    "remove an Augeas path",
1278    "\
1279 Remove C<path> and all of its children.
1280
1281 On success this returns the number of entries which were removed.");
1282
1283   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1284    [], (* XXX Augeas code needs tests. *)
1285    "move Augeas node",
1286    "\
1287 Move the node C<src> to C<dest>.  C<src> must match exactly
1288 one node.  C<dest> is overwritten if it exists.");
1289
1290   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1291    [], (* XXX Augeas code needs tests. *)
1292    "return Augeas nodes which match augpath",
1293    "\
1294 Returns a list of paths which match the path expression C<path>.
1295 The returned paths are sufficiently qualified so that they match
1296 exactly one node in the current tree.");
1297
1298   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1299    [], (* XXX Augeas code needs tests. *)
1300    "write all pending Augeas changes to disk",
1301    "\
1302 This writes all pending changes to disk.
1303
1304 The flags which were passed to C<guestfs_aug_init> affect exactly
1305 how files are saved.");
1306
1307   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1308    [], (* XXX Augeas code needs tests. *)
1309    "load files into the tree",
1310    "\
1311 Load files into the tree.
1312
1313 See C<aug_load> in the Augeas documentation for the full gory
1314 details.");
1315
1316   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1317    [], (* XXX Augeas code needs tests. *)
1318    "list Augeas nodes under augpath",
1319    "\
1320 This is just a shortcut for listing C<guestfs_aug_match>
1321 C<path/*> and sorting the resulting nodes into alphabetical order.");
1322
1323   ("rm", (RErr, [Pathname "path"]), 29, [],
1324    [InitBasicFS, Always, TestRun
1325       [["touch"; "/new"];
1326        ["rm"; "/new"]];
1327     InitBasicFS, Always, TestLastFail
1328       [["rm"; "/new"]];
1329     InitBasicFS, Always, TestLastFail
1330       [["mkdir"; "/new"];
1331        ["rm"; "/new"]]],
1332    "remove a file",
1333    "\
1334 Remove the single file C<path>.");
1335
1336   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1337    [InitBasicFS, Always, TestRun
1338       [["mkdir"; "/new"];
1339        ["rmdir"; "/new"]];
1340     InitBasicFS, Always, TestLastFail
1341       [["rmdir"; "/new"]];
1342     InitBasicFS, Always, TestLastFail
1343       [["touch"; "/new"];
1344        ["rmdir"; "/new"]]],
1345    "remove a directory",
1346    "\
1347 Remove the single directory C<path>.");
1348
1349   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1350    [InitBasicFS, Always, TestOutputFalse
1351       [["mkdir"; "/new"];
1352        ["mkdir"; "/new/foo"];
1353        ["touch"; "/new/foo/bar"];
1354        ["rm_rf"; "/new"];
1355        ["exists"; "/new"]]],
1356    "remove a file or directory recursively",
1357    "\
1358 Remove the file or directory C<path>, recursively removing the
1359 contents if its a directory.  This is like the C<rm -rf> shell
1360 command.");
1361
1362   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1363    [InitBasicFS, Always, TestOutputTrue
1364       [["mkdir"; "/new"];
1365        ["is_dir"; "/new"]];
1366     InitBasicFS, Always, TestLastFail
1367       [["mkdir"; "/new/foo/bar"]]],
1368    "create a directory",
1369    "\
1370 Create a directory named C<path>.");
1371
1372   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1373    [InitBasicFS, Always, TestOutputTrue
1374       [["mkdir_p"; "/new/foo/bar"];
1375        ["is_dir"; "/new/foo/bar"]];
1376     InitBasicFS, Always, TestOutputTrue
1377       [["mkdir_p"; "/new/foo/bar"];
1378        ["is_dir"; "/new/foo"]];
1379     InitBasicFS, Always, TestOutputTrue
1380       [["mkdir_p"; "/new/foo/bar"];
1381        ["is_dir"; "/new"]];
1382     (* Regression tests for RHBZ#503133: *)
1383     InitBasicFS, Always, TestRun
1384       [["mkdir"; "/new"];
1385        ["mkdir_p"; "/new"]];
1386     InitBasicFS, Always, TestLastFail
1387       [["touch"; "/new"];
1388        ["mkdir_p"; "/new"]]],
1389    "create a directory and parents",
1390    "\
1391 Create a directory named C<path>, creating any parent directories
1392 as necessary.  This is like the C<mkdir -p> shell command.");
1393
1394   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1395    [], (* XXX Need stat command to test *)
1396    "change file mode",
1397    "\
1398 Change the mode (permissions) of C<path> to C<mode>.  Only
1399 numeric modes are supported.
1400
1401 I<Note>: When using this command from guestfish, C<mode>
1402 by default would be decimal, unless you prefix it with
1403 C<0> to get octal, ie. use C<0700> not C<700>.
1404
1405 The mode actually set is affected by the umask.");
1406
1407   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1408    [], (* XXX Need stat command to test *)
1409    "change file owner and group",
1410    "\
1411 Change the file owner to C<owner> and group to C<group>.
1412
1413 Only numeric uid and gid are supported.  If you want to use
1414 names, you will need to locate and parse the password file
1415 yourself (Augeas support makes this relatively easy).");
1416
1417   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1418    [InitISOFS, Always, TestOutputTrue (
1419       [["exists"; "/empty"]]);
1420     InitISOFS, Always, TestOutputTrue (
1421       [["exists"; "/directory"]])],
1422    "test if file or directory exists",
1423    "\
1424 This returns C<true> if and only if there is a file, directory
1425 (or anything) with the given C<path> name.
1426
1427 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1428
1429   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1430    [InitISOFS, Always, TestOutputTrue (
1431       [["is_file"; "/known-1"]]);
1432     InitISOFS, Always, TestOutputFalse (
1433       [["is_file"; "/directory"]])],
1434    "test if file exists",
1435    "\
1436 This returns C<true> if and only if there is a file
1437 with the given C<path> name.  Note that it returns false for
1438 other objects like directories.
1439
1440 See also C<guestfs_stat>.");
1441
1442   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1443    [InitISOFS, Always, TestOutputFalse (
1444       [["is_dir"; "/known-3"]]);
1445     InitISOFS, Always, TestOutputTrue (
1446       [["is_dir"; "/directory"]])],
1447    "test if file exists",
1448    "\
1449 This returns C<true> if and only if there is a directory
1450 with the given C<path> name.  Note that it returns false for
1451 other objects like files.
1452
1453 See also C<guestfs_stat>.");
1454
1455   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1456    [InitEmpty, Always, TestOutputListOfDevices (
1457       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1458        ["pvcreate"; "/dev/sda1"];
1459        ["pvcreate"; "/dev/sda2"];
1460        ["pvcreate"; "/dev/sda3"];
1461        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1462    "create an LVM physical volume",
1463    "\
1464 This creates an LVM physical volume on the named C<device>,
1465 where C<device> should usually be a partition name such
1466 as C</dev/sda1>.");
1467
1468   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1469    [InitEmpty, Always, TestOutputList (
1470       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1471        ["pvcreate"; "/dev/sda1"];
1472        ["pvcreate"; "/dev/sda2"];
1473        ["pvcreate"; "/dev/sda3"];
1474        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1475        ["vgcreate"; "VG2"; "/dev/sda3"];
1476        ["vgs"]], ["VG1"; "VG2"])],
1477    "create an LVM volume group",
1478    "\
1479 This creates an LVM volume group called C<volgroup>
1480 from the non-empty list of physical volumes C<physvols>.");
1481
1482   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1483    [InitEmpty, Always, TestOutputList (
1484       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1485        ["pvcreate"; "/dev/sda1"];
1486        ["pvcreate"; "/dev/sda2"];
1487        ["pvcreate"; "/dev/sda3"];
1488        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1489        ["vgcreate"; "VG2"; "/dev/sda3"];
1490        ["lvcreate"; "LV1"; "VG1"; "50"];
1491        ["lvcreate"; "LV2"; "VG1"; "50"];
1492        ["lvcreate"; "LV3"; "VG2"; "50"];
1493        ["lvcreate"; "LV4"; "VG2"; "50"];
1494        ["lvcreate"; "LV5"; "VG2"; "50"];
1495        ["lvs"]],
1496       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1497        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1498    "create an LVM logical volume",
1499    "\
1500 This creates an LVM logical volume called C<logvol>
1501 on the volume group C<volgroup>, with C<size> megabytes.");
1502
1503   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1504    [InitEmpty, Always, TestOutput (
1505       [["part_disk"; "/dev/sda"; "mbr"];
1506        ["mkfs"; "ext2"; "/dev/sda1"];
1507        ["mount_options"; ""; "/dev/sda1"; "/"];
1508        ["write"; "/new"; "new file contents"];
1509        ["cat"; "/new"]], "new file contents")],
1510    "make a filesystem",
1511    "\
1512 This creates a filesystem on C<device> (usually a partition
1513 or LVM logical volume).  The filesystem type is C<fstype>, for
1514 example C<ext3>.");
1515
1516   ("sfdisk", (RErr, [Device "device";
1517                      Int "cyls"; Int "heads"; Int "sectors";
1518                      StringList "lines"]), 43, [DangerWillRobinson],
1519    [],
1520    "create partitions on a block device",
1521    "\
1522 This is a direct interface to the L<sfdisk(8)> program for creating
1523 partitions on block devices.
1524
1525 C<device> should be a block device, for example C</dev/sda>.
1526
1527 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1528 and sectors on the device, which are passed directly to sfdisk as
1529 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1530 of these, then the corresponding parameter is omitted.  Usually for
1531 'large' disks, you can just pass C<0> for these, but for small
1532 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1533 out the right geometry and you will need to tell it.
1534
1535 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1536 information refer to the L<sfdisk(8)> manpage.
1537
1538 To create a single partition occupying the whole disk, you would
1539 pass C<lines> as a single element list, when the single element being
1540 the string C<,> (comma).
1541
1542 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1543 C<guestfs_part_init>");
1544
1545   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1546    [],
1547    "create a file",
1548    "\
1549 This call creates a file called C<path>.  The contents of the
1550 file is the string C<content> (which can contain any 8 bit data),
1551 with length C<size>.
1552
1553 As a special case, if C<size> is C<0>
1554 then the length is calculated using C<strlen> (so in this case
1555 the content cannot contain embedded ASCII NULs).
1556
1557 I<NB.> Owing to a bug, writing content containing ASCII NUL
1558 characters does I<not> work, even if the length is specified.");
1559
1560   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1561    [InitEmpty, Always, TestOutputListOfDevices (
1562       [["part_disk"; "/dev/sda"; "mbr"];
1563        ["mkfs"; "ext2"; "/dev/sda1"];
1564        ["mount_options"; ""; "/dev/sda1"; "/"];
1565        ["mounts"]], ["/dev/sda1"]);
1566     InitEmpty, Always, TestOutputList (
1567       [["part_disk"; "/dev/sda"; "mbr"];
1568        ["mkfs"; "ext2"; "/dev/sda1"];
1569        ["mount_options"; ""; "/dev/sda1"; "/"];
1570        ["umount"; "/"];
1571        ["mounts"]], [])],
1572    "unmount a filesystem",
1573    "\
1574 This unmounts the given filesystem.  The filesystem may be
1575 specified either by its mountpoint (path) or the device which
1576 contains the filesystem.");
1577
1578   ("mounts", (RStringList "devices", []), 46, [],
1579    [InitBasicFS, Always, TestOutputListOfDevices (
1580       [["mounts"]], ["/dev/sda1"])],
1581    "show mounted filesystems",
1582    "\
1583 This returns the list of currently mounted filesystems.  It returns
1584 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1585
1586 Some internal mounts are not shown.
1587
1588 See also: C<guestfs_mountpoints>");
1589
1590   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1591    [InitBasicFS, Always, TestOutputList (
1592       [["umount_all"];
1593        ["mounts"]], []);
1594     (* check that umount_all can unmount nested mounts correctly: *)
1595     InitEmpty, Always, TestOutputList (
1596       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1597        ["mkfs"; "ext2"; "/dev/sda1"];
1598        ["mkfs"; "ext2"; "/dev/sda2"];
1599        ["mkfs"; "ext2"; "/dev/sda3"];
1600        ["mount_options"; ""; "/dev/sda1"; "/"];
1601        ["mkdir"; "/mp1"];
1602        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1603        ["mkdir"; "/mp1/mp2"];
1604        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1605        ["mkdir"; "/mp1/mp2/mp3"];
1606        ["umount_all"];
1607        ["mounts"]], [])],
1608    "unmount all filesystems",
1609    "\
1610 This unmounts all mounted filesystems.
1611
1612 Some internal mounts are not unmounted by this call.");
1613
1614   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1615    [],
1616    "remove all LVM LVs, VGs and PVs",
1617    "\
1618 This command removes all LVM logical volumes, volume groups
1619 and physical volumes.");
1620
1621   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1622    [InitISOFS, Always, TestOutput (
1623       [["file"; "/empty"]], "empty");
1624     InitISOFS, Always, TestOutput (
1625       [["file"; "/known-1"]], "ASCII text");
1626     InitISOFS, Always, TestLastFail (
1627       [["file"; "/notexists"]])],
1628    "determine file type",
1629    "\
1630 This call uses the standard L<file(1)> command to determine
1631 the type or contents of the file.  This also works on devices,
1632 for example to find out whether a partition contains a filesystem.
1633
1634 This call will also transparently look inside various types
1635 of compressed file.
1636
1637 The exact command which runs is C<file -zbsL path>.  Note in
1638 particular that the filename is not prepended to the output
1639 (the C<-b> option).");
1640
1641   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1642    [InitBasicFS, Always, TestOutput (
1643       [["upload"; "test-command"; "/test-command"];
1644        ["chmod"; "0o755"; "/test-command"];
1645        ["command"; "/test-command 1"]], "Result1");
1646     InitBasicFS, Always, TestOutput (
1647       [["upload"; "test-command"; "/test-command"];
1648        ["chmod"; "0o755"; "/test-command"];
1649        ["command"; "/test-command 2"]], "Result2\n");
1650     InitBasicFS, Always, TestOutput (
1651       [["upload"; "test-command"; "/test-command"];
1652        ["chmod"; "0o755"; "/test-command"];
1653        ["command"; "/test-command 3"]], "\nResult3");
1654     InitBasicFS, Always, TestOutput (
1655       [["upload"; "test-command"; "/test-command"];
1656        ["chmod"; "0o755"; "/test-command"];
1657        ["command"; "/test-command 4"]], "\nResult4\n");
1658     InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 5"]], "\nResult5\n\n");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 7"]], "");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 8"]], "\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 9"]], "\n\n");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1682     InitBasicFS, Always, TestOutput (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1686     InitBasicFS, Always, TestLastFail (
1687       [["upload"; "test-command"; "/test-command"];
1688        ["chmod"; "0o755"; "/test-command"];
1689        ["command"; "/test-command"]])],
1690    "run a command from the guest filesystem",
1691    "\
1692 This call runs a command from the guest filesystem.  The
1693 filesystem must be mounted, and must contain a compatible
1694 operating system (ie. something Linux, with the same
1695 or compatible processor architecture).
1696
1697 The single parameter is an argv-style list of arguments.
1698 The first element is the name of the program to run.
1699 Subsequent elements are parameters.  The list must be
1700 non-empty (ie. must contain a program name).  Note that
1701 the command runs directly, and is I<not> invoked via
1702 the shell (see C<guestfs_sh>).
1703
1704 The return value is anything printed to I<stdout> by
1705 the command.
1706
1707 If the command returns a non-zero exit status, then
1708 this function returns an error message.  The error message
1709 string is the content of I<stderr> from the command.
1710
1711 The C<$PATH> environment variable will contain at least
1712 C</usr/bin> and C</bin>.  If you require a program from
1713 another location, you should provide the full path in the
1714 first parameter.
1715
1716 Shared libraries and data files required by the program
1717 must be available on filesystems which are mounted in the
1718 correct places.  It is the caller's responsibility to ensure
1719 all filesystems that are needed are mounted at the right
1720 locations.");
1721
1722   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1723    [InitBasicFS, Always, TestOutputList (
1724       [["upload"; "test-command"; "/test-command"];
1725        ["chmod"; "0o755"; "/test-command"];
1726        ["command_lines"; "/test-command 1"]], ["Result1"]);
1727     InitBasicFS, Always, TestOutputList (
1728       [["upload"; "test-command"; "/test-command"];
1729        ["chmod"; "0o755"; "/test-command"];
1730        ["command_lines"; "/test-command 2"]], ["Result2"]);
1731     InitBasicFS, Always, TestOutputList (
1732       [["upload"; "test-command"; "/test-command"];
1733        ["chmod"; "0o755"; "/test-command"];
1734        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1735     InitBasicFS, Always, TestOutputList (
1736       [["upload"; "test-command"; "/test-command"];
1737        ["chmod"; "0o755"; "/test-command"];
1738        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1739     InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 7"]], []);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 8"]], [""]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 9"]], ["";""]);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1763     InitBasicFS, Always, TestOutputList (
1764       [["upload"; "test-command"; "/test-command"];
1765        ["chmod"; "0o755"; "/test-command"];
1766        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1767    "run a command, returning lines",
1768    "\
1769 This is the same as C<guestfs_command>, but splits the
1770 result into a list of lines.
1771
1772 See also: C<guestfs_sh_lines>");
1773
1774   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1775    [InitISOFS, Always, TestOutputStruct (
1776       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1777    "get file information",
1778    "\
1779 Returns file information for the given C<path>.
1780
1781 This is the same as the C<stat(2)> system call.");
1782
1783   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1784    [InitISOFS, Always, TestOutputStruct (
1785       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1786    "get file information for a symbolic link",
1787    "\
1788 Returns file information for the given C<path>.
1789
1790 This is the same as C<guestfs_stat> except that if C<path>
1791 is a symbolic link, then the link is stat-ed, not the file it
1792 refers to.
1793
1794 This is the same as the C<lstat(2)> system call.");
1795
1796   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1797    [InitISOFS, Always, TestOutputStruct (
1798       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1799    "get file system statistics",
1800    "\
1801 Returns file system statistics for any mounted file system.
1802 C<path> should be a file or directory in the mounted file system
1803 (typically it is the mount point itself, but it doesn't need to be).
1804
1805 This is the same as the C<statvfs(2)> system call.");
1806
1807   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1808    [], (* XXX test *)
1809    "get ext2/ext3/ext4 superblock details",
1810    "\
1811 This returns the contents of the ext2, ext3 or ext4 filesystem
1812 superblock on C<device>.
1813
1814 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1815 manpage for more details.  The list of fields returned isn't
1816 clearly defined, and depends on both the version of C<tune2fs>
1817 that libguestfs was built against, and the filesystem itself.");
1818
1819   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1820    [InitEmpty, Always, TestOutputTrue (
1821       [["blockdev_setro"; "/dev/sda"];
1822        ["blockdev_getro"; "/dev/sda"]])],
1823    "set block device to read-only",
1824    "\
1825 Sets the block device named C<device> to read-only.
1826
1827 This uses the L<blockdev(8)> command.");
1828
1829   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1830    [InitEmpty, Always, TestOutputFalse (
1831       [["blockdev_setrw"; "/dev/sda"];
1832        ["blockdev_getro"; "/dev/sda"]])],
1833    "set block device to read-write",
1834    "\
1835 Sets the block device named C<device> to read-write.
1836
1837 This uses the L<blockdev(8)> command.");
1838
1839   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1840    [InitEmpty, Always, TestOutputTrue (
1841       [["blockdev_setro"; "/dev/sda"];
1842        ["blockdev_getro"; "/dev/sda"]])],
1843    "is block device set to read-only",
1844    "\
1845 Returns a boolean indicating if the block device is read-only
1846 (true if read-only, false if not).
1847
1848 This uses the L<blockdev(8)> command.");
1849
1850   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1851    [InitEmpty, Always, TestOutputInt (
1852       [["blockdev_getss"; "/dev/sda"]], 512)],
1853    "get sectorsize of block device",
1854    "\
1855 This returns the size of sectors on a block device.
1856 Usually 512, but can be larger for modern devices.
1857
1858 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1859 for that).
1860
1861 This uses the L<blockdev(8)> command.");
1862
1863   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1864    [InitEmpty, Always, TestOutputInt (
1865       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1866    "get blocksize of block device",
1867    "\
1868 This returns the block size of a device.
1869
1870 (Note this is different from both I<size in blocks> and
1871 I<filesystem block size>).
1872
1873 This uses the L<blockdev(8)> command.");
1874
1875   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1876    [], (* XXX test *)
1877    "set blocksize of block device",
1878    "\
1879 This sets the block size of a device.
1880
1881 (Note this is different from both I<size in blocks> and
1882 I<filesystem block size>).
1883
1884 This uses the L<blockdev(8)> command.");
1885
1886   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1887    [InitEmpty, Always, TestOutputInt (
1888       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1889    "get total size of device in 512-byte sectors",
1890    "\
1891 This returns the size of the device in units of 512-byte sectors
1892 (even if the sectorsize isn't 512 bytes ... weird).
1893
1894 See also C<guestfs_blockdev_getss> for the real sector size of
1895 the device, and C<guestfs_blockdev_getsize64> for the more
1896 useful I<size in bytes>.
1897
1898 This uses the L<blockdev(8)> command.");
1899
1900   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1901    [InitEmpty, Always, TestOutputInt (
1902       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1903    "get total size of device in bytes",
1904    "\
1905 This returns the size of the device in bytes.
1906
1907 See also C<guestfs_blockdev_getsz>.
1908
1909 This uses the L<blockdev(8)> command.");
1910
1911   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1912    [InitEmpty, Always, TestRun
1913       [["blockdev_flushbufs"; "/dev/sda"]]],
1914    "flush device buffers",
1915    "\
1916 This tells the kernel to flush internal buffers associated
1917 with C<device>.
1918
1919 This uses the L<blockdev(8)> command.");
1920
1921   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1922    [InitEmpty, Always, TestRun
1923       [["blockdev_rereadpt"; "/dev/sda"]]],
1924    "reread partition table",
1925    "\
1926 Reread the partition table on C<device>.
1927
1928 This uses the L<blockdev(8)> command.");
1929
1930   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1931    [InitBasicFS, Always, TestOutput (
1932       (* Pick a file from cwd which isn't likely to change. *)
1933       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1934        ["checksum"; "md5"; "/COPYING.LIB"]],
1935       Digest.to_hex (Digest.file "COPYING.LIB"))],
1936    "upload a file from the local machine",
1937    "\
1938 Upload local file C<filename> to C<remotefilename> on the
1939 filesystem.
1940
1941 C<filename> can also be a named pipe.
1942
1943 See also C<guestfs_download>.");
1944
1945   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1946    [InitBasicFS, Always, TestOutput (
1947       (* Pick a file from cwd which isn't likely to change. *)
1948       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1949        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1950        ["upload"; "testdownload.tmp"; "/upload"];
1951        ["checksum"; "md5"; "/upload"]],
1952       Digest.to_hex (Digest.file "COPYING.LIB"))],
1953    "download a file to the local machine",
1954    "\
1955 Download file C<remotefilename> and save it as C<filename>
1956 on the local machine.
1957
1958 C<filename> can also be a named pipe.
1959
1960 See also C<guestfs_upload>, C<guestfs_cat>.");
1961
1962   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1963    [InitISOFS, Always, TestOutput (
1964       [["checksum"; "crc"; "/known-3"]], "2891671662");
1965     InitISOFS, Always, TestLastFail (
1966       [["checksum"; "crc"; "/notexists"]]);
1967     InitISOFS, Always, TestOutput (
1968       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1969     InitISOFS, Always, TestOutput (
1970       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1971     InitISOFS, Always, TestOutput (
1972       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1973     InitISOFS, Always, TestOutput (
1974       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1975     InitISOFS, Always, TestOutput (
1976       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1977     InitISOFS, Always, TestOutput (
1978       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1979     (* Test for RHBZ#579608, absolute symbolic links. *)
1980     InitISOFS, Always, TestOutput (
1981       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1982    "compute MD5, SHAx or CRC checksum of file",
1983    "\
1984 This call computes the MD5, SHAx or CRC checksum of the
1985 file named C<path>.
1986
1987 The type of checksum to compute is given by the C<csumtype>
1988 parameter which must have one of the following values:
1989
1990 =over 4
1991
1992 =item C<crc>
1993
1994 Compute the cyclic redundancy check (CRC) specified by POSIX
1995 for the C<cksum> command.
1996
1997 =item C<md5>
1998
1999 Compute the MD5 hash (using the C<md5sum> program).
2000
2001 =item C<sha1>
2002
2003 Compute the SHA1 hash (using the C<sha1sum> program).
2004
2005 =item C<sha224>
2006
2007 Compute the SHA224 hash (using the C<sha224sum> program).
2008
2009 =item C<sha256>
2010
2011 Compute the SHA256 hash (using the C<sha256sum> program).
2012
2013 =item C<sha384>
2014
2015 Compute the SHA384 hash (using the C<sha384sum> program).
2016
2017 =item C<sha512>
2018
2019 Compute the SHA512 hash (using the C<sha512sum> program).
2020
2021 =back
2022
2023 The checksum is returned as a printable string.
2024
2025 To get the checksum for a device, use C<guestfs_checksum_device>.
2026
2027 To get the checksums for many files, use C<guestfs_checksums_out>.");
2028
2029   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2030    [InitBasicFS, Always, TestOutput (
2031       [["tar_in"; "../images/helloworld.tar"; "/"];
2032        ["cat"; "/hello"]], "hello\n")],
2033    "unpack tarfile to directory",
2034    "\
2035 This command uploads and unpacks local file C<tarfile> (an
2036 I<uncompressed> tar file) into C<directory>.
2037
2038 To upload a compressed tarball, use C<guestfs_tgz_in>
2039 or C<guestfs_txz_in>.");
2040
2041   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2042    [],
2043    "pack directory into tarfile",
2044    "\
2045 This command packs the contents of C<directory> and downloads
2046 it to local file C<tarfile>.
2047
2048 To download a compressed tarball, use C<guestfs_tgz_out>
2049 or C<guestfs_txz_out>.");
2050
2051   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2052    [InitBasicFS, Always, TestOutput (
2053       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2054        ["cat"; "/hello"]], "hello\n")],
2055    "unpack compressed tarball to directory",
2056    "\
2057 This command uploads and unpacks local file C<tarball> (a
2058 I<gzip compressed> tar file) into C<directory>.
2059
2060 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2061
2062   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2063    [],
2064    "pack directory into compressed tarball",
2065    "\
2066 This command packs the contents of C<directory> and downloads
2067 it to local file C<tarball>.
2068
2069 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2070
2071   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2072    [InitBasicFS, Always, TestLastFail (
2073       [["umount"; "/"];
2074        ["mount_ro"; "/dev/sda1"; "/"];
2075        ["touch"; "/new"]]);
2076     InitBasicFS, Always, TestOutput (
2077       [["write"; "/new"; "data"];
2078        ["umount"; "/"];
2079        ["mount_ro"; "/dev/sda1"; "/"];
2080        ["cat"; "/new"]], "data")],
2081    "mount a guest disk, read-only",
2082    "\
2083 This is the same as the C<guestfs_mount> command, but it
2084 mounts the filesystem with the read-only (I<-o ro>) flag.");
2085
2086   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2087    [],
2088    "mount a guest disk with mount options",
2089    "\
2090 This is the same as the C<guestfs_mount> command, but it
2091 allows you to set the mount options as for the
2092 L<mount(8)> I<-o> flag.
2093
2094 If the C<options> parameter is an empty string, then
2095 no options are passed (all options default to whatever
2096 the filesystem uses).");
2097
2098   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2099    [],
2100    "mount a guest disk with mount options and vfstype",
2101    "\
2102 This is the same as the C<guestfs_mount> command, but it
2103 allows you to set both the mount options and the vfstype
2104 as for the L<mount(8)> I<-o> and I<-t> flags.");
2105
2106   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2107    [],
2108    "debugging and internals",
2109    "\
2110 The C<guestfs_debug> command exposes some internals of
2111 C<guestfsd> (the guestfs daemon) that runs inside the
2112 qemu subprocess.
2113
2114 There is no comprehensive help for this command.  You have
2115 to look at the file C<daemon/debug.c> in the libguestfs source
2116 to find out what you can do.");
2117
2118   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2119    [InitEmpty, Always, TestOutputList (
2120       [["part_disk"; "/dev/sda"; "mbr"];
2121        ["pvcreate"; "/dev/sda1"];
2122        ["vgcreate"; "VG"; "/dev/sda1"];
2123        ["lvcreate"; "LV1"; "VG"; "50"];
2124        ["lvcreate"; "LV2"; "VG"; "50"];
2125        ["lvremove"; "/dev/VG/LV1"];
2126        ["lvs"]], ["/dev/VG/LV2"]);
2127     InitEmpty, Always, TestOutputList (
2128       [["part_disk"; "/dev/sda"; "mbr"];
2129        ["pvcreate"; "/dev/sda1"];
2130        ["vgcreate"; "VG"; "/dev/sda1"];
2131        ["lvcreate"; "LV1"; "VG"; "50"];
2132        ["lvcreate"; "LV2"; "VG"; "50"];
2133        ["lvremove"; "/dev/VG"];
2134        ["lvs"]], []);
2135     InitEmpty, Always, TestOutputList (
2136       [["part_disk"; "/dev/sda"; "mbr"];
2137        ["pvcreate"; "/dev/sda1"];
2138        ["vgcreate"; "VG"; "/dev/sda1"];
2139        ["lvcreate"; "LV1"; "VG"; "50"];
2140        ["lvcreate"; "LV2"; "VG"; "50"];
2141        ["lvremove"; "/dev/VG"];
2142        ["vgs"]], ["VG"])],
2143    "remove an LVM logical volume",
2144    "\
2145 Remove an LVM logical volume C<device>, where C<device> is
2146 the path to the LV, such as C</dev/VG/LV>.
2147
2148 You can also remove all LVs in a volume group by specifying
2149 the VG name, C</dev/VG>.");
2150
2151   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2152    [InitEmpty, Always, TestOutputList (
2153       [["part_disk"; "/dev/sda"; "mbr"];
2154        ["pvcreate"; "/dev/sda1"];
2155        ["vgcreate"; "VG"; "/dev/sda1"];
2156        ["lvcreate"; "LV1"; "VG"; "50"];
2157        ["lvcreate"; "LV2"; "VG"; "50"];
2158        ["vgremove"; "VG"];
2159        ["lvs"]], []);
2160     InitEmpty, Always, TestOutputList (
2161       [["part_disk"; "/dev/sda"; "mbr"];
2162        ["pvcreate"; "/dev/sda1"];
2163        ["vgcreate"; "VG"; "/dev/sda1"];
2164        ["lvcreate"; "LV1"; "VG"; "50"];
2165        ["lvcreate"; "LV2"; "VG"; "50"];
2166        ["vgremove"; "VG"];
2167        ["vgs"]], [])],
2168    "remove an LVM volume group",
2169    "\
2170 Remove an LVM volume group C<vgname>, (for example C<VG>).
2171
2172 This also forcibly removes all logical volumes in the volume
2173 group (if any).");
2174
2175   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2176    [InitEmpty, Always, TestOutputListOfDevices (
2177       [["part_disk"; "/dev/sda"; "mbr"];
2178        ["pvcreate"; "/dev/sda1"];
2179        ["vgcreate"; "VG"; "/dev/sda1"];
2180        ["lvcreate"; "LV1"; "VG"; "50"];
2181        ["lvcreate"; "LV2"; "VG"; "50"];
2182        ["vgremove"; "VG"];
2183        ["pvremove"; "/dev/sda1"];
2184        ["lvs"]], []);
2185     InitEmpty, Always, TestOutputListOfDevices (
2186       [["part_disk"; "/dev/sda"; "mbr"];
2187        ["pvcreate"; "/dev/sda1"];
2188        ["vgcreate"; "VG"; "/dev/sda1"];
2189        ["lvcreate"; "LV1"; "VG"; "50"];
2190        ["lvcreate"; "LV2"; "VG"; "50"];
2191        ["vgremove"; "VG"];
2192        ["pvremove"; "/dev/sda1"];
2193        ["vgs"]], []);
2194     InitEmpty, Always, TestOutputListOfDevices (
2195       [["part_disk"; "/dev/sda"; "mbr"];
2196        ["pvcreate"; "/dev/sda1"];
2197        ["vgcreate"; "VG"; "/dev/sda1"];
2198        ["lvcreate"; "LV1"; "VG"; "50"];
2199        ["lvcreate"; "LV2"; "VG"; "50"];
2200        ["vgremove"; "VG"];
2201        ["pvremove"; "/dev/sda1"];
2202        ["pvs"]], [])],
2203    "remove an LVM physical volume",
2204    "\
2205 This wipes a physical volume C<device> so that LVM will no longer
2206 recognise it.
2207
2208 The implementation uses the C<pvremove> command which refuses to
2209 wipe physical volumes that contain any volume groups, so you have
2210 to remove those first.");
2211
2212   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2213    [InitBasicFS, Always, TestOutput (
2214       [["set_e2label"; "/dev/sda1"; "testlabel"];
2215        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2216    "set the ext2/3/4 filesystem label",
2217    "\
2218 This sets the ext2/3/4 filesystem label of the filesystem on
2219 C<device> to C<label>.  Filesystem labels are limited to
2220 16 characters.
2221
2222 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2223 to return the existing label on a filesystem.");
2224
2225   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2226    [],
2227    "get the ext2/3/4 filesystem label",
2228    "\
2229 This returns the ext2/3/4 filesystem label of the filesystem on
2230 C<device>.");
2231
2232   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2233    (let uuid = uuidgen () in
2234     [InitBasicFS, Always, TestOutput (
2235        [["set_e2uuid"; "/dev/sda1"; uuid];
2236         ["get_e2uuid"; "/dev/sda1"]], uuid);
2237      InitBasicFS, Always, TestOutput (
2238        [["set_e2uuid"; "/dev/sda1"; "clear"];
2239         ["get_e2uuid"; "/dev/sda1"]], "");
2240      (* We can't predict what UUIDs will be, so just check the commands run. *)
2241      InitBasicFS, Always, TestRun (
2242        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2243      InitBasicFS, Always, TestRun (
2244        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2245    "set the ext2/3/4 filesystem UUID",
2246    "\
2247 This sets the ext2/3/4 filesystem UUID of the filesystem on
2248 C<device> to C<uuid>.  The format of the UUID and alternatives
2249 such as C<clear>, C<random> and C<time> are described in the
2250 L<tune2fs(8)> manpage.
2251
2252 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2253 to return the existing UUID of a filesystem.");
2254
2255   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2256    [],
2257    "get the ext2/3/4 filesystem UUID",
2258    "\
2259 This returns the ext2/3/4 filesystem UUID of the filesystem on
2260 C<device>.");
2261
2262   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2263    [InitBasicFS, Always, TestOutputInt (
2264       [["umount"; "/dev/sda1"];
2265        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2266     InitBasicFS, Always, TestOutputInt (
2267       [["umount"; "/dev/sda1"];
2268        ["zero"; "/dev/sda1"];
2269        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2270    "run the filesystem checker",
2271    "\
2272 This runs the filesystem checker (fsck) on C<device> which
2273 should have filesystem type C<fstype>.
2274
2275 The returned integer is the status.  See L<fsck(8)> for the
2276 list of status codes from C<fsck>.
2277
2278 Notes:
2279
2280 =over 4
2281
2282 =item *
2283
2284 Multiple status codes can be summed together.
2285
2286 =item *
2287
2288 A non-zero return code can mean \"success\", for example if
2289 errors have been corrected on the filesystem.
2290
2291 =item *
2292
2293 Checking or repairing NTFS volumes is not supported
2294 (by linux-ntfs).
2295
2296 =back
2297
2298 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2299
2300   ("zero", (RErr, [Device "device"]), 85, [],
2301    [InitBasicFS, Always, TestOutput (
2302       [["umount"; "/dev/sda1"];
2303        ["zero"; "/dev/sda1"];
2304        ["file"; "/dev/sda1"]], "data")],
2305    "write zeroes to the device",
2306    "\
2307 This command writes zeroes over the first few blocks of C<device>.
2308
2309 How many blocks are zeroed isn't specified (but it's I<not> enough
2310 to securely wipe the device).  It should be sufficient to remove
2311 any partition tables, filesystem superblocks and so on.
2312
2313 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2314
2315   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2316    (* Test disabled because grub-install incompatible with virtio-blk driver.
2317     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2318     *)
2319    [InitBasicFS, Disabled, TestOutputTrue (
2320       [["grub_install"; "/"; "/dev/sda1"];
2321        ["is_dir"; "/boot"]])],
2322    "install GRUB",
2323    "\
2324 This command installs GRUB (the Grand Unified Bootloader) on
2325 C<device>, with the root directory being C<root>.");
2326
2327   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2328    [InitBasicFS, Always, TestOutput (
2329       [["write"; "/old"; "file content"];
2330        ["cp"; "/old"; "/new"];
2331        ["cat"; "/new"]], "file content");
2332     InitBasicFS, Always, TestOutputTrue (
2333       [["write"; "/old"; "file content"];
2334        ["cp"; "/old"; "/new"];
2335        ["is_file"; "/old"]]);
2336     InitBasicFS, Always, TestOutput (
2337       [["write"; "/old"; "file content"];
2338        ["mkdir"; "/dir"];
2339        ["cp"; "/old"; "/dir/new"];
2340        ["cat"; "/dir/new"]], "file content")],
2341    "copy a file",
2342    "\
2343 This copies a file from C<src> to C<dest> where C<dest> is
2344 either a destination filename or destination directory.");
2345
2346   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2347    [InitBasicFS, Always, TestOutput (
2348       [["mkdir"; "/olddir"];
2349        ["mkdir"; "/newdir"];
2350        ["write"; "/olddir/file"; "file content"];
2351        ["cp_a"; "/olddir"; "/newdir"];
2352        ["cat"; "/newdir/olddir/file"]], "file content")],
2353    "copy a file or directory recursively",
2354    "\
2355 This copies a file or directory from C<src> to C<dest>
2356 recursively using the C<cp -a> command.");
2357
2358   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2359    [InitBasicFS, Always, TestOutput (
2360       [["write"; "/old"; "file content"];
2361        ["mv"; "/old"; "/new"];
2362        ["cat"; "/new"]], "file content");
2363     InitBasicFS, Always, TestOutputFalse (
2364       [["write"; "/old"; "file content"];
2365        ["mv"; "/old"; "/new"];
2366        ["is_file"; "/old"]])],
2367    "move a file",
2368    "\
2369 This moves a file from C<src> to C<dest> where C<dest> is
2370 either a destination filename or destination directory.");
2371
2372   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2373    [InitEmpty, Always, TestRun (
2374       [["drop_caches"; "3"]])],
2375    "drop kernel page cache, dentries and inodes",
2376    "\
2377 This instructs the guest kernel to drop its page cache,
2378 and/or dentries and inode caches.  The parameter C<whattodrop>
2379 tells the kernel what precisely to drop, see
2380 L<http://linux-mm.org/Drop_Caches>
2381
2382 Setting C<whattodrop> to 3 should drop everything.
2383
2384 This automatically calls L<sync(2)> before the operation,
2385 so that the maximum guest memory is freed.");
2386
2387   ("dmesg", (RString "kmsgs", []), 91, [],
2388    [InitEmpty, Always, TestRun (
2389       [["dmesg"]])],
2390    "return kernel messages",
2391    "\
2392 This returns the kernel messages (C<dmesg> output) from
2393 the guest kernel.  This is sometimes useful for extended
2394 debugging of problems.
2395
2396 Another way to get the same information is to enable
2397 verbose messages with C<guestfs_set_verbose> or by setting
2398 the environment variable C<LIBGUESTFS_DEBUG=1> before
2399 running the program.");
2400
2401   ("ping_daemon", (RErr, []), 92, [],
2402    [InitEmpty, Always, TestRun (
2403       [["ping_daemon"]])],
2404    "ping the guest daemon",
2405    "\
2406 This is a test probe into the guestfs daemon running inside
2407 the qemu subprocess.  Calling this function checks that the
2408 daemon responds to the ping message, without affecting the daemon
2409 or attached block device(s) in any other way.");
2410
2411   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2412    [InitBasicFS, Always, TestOutputTrue (
2413       [["write"; "/file1"; "contents of a file"];
2414        ["cp"; "/file1"; "/file2"];
2415        ["equal"; "/file1"; "/file2"]]);
2416     InitBasicFS, Always, TestOutputFalse (
2417       [["write"; "/file1"; "contents of a file"];
2418        ["write"; "/file2"; "contents of another file"];
2419        ["equal"; "/file1"; "/file2"]]);
2420     InitBasicFS, Always, TestLastFail (
2421       [["equal"; "/file1"; "/file2"]])],
2422    "test if two files have equal contents",
2423    "\
2424 This compares the two files C<file1> and C<file2> and returns
2425 true if their content is exactly equal, or false otherwise.
2426
2427 The external L<cmp(1)> program is used for the comparison.");
2428
2429   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2430    [InitISOFS, Always, TestOutputList (
2431       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2432     InitISOFS, Always, TestOutputList (
2433       [["strings"; "/empty"]], []);
2434     (* Test for RHBZ#579608, absolute symbolic links. *)
2435     InitISOFS, Always, TestRun (
2436       [["strings"; "/abssymlink"]])],
2437    "print the printable strings in a file",
2438    "\
2439 This runs the L<strings(1)> command on a file and returns
2440 the list of printable strings found.");
2441
2442   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2443    [InitISOFS, Always, TestOutputList (
2444       [["strings_e"; "b"; "/known-5"]], []);
2445     InitBasicFS, Always, TestOutputList (
2446       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2447        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2448    "print the printable strings in a file",
2449    "\
2450 This is like the C<guestfs_strings> command, but allows you to
2451 specify the encoding of strings that are looked for in
2452 the source file C<path>.
2453
2454 Allowed encodings are:
2455
2456 =over 4
2457
2458 =item s
2459
2460 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2461 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2462
2463 =item S
2464
2465 Single 8-bit-byte characters.
2466
2467 =item b
2468
2469 16-bit big endian strings such as those encoded in
2470 UTF-16BE or UCS-2BE.
2471
2472 =item l (lower case letter L)
2473
2474 16-bit little endian such as UTF-16LE and UCS-2LE.
2475 This is useful for examining binaries in Windows guests.
2476
2477 =item B
2478
2479 32-bit big endian such as UCS-4BE.
2480
2481 =item L
2482
2483 32-bit little endian such as UCS-4LE.
2484
2485 =back
2486
2487 The returned strings are transcoded to UTF-8.");
2488
2489   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2490    [InitISOFS, Always, TestOutput (
2491       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2492     (* Test for RHBZ#501888c2 regression which caused large hexdump
2493      * commands to segfault.
2494      *)
2495     InitISOFS, Always, TestRun (
2496       [["hexdump"; "/100krandom"]]);
2497     (* Test for RHBZ#579608, absolute symbolic links. *)
2498     InitISOFS, Always, TestRun (
2499       [["hexdump"; "/abssymlink"]])],
2500    "dump a file in hexadecimal",
2501    "\
2502 This runs C<hexdump -C> on the given C<path>.  The result is
2503 the human-readable, canonical hex dump of the file.");
2504
2505   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2506    [InitNone, Always, TestOutput (
2507       [["part_disk"; "/dev/sda"; "mbr"];
2508        ["mkfs"; "ext3"; "/dev/sda1"];
2509        ["mount_options"; ""; "/dev/sda1"; "/"];
2510        ["write"; "/new"; "test file"];
2511        ["umount"; "/dev/sda1"];
2512        ["zerofree"; "/dev/sda1"];
2513        ["mount_options"; ""; "/dev/sda1"; "/"];
2514        ["cat"; "/new"]], "test file")],
2515    "zero unused inodes and disk blocks on ext2/3 filesystem",
2516    "\
2517 This runs the I<zerofree> program on C<device>.  This program
2518 claims to zero unused inodes and disk blocks on an ext2/3
2519 filesystem, thus making it possible to compress the filesystem
2520 more effectively.
2521
2522 You should B<not> run this program if the filesystem is
2523 mounted.
2524
2525 It is possible that using this program can damage the filesystem
2526 or data on the filesystem.");
2527
2528   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2529    [],
2530    "resize an LVM physical volume",
2531    "\
2532 This resizes (expands or shrinks) an existing LVM physical
2533 volume to match the new size of the underlying device.");
2534
2535   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2536                        Int "cyls"; Int "heads"; Int "sectors";
2537                        String "line"]), 99, [DangerWillRobinson],
2538    [],
2539    "modify a single partition on a block device",
2540    "\
2541 This runs L<sfdisk(8)> option to modify just the single
2542 partition C<n> (note: C<n> counts from 1).
2543
2544 For other parameters, see C<guestfs_sfdisk>.  You should usually
2545 pass C<0> for the cyls/heads/sectors parameters.
2546
2547 See also: C<guestfs_part_add>");
2548
2549   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2550    [],
2551    "display the partition table",
2552    "\
2553 This displays the partition table on C<device>, in the
2554 human-readable output of the L<sfdisk(8)> command.  It is
2555 not intended to be parsed.
2556
2557 See also: C<guestfs_part_list>");
2558
2559   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2560    [],
2561    "display the kernel geometry",
2562    "\
2563 This displays the kernel's idea of the geometry of C<device>.
2564
2565 The result is in human-readable format, and not designed to
2566 be parsed.");
2567
2568   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2569    [],
2570    "display the disk geometry from the partition table",
2571    "\
2572 This displays the disk geometry of C<device> read from the
2573 partition table.  Especially in the case where the underlying
2574 block device has been resized, this can be different from the
2575 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2576
2577 The result is in human-readable format, and not designed to
2578 be parsed.");
2579
2580   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2581    [],
2582    "activate or deactivate all volume groups",
2583    "\
2584 This command activates or (if C<activate> is false) deactivates
2585 all logical volumes in all volume groups.
2586 If activated, then they are made known to the
2587 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2588 then those devices disappear.
2589
2590 This command is the same as running C<vgchange -a y|n>");
2591
2592   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2593    [],
2594    "activate or deactivate some volume groups",
2595    "\
2596 This command activates or (if C<activate> is false) deactivates
2597 all logical volumes in the listed volume groups C<volgroups>.
2598 If activated, then they are made known to the
2599 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2600 then those devices disappear.
2601
2602 This command is the same as running C<vgchange -a y|n volgroups...>
2603
2604 Note that if C<volgroups> is an empty list then B<all> volume groups
2605 are activated or deactivated.");
2606
2607   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2608    [InitNone, Always, TestOutput (
2609       [["part_disk"; "/dev/sda"; "mbr"];
2610        ["pvcreate"; "/dev/sda1"];
2611        ["vgcreate"; "VG"; "/dev/sda1"];
2612        ["lvcreate"; "LV"; "VG"; "10"];
2613        ["mkfs"; "ext2"; "/dev/VG/LV"];
2614        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2615        ["write"; "/new"; "test content"];
2616        ["umount"; "/"];
2617        ["lvresize"; "/dev/VG/LV"; "20"];
2618        ["e2fsck_f"; "/dev/VG/LV"];
2619        ["resize2fs"; "/dev/VG/LV"];
2620        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2621        ["cat"; "/new"]], "test content");
2622     InitNone, Always, TestRun (
2623       (* Make an LV smaller to test RHBZ#587484. *)
2624       [["part_disk"; "/dev/sda"; "mbr"];
2625        ["pvcreate"; "/dev/sda1"];
2626        ["vgcreate"; "VG"; "/dev/sda1"];
2627        ["lvcreate"; "LV"; "VG"; "20"];
2628        ["lvresize"; "/dev/VG/LV"; "10"]])],
2629    "resize an LVM logical volume",
2630    "\
2631 This resizes (expands or shrinks) an existing LVM logical
2632 volume to C<mbytes>.  When reducing, data in the reduced part
2633 is lost.");
2634
2635   ("resize2fs", (RErr, [Device "device"]), 106, [],
2636    [], (* lvresize tests this *)
2637    "resize an ext2/ext3 filesystem",
2638    "\
2639 This resizes an ext2 or ext3 filesystem to match the size of
2640 the underlying device.
2641
2642 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2643 on the C<device> before calling this command.  For unknown reasons
2644 C<resize2fs> sometimes gives an error about this and sometimes not.
2645 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2646 calling this function.");
2647
2648   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2649    [InitBasicFS, Always, TestOutputList (
2650       [["find"; "/"]], ["lost+found"]);
2651     InitBasicFS, Always, TestOutputList (
2652       [["touch"; "/a"];
2653        ["mkdir"; "/b"];
2654        ["touch"; "/b/c"];
2655        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2656     InitBasicFS, Always, TestOutputList (
2657       [["mkdir_p"; "/a/b/c"];
2658        ["touch"; "/a/b/c/d"];
2659        ["find"; "/a/b/"]], ["c"; "c/d"])],
2660    "find all files and directories",
2661    "\
2662 This command lists out all files and directories, recursively,
2663 starting at C<directory>.  It is essentially equivalent to
2664 running the shell command C<find directory -print> but some
2665 post-processing happens on the output, described below.
2666
2667 This returns a list of strings I<without any prefix>.  Thus
2668 if the directory structure was:
2669
2670  /tmp/a
2671  /tmp/b
2672  /tmp/c/d
2673
2674 then the returned list from C<guestfs_find> C</tmp> would be
2675 4 elements:
2676
2677  a
2678  b
2679  c
2680  c/d
2681
2682 If C<directory> is not a directory, then this command returns
2683 an error.
2684
2685 The returned list is sorted.
2686
2687 See also C<guestfs_find0>.");
2688
2689   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2690    [], (* lvresize tests this *)
2691    "check an ext2/ext3 filesystem",
2692    "\
2693 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2694 filesystem checker on C<device>, noninteractively (C<-p>),
2695 even if the filesystem appears to be clean (C<-f>).
2696
2697 This command is only needed because of C<guestfs_resize2fs>
2698 (q.v.).  Normally you should use C<guestfs_fsck>.");
2699
2700   ("sleep", (RErr, [Int "secs"]), 109, [],
2701    [InitNone, Always, TestRun (
2702       [["sleep"; "1"]])],
2703    "sleep for some seconds",
2704    "\
2705 Sleep for C<secs> seconds.");
2706
2707   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2708    [InitNone, Always, TestOutputInt (
2709       [["part_disk"; "/dev/sda"; "mbr"];
2710        ["mkfs"; "ntfs"; "/dev/sda1"];
2711        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2712     InitNone, Always, TestOutputInt (
2713       [["part_disk"; "/dev/sda"; "mbr"];
2714        ["mkfs"; "ext2"; "/dev/sda1"];
2715        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2716    "probe NTFS volume",
2717    "\
2718 This command runs the L<ntfs-3g.probe(8)> command which probes
2719 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2720 be mounted read-write, and some cannot be mounted at all).
2721
2722 C<rw> is a boolean flag.  Set it to true if you want to test
2723 if the volume can be mounted read-write.  Set it to false if
2724 you want to test if the volume can be mounted read-only.
2725
2726 The return value is an integer which C<0> if the operation
2727 would succeed, or some non-zero value documented in the
2728 L<ntfs-3g.probe(8)> manual page.");
2729
2730   ("sh", (RString "output", [String "command"]), 111, [],
2731    [], (* XXX needs tests *)
2732    "run a command via the shell",
2733    "\
2734 This call runs a command from the guest filesystem via the
2735 guest's C</bin/sh>.
2736
2737 This is like C<guestfs_command>, but passes the command to:
2738
2739  /bin/sh -c \"command\"
2740
2741 Depending on the guest's shell, this usually results in
2742 wildcards being expanded, shell expressions being interpolated
2743 and so on.
2744
2745 All the provisos about C<guestfs_command> apply to this call.");
2746
2747   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2748    [], (* XXX needs tests *)
2749    "run a command via the shell returning lines",
2750    "\
2751 This is the same as C<guestfs_sh>, but splits the result
2752 into a list of lines.
2753
2754 See also: C<guestfs_command_lines>");
2755
2756   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2757    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2758     * code in stubs.c, since all valid glob patterns must start with "/".
2759     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2760     *)
2761    [InitBasicFS, Always, TestOutputList (
2762       [["mkdir_p"; "/a/b/c"];
2763        ["touch"; "/a/b/c/d"];
2764        ["touch"; "/a/b/c/e"];
2765        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2766     InitBasicFS, Always, TestOutputList (
2767       [["mkdir_p"; "/a/b/c"];
2768        ["touch"; "/a/b/c/d"];
2769        ["touch"; "/a/b/c/e"];
2770        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2771     InitBasicFS, Always, TestOutputList (
2772       [["mkdir_p"; "/a/b/c"];
2773        ["touch"; "/a/b/c/d"];
2774        ["touch"; "/a/b/c/e"];
2775        ["glob_expand"; "/a/*/x/*"]], [])],
2776    "expand a wildcard path",
2777    "\
2778 This command searches for all the pathnames matching
2779 C<pattern> according to the wildcard expansion rules
2780 used by the shell.
2781
2782 If no paths match, then this returns an empty list
2783 (note: not an error).
2784
2785 It is just a wrapper around the C L<glob(3)> function
2786 with flags C<GLOB_MARK|GLOB_BRACE>.
2787 See that manual page for more details.");
2788
2789   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2790    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2791       [["scrub_device"; "/dev/sdc"]])],
2792    "scrub (securely wipe) a device",
2793    "\
2794 This command writes patterns over C<device> to make data retrieval
2795 more difficult.
2796
2797 It is an interface to the L<scrub(1)> program.  See that
2798 manual page for more details.");
2799
2800   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2801    [InitBasicFS, Always, TestRun (
2802       [["write"; "/file"; "content"];
2803        ["scrub_file"; "/file"]])],
2804    "scrub (securely wipe) a file",
2805    "\
2806 This command writes patterns over a file to make data retrieval
2807 more difficult.
2808
2809 The file is I<removed> after scrubbing.
2810
2811 It is an interface to the L<scrub(1)> program.  See that
2812 manual page for more details.");
2813
2814   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2815    [], (* XXX needs testing *)
2816    "scrub (securely wipe) free space",
2817    "\
2818 This command creates the directory C<dir> and then fills it
2819 with files until the filesystem is full, and scrubs the files
2820 as for C<guestfs_scrub_file>, and deletes them.
2821 The intention is to scrub any free space on the partition
2822 containing C<dir>.
2823
2824 It is an interface to the L<scrub(1)> program.  See that
2825 manual page for more details.");
2826
2827   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2828    [InitBasicFS, Always, TestRun (
2829       [["mkdir"; "/tmp"];
2830        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2831    "create a temporary directory",
2832    "\
2833 This command creates a temporary directory.  The
2834 C<template> parameter should be a full pathname for the
2835 temporary directory name with the final six characters being
2836 \"XXXXXX\".
2837
2838 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2839 the second one being suitable for Windows filesystems.
2840
2841 The name of the temporary directory that was created
2842 is returned.
2843
2844 The temporary directory is created with mode 0700
2845 and is owned by root.
2846
2847 The caller is responsible for deleting the temporary
2848 directory and its contents after use.
2849
2850 See also: L<mkdtemp(3)>");
2851
2852   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2853    [InitISOFS, Always, TestOutputInt (
2854       [["wc_l"; "/10klines"]], 10000);
2855     (* Test for RHBZ#579608, absolute symbolic links. *)
2856     InitISOFS, Always, TestOutputInt (
2857       [["wc_l"; "/abssymlink"]], 10000)],
2858    "count lines in a file",
2859    "\
2860 This command counts the lines in a file, using the
2861 C<wc -l> external command.");
2862
2863   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2864    [InitISOFS, Always, TestOutputInt (
2865       [["wc_w"; "/10klines"]], 10000)],
2866    "count words in a file",
2867    "\
2868 This command counts the words in a file, using the
2869 C<wc -w> external command.");
2870
2871   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2872    [InitISOFS, Always, TestOutputInt (
2873       [["wc_c"; "/100kallspaces"]], 102400)],
2874    "count characters in a file",
2875    "\
2876 This command counts the characters in a file, using the
2877 C<wc -c> external command.");
2878
2879   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2880    [InitISOFS, Always, TestOutputList (
2881       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2882     (* Test for RHBZ#579608, absolute symbolic links. *)
2883     InitISOFS, Always, TestOutputList (
2884       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2885    "return first 10 lines of a file",
2886    "\
2887 This command returns up to the first 10 lines of a file as
2888 a list of strings.");
2889
2890   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2891    [InitISOFS, Always, TestOutputList (
2892       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2893     InitISOFS, Always, TestOutputList (
2894       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2895     InitISOFS, Always, TestOutputList (
2896       [["head_n"; "0"; "/10klines"]], [])],
2897    "return first N lines of a file",
2898    "\
2899 If the parameter C<nrlines> is a positive number, this returns the first
2900 C<nrlines> lines of the file C<path>.
2901
2902 If the parameter C<nrlines> is a negative number, this returns lines
2903 from the file C<path>, excluding the last C<nrlines> lines.
2904
2905 If the parameter C<nrlines> is zero, this returns an empty list.");
2906
2907   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2908    [InitISOFS, Always, TestOutputList (
2909       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2910    "return last 10 lines of a file",
2911    "\
2912 This command returns up to the last 10 lines of a file as
2913 a list of strings.");
2914
2915   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2916    [InitISOFS, Always, TestOutputList (
2917       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2918     InitISOFS, Always, TestOutputList (
2919       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2920     InitISOFS, Always, TestOutputList (
2921       [["tail_n"; "0"; "/10klines"]], [])],
2922    "return last N lines of a file",
2923    "\
2924 If the parameter C<nrlines> is a positive number, this returns the last
2925 C<nrlines> lines of the file C<path>.
2926
2927 If the parameter C<nrlines> is a negative number, this returns lines
2928 from the file C<path>, starting with the C<-nrlines>th line.
2929
2930 If the parameter C<nrlines> is zero, this returns an empty list.");
2931
2932   ("df", (RString "output", []), 125, [],
2933    [], (* XXX Tricky to test because it depends on the exact format
2934         * of the 'df' command and other imponderables.
2935         *)
2936    "report file system disk space usage",
2937    "\
2938 This command runs the C<df> command to report disk space used.
2939
2940 This command is mostly useful for interactive sessions.  It
2941 is I<not> intended that you try to parse the output string.
2942 Use C<statvfs> from programs.");
2943
2944   ("df_h", (RString "output", []), 126, [],
2945    [], (* XXX Tricky to test because it depends on the exact format
2946         * of the 'df' command and other imponderables.
2947         *)
2948    "report file system disk space usage (human readable)",
2949    "\
2950 This command runs the C<df -h> command to report disk space used
2951 in human-readable format.
2952
2953 This command is mostly useful for interactive sessions.  It
2954 is I<not> intended that you try to parse the output string.
2955 Use C<statvfs> from programs.");
2956
2957   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2958    [InitISOFS, Always, TestOutputInt (
2959       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2960    "estimate file space usage",
2961    "\
2962 This command runs the C<du -s> command to estimate file space
2963 usage for C<path>.
2964
2965 C<path> can be a file or a directory.  If C<path> is a directory
2966 then the estimate includes the contents of the directory and all
2967 subdirectories (recursively).
2968
2969 The result is the estimated size in I<kilobytes>
2970 (ie. units of 1024 bytes).");
2971
2972   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2973    [InitISOFS, Always, TestOutputList (
2974       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2975    "list files in an initrd",
2976    "\
2977 This command lists out files contained in an initrd.
2978
2979 The files are listed without any initial C</> character.  The
2980 files are listed in the order they appear (not necessarily
2981 alphabetical).  Directory names are listed as separate items.
2982
2983 Old Linux kernels (2.4 and earlier) used a compressed ext2
2984 filesystem as initrd.  We I<only> support the newer initramfs
2985 format (compressed cpio files).");
2986
2987   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2988    [],
2989    "mount a file using the loop device",
2990    "\
2991 This command lets you mount C<file> (a filesystem image
2992 in a file) on a mount point.  It is entirely equivalent to
2993 the command C<mount -o loop file mountpoint>.");
2994
2995   ("mkswap", (RErr, [Device "device"]), 130, [],
2996    [InitEmpty, Always, TestRun (
2997       [["part_disk"; "/dev/sda"; "mbr"];
2998        ["mkswap"; "/dev/sda1"]])],
2999    "create a swap partition",
3000    "\
3001 Create a swap partition on C<device>.");
3002
3003   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3004    [InitEmpty, Always, TestRun (
3005       [["part_disk"; "/dev/sda"; "mbr"];
3006        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3007    "create a swap partition with a label",
3008    "\
3009 Create a swap partition on C<device> with label C<label>.
3010
3011 Note that you cannot attach a swap label to a block device
3012 (eg. C</dev/sda>), just to a partition.  This appears to be
3013 a limitation of the kernel or swap tools.");
3014
3015   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3016    (let uuid = uuidgen () in
3017     [InitEmpty, Always, TestRun (
3018        [["part_disk"; "/dev/sda"; "mbr"];
3019         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3020    "create a swap partition with an explicit UUID",
3021    "\
3022 Create a swap partition on C<device> with UUID C<uuid>.");
3023
3024   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3025    [InitBasicFS, Always, TestOutputStruct (
3026       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3027        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3028        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3029     InitBasicFS, Always, TestOutputStruct (
3030       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3031        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3032    "make block, character or FIFO devices",
3033    "\
3034 This call creates block or character special devices, or
3035 named pipes (FIFOs).
3036
3037 The C<mode> parameter should be the mode, using the standard
3038 constants.  C<devmajor> and C<devminor> are the
3039 device major and minor numbers, only used when creating block
3040 and character special devices.
3041
3042 Note that, just like L<mknod(2)>, the mode must be bitwise
3043 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3044 just creates a regular file).  These constants are
3045 available in the standard Linux header files, or you can use
3046 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3047 which are wrappers around this command which bitwise OR
3048 in the appropriate constant for you.
3049
3050 The mode actually set is affected by the umask.");
3051
3052   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3053    [InitBasicFS, Always, TestOutputStruct (
3054       [["mkfifo"; "0o777"; "/node"];
3055        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3056    "make FIFO (named pipe)",
3057    "\
3058 This call creates a FIFO (named pipe) called C<path> with
3059 mode C<mode>.  It is just a convenient wrapper around
3060 C<guestfs_mknod>.
3061
3062 The mode actually set is affected by the umask.");
3063
3064   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3065    [InitBasicFS, Always, TestOutputStruct (
3066       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3067        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3068    "make block device node",
3069    "\
3070 This call creates a block device node called C<path> with
3071 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3072 It is just a convenient wrapper around C<guestfs_mknod>.
3073
3074 The mode actually set is affected by the umask.");
3075
3076   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3077    [InitBasicFS, Always, TestOutputStruct (
3078       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3079        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3080    "make char device node",
3081    "\
3082 This call creates a char device node called C<path> with
3083 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3084 It is just a convenient wrapper around C<guestfs_mknod>.
3085
3086 The mode actually set is affected by the umask.");
3087
3088   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3089    [InitEmpty, Always, TestOutputInt (
3090       [["umask"; "0o22"]], 0o22)],
3091    "set file mode creation mask (umask)",
3092    "\
3093 This function sets the mask used for creating new files and
3094 device nodes to C<mask & 0777>.
3095
3096 Typical umask values would be C<022> which creates new files
3097 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3098 C<002> which creates new files with permissions like
3099 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3100
3101 The default umask is C<022>.  This is important because it
3102 means that directories and device nodes will be created with
3103 C<0644> or C<0755> mode even if you specify C<0777>.
3104
3105 See also C<guestfs_get_umask>,
3106 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3107
3108 This call returns the previous umask.");
3109
3110   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3111    [],
3112    "read directories entries",
3113    "\
3114 This returns the list of directory entries in directory C<dir>.
3115
3116 All entries in the directory are returned, including C<.> and
3117 C<..>.  The entries are I<not> sorted, but returned in the same
3118 order as the underlying filesystem.
3119
3120 Also this call returns basic file type information about each
3121 file.  The C<ftyp> field will contain one of the following characters:
3122
3123 =over 4
3124
3125 =item 'b'
3126
3127 Block special
3128
3129 =item 'c'
3130
3131 Char special
3132
3133 =item 'd'
3134
3135 Directory
3136
3137 =item 'f'
3138
3139 FIFO (named pipe)
3140
3141 =item 'l'
3142
3143 Symbolic link
3144
3145 =item 'r'
3146
3147 Regular file
3148
3149 =item 's'
3150
3151 Socket
3152
3153 =item 'u'
3154
3155 Unknown file type
3156
3157 =item '?'
3158
3159 The L<readdir(3)> call returned a C<d_type> field with an
3160 unexpected value
3161
3162 =back
3163
3164 This function is primarily intended for use by programs.  To
3165 get a simple list of names, use C<guestfs_ls>.  To get a printable
3166 directory for human consumption, use C<guestfs_ll>.");
3167
3168   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3169    [],
3170    "create partitions on a block device",
3171    "\
3172 This is a simplified interface to the C<guestfs_sfdisk>
3173 command, where partition sizes are specified in megabytes
3174 only (rounded to the nearest cylinder) and you don't need
3175 to specify the cyls, heads and sectors parameters which
3176 were rarely if ever used anyway.
3177
3178 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3179 and C<guestfs_part_disk>");
3180
3181   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3182    [],
3183    "determine file type inside a compressed file",
3184    "\
3185 This command runs C<file> after first decompressing C<path>
3186 using C<method>.
3187
3188 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3189
3190 Since 1.0.63, use C<guestfs_file> instead which can now
3191 process compressed files.");
3192
3193   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3194    [],
3195    "list extended attributes of a file or directory",
3196    "\
3197 This call lists the extended attributes of the file or directory
3198 C<path>.
3199
3200 At the system call level, this is a combination of the
3201 L<listxattr(2)> and L<getxattr(2)> calls.
3202
3203 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3204
3205   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3206    [],
3207    "list extended attributes of a file or directory",
3208    "\
3209 This is the same as C<guestfs_getxattrs>, but if C<path>
3210 is a symbolic link, then it returns the extended attributes
3211 of the link itself.");
3212
3213   ("setxattr", (RErr, [String "xattr";
3214                        String "val"; Int "vallen"; (* will be BufferIn *)
3215                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3216    [],
3217    "set extended attribute of a file or directory",
3218    "\
3219 This call sets the extended attribute named C<xattr>
3220 of the file C<path> to the value C<val> (of length C<vallen>).
3221 The value is arbitrary 8 bit data.
3222
3223 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3224
3225   ("lsetxattr", (RErr, [String "xattr";
3226                         String "val"; Int "vallen"; (* will be BufferIn *)
3227                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3228    [],
3229    "set extended attribute of a file or directory",
3230    "\
3231 This is the same as C<guestfs_setxattr>, but if C<path>
3232 is a symbolic link, then it sets an extended attribute
3233 of the link itself.");
3234
3235   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3236    [],
3237    "remove extended attribute of a file or directory",
3238    "\
3239 This call removes the extended attribute named C<xattr>
3240 of the file C<path>.
3241
3242 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3243
3244   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3245    [],
3246    "remove extended attribute of a file or directory",
3247    "\
3248 This is the same as C<guestfs_removexattr>, but if C<path>
3249 is a symbolic link, then it removes an extended attribute
3250 of the link itself.");
3251
3252   ("mountpoints", (RHashtable "mps", []), 147, [],
3253    [],
3254    "show mountpoints",
3255    "\
3256 This call is similar to C<guestfs_mounts>.  That call returns
3257 a list of devices.  This one returns a hash table (map) of
3258 device name to directory where the device is mounted.");
3259
3260   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3261    (* This is a special case: while you would expect a parameter
3262     * of type "Pathname", that doesn't work, because it implies
3263     * NEED_ROOT in the generated calling code in stubs.c, and
3264     * this function cannot use NEED_ROOT.
3265     *)
3266    [],
3267    "create a mountpoint",
3268    "\
3269 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3270 specialized calls that can be used to create extra mountpoints
3271 before mounting the first filesystem.
3272
3273 These calls are I<only> necessary in some very limited circumstances,
3274 mainly the case where you want to mount a mix of unrelated and/or
3275 read-only filesystems together.
3276
3277 For example, live CDs often contain a \"Russian doll\" nest of
3278 filesystems, an ISO outer layer, with a squashfs image inside, with
3279 an ext2/3 image inside that.  You can unpack this as follows
3280 in guestfish:
3281
3282  add-ro Fedora-11-i686-Live.iso
3283  run
3284  mkmountpoint /cd
3285  mkmountpoint /squash
3286  mkmountpoint /ext3
3287  mount /dev/sda /cd
3288  mount-loop /cd/LiveOS/squashfs.img /squash
3289  mount-loop /squash/LiveOS/ext3fs.img /ext3
3290
3291 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3292
3293   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3294    [],
3295    "remove a mountpoint",
3296    "\
3297 This calls removes a mountpoint that was previously created
3298 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3299 for full details.");
3300
3301   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3302    [InitISOFS, Always, TestOutputBuffer (
3303       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3304     (* Test various near large, large and too large files (RHBZ#589039). *)
3305     InitBasicFS, Always, TestLastFail (
3306       [["touch"; "/a"];
3307        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3308        ["read_file"; "/a"]]);
3309     InitBasicFS, Always, TestLastFail (
3310       [["touch"; "/a"];
3311        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3312        ["read_file"; "/a"]]);
3313     InitBasicFS, Always, TestLastFail (
3314       [["touch"; "/a"];
3315        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3316        ["read_file"; "/a"]])],
3317    "read a file",
3318    "\
3319 This calls returns the contents of the file C<path> as a
3320 buffer.
3321
3322 Unlike C<guestfs_cat>, this function can correctly
3323 handle files that contain embedded ASCII NUL characters.
3324 However unlike C<guestfs_download>, this function is limited
3325 in the total size of file that can be handled.");
3326
3327   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3328    [InitISOFS, Always, TestOutputList (
3329       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3330     InitISOFS, Always, TestOutputList (
3331       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3332     (* Test for RHBZ#579608, absolute symbolic links. *)
3333     InitISOFS, Always, TestOutputList (
3334       [["grep"; "nomatch"; "/abssymlink"]], [])],
3335    "return lines matching a pattern",
3336    "\
3337 This calls the external C<grep> program and returns the
3338 matching lines.");
3339
3340   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3341    [InitISOFS, Always, TestOutputList (
3342       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3343    "return lines matching a pattern",
3344    "\
3345 This calls the external C<egrep> program and returns the
3346 matching lines.");
3347
3348   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3349    [InitISOFS, Always, TestOutputList (
3350       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3351    "return lines matching a pattern",
3352    "\
3353 This calls the external C<fgrep> program and returns the
3354 matching lines.");
3355
3356   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3357    [InitISOFS, Always, TestOutputList (
3358       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3359    "return lines matching a pattern",
3360    "\
3361 This calls the external C<grep -i> program and returns the
3362 matching lines.");
3363
3364   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3365    [InitISOFS, Always, TestOutputList (
3366       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3367    "return lines matching a pattern",
3368    "\
3369 This calls the external C<egrep -i> program and returns the
3370 matching lines.");
3371
3372   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3373    [InitISOFS, Always, TestOutputList (
3374       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3375    "return lines matching a pattern",
3376    "\
3377 This calls the external C<fgrep -i> program and returns the
3378 matching lines.");
3379
3380   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3381    [InitISOFS, Always, TestOutputList (
3382       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3383    "return lines matching a pattern",
3384    "\
3385 This calls the external C<zgrep> program and returns the
3386 matching lines.");
3387
3388   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3389    [InitISOFS, Always, TestOutputList (
3390       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3391    "return lines matching a pattern",
3392    "\
3393 This calls the external C<zegrep> program and returns the
3394 matching lines.");
3395
3396   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3397    [InitISOFS, Always, TestOutputList (
3398       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3399    "return lines matching a pattern",
3400    "\
3401 This calls the external C<zfgrep> program and returns the
3402 matching lines.");
3403
3404   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3405    [InitISOFS, Always, TestOutputList (
3406       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3407    "return lines matching a pattern",
3408    "\
3409 This calls the external C<zgrep -i> program and returns the
3410 matching lines.");
3411
3412   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3413    [InitISOFS, Always, TestOutputList (
3414       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3415    "return lines matching a pattern",
3416    "\
3417 This calls the external C<zegrep -i> program and returns the
3418 matching lines.");
3419
3420   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3421    [InitISOFS, Always, TestOutputList (
3422       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3423    "return lines matching a pattern",
3424    "\
3425 This calls the external C<zfgrep -i> program and returns the
3426 matching lines.");
3427
3428   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3429    [InitISOFS, Always, TestOutput (
3430       [["realpath"; "/../directory"]], "/directory")],
3431    "canonicalized absolute pathname",
3432    "\
3433 Return the canonicalized absolute pathname of C<path>.  The
3434 returned path has no C<.>, C<..> or symbolic link path elements.");
3435
3436   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3437    [InitBasicFS, Always, TestOutputStruct (
3438       [["touch"; "/a"];
3439        ["ln"; "/a"; "/b"];
3440        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3441    "create a hard link",
3442    "\
3443 This command creates a hard link using the C<ln> command.");
3444
3445   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3446    [InitBasicFS, Always, TestOutputStruct (
3447       [["touch"; "/a"];
3448        ["touch"; "/b"];
3449        ["ln_f"; "/a"; "/b"];
3450        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3451    "create a hard link",
3452    "\
3453 This command creates a hard link using the C<ln -f> command.
3454 The C<-f> option removes the link (C<linkname>) if it exists already.");
3455
3456   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3457    [InitBasicFS, Always, TestOutputStruct (
3458       [["touch"; "/a"];
3459        ["ln_s"; "a"; "/b"];
3460        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3461    "create a symbolic link",
3462    "\
3463 This command creates a symbolic link using the C<ln -s> command.");
3464
3465   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3466    [InitBasicFS, Always, TestOutput (
3467       [["mkdir_p"; "/a/b"];
3468        ["touch"; "/a/b/c"];
3469        ["ln_sf"; "../d"; "/a/b/c"];
3470        ["readlink"; "/a/b/c"]], "../d")],
3471    "create a symbolic link",
3472    "\
3473 This command creates a symbolic link using the C<ln -sf> command,
3474 The C<-f> option removes the link (C<linkname>) if it exists already.");
3475
3476   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3477    [] (* XXX tested above *),
3478    "read the target of a symbolic link",
3479    "\
3480 This command reads the target of a symbolic link.");
3481
3482   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3483    [InitBasicFS, Always, TestOutputStruct (
3484       [["fallocate"; "/a"; "1000000"];
3485        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3486    "preallocate a file in the guest filesystem",
3487    "\
3488 This command preallocates a file (containing zero bytes) named
3489 C<path> of size C<len> bytes.  If the file exists already, it
3490 is overwritten.
3491
3492 Do not confuse this with the guestfish-specific
3493 C<alloc> command which allocates a file in the host and
3494 attaches it as a device.");
3495
3496   ("swapon_device", (RErr, [Device "device"]), 170, [],
3497    [InitPartition, Always, TestRun (
3498       [["mkswap"; "/dev/sda1"];
3499        ["swapon_device"; "/dev/sda1"];
3500        ["swapoff_device"; "/dev/sda1"]])],
3501    "enable swap on device",
3502    "\
3503 This command enables the libguestfs appliance to use the
3504 swap device or partition named C<device>.  The increased
3505 memory is made available for all commands, for example
3506 those run using C<guestfs_command> or C<guestfs_sh>.
3507
3508 Note that you should not swap to existing guest swap
3509 partitions unless you know what you are doing.  They may
3510 contain hibernation information, or other information that
3511 the guest doesn't want you to trash.  You also risk leaking
3512 information about the host to the guest this way.  Instead,
3513 attach a new host device to the guest and swap on that.");
3514
3515   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3516    [], (* XXX tested by swapon_device *)
3517    "disable swap on device",
3518    "\
3519 This command disables the libguestfs appliance swap
3520 device or partition named C<device>.
3521 See C<guestfs_swapon_device>.");
3522
3523   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3524    [InitBasicFS, Always, TestRun (
3525       [["fallocate"; "/swap"; "8388608"];
3526        ["mkswap_file"; "/swap"];
3527        ["swapon_file"; "/swap"];
3528        ["swapoff_file"; "/swap"]])],
3529    "enable swap on file",
3530    "\
3531 This command enables swap to a file.
3532 See C<guestfs_swapon_device> for other notes.");
3533
3534   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3535    [], (* XXX tested by swapon_file *)
3536    "disable swap on file",
3537    "\
3538 This command disables the libguestfs appliance swap on file.");
3539
3540   ("swapon_label", (RErr, [String "label"]), 174, [],
3541    [InitEmpty, Always, TestRun (
3542       [["part_disk"; "/dev/sdb"; "mbr"];
3543        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3544        ["swapon_label"; "swapit"];
3545        ["swapoff_label"; "swapit"];
3546        ["zero"; "/dev/sdb"];
3547        ["blockdev_rereadpt"; "/dev/sdb"]])],
3548    "enable swap on labeled swap partition",
3549    "\
3550 This command enables swap to a labeled swap partition.
3551 See C<guestfs_swapon_device> for other notes.");
3552
3553   ("swapoff_label", (RErr, [String "label"]), 175, [],
3554    [], (* XXX tested by swapon_label *)
3555    "disable swap on labeled swap partition",
3556    "\
3557 This command disables the libguestfs appliance swap on
3558 labeled swap partition.");
3559
3560   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3561    (let uuid = uuidgen () in
3562     [InitEmpty, Always, TestRun (
3563        [["mkswap_U"; uuid; "/dev/sdb"];
3564         ["swapon_uuid"; uuid];
3565         ["swapoff_uuid"; uuid]])]),
3566    "enable swap on swap partition by UUID",
3567    "\
3568 This command enables swap to a swap partition with the given UUID.
3569 See C<guestfs_swapon_device> for other notes.");
3570
3571   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3572    [], (* XXX tested by swapon_uuid *)
3573    "disable swap on swap partition by UUID",
3574    "\
3575 This command disables the libguestfs appliance swap partition
3576 with the given UUID.");
3577
3578   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3579    [InitBasicFS, Always, TestRun (
3580       [["fallocate"; "/swap"; "8388608"];
3581        ["mkswap_file"; "/swap"]])],
3582    "create a swap file",
3583    "\
3584 Create a swap file.
3585
3586 This command just writes a swap file signature to an existing
3587 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3588
3589   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3590    [InitISOFS, Always, TestRun (
3591       [["inotify_init"; "0"]])],
3592    "create an inotify handle",
3593    "\
3594 This command creates a new inotify handle.
3595 The inotify subsystem can be used to notify events which happen to
3596 objects in the guest filesystem.
3597
3598 C<maxevents> is the maximum number of events which will be
3599 queued up between calls to C<guestfs_inotify_read> or
3600 C<guestfs_inotify_files>.
3601 If this is passed as C<0>, then the kernel (or previously set)
3602 default is used.  For Linux 2.6.29 the default was 16384 events.
3603 Beyond this limit, the kernel throws away events, but records
3604 the fact that it threw them away by setting a flag
3605 C<IN_Q_OVERFLOW> in the returned structure list (see
3606 C<guestfs_inotify_read>).
3607
3608 Before any events are generated, you have to add some
3609 watches to the internal watch list.  See:
3610 C<guestfs_inotify_add_watch>,
3611 C<guestfs_inotify_rm_watch> and
3612 C<guestfs_inotify_watch_all>.
3613
3614 Queued up events should be read periodically by calling
3615 C<guestfs_inotify_read>
3616 (or C<guestfs_inotify_files> which is just a helpful
3617 wrapper around C<guestfs_inotify_read>).  If you don't
3618 read the events out often enough then you risk the internal
3619 queue overflowing.
3620
3621 The handle should be closed after use by calling
3622 C<guestfs_inotify_close>.  This also removes any
3623 watches automatically.
3624
3625 See also L<inotify(7)> for an overview of the inotify interface
3626 as exposed by the Linux kernel, which is roughly what we expose
3627 via libguestfs.  Note that there is one global inotify handle
3628 per libguestfs instance.");
3629
3630   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3631    [InitBasicFS, Always, TestOutputList (
3632       [["inotify_init"; "0"];
3633        ["inotify_add_watch"; "/"; "1073741823"];
3634        ["touch"; "/a"];
3635        ["touch"; "/b"];
3636        ["inotify_files"]], ["a"; "b"])],
3637    "add an inotify watch",
3638    "\
3639 Watch C<path> for the events listed in C<mask>.
3640
3641 Note that if C<path> is a directory then events within that
3642 directory are watched, but this does I<not> happen recursively
3643 (in subdirectories).
3644
3645 Note for non-C or non-Linux callers: the inotify events are
3646 defined by the Linux kernel ABI and are listed in
3647 C</usr/include/sys/inotify.h>.");
3648
3649   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3650    [],
3651    "remove an inotify watch",
3652    "\
3653 Remove a previously defined inotify watch.
3654 See C<guestfs_inotify_add_watch>.");
3655
3656   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3657    [],
3658    "return list of inotify events",
3659    "\
3660 Return the complete queue of events that have happened
3661 since the previous read call.
3662
3663 If no events have happened, this returns an empty list.
3664
3665 I<Note>: In order to make sure that all events have been
3666 read, you must call this function repeatedly until it
3667 returns an empty list.  The reason is that the call will
3668 read events up to the maximum appliance-to-host message
3669 size and leave remaining events in the queue.");
3670
3671   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3672    [],
3673    "return list of watched files that had events",
3674    "\
3675 This function is a helpful wrapper around C<guestfs_inotify_read>
3676 which just returns a list of pathnames of objects that were
3677 touched.  The returned pathnames are sorted and deduplicated.");
3678
3679   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3680    [],
3681    "close the inotify handle",
3682    "\
3683 This closes the inotify handle which was previously
3684 opened by inotify_init.  It removes all watches, throws
3685 away any pending events, and deallocates all resources.");
3686
3687   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3688    [],
3689    "set SELinux security context",
3690    "\
3691 This sets the SELinux security context of the daemon
3692 to the string C<context>.
3693
3694 See the documentation about SELINUX in L<guestfs(3)>.");
3695
3696   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3697    [],
3698    "get SELinux security context",
3699    "\
3700 This gets the SELinux security context of the daemon.
3701
3702 See the documentation about SELINUX in L<guestfs(3)>,
3703 and C<guestfs_setcon>");
3704
3705   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3706    [InitEmpty, Always, TestOutput (
3707       [["part_disk"; "/dev/sda"; "mbr"];
3708        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3709        ["mount_options"; ""; "/dev/sda1"; "/"];
3710        ["write"; "/new"; "new file contents"];
3711        ["cat"; "/new"]], "new file contents")],
3712    "make a filesystem with block size",
3713    "\
3714 This call is similar to C<guestfs_mkfs>, but it allows you to
3715 control the block size of the resulting filesystem.  Supported
3716 block sizes depend on the filesystem type, but typically they
3717 are C<1024>, C<2048> or C<4096> only.");
3718
3719   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3720    [InitEmpty, Always, TestOutput (
3721       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3722        ["mke2journal"; "4096"; "/dev/sda1"];
3723        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3724        ["mount_options"; ""; "/dev/sda2"; "/"];
3725        ["write"; "/new"; "new file contents"];
3726        ["cat"; "/new"]], "new file contents")],
3727    "make ext2/3/4 external journal",
3728    "\
3729 This creates an ext2 external journal on C<device>.  It is equivalent
3730 to the command:
3731
3732  mke2fs -O journal_dev -b blocksize device");
3733
3734   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3735    [InitEmpty, Always, TestOutput (
3736       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3737        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3738        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3739        ["mount_options"; ""; "/dev/sda2"; "/"];
3740        ["write"; "/new"; "new file contents"];
3741        ["cat"; "/new"]], "new file contents")],
3742    "make ext2/3/4 external journal with label",
3743    "\
3744 This creates an ext2 external journal on C<device> with label C<label>.");
3745
3746   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3747    (let uuid = uuidgen () in
3748     [InitEmpty, Always, TestOutput (
3749        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3750         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3751         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3752         ["mount_options"; ""; "/dev/sda2"; "/"];
3753         ["write"; "/new"; "new file contents"];
3754         ["cat"; "/new"]], "new file contents")]),
3755    "make ext2/3/4 external journal with UUID",
3756    "\
3757 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3758
3759   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3760    [],
3761    "make ext2/3/4 filesystem with external journal",
3762    "\
3763 This creates an ext2/3/4 filesystem on C<device> with
3764 an external journal on C<journal>.  It is equivalent
3765 to the command:
3766
3767  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3768
3769 See also C<guestfs_mke2journal>.");
3770
3771   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3772    [],
3773    "make ext2/3/4 filesystem with external journal",
3774    "\
3775 This creates an ext2/3/4 filesystem on C<device> with
3776 an external journal on the journal labeled C<label>.
3777
3778 See also C<guestfs_mke2journal_L>.");
3779
3780   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3781    [],
3782    "make ext2/3/4 filesystem with external journal",
3783    "\
3784 This creates an ext2/3/4 filesystem on C<device> with
3785 an external journal on the journal with UUID C<uuid>.
3786
3787 See also C<guestfs_mke2journal_U>.");
3788
3789   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3790    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3791    "load a kernel module",
3792    "\
3793 This loads a kernel module in the appliance.
3794
3795 The kernel module must have been whitelisted when libguestfs
3796 was built (see C<appliance/kmod.whitelist.in> in the source).");
3797
3798   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3799    [InitNone, Always, TestOutput (
3800       [["echo_daemon"; "This is a test"]], "This is a test"
3801     )],
3802    "echo arguments back to the client",
3803    "\
3804 This command concatenates the list of C<words> passed with single spaces
3805 between them and returns the resulting string.
3806
3807 You can use this command to test the connection through to the daemon.
3808
3809 See also C<guestfs_ping_daemon>.");
3810
3811   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3812    [], (* There is a regression test for this. *)
3813    "find all files and directories, returning NUL-separated list",
3814    "\
3815 This command lists out all files and directories, recursively,
3816 starting at C<directory>, placing the resulting list in the
3817 external file called C<files>.
3818
3819 This command works the same way as C<guestfs_find> with the
3820 following exceptions:
3821
3822 =over 4
3823
3824 =item *
3825
3826 The resulting list is written to an external file.
3827
3828 =item *
3829
3830 Items (filenames) in the result are separated
3831 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3832
3833 =item *
3834
3835 This command is not limited in the number of names that it
3836 can return.
3837
3838 =item *
3839
3840 The result list is not sorted.
3841
3842 =back");
3843
3844   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3845    [InitISOFS, Always, TestOutput (
3846       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3847     InitISOFS, Always, TestOutput (
3848       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3849     InitISOFS, Always, TestOutput (
3850       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3851     InitISOFS, Always, TestLastFail (
3852       [["case_sensitive_path"; "/Known-1/"]]);
3853     InitBasicFS, Always, TestOutput (
3854       [["mkdir"; "/a"];
3855        ["mkdir"; "/a/bbb"];
3856        ["touch"; "/a/bbb/c"];
3857        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3858     InitBasicFS, Always, TestOutput (
3859       [["mkdir"; "/a"];
3860        ["mkdir"; "/a/bbb"];
3861        ["touch"; "/a/bbb/c"];
3862        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3863     InitBasicFS, Always, TestLastFail (
3864       [["mkdir"; "/a"];
3865        ["mkdir"; "/a/bbb"];
3866        ["touch"; "/a/bbb/c"];
3867        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3868    "return true path on case-insensitive filesystem",
3869    "\
3870 This can be used to resolve case insensitive paths on
3871 a filesystem which is case sensitive.  The use case is
3872 to resolve paths which you have read from Windows configuration
3873 files or the Windows Registry, to the true path.
3874
3875 The command handles a peculiarity of the Linux ntfs-3g
3876 filesystem driver (and probably others), which is that although
3877 the underlying filesystem is case-insensitive, the driver
3878 exports the filesystem to Linux as case-sensitive.
3879
3880 One consequence of this is that special directories such
3881 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3882 (or other things) depending on the precise details of how
3883 they were created.  In Windows itself this would not be
3884 a problem.
3885
3886 Bug or feature?  You decide:
3887 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3888
3889 This function resolves the true case of each element in the
3890 path and returns the case-sensitive path.
3891
3892 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3893 might return C<\"/WINDOWS/system32\"> (the exact return value
3894 would depend on details of how the directories were originally
3895 created under Windows).
3896
3897 I<Note>:
3898 This function does not handle drive names, backslashes etc.
3899
3900 See also C<guestfs_realpath>.");
3901
3902   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3903    [InitBasicFS, Always, TestOutput (
3904       [["vfs_type"; "/dev/sda1"]], "ext2")],
3905    "get the Linux VFS type corresponding to a mounted device",
3906    "\
3907 This command gets the filesystem type corresponding to
3908 the filesystem on C<device>.
3909
3910 For most filesystems, the result is the name of the Linux
3911 VFS module which would be used to mount this filesystem
3912 if you mounted it without specifying the filesystem type.
3913 For example a string such as C<ext3> or C<ntfs>.");
3914
3915   ("truncate", (RErr, [Pathname "path"]), 199, [],
3916    [InitBasicFS, Always, TestOutputStruct (
3917       [["write"; "/test"; "some stuff so size is not zero"];
3918        ["truncate"; "/test"];
3919        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3920    "truncate a file to zero size",
3921    "\
3922 This command truncates C<path> to a zero-length file.  The
3923 file must exist already.");
3924
3925   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3926    [InitBasicFS, Always, TestOutputStruct (
3927       [["touch"; "/test"];
3928        ["truncate_size"; "/test"; "1000"];
3929        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3930    "truncate a file to a particular size",
3931    "\
3932 This command truncates C<path> to size C<size> bytes.  The file
3933 must exist already.
3934
3935 If the current file size is less than C<size> then
3936 the file is extended to the required size with zero bytes.
3937 This creates a sparse file (ie. disk blocks are not allocated
3938 for the file until you write to it).  To create a non-sparse
3939 file of zeroes, use C<guestfs_fallocate64> instead.");
3940
3941   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3942    [InitBasicFS, Always, TestOutputStruct (
3943       [["touch"; "/test"];
3944        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3945        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3946    "set timestamp of a file with nanosecond precision",
3947    "\
3948 This command sets the timestamps of a file with nanosecond
3949 precision.
3950
3951 C<atsecs, atnsecs> are the last access time (atime) in secs and
3952 nanoseconds from the epoch.
3953
3954 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3955 secs and nanoseconds from the epoch.
3956
3957 If the C<*nsecs> field contains the special value C<-1> then
3958 the corresponding timestamp is set to the current time.  (The
3959 C<*secs> field is ignored in this case).
3960
3961 If the C<*nsecs> field contains the special value C<-2> then
3962 the corresponding timestamp is left unchanged.  (The
3963 C<*secs> field is ignored in this case).");
3964
3965   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3966    [InitBasicFS, Always, TestOutputStruct (
3967       [["mkdir_mode"; "/test"; "0o111"];
3968        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3969    "create a directory with a particular mode",
3970    "\
3971 This command creates a directory, setting the initial permissions
3972 of the directory to C<mode>.
3973
3974 For common Linux filesystems, the actual mode which is set will
3975 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3976 interpret the mode in other ways.
3977
3978 See also C<guestfs_mkdir>, C<guestfs_umask>");
3979
3980   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3981    [], (* XXX *)
3982    "change file owner and group",
3983    "\
3984 Change the file owner to C<owner> and group to C<group>.
3985 This is like C<guestfs_chown> but if C<path> is a symlink then
3986 the link itself is changed, not the target.
3987
3988 Only numeric uid and gid are supported.  If you want to use
3989 names, you will need to locate and parse the password file
3990 yourself (Augeas support makes this relatively easy).");
3991
3992   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3993    [], (* XXX *)
3994    "lstat on multiple files",
3995    "\
3996 This call allows you to perform the C<guestfs_lstat> operation
3997 on multiple files, where all files are in the directory C<path>.
3998 C<names> is the list of files from this directory.
3999
4000 On return you get a list of stat structs, with a one-to-one
4001 correspondence to the C<names> list.  If any name did not exist
4002 or could not be lstat'd, then the C<ino> field of that structure
4003 is set to C<-1>.
4004
4005 This call is intended for programs that want to efficiently
4006 list a directory contents without making many round-trips.
4007 See also C<guestfs_lxattrlist> for a similarly efficient call
4008 for getting extended attributes.  Very long directory listings
4009 might cause the protocol message size to be exceeded, causing
4010 this call to fail.  The caller must split up such requests
4011 into smaller groups of names.");
4012
4013   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4014    [], (* XXX *)
4015    "lgetxattr on multiple files",
4016    "\
4017 This call allows you to get the extended attributes
4018 of multiple files, where all files are in the directory C<path>.
4019 C<names> is the list of files from this directory.
4020
4021 On return you get a flat list of xattr structs which must be
4022 interpreted sequentially.  The first xattr struct always has a zero-length
4023 C<attrname>.  C<attrval> in this struct is zero-length
4024 to indicate there was an error doing C<lgetxattr> for this
4025 file, I<or> is a C string which is a decimal number
4026 (the number of following attributes for this file, which could
4027 be C<\"0\">).  Then after the first xattr struct are the
4028 zero or more attributes for the first named file.
4029 This repeats for the second and subsequent files.
4030
4031 This call is intended for programs that want to efficiently
4032 list a directory contents without making many round-trips.
4033 See also C<guestfs_lstatlist> for a similarly efficient call
4034 for getting standard stats.  Very long directory listings
4035 might cause the protocol message size to be exceeded, causing
4036 this call to fail.  The caller must split up such requests
4037 into smaller groups of names.");
4038
4039   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4040    [], (* XXX *)
4041    "readlink on multiple files",
4042    "\
4043 This call allows you to do a C<readlink> operation
4044 on multiple files, where all files are in the directory C<path>.
4045 C<names> is the list of files from this directory.
4046
4047 On return you get a list of strings, with a one-to-one
4048 correspondence to the C<names> list.  Each string is the
4049 value of the symbolic link.
4050
4051 If the C<readlink(2)> operation fails on any name, then
4052 the corresponding result string is the empty string C<\"\">.
4053 However the whole operation is completed even if there
4054 were C<readlink(2)> errors, and so you can call this
4055 function with names where you don't know if they are
4056 symbolic links already (albeit slightly less efficient).
4057
4058 This call is intended for programs that want to efficiently
4059 list a directory contents without making many round-trips.
4060 Very long directory listings might cause the protocol
4061 message size to be exceeded, causing
4062 this call to fail.  The caller must split up such requests
4063 into smaller groups of names.");
4064
4065   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4066    [InitISOFS, Always, TestOutputBuffer (
4067       [["pread"; "/known-4"; "1"; "3"]], "\n");
4068     InitISOFS, Always, TestOutputBuffer (
4069       [["pread"; "/empty"; "0"; "100"]], "")],
4070    "read part of a file",
4071    "\
4072 This command lets you read part of a file.  It reads C<count>
4073 bytes of the file, starting at C<offset>, from file C<path>.
4074
4075 This may read fewer bytes than requested.  For further details
4076 see the L<pread(2)> system call.
4077
4078 See also C<guestfs_pwrite>.");
4079
4080   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4081    [InitEmpty, Always, TestRun (
4082       [["part_init"; "/dev/sda"; "gpt"]])],
4083    "create an empty partition table",
4084    "\
4085 This creates an empty partition table on C<device> of one of the
4086 partition types listed below.  Usually C<parttype> should be
4087 either C<msdos> or C<gpt> (for large disks).
4088
4089 Initially there are no partitions.  Following this, you should
4090 call C<guestfs_part_add> for each partition required.
4091
4092 Possible values for C<parttype> are:
4093
4094 =over 4
4095
4096 =item B<efi> | B<gpt>
4097
4098 Intel EFI / GPT partition table.
4099
4100 This is recommended for >= 2 TB partitions that will be accessed
4101 from Linux and Intel-based Mac OS X.  It also has limited backwards
4102 compatibility with the C<mbr> format.
4103
4104 =item B<mbr> | B<msdos>
4105
4106 The standard PC \"Master Boot Record\" (MBR) format used
4107 by MS-DOS and Windows.  This partition type will B<only> work
4108 for device sizes up to 2 TB.  For large disks we recommend
4109 using C<gpt>.
4110
4111 =back
4112
4113 Other partition table types that may work but are not
4114 supported include:
4115
4116 =over 4
4117
4118 =item B<aix>
4119
4120 AIX disk labels.
4121
4122 =item B<amiga> | B<rdb>
4123
4124 Amiga \"Rigid Disk Block\" format.
4125
4126 =item B<bsd>
4127
4128 BSD disk labels.
4129
4130 =item B<dasd>
4131
4132 DASD, used on IBM mainframes.
4133
4134 =item B<dvh>
4135
4136 MIPS/SGI volumes.
4137
4138 =item B<mac>
4139
4140 Old Mac partition format.  Modern Macs use C<gpt>.
4141
4142 =item B<pc98>
4143
4144 NEC PC-98 format, common in Japan apparently.
4145
4146 =item B<sun>
4147
4148 Sun disk labels.
4149
4150 =back");
4151
4152   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4153    [InitEmpty, Always, TestRun (
4154       [["part_init"; "/dev/sda"; "mbr"];
4155        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4156     InitEmpty, Always, TestRun (
4157       [["part_init"; "/dev/sda"; "gpt"];
4158        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4159        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4160     InitEmpty, Always, TestRun (
4161       [["part_init"; "/dev/sda"; "mbr"];
4162        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4163        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4164        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4165        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4166    "add a partition to the device",
4167    "\
4168 This command adds a partition to C<device>.  If there is no partition
4169 table on the device, call C<guestfs_part_init> first.
4170
4171 The C<prlogex> parameter is the type of partition.  Normally you
4172 should pass C<p> or C<primary> here, but MBR partition tables also
4173 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4174 types.
4175
4176 C<startsect> and C<endsect> are the start and end of the partition
4177 in I<sectors>.  C<endsect> may be negative, which means it counts
4178 backwards from the end of the disk (C<-1> is the last sector).
4179
4180 Creating a partition which covers the whole disk is not so easy.
4181 Use C<guestfs_part_disk> to do that.");
4182
4183   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4184    [InitEmpty, Always, TestRun (
4185       [["part_disk"; "/dev/sda"; "mbr"]]);
4186     InitEmpty, Always, TestRun (
4187       [["part_disk"; "/dev/sda"; "gpt"]])],
4188    "partition whole disk with a single primary partition",
4189    "\
4190 This command is simply a combination of C<guestfs_part_init>
4191 followed by C<guestfs_part_add> to create a single primary partition
4192 covering the whole disk.
4193
4194 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4195 but other possible values are described in C<guestfs_part_init>.");
4196
4197   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4198    [InitEmpty, Always, TestRun (
4199       [["part_disk"; "/dev/sda"; "mbr"];
4200        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4201    "make a partition bootable",
4202    "\
4203 This sets the bootable flag on partition numbered C<partnum> on
4204 device C<device>.  Note that partitions are numbered from 1.
4205
4206 The bootable flag is used by some operating systems (notably
4207 Windows) to determine which partition to boot from.  It is by
4208 no means universally recognized.");
4209
4210   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4211    [InitEmpty, Always, TestRun (
4212       [["part_disk"; "/dev/sda"; "gpt"];
4213        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4214    "set partition name",
4215    "\
4216 This sets the partition name on partition numbered C<partnum> on
4217 device C<device>.  Note that partitions are numbered from 1.
4218
4219 The partition name can only be set on certain types of partition
4220 table.  This works on C<gpt> but not on C<mbr> partitions.");
4221
4222   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4223    [], (* XXX Add a regression test for this. *)
4224    "list partitions on a device",
4225    "\
4226 This command parses the partition table on C<device> and
4227 returns the list of partitions found.
4228
4229 The fields in the returned structure are:
4230
4231 =over 4
4232
4233 =item B<part_num>
4234
4235 Partition number, counting from 1.
4236
4237 =item B<part_start>
4238
4239 Start of the partition I<in bytes>.  To get sectors you have to
4240 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4241
4242 =item B<part_end>
4243
4244 End of the partition in bytes.
4245
4246 =item B<part_size>
4247
4248 Size of the partition in bytes.
4249
4250 =back");
4251
4252   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4253    [InitEmpty, Always, TestOutput (
4254       [["part_disk"; "/dev/sda"; "gpt"];
4255        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4256    "get the partition table type",
4257    "\
4258 This command examines the partition table on C<device> and
4259 returns the partition table type (format) being used.
4260
4261 Common return values include: C<msdos> (a DOS/Windows style MBR
4262 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4263 values are possible, although unusual.  See C<guestfs_part_init>
4264 for a full list.");
4265
4266   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4267    [InitBasicFS, Always, TestOutputBuffer (
4268       [["fill"; "0x63"; "10"; "/test"];
4269        ["read_file"; "/test"]], "cccccccccc")],
4270    "fill a file with octets",
4271    "\
4272 This command creates a new file called C<path>.  The initial
4273 content of the file is C<len> octets of C<c>, where C<c>
4274 must be a number in the range C<[0..255]>.
4275
4276 To fill a file with zero bytes (sparsely), it is
4277 much more efficient to use C<guestfs_truncate_size>.
4278 To create a file with a pattern of repeating bytes
4279 use C<guestfs_fill_pattern>.");
4280
4281   ("available", (RErr, [StringList "groups"]), 216, [],
4282    [InitNone, Always, TestRun [["available"; ""]]],
4283    "test availability of some parts of the API",
4284    "\
4285 This command is used to check the availability of some
4286 groups of functionality in the appliance, which not all builds of
4287 the libguestfs appliance will be able to provide.
4288
4289 The libguestfs groups, and the functions that those
4290 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4291 You can also fetch this list at runtime by calling
4292 C<guestfs_available_all_groups>.
4293
4294 The argument C<groups> is a list of group names, eg:
4295 C<[\"inotify\", \"augeas\"]> would check for the availability of
4296 the Linux inotify functions and Augeas (configuration file
4297 editing) functions.
4298
4299 The command returns no error if I<all> requested groups are available.
4300
4301 It fails with an error if one or more of the requested
4302 groups is unavailable in the appliance.
4303
4304 If an unknown group name is included in the
4305 list of groups then an error is always returned.
4306
4307 I<Notes:>
4308
4309 =over 4
4310
4311 =item *
4312
4313 You must call C<guestfs_launch> before calling this function.
4314
4315 The reason is because we don't know what groups are
4316 supported by the appliance/daemon until it is running and can
4317 be queried.
4318
4319 =item *
4320
4321 If a group of functions is available, this does not necessarily
4322 mean that they will work.  You still have to check for errors
4323 when calling individual API functions even if they are
4324 available.
4325
4326 =item *
4327
4328 It is usually the job of distro packagers to build
4329 complete functionality into the libguestfs appliance.
4330 Upstream libguestfs, if built from source with all
4331 requirements satisfied, will support everything.
4332
4333 =item *
4334
4335 This call was added in version C<1.0.80>.  In previous
4336 versions of libguestfs all you could do would be to speculatively
4337 execute a command to find out if the daemon implemented it.
4338 See also C<guestfs_version>.
4339
4340 =back");
4341
4342   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4343    [InitBasicFS, Always, TestOutputBuffer (
4344       [["write"; "/src"; "hello, world"];
4345        ["dd"; "/src"; "/dest"];
4346        ["read_file"; "/dest"]], "hello, world")],
4347    "copy from source to destination using dd",
4348    "\
4349 This command copies from one source device or file C<src>
4350 to another destination device or file C<dest>.  Normally you
4351 would use this to copy to or from a device or partition, for
4352 example to duplicate a filesystem.
4353
4354 If the destination is a device, it must be as large or larger
4355 than the source file or device, otherwise the copy will fail.
4356 This command cannot do partial copies (see C<guestfs_copy_size>).");
4357
4358   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4359    [InitBasicFS, Always, TestOutputInt (
4360       [["write"; "/file"; "hello, world"];
4361        ["filesize"; "/file"]], 12)],
4362    "return the size of the file in bytes",
4363    "\
4364 This command returns the size of C<file> in bytes.
4365
4366 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4367 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4368 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4369
4370   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4371    [InitBasicFSonLVM, Always, TestOutputList (
4372       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4373        ["lvs"]], ["/dev/VG/LV2"])],
4374    "rename an LVM logical volume",
4375    "\
4376 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4377
4378   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4379    [InitBasicFSonLVM, Always, TestOutputList (
4380       [["umount"; "/"];
4381        ["vg_activate"; "false"; "VG"];
4382        ["vgrename"; "VG"; "VG2"];
4383        ["vg_activate"; "true"; "VG2"];
4384        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4385        ["vgs"]], ["VG2"])],
4386    "rename an LVM volume group",
4387    "\
4388 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4389
4390   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4391    [InitISOFS, Always, TestOutputBuffer (
4392       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4393    "list the contents of a single file in an initrd",
4394    "\
4395 This command unpacks the file C<filename> from the initrd file
4396 called C<initrdpath>.  The filename must be given I<without> the
4397 initial C</> character.
4398
4399 For example, in guestfish you could use the following command
4400 to examine the boot script (usually called C</init>)
4401 contained in a Linux initrd or initramfs image:
4402
4403  initrd-cat /boot/initrd-<version>.img init
4404
4405 See also C<guestfs_initrd_list>.");
4406
4407   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4408    [],
4409    "get the UUID of a physical volume",
4410    "\
4411 This command returns the UUID of the LVM PV C<device>.");
4412
4413   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4414    [],
4415    "get the UUID of a volume group",
4416    "\
4417 This command returns the UUID of the LVM VG named C<vgname>.");
4418
4419   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4420    [],
4421    "get the UUID of a logical volume",
4422    "\
4423 This command returns the UUID of the LVM LV C<device>.");
4424
4425   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4426    [],
4427    "get the PV UUIDs containing the volume group",
4428    "\
4429 Given a VG called C<vgname>, this returns the UUIDs of all
4430 the physical volumes that this volume group resides on.
4431
4432 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4433 calls to associate physical volumes and volume groups.
4434
4435 See also C<guestfs_vglvuuids>.");
4436
4437   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4438    [],
4439    "get the LV UUIDs of all LVs in the volume group",
4440    "\
4441 Given a VG called C<vgname>, this returns the UUIDs of all
4442 the logical volumes created in this volume group.
4443
4444 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4445 calls to associate logical volumes and volume groups.
4446
4447 See also C<guestfs_vgpvuuids>.");
4448
4449   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4450    [InitBasicFS, Always, TestOutputBuffer (
4451       [["write"; "/src"; "hello, world"];
4452        ["copy_size"; "/src"; "/dest"; "5"];
4453        ["read_file"; "/dest"]], "hello")],
4454    "copy size bytes from source to destination using dd",
4455    "\
4456 This command copies exactly C<size> bytes from one source device
4457 or file C<src> to another destination device or file C<dest>.
4458
4459 Note this will fail if the source is too short or if the destination
4460 is not large enough.");
4461
4462   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4463    [InitBasicFSonLVM, Always, TestRun (
4464       [["zero_device"; "/dev/VG/LV"]])],
4465    "write zeroes to an entire device",
4466    "\
4467 This command writes zeroes over the entire C<device>.  Compare
4468 with C<guestfs_zero> which just zeroes the first few blocks of
4469 a device.");
4470
4471   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4472    [InitBasicFS, Always, TestOutput (
4473       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4474        ["cat"; "/hello"]], "hello\n")],
4475    "unpack compressed tarball to directory",
4476    "\
4477 This command uploads and unpacks local file C<tarball> (an
4478 I<xz compressed> tar file) into C<directory>.");
4479
4480   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4481    [],
4482    "pack directory into compressed tarball",
4483    "\
4484 This command packs the contents of C<directory> and downloads
4485 it to local file C<tarball> (as an xz compressed tar archive).");
4486
4487   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4488    [],
4489    "resize an NTFS filesystem",
4490    "\
4491 This command resizes an NTFS filesystem, expanding or
4492 shrinking it to the size of the underlying device.
4493 See also L<ntfsresize(8)>.");
4494
4495   ("vgscan", (RErr, []), 232, [],
4496    [InitEmpty, Always, TestRun (
4497       [["vgscan"]])],
4498    "rescan for LVM physical volumes, volume groups and logical volumes",
4499    "\
4500 This rescans all block devices and rebuilds the list of LVM
4501 physical volumes, volume groups and logical volumes.");
4502
4503   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4504    [InitEmpty, Always, TestRun (
4505       [["part_init"; "/dev/sda"; "mbr"];
4506        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4507        ["part_del"; "/dev/sda"; "1"]])],
4508    "delete a partition",
4509    "\
4510 This command deletes the partition numbered C<partnum> on C<device>.
4511
4512 Note that in the case of MBR partitioning, deleting an
4513 extended partition also deletes any logical partitions
4514 it contains.");
4515
4516   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4517    [InitEmpty, Always, TestOutputTrue (
4518       [["part_init"; "/dev/sda"; "mbr"];
4519        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4520        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4521        ["part_get_bootable"; "/dev/sda"; "1"]])],
4522    "return true if a partition is bootable",
4523    "\
4524 This command returns true if the partition C<partnum> on
4525 C<device> has the bootable flag set.
4526
4527 See also C<guestfs_part_set_bootable>.");
4528
4529   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4530    [InitEmpty, Always, TestOutputInt (
4531       [["part_init"; "/dev/sda"; "mbr"];
4532        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4533        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4534        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4535    "get the MBR type byte (ID byte) from a partition",
4536    "\
4537 Returns the MBR type byte (also known as the ID byte) from
4538 the numbered partition C<partnum>.
4539
4540 Note that only MBR (old DOS-style) partitions have type bytes.
4541 You will get undefined results for other partition table
4542 types (see C<guestfs_part_get_parttype>).");
4543
4544   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4545    [], (* tested by part_get_mbr_id *)
4546    "set the MBR type byte (ID byte) of a partition",
4547    "\
4548 Sets the MBR type byte (also known as the ID byte) of
4549 the numbered partition C<partnum> to C<idbyte>.  Note
4550 that the type bytes quoted in most documentation are
4551 in fact hexadecimal numbers, but usually documented
4552 without any leading \"0x\" which might be confusing.
4553
4554 Note that only MBR (old DOS-style) partitions have type bytes.
4555 You will get undefined results for other partition table
4556 types (see C<guestfs_part_get_parttype>).");
4557
4558   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4559    [InitISOFS, Always, TestOutput (
4560       [["checksum_device"; "md5"; "/dev/sdd"]],
4561       (Digest.to_hex (Digest.file "images/test.iso")))],
4562    "compute MD5, SHAx or CRC checksum of the contents of a device",
4563    "\
4564 This call computes the MD5, SHAx or CRC checksum of the
4565 contents of the device named C<device>.  For the types of
4566 checksums supported see the C<guestfs_checksum> command.");
4567
4568   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4569    [InitNone, Always, TestRun (
4570       [["part_disk"; "/dev/sda"; "mbr"];
4571        ["pvcreate"; "/dev/sda1"];
4572        ["vgcreate"; "VG"; "/dev/sda1"];
4573        ["lvcreate"; "LV"; "VG"; "10"];
4574        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4575    "expand an LV to fill free space",
4576    "\
4577 This expands an existing logical volume C<lv> so that it fills
4578 C<pc>% of the remaining free space in the volume group.  Commonly
4579 you would call this with pc = 100 which expands the logical volume
4580 as much as possible, using all remaining free space in the volume
4581 group.");
4582
4583   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4584    [], (* XXX Augeas code needs tests. *)
4585    "clear Augeas path",
4586    "\
4587 Set the value associated with C<path> to C<NULL>.  This
4588 is the same as the L<augtool(1)> C<clear> command.");
4589
4590   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4591    [InitEmpty, Always, TestOutputInt (
4592       [["get_umask"]], 0o22)],
4593    "get the current umask",
4594    "\
4595 Return the current umask.  By default the umask is C<022>
4596 unless it has been set by calling C<guestfs_umask>.");
4597
4598   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4599    [],
4600    "upload a file to the appliance (internal use only)",
4601    "\
4602 The C<guestfs_debug_upload> command uploads a file to
4603 the libguestfs appliance.
4604
4605 There is no comprehensive help for this command.  You have
4606 to look at the file C<daemon/debug.c> in the libguestfs source
4607 to find out what it is for.");
4608
4609   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4610    [InitBasicFS, Always, TestOutput (
4611       [["base64_in"; "../images/hello.b64"; "/hello"];
4612        ["cat"; "/hello"]], "hello\n")],
4613    "upload base64-encoded data to file",
4614    "\
4615 This command uploads base64-encoded data from C<base64file>
4616 to C<filename>.");
4617
4618   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4619    [],
4620    "download file and encode as base64",
4621    "\
4622 This command downloads the contents of C<filename>, writing
4623 it out to local file C<base64file> encoded as base64.");
4624
4625   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4626    [],
4627    "compute MD5, SHAx or CRC checksum of files in a directory",
4628    "\
4629 This command computes the checksums of all regular files in
4630 C<directory> and then emits a list of those checksums to
4631 the local output file C<sumsfile>.
4632
4633 This can be used for verifying the integrity of a virtual
4634 machine.  However to be properly secure you should pay
4635 attention to the output of the checksum command (it uses
4636 the ones from GNU coreutils).  In particular when the
4637 filename is not printable, coreutils uses a special
4638 backslash syntax.  For more information, see the GNU
4639 coreutils info file.");
4640
4641   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4642    [InitBasicFS, Always, TestOutputBuffer (
4643       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4644        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4645    "fill a file with a repeating pattern of bytes",
4646    "\
4647 This function is like C<guestfs_fill> except that it creates
4648 a new file of length C<len> containing the repeating pattern
4649 of bytes in C<pattern>.  The pattern is truncated if necessary
4650 to ensure the length of the file is exactly C<len> bytes.");
4651
4652   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4653    [InitBasicFS, Always, TestOutput (
4654       [["write"; "/new"; "new file contents"];
4655        ["cat"; "/new"]], "new file contents");
4656     InitBasicFS, Always, TestOutput (
4657       [["write"; "/new"; "\nnew file contents\n"];
4658        ["cat"; "/new"]], "\nnew file contents\n");
4659     InitBasicFS, Always, TestOutput (
4660       [["write"; "/new"; "\n\n"];
4661        ["cat"; "/new"]], "\n\n");
4662     InitBasicFS, Always, TestOutput (
4663       [["write"; "/new"; ""];
4664        ["cat"; "/new"]], "");
4665     InitBasicFS, Always, TestOutput (
4666       [["write"; "/new"; "\n\n\n"];
4667        ["cat"; "/new"]], "\n\n\n");
4668     InitBasicFS, Always, TestOutput (
4669       [["write"; "/new"; "\n"];
4670        ["cat"; "/new"]], "\n")],
4671    "create a new file",
4672    "\
4673 This call creates a file called C<path>.  The content of the
4674 file is the string C<content> (which can contain any 8 bit data).");
4675
4676   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4677    [InitBasicFS, Always, TestOutput (
4678       [["write"; "/new"; "new file contents"];
4679        ["pwrite"; "/new"; "data"; "4"];
4680        ["cat"; "/new"]], "new data contents");
4681     InitBasicFS, Always, TestOutput (
4682       [["write"; "/new"; "new file contents"];
4683        ["pwrite"; "/new"; "is extended"; "9"];
4684        ["cat"; "/new"]], "new file is extended");
4685     InitBasicFS, Always, TestOutput (
4686       [["write"; "/new"; "new file contents"];
4687        ["pwrite"; "/new"; ""; "4"];
4688        ["cat"; "/new"]], "new file contents")],
4689    "write to part of a file",
4690    "\
4691 This command writes to part of a file.  It writes the data
4692 buffer C<content> to the file C<path> starting at offset C<offset>.
4693
4694 This command implements the L<pwrite(2)> system call, and like
4695 that system call it may not write the full data requested.  The
4696 return value is the number of bytes that were actually written
4697 to the file.  This could even be 0, although short writes are
4698 unlikely for regular files in ordinary circumstances.
4699
4700 See also C<guestfs_pread>.");
4701
4702   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4703    [],
4704    "resize an ext2/ext3 filesystem (with size)",
4705    "\
4706 This command is the same as C<guestfs_resize2fs> except that it
4707 allows you to specify the new size (in bytes) explicitly.");
4708
4709   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4710    [],
4711    "resize an LVM physical volume (with size)",
4712    "\
4713 This command is the same as C<guestfs_pvresize> except that it
4714 allows you to specify the new size (in bytes) explicitly.");
4715
4716   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4717    [],
4718    "resize an NTFS filesystem (with size)",
4719    "\
4720 This command is the same as C<guestfs_ntfsresize> except that it
4721 allows you to specify the new size (in bytes) explicitly.");
4722
4723   ("available_all_groups", (RStringList "groups", []), 251, [],
4724    [InitNone, Always, TestRun [["available_all_groups"]]],
4725    "return a list of all optional groups",
4726    "\
4727 This command returns a list of all optional groups that this
4728 daemon knows about.  Note this returns both supported and unsupported
4729 groups.  To find out which ones the daemon can actually support
4730 you have to call C<guestfs_available> on each member of the
4731 returned list.
4732
4733 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4734
4735   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4736    [InitBasicFS, Always, TestOutputStruct (
4737       [["fallocate64"; "/a"; "1000000"];
4738        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4739    "preallocate a file in the guest filesystem",
4740    "\
4741 This command preallocates a file (containing zero bytes) named
4742 C<path> of size C<len> bytes.  If the file exists already, it
4743 is overwritten.
4744
4745 Note that this call allocates disk blocks for the file.
4746 To create a sparse file use C<guestfs_truncate_size> instead.
4747
4748 The deprecated call C<guestfs_fallocate> does the same,
4749 but owing to an oversight it only allowed 30 bit lengths
4750 to be specified, effectively limiting the maximum size
4751 of files created through that call to 1GB.
4752
4753 Do not confuse this with the guestfish-specific
4754 C<alloc> and C<sparse> commands which create
4755 a file in the host and attach it as a device.");
4756
4757 ]
4758
4759 let all_functions = non_daemon_functions @ daemon_functions
4760
4761 (* In some places we want the functions to be displayed sorted
4762  * alphabetically, so this is useful:
4763  *)
4764 let all_functions_sorted =
4765   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4766                compare n1 n2) all_functions
4767
4768 (* This is used to generate the src/MAX_PROC_NR file which
4769  * contains the maximum procedure number, a surrogate for the
4770  * ABI version number.  See src/Makefile.am for the details.
4771  *)
4772 let max_proc_nr =
4773   let proc_nrs = List.map (
4774     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4775   ) daemon_functions in
4776   List.fold_left max 0 proc_nrs
4777
4778 (* Field types for structures. *)
4779 type field =
4780   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4781   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4782   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4783   | FUInt32
4784   | FInt32
4785   | FUInt64
4786   | FInt64
4787   | FBytes                      (* Any int measure that counts bytes. *)
4788   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4789   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4790
4791 (* Because we generate extra parsing code for LVM command line tools,
4792  * we have to pull out the LVM columns separately here.
4793  *)
4794 let lvm_pv_cols = [
4795   "pv_name", FString;
4796   "pv_uuid", FUUID;
4797   "pv_fmt", FString;
4798   "pv_size", FBytes;
4799   "dev_size", FBytes;
4800   "pv_free", FBytes;
4801   "pv_used", FBytes;
4802   "pv_attr", FString (* XXX *);
4803   "pv_pe_count", FInt64;
4804   "pv_pe_alloc_count", FInt64;
4805   "pv_tags", FString;
4806   "pe_start", FBytes;
4807   "pv_mda_count", FInt64;
4808   "pv_mda_free", FBytes;
4809   (* Not in Fedora 10:
4810      "pv_mda_size", FBytes;
4811   *)
4812 ]
4813 let lvm_vg_cols = [
4814   "vg_name", FString;
4815   "vg_uuid", FUUID;
4816   "vg_fmt", FString;
4817   "vg_attr", FString (* XXX *);
4818   "vg_size", FBytes;
4819   "vg_free", FBytes;
4820   "vg_sysid", FString;
4821   "vg_extent_size", FBytes;
4822   "vg_extent_count", FInt64;
4823   "vg_free_count", FInt64;
4824   "max_lv", FInt64;
4825   "max_pv", FInt64;
4826   "pv_count", FInt64;
4827   "lv_count", FInt64;
4828   "snap_count", FInt64;
4829   "vg_seqno", FInt64;
4830   "vg_tags", FString;
4831   "vg_mda_count", FInt64;
4832   "vg_mda_free", FBytes;
4833   (* Not in Fedora 10:
4834      "vg_mda_size", FBytes;
4835   *)
4836 ]
4837 let lvm_lv_cols = [
4838   "lv_name", FString;
4839   "lv_uuid", FUUID;
4840   "lv_attr", FString (* XXX *);
4841   "lv_major", FInt64;
4842   "lv_minor", FInt64;
4843   "lv_kernel_major", FInt64;
4844   "lv_kernel_minor", FInt64;
4845   "lv_size", FBytes;
4846   "seg_count", FInt64;
4847   "origin", FString;
4848   "snap_percent", FOptPercent;
4849   "copy_percent", FOptPercent;
4850   "move_pv", FString;
4851   "lv_tags", FString;
4852   "mirror_log", FString;
4853   "modules", FString;
4854 ]
4855
4856 (* Names and fields in all structures (in RStruct and RStructList)
4857  * that we support.
4858  *)
4859 let structs = [
4860   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4861    * not use this struct in any new code.
4862    *)
4863   "int_bool", [
4864     "i", FInt32;                (* for historical compatibility *)
4865     "b", FInt32;                (* for historical compatibility *)
4866   ];
4867
4868   (* LVM PVs, VGs, LVs. *)
4869   "lvm_pv", lvm_pv_cols;
4870   "lvm_vg", lvm_vg_cols;
4871   "lvm_lv", lvm_lv_cols;
4872
4873   (* Column names and types from stat structures.
4874    * NB. Can't use things like 'st_atime' because glibc header files
4875    * define some of these as macros.  Ugh.
4876    *)
4877   "stat", [
4878     "dev", FInt64;
4879     "ino", FInt64;
4880     "mode", FInt64;
4881     "nlink", FInt64;
4882     "uid", FInt64;
4883     "gid", FInt64;
4884     "rdev", FInt64;
4885     "size", FInt64;
4886     "blksize", FInt64;
4887     "blocks", FInt64;
4888     "atime", FInt64;
4889     "mtime", FInt64;
4890     "ctime", FInt64;
4891   ];
4892   "statvfs", [
4893     "bsize", FInt64;
4894     "frsize", FInt64;
4895     "blocks", FInt64;
4896     "bfree", FInt64;
4897     "bavail", FInt64;
4898     "files", FInt64;
4899     "ffree", FInt64;
4900     "favail", FInt64;
4901     "fsid", FInt64;
4902     "flag", FInt64;
4903     "namemax", FInt64;
4904   ];
4905
4906   (* Column names in dirent structure. *)
4907   "dirent", [
4908     "ino", FInt64;
4909     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4910     "ftyp", FChar;
4911     "name", FString;
4912   ];
4913
4914   (* Version numbers. *)
4915   "version", [
4916     "major", FInt64;
4917     "minor", FInt64;
4918     "release", FInt64;
4919     "extra", FString;
4920   ];
4921
4922   (* Extended attribute. *)
4923   "xattr", [
4924     "attrname", FString;
4925     "attrval", FBuffer;
4926   ];
4927
4928   (* Inotify events. *)
4929   "inotify_event", [
4930     "in_wd", FInt64;
4931     "in_mask", FUInt32;
4932     "in_cookie", FUInt32;
4933     "in_name", FString;
4934   ];
4935
4936   (* Partition table entry. *)
4937   "partition", [
4938     "part_num", FInt32;
4939     "part_start", FBytes;
4940     "part_end", FBytes;
4941     "part_size", FBytes;
4942   ];
4943 ] (* end of structs *)
4944
4945 (* Ugh, Java has to be different ..
4946  * These names are also used by the Haskell bindings.
4947  *)
4948 let java_structs = [
4949   "int_bool", "IntBool";
4950   "lvm_pv", "PV";
4951   "lvm_vg", "VG";
4952   "lvm_lv", "LV";
4953   "stat", "Stat";
4954   "statvfs", "StatVFS";
4955   "dirent", "Dirent";
4956   "version", "Version";
4957   "xattr", "XAttr";
4958   "inotify_event", "INotifyEvent";
4959   "partition", "Partition";
4960 ]
4961
4962 (* What structs are actually returned. *)
4963 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4964
4965 (* Returns a list of RStruct/RStructList structs that are returned
4966  * by any function.  Each element of returned list is a pair:
4967  *
4968  * (structname, RStructOnly)
4969  *    == there exists function which returns RStruct (_, structname)
4970  * (structname, RStructListOnly)
4971  *    == there exists function which returns RStructList (_, structname)
4972  * (structname, RStructAndList)
4973  *    == there are functions returning both RStruct (_, structname)
4974  *                                      and RStructList (_, structname)
4975  *)
4976 let rstructs_used_by functions =
4977   (* ||| is a "logical OR" for rstructs_used_t *)
4978   let (|||) a b =
4979     match a, b with
4980     | RStructAndList, _
4981     | _, RStructAndList -> RStructAndList
4982     | RStructOnly, RStructListOnly
4983     | RStructListOnly, RStructOnly -> RStructAndList
4984     | RStructOnly, RStructOnly -> RStructOnly
4985     | RStructListOnly, RStructListOnly -> RStructListOnly
4986   in
4987
4988   let h = Hashtbl.create 13 in
4989
4990   (* if elem->oldv exists, update entry using ||| operator,
4991    * else just add elem->newv to the hash
4992    *)
4993   let update elem newv =
4994     try  let oldv = Hashtbl.find h elem in
4995          Hashtbl.replace h elem (newv ||| oldv)
4996     with Not_found -> Hashtbl.add h elem newv
4997   in
4998
4999   List.iter (
5000     fun (_, style, _, _, _, _, _) ->
5001       match fst style with
5002       | RStruct (_, structname) -> update structname RStructOnly
5003       | RStructList (_, structname) -> update structname RStructListOnly
5004       | _ -> ()
5005   ) functions;
5006
5007   (* return key->values as a list of (key,value) *)
5008   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5009
5010 (* Used for testing language bindings. *)
5011 type callt =
5012   | CallString of string
5013   | CallOptString of string option
5014   | CallStringList of string list
5015   | CallInt of int
5016   | CallInt64 of int64
5017   | CallBool of bool
5018   | CallBuffer of string
5019
5020 (* Used to memoize the result of pod2text. *)
5021 let pod2text_memo_filename = "src/.pod2text.data"
5022 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5023   try
5024     let chan = open_in pod2text_memo_filename in
5025     let v = input_value chan in
5026     close_in chan;
5027     v
5028   with
5029     _ -> Hashtbl.create 13
5030 let pod2text_memo_updated () =
5031   let chan = open_out pod2text_memo_filename in
5032   output_value chan pod2text_memo;
5033   close_out chan
5034
5035 (* Useful functions.
5036  * Note we don't want to use any external OCaml libraries which
5037  * makes this a bit harder than it should be.
5038  *)
5039 module StringMap = Map.Make (String)
5040
5041 let failwithf fs = ksprintf failwith fs
5042
5043 let unique = let i = ref 0 in fun () -> incr i; !i
5044
5045 let replace_char s c1 c2 =
5046   let s2 = String.copy s in
5047   let r = ref false in
5048   for i = 0 to String.length s2 - 1 do
5049     if String.unsafe_get s2 i = c1 then (
5050       String.unsafe_set s2 i c2;
5051       r := true
5052     )
5053   done;
5054   if not !r then s else s2
5055
5056 let isspace c =
5057   c = ' '
5058   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5059
5060 let triml ?(test = isspace) str =
5061   let i = ref 0 in
5062   let n = ref (String.length str) in
5063   while !n > 0 && test str.[!i]; do
5064     decr n;
5065     incr i
5066   done;
5067   if !i = 0 then str
5068   else String.sub str !i !n
5069
5070 let trimr ?(test = isspace) str =
5071   let n = ref (String.length str) in
5072   while !n > 0 && test str.[!n-1]; do
5073     decr n
5074   done;
5075   if !n = String.length str then str
5076   else String.sub str 0 !n
5077
5078 let trim ?(test = isspace) str =
5079   trimr ~test (triml ~test str)
5080
5081 let rec find s sub =
5082   let len = String.length s in
5083   let sublen = String.length sub in
5084   let rec loop i =
5085     if i <= len-sublen then (
5086       let rec loop2 j =
5087         if j < sublen then (
5088           if s.[i+j] = sub.[j] then loop2 (j+1)
5089           else -1
5090         ) else
5091           i (* found *)
5092       in
5093       let r = loop2 0 in
5094       if r = -1 then loop (i+1) else r
5095     ) else
5096       -1 (* not found *)
5097   in
5098   loop 0
5099
5100 let rec replace_str s s1 s2 =
5101   let len = String.length s in
5102   let sublen = String.length s1 in
5103   let i = find s s1 in
5104   if i = -1 then s
5105   else (
5106     let s' = String.sub s 0 i in
5107     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5108     s' ^ s2 ^ replace_str s'' s1 s2
5109   )
5110
5111 let rec string_split sep str =
5112   let len = String.length str in
5113   let seplen = String.length sep in
5114   let i = find str sep in
5115   if i = -1 then [str]
5116   else (
5117     let s' = String.sub str 0 i in
5118     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5119     s' :: string_split sep s''
5120   )
5121
5122 let files_equal n1 n2 =
5123   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5124   match Sys.command cmd with
5125   | 0 -> true
5126   | 1 -> false
5127   | i -> failwithf "%s: failed with error code %d" cmd i
5128
5129 let rec filter_map f = function
5130   | [] -> []
5131   | x :: xs ->
5132       match f x with
5133       | Some y -> y :: filter_map f xs
5134       | None -> filter_map f xs
5135
5136 let rec find_map f = function
5137   | [] -> raise Not_found
5138   | x :: xs ->
5139       match f x with
5140       | Some y -> y
5141       | None -> find_map f xs
5142
5143 let iteri f xs =
5144   let rec loop i = function
5145     | [] -> ()
5146     | x :: xs -> f i x; loop (i+1) xs
5147   in
5148   loop 0 xs
5149
5150 let mapi f xs =
5151   let rec loop i = function
5152     | [] -> []
5153     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5154   in
5155   loop 0 xs
5156
5157 let count_chars c str =
5158   let count = ref 0 in
5159   for i = 0 to String.length str - 1 do
5160     if c = String.unsafe_get str i then incr count
5161   done;
5162   !count
5163
5164 let explode str =
5165   let r = ref [] in
5166   for i = 0 to String.length str - 1 do
5167     let c = String.unsafe_get str i in
5168     r := c :: !r;
5169   done;
5170   List.rev !r
5171
5172 let map_chars f str =
5173   List.map f (explode str)
5174
5175 let name_of_argt = function
5176   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5177   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5178   | FileIn n | FileOut n | BufferIn n -> n
5179
5180 let java_name_of_struct typ =
5181   try List.assoc typ java_structs
5182   with Not_found ->
5183     failwithf
5184       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5185
5186 let cols_of_struct typ =
5187   try List.assoc typ structs
5188   with Not_found ->
5189     failwithf "cols_of_struct: unknown struct %s" typ
5190
5191 let seq_of_test = function
5192   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5193   | TestOutputListOfDevices (s, _)
5194   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5195   | TestOutputTrue s | TestOutputFalse s
5196   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5197   | TestOutputStruct (s, _)
5198   | TestLastFail s -> s
5199
5200 (* Handling for function flags. *)
5201 let protocol_limit_warning =
5202   "Because of the message protocol, there is a transfer limit
5203 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5204
5205 let danger_will_robinson =
5206   "B<This command is dangerous.  Without careful use you
5207 can easily destroy all your data>."
5208
5209 let deprecation_notice flags =
5210   try
5211     let alt =
5212       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5213     let txt =
5214       sprintf "This function is deprecated.
5215 In new code, use the C<%s> call instead.
5216
5217 Deprecated functions will not be removed from the API, but the
5218 fact that they are deprecated indicates that there are problems
5219 with correct use of these functions." alt in
5220     Some txt
5221   with
5222     Not_found -> None
5223
5224 (* Create list of optional groups. *)
5225 let optgroups =
5226   let h = Hashtbl.create 13 in
5227   List.iter (
5228     fun (name, _, _, flags, _, _, _) ->
5229       List.iter (
5230         function
5231         | Optional group ->
5232             let names = try Hashtbl.find h group with Not_found -> [] in
5233             Hashtbl.replace h group (name :: names)
5234         | _ -> ()
5235       ) flags
5236   ) daemon_functions;
5237   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5238   let groups =
5239     List.map (
5240       fun group -> group, List.sort compare (Hashtbl.find h group)
5241     ) groups in
5242   List.sort (fun x y -> compare (fst x) (fst y)) groups
5243
5244 (* Check function names etc. for consistency. *)
5245 let check_functions () =
5246   let contains_uppercase str =
5247     let len = String.length str in
5248     let rec loop i =
5249       if i >= len then false
5250       else (
5251         let c = str.[i] in
5252         if c >= 'A' && c <= 'Z' then true
5253         else loop (i+1)
5254       )
5255     in
5256     loop 0
5257   in
5258
5259   (* Check function names. *)
5260   List.iter (
5261     fun (name, _, _, _, _, _, _) ->
5262       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5263         failwithf "function name %s does not need 'guestfs' prefix" name;
5264       if name = "" then
5265         failwithf "function name is empty";
5266       if name.[0] < 'a' || name.[0] > 'z' then
5267         failwithf "function name %s must start with lowercase a-z" name;
5268       if String.contains name '-' then
5269         failwithf "function name %s should not contain '-', use '_' instead."
5270           name
5271   ) all_functions;
5272
5273   (* Check function parameter/return names. *)
5274   List.iter (
5275     fun (name, style, _, _, _, _, _) ->
5276       let check_arg_ret_name n =
5277         if contains_uppercase n then
5278           failwithf "%s param/ret %s should not contain uppercase chars"
5279             name n;
5280         if String.contains n '-' || String.contains n '_' then
5281           failwithf "%s param/ret %s should not contain '-' or '_'"
5282             name n;
5283         if n = "value" then
5284           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;
5285         if n = "int" || n = "char" || n = "short" || n = "long" then
5286           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5287         if n = "i" || n = "n" then
5288           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5289         if n = "argv" || n = "args" then
5290           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5291
5292         (* List Haskell, OCaml and C keywords here.
5293          * http://www.haskell.org/haskellwiki/Keywords
5294          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5295          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5296          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5297          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5298          * Omitting _-containing words, since they're handled above.
5299          * Omitting the OCaml reserved word, "val", is ok,
5300          * and saves us from renaming several parameters.
5301          *)
5302         let reserved = [
5303           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5304           "char"; "class"; "const"; "constraint"; "continue"; "data";
5305           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5306           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5307           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5308           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5309           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5310           "interface";
5311           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5312           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5313           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5314           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5315           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5316           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5317           "volatile"; "when"; "where"; "while";
5318           ] in
5319         if List.mem n reserved then
5320           failwithf "%s has param/ret using reserved word %s" name n;
5321       in
5322
5323       (match fst style with
5324        | RErr -> ()
5325        | RInt n | RInt64 n | RBool n
5326        | RConstString n | RConstOptString n | RString n
5327        | RStringList n | RStruct (n, _) | RStructList (n, _)
5328        | RHashtable n | RBufferOut n ->
5329            check_arg_ret_name n
5330       );
5331       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5332   ) all_functions;
5333
5334   (* Check short descriptions. *)
5335   List.iter (
5336     fun (name, _, _, _, _, shortdesc, _) ->
5337       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5338         failwithf "short description of %s should begin with lowercase." name;
5339       let c = shortdesc.[String.length shortdesc-1] in
5340       if c = '\n' || c = '.' then
5341         failwithf "short description of %s should not end with . or \\n." name
5342   ) all_functions;
5343
5344   (* Check long descriptions. *)
5345   List.iter (
5346     fun (name, _, _, _, _, _, longdesc) ->
5347       if longdesc.[String.length longdesc-1] = '\n' then
5348         failwithf "long description of %s should not end with \\n." name
5349   ) all_functions;
5350
5351   (* Check proc_nrs. *)
5352   List.iter (
5353     fun (name, _, proc_nr, _, _, _, _) ->
5354       if proc_nr <= 0 then
5355         failwithf "daemon function %s should have proc_nr > 0" name
5356   ) daemon_functions;
5357
5358   List.iter (
5359     fun (name, _, proc_nr, _, _, _, _) ->
5360       if proc_nr <> -1 then
5361         failwithf "non-daemon function %s should have proc_nr -1" name
5362   ) non_daemon_functions;
5363
5364   let proc_nrs =
5365     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5366       daemon_functions in
5367   let proc_nrs =
5368     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5369   let rec loop = function
5370     | [] -> ()
5371     | [_] -> ()
5372     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5373         loop rest
5374     | (name1,nr1) :: (name2,nr2) :: _ ->
5375         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5376           name1 name2 nr1 nr2
5377   in
5378   loop proc_nrs;
5379
5380   (* Check tests. *)
5381   List.iter (
5382     function
5383       (* Ignore functions that have no tests.  We generate a
5384        * warning when the user does 'make check' instead.
5385        *)
5386     | name, _, _, _, [], _, _ -> ()
5387     | name, _, _, _, tests, _, _ ->
5388         let funcs =
5389           List.map (
5390             fun (_, _, test) ->
5391               match seq_of_test test with
5392               | [] ->
5393                   failwithf "%s has a test containing an empty sequence" name
5394               | cmds -> List.map List.hd cmds
5395           ) tests in
5396         let funcs = List.flatten funcs in
5397
5398         let tested = List.mem name funcs in
5399
5400         if not tested then
5401           failwithf "function %s has tests but does not test itself" name
5402   ) all_functions
5403
5404 (* 'pr' prints to the current output file. *)
5405 let chan = ref Pervasives.stdout
5406 let lines = ref 0
5407 let pr fs =
5408   ksprintf
5409     (fun str ->
5410        let i = count_chars '\n' str in
5411        lines := !lines + i;
5412        output_string !chan str
5413     ) fs
5414
5415 let copyright_years =
5416   let this_year = 1900 + (localtime (time ())).tm_year in
5417   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5418
5419 (* Generate a header block in a number of standard styles. *)
5420 type comment_style =
5421     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5422 type license = GPLv2plus | LGPLv2plus
5423
5424 let generate_header ?(extra_inputs = []) comment license =
5425   let inputs = "src/generator.ml" :: extra_inputs in
5426   let c = match comment with
5427     | CStyle ->         pr "/* "; " *"
5428     | CPlusPlusStyle -> pr "// "; "//"
5429     | HashStyle ->      pr "# ";  "#"
5430     | OCamlStyle ->     pr "(* "; " *"
5431     | HaskellStyle ->   pr "{- "; "  " in
5432   pr "libguestfs generated file\n";
5433   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5434   List.iter (pr "%s   %s\n" c) inputs;
5435   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5436   pr "%s\n" c;
5437   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5438   pr "%s\n" c;
5439   (match license with
5440    | GPLv2plus ->
5441        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5442        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5443        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5444        pr "%s (at your option) any later version.\n" c;
5445        pr "%s\n" c;
5446        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5447        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5448        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5449        pr "%s GNU General Public License for more details.\n" c;
5450        pr "%s\n" c;
5451        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5452        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5453        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5454
5455    | LGPLv2plus ->
5456        pr "%s This library is free software; you can redistribute it and/or\n" c;
5457        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5458        pr "%s License as published by the Free Software Foundation; either\n" c;
5459        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5460        pr "%s\n" c;
5461        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5462        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5463        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5464        pr "%s Lesser General Public License for more details.\n" c;
5465        pr "%s\n" c;
5466        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5467        pr "%s License along with this library; if not, write to the Free Software\n" c;
5468        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5469   );
5470   (match comment with
5471    | CStyle -> pr " */\n"
5472    | CPlusPlusStyle
5473    | HashStyle -> ()
5474    | OCamlStyle -> pr " *)\n"
5475    | HaskellStyle -> pr "-}\n"
5476   );
5477   pr "\n"
5478
5479 (* Start of main code generation functions below this line. *)
5480
5481 (* Generate the pod documentation for the C API. *)
5482 let rec generate_actions_pod () =
5483   List.iter (
5484     fun (shortname, style, _, flags, _, _, longdesc) ->
5485       if not (List.mem NotInDocs flags) then (
5486         let name = "guestfs_" ^ shortname in
5487         pr "=head2 %s\n\n" name;
5488         pr " ";
5489         generate_prototype ~extern:false ~handle:"g" name style;
5490         pr "\n\n";
5491         pr "%s\n\n" longdesc;
5492         (match fst style with
5493          | RErr ->
5494              pr "This function returns 0 on success or -1 on error.\n\n"
5495          | RInt _ ->
5496              pr "On error this function returns -1.\n\n"
5497          | RInt64 _ ->
5498              pr "On error this function returns -1.\n\n"
5499          | RBool _ ->
5500              pr "This function returns a C truth value on success or -1 on error.\n\n"
5501          | RConstString _ ->
5502              pr "This function returns a string, or NULL on error.
5503 The string is owned by the guest handle and must I<not> be freed.\n\n"
5504          | RConstOptString _ ->
5505              pr "This function returns a string which may be NULL.
5506 There is way to return an error from this function.
5507 The string is owned by the guest handle and must I<not> be freed.\n\n"
5508          | RString _ ->
5509              pr "This function returns a string, or NULL on error.
5510 I<The caller must free the returned string after use>.\n\n"
5511          | RStringList _ ->
5512              pr "This function returns a NULL-terminated array of strings
5513 (like L<environ(3)>), or NULL if there was an error.
5514 I<The caller must free the strings and the array after use>.\n\n"
5515          | RStruct (_, typ) ->
5516              pr "This function returns a C<struct guestfs_%s *>,
5517 or NULL if there was an error.
5518 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5519          | RStructList (_, typ) ->
5520              pr "This function returns a C<struct guestfs_%s_list *>
5521 (see E<lt>guestfs-structs.hE<gt>),
5522 or NULL if there was an error.
5523 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5524          | RHashtable _ ->
5525              pr "This function returns a NULL-terminated array of
5526 strings, or NULL if there was an error.
5527 The array of strings will always have length C<2n+1>, where
5528 C<n> keys and values alternate, followed by the trailing NULL entry.
5529 I<The caller must free the strings and the array after use>.\n\n"
5530          | RBufferOut _ ->
5531              pr "This function returns a buffer, or NULL on error.
5532 The size of the returned buffer is written to C<*size_r>.
5533 I<The caller must free the returned buffer after use>.\n\n"
5534         );
5535         if List.mem ProtocolLimitWarning flags then
5536           pr "%s\n\n" protocol_limit_warning;
5537         if List.mem DangerWillRobinson flags then
5538           pr "%s\n\n" danger_will_robinson;
5539         match deprecation_notice flags with
5540         | None -> ()
5541         | Some txt -> pr "%s\n\n" txt
5542       )
5543   ) all_functions_sorted
5544
5545 and generate_structs_pod () =
5546   (* Structs documentation. *)
5547   List.iter (
5548     fun (typ, cols) ->
5549       pr "=head2 guestfs_%s\n" typ;
5550       pr "\n";
5551       pr " struct guestfs_%s {\n" typ;
5552       List.iter (
5553         function
5554         | name, FChar -> pr "   char %s;\n" name
5555         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5556         | name, FInt32 -> pr "   int32_t %s;\n" name
5557         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5558         | name, FInt64 -> pr "   int64_t %s;\n" name
5559         | name, FString -> pr "   char *%s;\n" name
5560         | name, FBuffer ->
5561             pr "   /* The next two fields describe a byte array. */\n";
5562             pr "   uint32_t %s_len;\n" name;
5563             pr "   char *%s;\n" name
5564         | name, FUUID ->
5565             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5566             pr "   char %s[32];\n" name
5567         | name, FOptPercent ->
5568             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5569             pr "   float %s;\n" name
5570       ) cols;
5571       pr " };\n";
5572       pr " \n";
5573       pr " struct guestfs_%s_list {\n" typ;
5574       pr "   uint32_t len; /* Number of elements in list. */\n";
5575       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5576       pr " };\n";
5577       pr " \n";
5578       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5579       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5580         typ typ;
5581       pr "\n"
5582   ) structs
5583
5584 and generate_availability_pod () =
5585   (* Availability documentation. *)
5586   pr "=over 4\n";
5587   pr "\n";
5588   List.iter (
5589     fun (group, functions) ->
5590       pr "=item B<%s>\n" group;
5591       pr "\n";
5592       pr "The following functions:\n";
5593       List.iter (pr "L</guestfs_%s>\n") functions;
5594       pr "\n"
5595   ) optgroups;
5596   pr "=back\n";
5597   pr "\n"
5598
5599 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5600  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5601  *
5602  * We have to use an underscore instead of a dash because otherwise
5603  * rpcgen generates incorrect code.
5604  *
5605  * This header is NOT exported to clients, but see also generate_structs_h.
5606  *)
5607 and generate_xdr () =
5608   generate_header CStyle LGPLv2plus;
5609
5610   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5611   pr "typedef string str<>;\n";
5612   pr "\n";
5613
5614   (* Internal structures. *)
5615   List.iter (
5616     function
5617     | typ, cols ->
5618         pr "struct guestfs_int_%s {\n" typ;
5619         List.iter (function
5620                    | name, FChar -> pr "  char %s;\n" name
5621                    | name, FString -> pr "  string %s<>;\n" name
5622                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5623                    | name, FUUID -> pr "  opaque %s[32];\n" name
5624                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5625                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5626                    | name, FOptPercent -> pr "  float %s;\n" name
5627                   ) cols;
5628         pr "};\n";
5629         pr "\n";
5630         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5631         pr "\n";
5632   ) structs;
5633
5634   List.iter (
5635     fun (shortname, style, _, _, _, _, _) ->
5636       let name = "guestfs_" ^ shortname in
5637
5638       (match snd style with
5639        | [] -> ()
5640        | args ->
5641            pr "struct %s_args {\n" name;
5642            List.iter (
5643              function
5644              | Pathname n | Device n | Dev_or_Path n | String n ->
5645                  pr "  string %s<>;\n" n
5646              | OptString n -> pr "  str *%s;\n" n
5647              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5648              | Bool n -> pr "  bool %s;\n" n
5649              | Int n -> pr "  int %s;\n" n
5650              | Int64 n -> pr "  hyper %s;\n" n
5651              | BufferIn n ->
5652                  pr "  opaque %s<>;\n" n
5653              | FileIn _ | FileOut _ -> ()
5654            ) args;
5655            pr "};\n\n"
5656       );
5657       (match fst style with
5658        | RErr -> ()
5659        | RInt n ->
5660            pr "struct %s_ret {\n" name;
5661            pr "  int %s;\n" n;
5662            pr "};\n\n"
5663        | RInt64 n ->
5664            pr "struct %s_ret {\n" name;
5665            pr "  hyper %s;\n" n;
5666            pr "};\n\n"
5667        | RBool n ->
5668            pr "struct %s_ret {\n" name;
5669            pr "  bool %s;\n" n;
5670            pr "};\n\n"
5671        | RConstString _ | RConstOptString _ ->
5672            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5673        | RString n ->
5674            pr "struct %s_ret {\n" name;
5675            pr "  string %s<>;\n" n;
5676            pr "};\n\n"
5677        | RStringList n ->
5678            pr "struct %s_ret {\n" name;
5679            pr "  str %s<>;\n" n;
5680            pr "};\n\n"
5681        | RStruct (n, typ) ->
5682            pr "struct %s_ret {\n" name;
5683            pr "  guestfs_int_%s %s;\n" typ n;
5684            pr "};\n\n"
5685        | RStructList (n, typ) ->
5686            pr "struct %s_ret {\n" name;
5687            pr "  guestfs_int_%s_list %s;\n" typ n;
5688            pr "};\n\n"
5689        | RHashtable n ->
5690            pr "struct %s_ret {\n" name;
5691            pr "  str %s<>;\n" n;
5692            pr "};\n\n"
5693        | RBufferOut n ->
5694            pr "struct %s_ret {\n" name;
5695            pr "  opaque %s<>;\n" n;
5696            pr "};\n\n"
5697       );
5698   ) daemon_functions;
5699
5700   (* Table of procedure numbers. *)
5701   pr "enum guestfs_procedure {\n";
5702   List.iter (
5703     fun (shortname, _, proc_nr, _, _, _, _) ->
5704       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5705   ) daemon_functions;
5706   pr "  GUESTFS_PROC_NR_PROCS\n";
5707   pr "};\n";
5708   pr "\n";
5709
5710   (* Having to choose a maximum message size is annoying for several
5711    * reasons (it limits what we can do in the API), but it (a) makes
5712    * the protocol a lot simpler, and (b) provides a bound on the size
5713    * of the daemon which operates in limited memory space.
5714    *)
5715   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5716   pr "\n";
5717
5718   (* Message header, etc. *)
5719   pr "\
5720 /* The communication protocol is now documented in the guestfs(3)
5721  * manpage.
5722  */
5723
5724 const GUESTFS_PROGRAM = 0x2000F5F5;
5725 const GUESTFS_PROTOCOL_VERSION = 1;
5726
5727 /* These constants must be larger than any possible message length. */
5728 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5729 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5730
5731 enum guestfs_message_direction {
5732   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5733   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5734 };
5735
5736 enum guestfs_message_status {
5737   GUESTFS_STATUS_OK = 0,
5738   GUESTFS_STATUS_ERROR = 1
5739 };
5740
5741 const GUESTFS_ERROR_LEN = 256;
5742
5743 struct guestfs_message_error {
5744   string error_message<GUESTFS_ERROR_LEN>;
5745 };
5746
5747 struct guestfs_message_header {
5748   unsigned prog;                     /* GUESTFS_PROGRAM */
5749   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5750   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5751   guestfs_message_direction direction;
5752   unsigned serial;                   /* message serial number */
5753   guestfs_message_status status;
5754 };
5755
5756 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5757
5758 struct guestfs_chunk {
5759   int cancel;                        /* if non-zero, transfer is cancelled */
5760   /* data size is 0 bytes if the transfer has finished successfully */
5761   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5762 };
5763 "
5764
5765 (* Generate the guestfs-structs.h file. *)
5766 and generate_structs_h () =
5767   generate_header CStyle LGPLv2plus;
5768
5769   (* This is a public exported header file containing various
5770    * structures.  The structures are carefully written to have
5771    * exactly the same in-memory format as the XDR structures that
5772    * we use on the wire to the daemon.  The reason for creating
5773    * copies of these structures here is just so we don't have to
5774    * export the whole of guestfs_protocol.h (which includes much
5775    * unrelated and XDR-dependent stuff that we don't want to be
5776    * public, or required by clients).
5777    *
5778    * To reiterate, we will pass these structures to and from the
5779    * client with a simple assignment or memcpy, so the format
5780    * must be identical to what rpcgen / the RFC defines.
5781    *)
5782
5783   (* Public structures. *)
5784   List.iter (
5785     fun (typ, cols) ->
5786       pr "struct guestfs_%s {\n" typ;
5787       List.iter (
5788         function
5789         | name, FChar -> pr "  char %s;\n" name
5790         | name, FString -> pr "  char *%s;\n" name
5791         | name, FBuffer ->
5792             pr "  uint32_t %s_len;\n" name;
5793             pr "  char *%s;\n" name
5794         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5795         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5796         | name, FInt32 -> pr "  int32_t %s;\n" name
5797         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5798         | name, FInt64 -> pr "  int64_t %s;\n" name
5799         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5800       ) cols;
5801       pr "};\n";
5802       pr "\n";
5803       pr "struct guestfs_%s_list {\n" typ;
5804       pr "  uint32_t len;\n";
5805       pr "  struct guestfs_%s *val;\n" typ;
5806       pr "};\n";
5807       pr "\n";
5808       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5809       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5810       pr "\n"
5811   ) structs
5812
5813 (* Generate the guestfs-actions.h file. *)
5814 and generate_actions_h () =
5815   generate_header CStyle LGPLv2plus;
5816   List.iter (
5817     fun (shortname, style, _, _, _, _, _) ->
5818       let name = "guestfs_" ^ shortname in
5819       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5820         name style
5821   ) all_functions
5822
5823 (* Generate the guestfs-internal-actions.h file. *)
5824 and generate_internal_actions_h () =
5825   generate_header CStyle LGPLv2plus;
5826   List.iter (
5827     fun (shortname, style, _, _, _, _, _) ->
5828       let name = "guestfs__" ^ shortname in
5829       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5830         name style
5831   ) non_daemon_functions
5832
5833 (* Generate the client-side dispatch stubs. *)
5834 and generate_client_actions () =
5835   generate_header CStyle LGPLv2plus;
5836
5837   pr "\
5838 #include <stdio.h>
5839 #include <stdlib.h>
5840 #include <stdint.h>
5841 #include <string.h>
5842 #include <inttypes.h>
5843
5844 #include \"guestfs.h\"
5845 #include \"guestfs-internal.h\"
5846 #include \"guestfs-internal-actions.h\"
5847 #include \"guestfs_protocol.h\"
5848
5849 #define error guestfs_error
5850 //#define perrorf guestfs_perrorf
5851 #define safe_malloc guestfs_safe_malloc
5852 #define safe_realloc guestfs_safe_realloc
5853 //#define safe_strdup guestfs_safe_strdup
5854 #define safe_memdup guestfs_safe_memdup
5855
5856 /* Check the return message from a call for validity. */
5857 static int
5858 check_reply_header (guestfs_h *g,
5859                     const struct guestfs_message_header *hdr,
5860                     unsigned int proc_nr, unsigned int serial)
5861 {
5862   if (hdr->prog != GUESTFS_PROGRAM) {
5863     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5864     return -1;
5865   }
5866   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5867     error (g, \"wrong protocol version (%%d/%%d)\",
5868            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5869     return -1;
5870   }
5871   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5872     error (g, \"unexpected message direction (%%d/%%d)\",
5873            hdr->direction, GUESTFS_DIRECTION_REPLY);
5874     return -1;
5875   }
5876   if (hdr->proc != proc_nr) {
5877     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5878     return -1;
5879   }
5880   if (hdr->serial != serial) {
5881     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5882     return -1;
5883   }
5884
5885   return 0;
5886 }
5887
5888 /* Check we are in the right state to run a high-level action. */
5889 static int
5890 check_state (guestfs_h *g, const char *caller)
5891 {
5892   if (!guestfs__is_ready (g)) {
5893     if (guestfs__is_config (g) || guestfs__is_launching (g))
5894       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5895         caller);
5896     else
5897       error (g, \"%%s called from the wrong state, %%d != READY\",
5898         caller, guestfs__get_state (g));
5899     return -1;
5900   }
5901   return 0;
5902 }
5903
5904 ";
5905
5906   let error_code_of = function
5907     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5908     | RConstString _ | RConstOptString _
5909     | RString _ | RStringList _
5910     | RStruct _ | RStructList _
5911     | RHashtable _ | RBufferOut _ -> "NULL"
5912   in
5913
5914   (* Generate code to check String-like parameters are not passed in
5915    * as NULL (returning an error if they are).
5916    *)
5917   let check_null_strings shortname style =
5918     let pr_newline = ref false in
5919     List.iter (
5920       function
5921       (* parameters which should not be NULL *)
5922       | String n
5923       | Device n
5924       | Pathname n
5925       | Dev_or_Path n
5926       | FileIn n
5927       | FileOut n
5928       | BufferIn n
5929       | StringList n
5930       | DeviceList n ->
5931           pr "  if (%s == NULL) {\n" n;
5932           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
5933           pr "           \"%s\", \"%s\");\n" shortname n;
5934           pr "    return %s;\n" (error_code_of (fst style));
5935           pr "  }\n";
5936           pr_newline := true
5937
5938       (* can be NULL *)
5939       | OptString _
5940
5941       (* not applicable *)
5942       | Bool _
5943       | Int _
5944       | Int64 _ -> ()
5945     ) (snd style);
5946
5947     if !pr_newline then pr "\n";
5948   in
5949
5950   (* Generate code to generate guestfish call traces. *)
5951   let trace_call shortname style =
5952     pr "  if (guestfs__get_trace (g)) {\n";
5953
5954     let needs_i =
5955       List.exists (function
5956                    | StringList _ | DeviceList _ -> true
5957                    | _ -> false) (snd style) in
5958     if needs_i then (
5959       pr "    int i;\n";
5960       pr "\n"
5961     );
5962
5963     pr "    printf (\"%s\");\n" shortname;
5964     List.iter (
5965       function
5966       | String n                        (* strings *)
5967       | Device n
5968       | Pathname n
5969       | Dev_or_Path n
5970       | FileIn n
5971       | FileOut n
5972       | BufferIn n ->
5973           (* guestfish doesn't support string escaping, so neither do we *)
5974           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5975       | OptString n ->                  (* string option *)
5976           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5977           pr "    else printf (\" null\");\n"
5978       | StringList n
5979       | DeviceList n ->                 (* string list *)
5980           pr "    putchar (' ');\n";
5981           pr "    putchar ('\"');\n";
5982           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5983           pr "      if (i > 0) putchar (' ');\n";
5984           pr "      fputs (%s[i], stdout);\n" n;
5985           pr "    }\n";
5986           pr "    putchar ('\"');\n";
5987       | Bool n ->                       (* boolean *)
5988           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5989       | Int n ->                        (* int *)
5990           pr "    printf (\" %%d\", %s);\n" n
5991       | Int64 n ->
5992           pr "    printf (\" %%\" PRIi64, %s);\n" n
5993     ) (snd style);
5994     pr "    putchar ('\\n');\n";
5995     pr "  }\n";
5996     pr "\n";
5997   in
5998
5999   (* For non-daemon functions, generate a wrapper around each function. *)
6000   List.iter (
6001     fun (shortname, style, _, _, _, _, _) ->
6002       let name = "guestfs_" ^ shortname in
6003
6004       generate_prototype ~extern:false ~semicolon:false ~newline:true
6005         ~handle:"g" name style;
6006       pr "{\n";
6007       check_null_strings shortname style;
6008       trace_call shortname style;
6009       pr "  return guestfs__%s " shortname;
6010       generate_c_call_args ~handle:"g" style;
6011       pr ";\n";
6012       pr "}\n";
6013       pr "\n"
6014   ) non_daemon_functions;
6015
6016   (* Client-side stubs for each function. *)
6017   List.iter (
6018     fun (shortname, style, _, _, _, _, _) ->
6019       let name = "guestfs_" ^ shortname in
6020       let error_code = error_code_of (fst style) in
6021
6022       (* Generate the action stub. *)
6023       generate_prototype ~extern:false ~semicolon:false ~newline:true
6024         ~handle:"g" name style;
6025
6026       pr "{\n";
6027
6028       (match snd style with
6029        | [] -> ()
6030        | _ -> pr "  struct %s_args args;\n" name
6031       );
6032
6033       pr "  guestfs_message_header hdr;\n";
6034       pr "  guestfs_message_error err;\n";
6035       let has_ret =
6036         match fst style with
6037         | RErr -> false
6038         | RConstString _ | RConstOptString _ ->
6039             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6040         | RInt _ | RInt64 _
6041         | RBool _ | RString _ | RStringList _
6042         | RStruct _ | RStructList _
6043         | RHashtable _ | RBufferOut _ ->
6044             pr "  struct %s_ret ret;\n" name;
6045             true in
6046
6047       pr "  int serial;\n";
6048       pr "  int r;\n";
6049       pr "\n";
6050       check_null_strings shortname style;
6051       trace_call shortname style;
6052       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6053         shortname error_code;
6054       pr "  guestfs___set_busy (g);\n";
6055       pr "\n";
6056
6057       (* Send the main header and arguments. *)
6058       (match snd style with
6059        | [] ->
6060            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6061              (String.uppercase shortname)
6062        | args ->
6063            List.iter (
6064              function
6065              | Pathname n | Device n | Dev_or_Path n | String n ->
6066                  pr "  args.%s = (char *) %s;\n" n n
6067              | OptString n ->
6068                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6069              | StringList n | DeviceList n ->
6070                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6071                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6072              | Bool n ->
6073                  pr "  args.%s = %s;\n" n n
6074              | Int n ->
6075                  pr "  args.%s = %s;\n" n n
6076              | Int64 n ->
6077                  pr "  args.%s = %s;\n" n n
6078              | FileIn _ | FileOut _ -> ()
6079              | BufferIn n ->
6080                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6081                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6082                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6083                    shortname;
6084                  pr "    guestfs___end_busy (g);\n";
6085                  pr "    return %s;\n" error_code;
6086                  pr "  }\n";
6087                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6088                  pr "  args.%s.%s_len = %s_size;\n" n n n
6089            ) args;
6090            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6091              (String.uppercase shortname);
6092            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6093              name;
6094       );
6095       pr "  if (serial == -1) {\n";
6096       pr "    guestfs___end_busy (g);\n";
6097       pr "    return %s;\n" error_code;
6098       pr "  }\n";
6099       pr "\n";
6100
6101       (* Send any additional files (FileIn) requested. *)
6102       let need_read_reply_label = ref false in
6103       List.iter (
6104         function
6105         | FileIn n ->
6106             pr "  r = guestfs___send_file (g, %s);\n" n;
6107             pr "  if (r == -1) {\n";
6108             pr "    guestfs___end_busy (g);\n";
6109             pr "    return %s;\n" error_code;
6110             pr "  }\n";
6111             pr "  if (r == -2) /* daemon cancelled */\n";
6112             pr "    goto read_reply;\n";
6113             need_read_reply_label := true;
6114             pr "\n";
6115         | _ -> ()
6116       ) (snd style);
6117
6118       (* Wait for the reply from the remote end. *)
6119       if !need_read_reply_label then pr " read_reply:\n";
6120       pr "  memset (&hdr, 0, sizeof hdr);\n";
6121       pr "  memset (&err, 0, sizeof err);\n";
6122       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6123       pr "\n";
6124       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6125       if not has_ret then
6126         pr "NULL, NULL"
6127       else
6128         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6129       pr ");\n";
6130
6131       pr "  if (r == -1) {\n";
6132       pr "    guestfs___end_busy (g);\n";
6133       pr "    return %s;\n" error_code;
6134       pr "  }\n";
6135       pr "\n";
6136
6137       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6138         (String.uppercase shortname);
6139       pr "    guestfs___end_busy (g);\n";
6140       pr "    return %s;\n" error_code;
6141       pr "  }\n";
6142       pr "\n";
6143
6144       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6145       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6146       pr "    free (err.error_message);\n";
6147       pr "    guestfs___end_busy (g);\n";
6148       pr "    return %s;\n" error_code;
6149       pr "  }\n";
6150       pr "\n";
6151
6152       (* Expecting to receive further files (FileOut)? *)
6153       List.iter (
6154         function
6155         | FileOut n ->
6156             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6157             pr "    guestfs___end_busy (g);\n";
6158             pr "    return %s;\n" error_code;
6159             pr "  }\n";
6160             pr "\n";
6161         | _ -> ()
6162       ) (snd style);
6163
6164       pr "  guestfs___end_busy (g);\n";
6165
6166       (match fst style with
6167        | RErr -> pr "  return 0;\n"
6168        | RInt n | RInt64 n | RBool n ->
6169            pr "  return ret.%s;\n" n
6170        | RConstString _ | RConstOptString _ ->
6171            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6172        | RString n ->
6173            pr "  return ret.%s; /* caller will free */\n" n
6174        | RStringList n | RHashtable n ->
6175            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6176            pr "  ret.%s.%s_val =\n" n n;
6177            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6178            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6179              n n;
6180            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6181            pr "  return ret.%s.%s_val;\n" n n
6182        | RStruct (n, _) ->
6183            pr "  /* caller will free this */\n";
6184            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6185        | RStructList (n, _) ->
6186            pr "  /* caller will free this */\n";
6187            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6188        | RBufferOut n ->
6189            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6190            pr "   * _val might be NULL here.  To make the API saner for\n";
6191            pr "   * callers, we turn this case into a unique pointer (using\n";
6192            pr "   * malloc(1)).\n";
6193            pr "   */\n";
6194            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6195            pr "    *size_r = ret.%s.%s_len;\n" n n;
6196            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6197            pr "  } else {\n";
6198            pr "    free (ret.%s.%s_val);\n" n n;
6199            pr "    char *p = safe_malloc (g, 1);\n";
6200            pr "    *size_r = ret.%s.%s_len;\n" n n;
6201            pr "    return p;\n";
6202            pr "  }\n";
6203       );
6204
6205       pr "}\n\n"
6206   ) daemon_functions;
6207
6208   (* Functions to free structures. *)
6209   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6210   pr " * structure format is identical to the XDR format.  See note in\n";
6211   pr " * generator.ml.\n";
6212   pr " */\n";
6213   pr "\n";
6214
6215   List.iter (
6216     fun (typ, _) ->
6217       pr "void\n";
6218       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6219       pr "{\n";
6220       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6221       pr "  free (x);\n";
6222       pr "}\n";
6223       pr "\n";
6224
6225       pr "void\n";
6226       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6227       pr "{\n";
6228       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6229       pr "  free (x);\n";
6230       pr "}\n";
6231       pr "\n";
6232
6233   ) structs;
6234
6235 (* Generate daemon/actions.h. *)
6236 and generate_daemon_actions_h () =
6237   generate_header CStyle GPLv2plus;
6238
6239   pr "#include \"../src/guestfs_protocol.h\"\n";
6240   pr "\n";
6241
6242   List.iter (
6243     fun (name, style, _, _, _, _, _) ->
6244       generate_prototype
6245         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6246         name style;
6247   ) daemon_functions
6248
6249 (* Generate the linker script which controls the visibility of
6250  * symbols in the public ABI and ensures no other symbols get
6251  * exported accidentally.
6252  *)
6253 and generate_linker_script () =
6254   generate_header HashStyle GPLv2plus;
6255
6256   let globals = [
6257     "guestfs_create";
6258     "guestfs_close";
6259     "guestfs_get_error_handler";
6260     "guestfs_get_out_of_memory_handler";
6261     "guestfs_last_error";
6262     "guestfs_set_error_handler";
6263     "guestfs_set_launch_done_callback";
6264     "guestfs_set_log_message_callback";
6265     "guestfs_set_out_of_memory_handler";
6266     "guestfs_set_subprocess_quit_callback";
6267
6268     (* Unofficial parts of the API: the bindings code use these
6269      * functions, so it is useful to export them.
6270      *)
6271     "guestfs_safe_calloc";
6272     "guestfs_safe_malloc";
6273   ] in
6274   let functions =
6275     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6276       all_functions in
6277   let structs =
6278     List.concat (
6279       List.map (fun (typ, _) ->
6280                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6281         structs
6282     ) in
6283   let globals = List.sort compare (globals @ functions @ structs) in
6284
6285   pr "{\n";
6286   pr "    global:\n";
6287   List.iter (pr "        %s;\n") globals;
6288   pr "\n";
6289
6290   pr "    local:\n";
6291   pr "        *;\n";
6292   pr "};\n"
6293
6294 (* Generate the server-side stubs. *)
6295 and generate_daemon_actions () =
6296   generate_header CStyle GPLv2plus;
6297
6298   pr "#include <config.h>\n";
6299   pr "\n";
6300   pr "#include <stdio.h>\n";
6301   pr "#include <stdlib.h>\n";
6302   pr "#include <string.h>\n";
6303   pr "#include <inttypes.h>\n";
6304   pr "#include <rpc/types.h>\n";
6305   pr "#include <rpc/xdr.h>\n";
6306   pr "\n";
6307   pr "#include \"daemon.h\"\n";
6308   pr "#include \"c-ctype.h\"\n";
6309   pr "#include \"../src/guestfs_protocol.h\"\n";
6310   pr "#include \"actions.h\"\n";
6311   pr "\n";
6312
6313   List.iter (
6314     fun (name, style, _, _, _, _, _) ->
6315       (* Generate server-side stubs. *)
6316       pr "static void %s_stub (XDR *xdr_in)\n" name;
6317       pr "{\n";
6318       let error_code =
6319         match fst style with
6320         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6321         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6322         | RBool _ -> pr "  int r;\n"; "-1"
6323         | RConstString _ | RConstOptString _ ->
6324             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6325         | RString _ -> pr "  char *r;\n"; "NULL"
6326         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6327         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6328         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6329         | RBufferOut _ ->
6330             pr "  size_t size = 1;\n";
6331             pr "  char *r;\n";
6332             "NULL" in
6333
6334       (match snd style with
6335        | [] -> ()
6336        | args ->
6337            pr "  struct guestfs_%s_args args;\n" name;
6338            List.iter (
6339              function
6340              | Device n | Dev_or_Path n
6341              | Pathname n
6342              | String n -> ()
6343              | OptString n -> pr "  char *%s;\n" n
6344              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6345              | Bool n -> pr "  int %s;\n" n
6346              | Int n -> pr "  int %s;\n" n
6347              | Int64 n -> pr "  int64_t %s;\n" n
6348              | FileIn _ | FileOut _ -> ()
6349              | BufferIn n ->
6350                  pr "  const char *%s;\n" n;
6351                  pr "  size_t %s_size;\n" n
6352            ) args
6353       );
6354       pr "\n";
6355
6356       let is_filein =
6357         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6358
6359       (match snd style with
6360        | [] -> ()
6361        | args ->
6362            pr "  memset (&args, 0, sizeof args);\n";
6363            pr "\n";
6364            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6365            if is_filein then
6366              pr "    if (cancel_receive () != -2)\n";
6367            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6368            pr "    goto done;\n";
6369            pr "  }\n";
6370            let pr_args n =
6371              pr "  char *%s = args.%s;\n" n n
6372            in
6373            let pr_list_handling_code n =
6374              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6375              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6376              pr "  if (%s == NULL) {\n" n;
6377              if is_filein then
6378                pr "    if (cancel_receive () != -2)\n";
6379              pr "      reply_with_perror (\"realloc\");\n";
6380              pr "    goto done;\n";
6381              pr "  }\n";
6382              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6383              pr "  args.%s.%s_val = %s;\n" n n n;
6384            in
6385            List.iter (
6386              function
6387              | Pathname n ->
6388                  pr_args n;
6389                  pr "  ABS_PATH (%s, %s, goto done);\n"
6390                    n (if is_filein then "cancel_receive ()" else "0");
6391              | Device n ->
6392                  pr_args n;
6393                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6394                    n (if is_filein then "cancel_receive ()" else "0");
6395              | Dev_or_Path n ->
6396                  pr_args n;
6397                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6398                    n (if is_filein then "cancel_receive ()" else "0");
6399              | String n -> pr_args n
6400              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6401              | StringList n ->
6402                  pr_list_handling_code n;
6403              | DeviceList n ->
6404                  pr_list_handling_code n;
6405                  pr "  /* Ensure that each is a device,\n";
6406                  pr "   * and perform device name translation. */\n";
6407                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6408                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6409                    (if is_filein then "cancel_receive ()" else "0");
6410                  pr "  }\n";
6411              | Bool n -> pr "  %s = args.%s;\n" n n
6412              | Int n -> pr "  %s = args.%s;\n" n n
6413              | Int64 n -> pr "  %s = args.%s;\n" n n
6414              | FileIn _ | FileOut _ -> ()
6415              | BufferIn n ->
6416                  pr "  %s = args.%s.%s_val;\n" n n n;
6417                  pr "  %s_size = args.%s.%s_len;\n" n n n
6418            ) args;
6419            pr "\n"
6420       );
6421
6422       (* this is used at least for do_equal *)
6423       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6424         (* Emit NEED_ROOT just once, even when there are two or
6425            more Pathname args *)
6426         pr "  NEED_ROOT (%s, goto done);\n"
6427           (if is_filein then "cancel_receive ()" else "0");
6428       );
6429
6430       (* Don't want to call the impl with any FileIn or FileOut
6431        * parameters, since these go "outside" the RPC protocol.
6432        *)
6433       let args' =
6434         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6435           (snd style) in
6436       pr "  r = do_%s " name;
6437       generate_c_call_args (fst style, args');
6438       pr ";\n";
6439
6440       (match fst style with
6441        | RErr | RInt _ | RInt64 _ | RBool _
6442        | RConstString _ | RConstOptString _
6443        | RString _ | RStringList _ | RHashtable _
6444        | RStruct (_, _) | RStructList (_, _) ->
6445            pr "  if (r == %s)\n" error_code;
6446            pr "    /* do_%s has already called reply_with_error */\n" name;
6447            pr "    goto done;\n";
6448            pr "\n"
6449        | RBufferOut _ ->
6450            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6451            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6452            pr "   */\n";
6453            pr "  if (size == 1 && r == %s)\n" error_code;
6454            pr "    /* do_%s has already called reply_with_error */\n" name;
6455            pr "    goto done;\n";
6456            pr "\n"
6457       );
6458
6459       (* If there are any FileOut parameters, then the impl must
6460        * send its own reply.
6461        *)
6462       let no_reply =
6463         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6464       if no_reply then
6465         pr "  /* do_%s has already sent a reply */\n" name
6466       else (
6467         match fst style with
6468         | RErr -> pr "  reply (NULL, NULL);\n"
6469         | RInt n | RInt64 n | RBool n ->
6470             pr "  struct guestfs_%s_ret ret;\n" name;
6471             pr "  ret.%s = r;\n" n;
6472             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6473               name
6474         | RConstString _ | RConstOptString _ ->
6475             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6476         | RString n ->
6477             pr "  struct guestfs_%s_ret ret;\n" name;
6478             pr "  ret.%s = r;\n" n;
6479             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6480               name;
6481             pr "  free (r);\n"
6482         | RStringList n | RHashtable n ->
6483             pr "  struct guestfs_%s_ret ret;\n" name;
6484             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6485             pr "  ret.%s.%s_val = r;\n" n n;
6486             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6487               name;
6488             pr "  free_strings (r);\n"
6489         | RStruct (n, _) ->
6490             pr "  struct guestfs_%s_ret ret;\n" name;
6491             pr "  ret.%s = *r;\n" n;
6492             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6493               name;
6494             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6495               name
6496         | RStructList (n, _) ->
6497             pr "  struct guestfs_%s_ret ret;\n" name;
6498             pr "  ret.%s = *r;\n" n;
6499             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6500               name;
6501             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6502               name
6503         | RBufferOut n ->
6504             pr "  struct guestfs_%s_ret ret;\n" name;
6505             pr "  ret.%s.%s_val = r;\n" n n;
6506             pr "  ret.%s.%s_len = size;\n" n n;
6507             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6508               name;
6509             pr "  free (r);\n"
6510       );
6511
6512       (* Free the args. *)
6513       pr "done:\n";
6514       (match snd style with
6515        | [] -> ()
6516        | _ ->
6517            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6518              name
6519       );
6520       pr "  return;\n";
6521       pr "}\n\n";
6522   ) daemon_functions;
6523
6524   (* Dispatch function. *)
6525   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6526   pr "{\n";
6527   pr "  switch (proc_nr) {\n";
6528
6529   List.iter (
6530     fun (name, style, _, _, _, _, _) ->
6531       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6532       pr "      %s_stub (xdr_in);\n" name;
6533       pr "      break;\n"
6534   ) daemon_functions;
6535
6536   pr "    default:\n";
6537   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";
6538   pr "  }\n";
6539   pr "}\n";
6540   pr "\n";
6541
6542   (* LVM columns and tokenization functions. *)
6543   (* XXX This generates crap code.  We should rethink how we
6544    * do this parsing.
6545    *)
6546   List.iter (
6547     function
6548     | typ, cols ->
6549         pr "static const char *lvm_%s_cols = \"%s\";\n"
6550           typ (String.concat "," (List.map fst cols));
6551         pr "\n";
6552
6553         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6554         pr "{\n";
6555         pr "  char *tok, *p, *next;\n";
6556         pr "  int i, j;\n";
6557         pr "\n";
6558         (*
6559           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6560           pr "\n";
6561         *)
6562         pr "  if (!str) {\n";
6563         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6564         pr "    return -1;\n";
6565         pr "  }\n";
6566         pr "  if (!*str || c_isspace (*str)) {\n";
6567         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6568         pr "    return -1;\n";
6569         pr "  }\n";
6570         pr "  tok = str;\n";
6571         List.iter (
6572           fun (name, coltype) ->
6573             pr "  if (!tok) {\n";
6574             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6575             pr "    return -1;\n";
6576             pr "  }\n";
6577             pr "  p = strchrnul (tok, ',');\n";
6578             pr "  if (*p) next = p+1; else next = NULL;\n";
6579             pr "  *p = '\\0';\n";
6580             (match coltype with
6581              | FString ->
6582                  pr "  r->%s = strdup (tok);\n" name;
6583                  pr "  if (r->%s == NULL) {\n" name;
6584                  pr "    perror (\"strdup\");\n";
6585                  pr "    return -1;\n";
6586                  pr "  }\n"
6587              | FUUID ->
6588                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6589                  pr "    if (tok[j] == '\\0') {\n";
6590                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6591                  pr "      return -1;\n";
6592                  pr "    } else if (tok[j] != '-')\n";
6593                  pr "      r->%s[i++] = tok[j];\n" name;
6594                  pr "  }\n";
6595              | FBytes ->
6596                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6597                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6598                  pr "    return -1;\n";
6599                  pr "  }\n";
6600              | FInt64 ->
6601                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6602                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6603                  pr "    return -1;\n";
6604                  pr "  }\n";
6605              | FOptPercent ->
6606                  pr "  if (tok[0] == '\\0')\n";
6607                  pr "    r->%s = -1;\n" name;
6608                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6609                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6610                  pr "    return -1;\n";
6611                  pr "  }\n";
6612              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6613                  assert false (* can never be an LVM column *)
6614             );
6615             pr "  tok = next;\n";
6616         ) cols;
6617
6618         pr "  if (tok != NULL) {\n";
6619         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6620         pr "    return -1;\n";
6621         pr "  }\n";
6622         pr "  return 0;\n";
6623         pr "}\n";
6624         pr "\n";
6625
6626         pr "guestfs_int_lvm_%s_list *\n" typ;
6627         pr "parse_command_line_%ss (void)\n" typ;
6628         pr "{\n";
6629         pr "  char *out, *err;\n";
6630         pr "  char *p, *pend;\n";
6631         pr "  int r, i;\n";
6632         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6633         pr "  void *newp;\n";
6634         pr "\n";
6635         pr "  ret = malloc (sizeof *ret);\n";
6636         pr "  if (!ret) {\n";
6637         pr "    reply_with_perror (\"malloc\");\n";
6638         pr "    return NULL;\n";
6639         pr "  }\n";
6640         pr "\n";
6641         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6642         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6643         pr "\n";
6644         pr "  r = command (&out, &err,\n";
6645         pr "           \"lvm\", \"%ss\",\n" typ;
6646         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6647         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6648         pr "  if (r == -1) {\n";
6649         pr "    reply_with_error (\"%%s\", err);\n";
6650         pr "    free (out);\n";
6651         pr "    free (err);\n";
6652         pr "    free (ret);\n";
6653         pr "    return NULL;\n";
6654         pr "  }\n";
6655         pr "\n";
6656         pr "  free (err);\n";
6657         pr "\n";
6658         pr "  /* Tokenize each line of the output. */\n";
6659         pr "  p = out;\n";
6660         pr "  i = 0;\n";
6661         pr "  while (p) {\n";
6662         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6663         pr "    if (pend) {\n";
6664         pr "      *pend = '\\0';\n";
6665         pr "      pend++;\n";
6666         pr "    }\n";
6667         pr "\n";
6668         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6669         pr "      p++;\n";
6670         pr "\n";
6671         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6672         pr "      p = pend;\n";
6673         pr "      continue;\n";
6674         pr "    }\n";
6675         pr "\n";
6676         pr "    /* Allocate some space to store this next entry. */\n";
6677         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6678         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6679         pr "    if (newp == NULL) {\n";
6680         pr "      reply_with_perror (\"realloc\");\n";
6681         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6682         pr "      free (ret);\n";
6683         pr "      free (out);\n";
6684         pr "      return NULL;\n";
6685         pr "    }\n";
6686         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6687         pr "\n";
6688         pr "    /* Tokenize the next entry. */\n";
6689         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6690         pr "    if (r == -1) {\n";
6691         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6692         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6693         pr "      free (ret);\n";
6694         pr "      free (out);\n";
6695         pr "      return NULL;\n";
6696         pr "    }\n";
6697         pr "\n";
6698         pr "    ++i;\n";
6699         pr "    p = pend;\n";
6700         pr "  }\n";
6701         pr "\n";
6702         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6703         pr "\n";
6704         pr "  free (out);\n";
6705         pr "  return ret;\n";
6706         pr "}\n"
6707
6708   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6709
6710 (* Generate a list of function names, for debugging in the daemon.. *)
6711 and generate_daemon_names () =
6712   generate_header CStyle GPLv2plus;
6713
6714   pr "#include <config.h>\n";
6715   pr "\n";
6716   pr "#include \"daemon.h\"\n";
6717   pr "\n";
6718
6719   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6720   pr "const char *function_names[] = {\n";
6721   List.iter (
6722     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6723   ) daemon_functions;
6724   pr "};\n";
6725
6726 (* Generate the optional groups for the daemon to implement
6727  * guestfs_available.
6728  *)
6729 and generate_daemon_optgroups_c () =
6730   generate_header CStyle GPLv2plus;
6731
6732   pr "#include <config.h>\n";
6733   pr "\n";
6734   pr "#include \"daemon.h\"\n";
6735   pr "#include \"optgroups.h\"\n";
6736   pr "\n";
6737
6738   pr "struct optgroup optgroups[] = {\n";
6739   List.iter (
6740     fun (group, _) ->
6741       pr "  { \"%s\", optgroup_%s_available },\n" group group
6742   ) optgroups;
6743   pr "  { NULL, NULL }\n";
6744   pr "};\n"
6745
6746 and generate_daemon_optgroups_h () =
6747   generate_header CStyle GPLv2plus;
6748
6749   List.iter (
6750     fun (group, _) ->
6751       pr "extern int optgroup_%s_available (void);\n" group
6752   ) optgroups
6753
6754 (* Generate the tests. *)
6755 and generate_tests () =
6756   generate_header CStyle GPLv2plus;
6757
6758   pr "\
6759 #include <stdio.h>
6760 #include <stdlib.h>
6761 #include <string.h>
6762 #include <unistd.h>
6763 #include <sys/types.h>
6764 #include <fcntl.h>
6765
6766 #include \"guestfs.h\"
6767 #include \"guestfs-internal.h\"
6768
6769 static guestfs_h *g;
6770 static int suppress_error = 0;
6771
6772 static void print_error (guestfs_h *g, void *data, const char *msg)
6773 {
6774   if (!suppress_error)
6775     fprintf (stderr, \"%%s\\n\", msg);
6776 }
6777
6778 /* FIXME: nearly identical code appears in fish.c */
6779 static void print_strings (char *const *argv)
6780 {
6781   int argc;
6782
6783   for (argc = 0; argv[argc] != NULL; ++argc)
6784     printf (\"\\t%%s\\n\", argv[argc]);
6785 }
6786
6787 /*
6788 static void print_table (char const *const *argv)
6789 {
6790   int i;
6791
6792   for (i = 0; argv[i] != NULL; i += 2)
6793     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6794 }
6795 */
6796
6797 ";
6798
6799   (* Generate a list of commands which are not tested anywhere. *)
6800   pr "static void no_test_warnings (void)\n";
6801   pr "{\n";
6802
6803   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6804   List.iter (
6805     fun (_, _, _, _, tests, _, _) ->
6806       let tests = filter_map (
6807         function
6808         | (_, (Always|If _|Unless _), test) -> Some test
6809         | (_, Disabled, _) -> None
6810       ) tests in
6811       let seq = List.concat (List.map seq_of_test tests) in
6812       let cmds_tested = List.map List.hd seq in
6813       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6814   ) all_functions;
6815
6816   List.iter (
6817     fun (name, _, _, _, _, _, _) ->
6818       if not (Hashtbl.mem hash name) then
6819         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6820   ) all_functions;
6821
6822   pr "}\n";
6823   pr "\n";
6824
6825   (* Generate the actual tests.  Note that we generate the tests
6826    * in reverse order, deliberately, so that (in general) the
6827    * newest tests run first.  This makes it quicker and easier to
6828    * debug them.
6829    *)
6830   let test_names =
6831     List.map (
6832       fun (name, _, _, flags, tests, _, _) ->
6833         mapi (generate_one_test name flags) tests
6834     ) (List.rev all_functions) in
6835   let test_names = List.concat test_names in
6836   let nr_tests = List.length test_names in
6837
6838   pr "\
6839 int main (int argc, char *argv[])
6840 {
6841   char c = 0;
6842   unsigned long int n_failed = 0;
6843   const char *filename;
6844   int fd;
6845   int nr_tests, test_num = 0;
6846
6847   setbuf (stdout, NULL);
6848
6849   no_test_warnings ();
6850
6851   g = guestfs_create ();
6852   if (g == NULL) {
6853     printf (\"guestfs_create FAILED\\n\");
6854     exit (EXIT_FAILURE);
6855   }
6856
6857   guestfs_set_error_handler (g, print_error, NULL);
6858
6859   guestfs_set_path (g, \"../appliance\");
6860
6861   filename = \"test1.img\";
6862   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6863   if (fd == -1) {
6864     perror (filename);
6865     exit (EXIT_FAILURE);
6866   }
6867   if (lseek (fd, %d, SEEK_SET) == -1) {
6868     perror (\"lseek\");
6869     close (fd);
6870     unlink (filename);
6871     exit (EXIT_FAILURE);
6872   }
6873   if (write (fd, &c, 1) == -1) {
6874     perror (\"write\");
6875     close (fd);
6876     unlink (filename);
6877     exit (EXIT_FAILURE);
6878   }
6879   if (close (fd) == -1) {
6880     perror (filename);
6881     unlink (filename);
6882     exit (EXIT_FAILURE);
6883   }
6884   if (guestfs_add_drive (g, filename) == -1) {
6885     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6886     exit (EXIT_FAILURE);
6887   }
6888
6889   filename = \"test2.img\";
6890   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6891   if (fd == -1) {
6892     perror (filename);
6893     exit (EXIT_FAILURE);
6894   }
6895   if (lseek (fd, %d, SEEK_SET) == -1) {
6896     perror (\"lseek\");
6897     close (fd);
6898     unlink (filename);
6899     exit (EXIT_FAILURE);
6900   }
6901   if (write (fd, &c, 1) == -1) {
6902     perror (\"write\");
6903     close (fd);
6904     unlink (filename);
6905     exit (EXIT_FAILURE);
6906   }
6907   if (close (fd) == -1) {
6908     perror (filename);
6909     unlink (filename);
6910     exit (EXIT_FAILURE);
6911   }
6912   if (guestfs_add_drive (g, filename) == -1) {
6913     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6914     exit (EXIT_FAILURE);
6915   }
6916
6917   filename = \"test3.img\";
6918   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6919   if (fd == -1) {
6920     perror (filename);
6921     exit (EXIT_FAILURE);
6922   }
6923   if (lseek (fd, %d, SEEK_SET) == -1) {
6924     perror (\"lseek\");
6925     close (fd);
6926     unlink (filename);
6927     exit (EXIT_FAILURE);
6928   }
6929   if (write (fd, &c, 1) == -1) {
6930     perror (\"write\");
6931     close (fd);
6932     unlink (filename);
6933     exit (EXIT_FAILURE);
6934   }
6935   if (close (fd) == -1) {
6936     perror (filename);
6937     unlink (filename);
6938     exit (EXIT_FAILURE);
6939   }
6940   if (guestfs_add_drive (g, filename) == -1) {
6941     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6942     exit (EXIT_FAILURE);
6943   }
6944
6945   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6946     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6947     exit (EXIT_FAILURE);
6948   }
6949
6950   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6951   alarm (600);
6952
6953   if (guestfs_launch (g) == -1) {
6954     printf (\"guestfs_launch FAILED\\n\");
6955     exit (EXIT_FAILURE);
6956   }
6957
6958   /* Cancel previous alarm. */
6959   alarm (0);
6960
6961   nr_tests = %d;
6962
6963 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6964
6965   iteri (
6966     fun i test_name ->
6967       pr "  test_num++;\n";
6968       pr "  if (guestfs_get_verbose (g))\n";
6969       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6970       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6971       pr "  if (%s () == -1) {\n" test_name;
6972       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6973       pr "    n_failed++;\n";
6974       pr "  }\n";
6975   ) test_names;
6976   pr "\n";
6977
6978   pr "  guestfs_close (g);\n";
6979   pr "  unlink (\"test1.img\");\n";
6980   pr "  unlink (\"test2.img\");\n";
6981   pr "  unlink (\"test3.img\");\n";
6982   pr "\n";
6983
6984   pr "  if (n_failed > 0) {\n";
6985   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6986   pr "    exit (EXIT_FAILURE);\n";
6987   pr "  }\n";
6988   pr "\n";
6989
6990   pr "  exit (EXIT_SUCCESS);\n";
6991   pr "}\n"
6992
6993 and generate_one_test name flags i (init, prereq, test) =
6994   let test_name = sprintf "test_%s_%d" name i in
6995
6996   pr "\
6997 static int %s_skip (void)
6998 {
6999   const char *str;
7000
7001   str = getenv (\"TEST_ONLY\");
7002   if (str)
7003     return strstr (str, \"%s\") == NULL;
7004   str = getenv (\"SKIP_%s\");
7005   if (str && STREQ (str, \"1\")) return 1;
7006   str = getenv (\"SKIP_TEST_%s\");
7007   if (str && STREQ (str, \"1\")) return 1;
7008   return 0;
7009 }
7010
7011 " test_name name (String.uppercase test_name) (String.uppercase name);
7012
7013   (match prereq with
7014    | Disabled | Always -> ()
7015    | If code | Unless code ->
7016        pr "static int %s_prereq (void)\n" test_name;
7017        pr "{\n";
7018        pr "  %s\n" code;
7019        pr "}\n";
7020        pr "\n";
7021   );
7022
7023   pr "\
7024 static int %s (void)
7025 {
7026   if (%s_skip ()) {
7027     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7028     return 0;
7029   }
7030
7031 " test_name test_name test_name;
7032
7033   (* Optional functions should only be tested if the relevant
7034    * support is available in the daemon.
7035    *)
7036   List.iter (
7037     function
7038     | Optional group ->
7039         pr "  {\n";
7040         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
7041         pr "    int r;\n";
7042         pr "    suppress_error = 1;\n";
7043         pr "    r = guestfs_available (g, (char **) groups);\n";
7044         pr "    suppress_error = 0;\n";
7045         pr "    if (r == -1) {\n";
7046         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
7047         pr "      return 0;\n";
7048         pr "    }\n";
7049         pr "  }\n";
7050     | _ -> ()
7051   ) flags;
7052
7053   (match prereq with
7054    | Disabled ->
7055        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7056    | If _ ->
7057        pr "  if (! %s_prereq ()) {\n" test_name;
7058        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7059        pr "    return 0;\n";
7060        pr "  }\n";
7061        pr "\n";
7062        generate_one_test_body name i test_name init test;
7063    | Unless _ ->
7064        pr "  if (%s_prereq ()) {\n" test_name;
7065        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7066        pr "    return 0;\n";
7067        pr "  }\n";
7068        pr "\n";
7069        generate_one_test_body name i test_name init test;
7070    | Always ->
7071        generate_one_test_body name i test_name init test
7072   );
7073
7074   pr "  return 0;\n";
7075   pr "}\n";
7076   pr "\n";
7077   test_name
7078
7079 and generate_one_test_body name i test_name init test =
7080   (match init with
7081    | InitNone (* XXX at some point, InitNone and InitEmpty became
7082                * folded together as the same thing.  Really we should
7083                * make InitNone do nothing at all, but the tests may
7084                * need to be checked to make sure this is OK.
7085                *)
7086    | InitEmpty ->
7087        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7088        List.iter (generate_test_command_call test_name)
7089          [["blockdev_setrw"; "/dev/sda"];
7090           ["umount_all"];
7091           ["lvm_remove_all"]]
7092    | InitPartition ->
7093        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7094        List.iter (generate_test_command_call test_name)
7095          [["blockdev_setrw"; "/dev/sda"];
7096           ["umount_all"];
7097           ["lvm_remove_all"];
7098           ["part_disk"; "/dev/sda"; "mbr"]]
7099    | InitBasicFS ->
7100        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7101        List.iter (generate_test_command_call test_name)
7102          [["blockdev_setrw"; "/dev/sda"];
7103           ["umount_all"];
7104           ["lvm_remove_all"];
7105           ["part_disk"; "/dev/sda"; "mbr"];
7106           ["mkfs"; "ext2"; "/dev/sda1"];
7107           ["mount_options"; ""; "/dev/sda1"; "/"]]
7108    | InitBasicFSonLVM ->
7109        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7110          test_name;
7111        List.iter (generate_test_command_call test_name)
7112          [["blockdev_setrw"; "/dev/sda"];
7113           ["umount_all"];
7114           ["lvm_remove_all"];
7115           ["part_disk"; "/dev/sda"; "mbr"];
7116           ["pvcreate"; "/dev/sda1"];
7117           ["vgcreate"; "VG"; "/dev/sda1"];
7118           ["lvcreate"; "LV"; "VG"; "8"];
7119           ["mkfs"; "ext2"; "/dev/VG/LV"];
7120           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7121    | InitISOFS ->
7122        pr "  /* InitISOFS for %s */\n" test_name;
7123        List.iter (generate_test_command_call test_name)
7124          [["blockdev_setrw"; "/dev/sda"];
7125           ["umount_all"];
7126           ["lvm_remove_all"];
7127           ["mount_ro"; "/dev/sdd"; "/"]]
7128   );
7129
7130   let get_seq_last = function
7131     | [] ->
7132         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7133           test_name
7134     | seq ->
7135         let seq = List.rev seq in
7136         List.rev (List.tl seq), List.hd seq
7137   in
7138
7139   match test with
7140   | TestRun seq ->
7141       pr "  /* TestRun for %s (%d) */\n" name i;
7142       List.iter (generate_test_command_call test_name) seq
7143   | TestOutput (seq, expected) ->
7144       pr "  /* TestOutput for %s (%d) */\n" name i;
7145       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7146       let seq, last = get_seq_last seq in
7147       let test () =
7148         pr "    if (STRNEQ (r, expected)) {\n";
7149         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7150         pr "      return -1;\n";
7151         pr "    }\n"
7152       in
7153       List.iter (generate_test_command_call test_name) seq;
7154       generate_test_command_call ~test test_name last
7155   | TestOutputList (seq, expected) ->
7156       pr "  /* TestOutputList for %s (%d) */\n" name i;
7157       let seq, last = get_seq_last seq in
7158       let test () =
7159         iteri (
7160           fun i str ->
7161             pr "    if (!r[%d]) {\n" i;
7162             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7163             pr "      print_strings (r);\n";
7164             pr "      return -1;\n";
7165             pr "    }\n";
7166             pr "    {\n";
7167             pr "      const char *expected = \"%s\";\n" (c_quote str);
7168             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7169             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7170             pr "        return -1;\n";
7171             pr "      }\n";
7172             pr "    }\n"
7173         ) expected;
7174         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7175         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7176           test_name;
7177         pr "      print_strings (r);\n";
7178         pr "      return -1;\n";
7179         pr "    }\n"
7180       in
7181       List.iter (generate_test_command_call test_name) seq;
7182       generate_test_command_call ~test test_name last
7183   | TestOutputListOfDevices (seq, expected) ->
7184       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7185       let seq, last = get_seq_last seq in
7186       let test () =
7187         iteri (
7188           fun i str ->
7189             pr "    if (!r[%d]) {\n" i;
7190             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7191             pr "      print_strings (r);\n";
7192             pr "      return -1;\n";
7193             pr "    }\n";
7194             pr "    {\n";
7195             pr "      const char *expected = \"%s\";\n" (c_quote str);
7196             pr "      r[%d][5] = 's';\n" i;
7197             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7198             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7199             pr "        return -1;\n";
7200             pr "      }\n";
7201             pr "    }\n"
7202         ) expected;
7203         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7204         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7205           test_name;
7206         pr "      print_strings (r);\n";
7207         pr "      return -1;\n";
7208         pr "    }\n"
7209       in
7210       List.iter (generate_test_command_call test_name) seq;
7211       generate_test_command_call ~test test_name last
7212   | TestOutputInt (seq, expected) ->
7213       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7214       let seq, last = get_seq_last seq in
7215       let test () =
7216         pr "    if (r != %d) {\n" expected;
7217         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7218           test_name expected;
7219         pr "               (int) r);\n";
7220         pr "      return -1;\n";
7221         pr "    }\n"
7222       in
7223       List.iter (generate_test_command_call test_name) seq;
7224       generate_test_command_call ~test test_name last
7225   | TestOutputIntOp (seq, op, expected) ->
7226       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7227       let seq, last = get_seq_last seq in
7228       let test () =
7229         pr "    if (! (r %s %d)) {\n" op expected;
7230         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7231           test_name op expected;
7232         pr "               (int) r);\n";
7233         pr "      return -1;\n";
7234         pr "    }\n"
7235       in
7236       List.iter (generate_test_command_call test_name) seq;
7237       generate_test_command_call ~test test_name last
7238   | TestOutputTrue seq ->
7239       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7240       let seq, last = get_seq_last seq in
7241       let test () =
7242         pr "    if (!r) {\n";
7243         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7244           test_name;
7245         pr "      return -1;\n";
7246         pr "    }\n"
7247       in
7248       List.iter (generate_test_command_call test_name) seq;
7249       generate_test_command_call ~test test_name last
7250   | TestOutputFalse seq ->
7251       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7252       let seq, last = get_seq_last seq in
7253       let test () =
7254         pr "    if (r) {\n";
7255         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7256           test_name;
7257         pr "      return -1;\n";
7258         pr "    }\n"
7259       in
7260       List.iter (generate_test_command_call test_name) seq;
7261       generate_test_command_call ~test test_name last
7262   | TestOutputLength (seq, expected) ->
7263       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7264       let seq, last = get_seq_last seq in
7265       let test () =
7266         pr "    int j;\n";
7267         pr "    for (j = 0; j < %d; ++j)\n" expected;
7268         pr "      if (r[j] == NULL) {\n";
7269         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7270           test_name;
7271         pr "        print_strings (r);\n";
7272         pr "        return -1;\n";
7273         pr "      }\n";
7274         pr "    if (r[j] != NULL) {\n";
7275         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7276           test_name;
7277         pr "      print_strings (r);\n";
7278         pr "      return -1;\n";
7279         pr "    }\n"
7280       in
7281       List.iter (generate_test_command_call test_name) seq;
7282       generate_test_command_call ~test test_name last
7283   | TestOutputBuffer (seq, expected) ->
7284       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7285       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7286       let seq, last = get_seq_last seq in
7287       let len = String.length expected in
7288       let test () =
7289         pr "    if (size != %d) {\n" len;
7290         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7291         pr "      return -1;\n";
7292         pr "    }\n";
7293         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7294         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7295         pr "      return -1;\n";
7296         pr "    }\n"
7297       in
7298       List.iter (generate_test_command_call test_name) seq;
7299       generate_test_command_call ~test test_name last
7300   | TestOutputStruct (seq, checks) ->
7301       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7302       let seq, last = get_seq_last seq in
7303       let test () =
7304         List.iter (
7305           function
7306           | CompareWithInt (field, expected) ->
7307               pr "    if (r->%s != %d) {\n" field expected;
7308               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7309                 test_name field expected;
7310               pr "               (int) r->%s);\n" field;
7311               pr "      return -1;\n";
7312               pr "    }\n"
7313           | CompareWithIntOp (field, op, expected) ->
7314               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7315               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7316                 test_name field op expected;
7317               pr "               (int) r->%s);\n" field;
7318               pr "      return -1;\n";
7319               pr "    }\n"
7320           | CompareWithString (field, expected) ->
7321               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7322               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7323                 test_name field expected;
7324               pr "               r->%s);\n" field;
7325               pr "      return -1;\n";
7326               pr "    }\n"
7327           | CompareFieldsIntEq (field1, field2) ->
7328               pr "    if (r->%s != r->%s) {\n" field1 field2;
7329               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7330                 test_name field1 field2;
7331               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7332               pr "      return -1;\n";
7333               pr "    }\n"
7334           | CompareFieldsStrEq (field1, field2) ->
7335               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7336               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7337                 test_name field1 field2;
7338               pr "               r->%s, r->%s);\n" field1 field2;
7339               pr "      return -1;\n";
7340               pr "    }\n"
7341         ) checks
7342       in
7343       List.iter (generate_test_command_call test_name) seq;
7344       generate_test_command_call ~test test_name last
7345   | TestLastFail seq ->
7346       pr "  /* TestLastFail for %s (%d) */\n" name i;
7347       let seq, last = get_seq_last seq in
7348       List.iter (generate_test_command_call test_name) seq;
7349       generate_test_command_call test_name ~expect_error:true last
7350
7351 (* Generate the code to run a command, leaving the result in 'r'.
7352  * If you expect to get an error then you should set expect_error:true.
7353  *)
7354 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7355   match cmd with
7356   | [] -> assert false
7357   | name :: args ->
7358       (* Look up the command to find out what args/ret it has. *)
7359       let style =
7360         try
7361           let _, style, _, _, _, _, _ =
7362             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7363           style
7364         with Not_found ->
7365           failwithf "%s: in test, command %s was not found" test_name name in
7366
7367       if List.length (snd style) <> List.length args then
7368         failwithf "%s: in test, wrong number of args given to %s"
7369           test_name name;
7370
7371       pr "  {\n";
7372
7373       List.iter (
7374         function
7375         | OptString n, "NULL" -> ()
7376         | Pathname n, arg
7377         | Device n, arg
7378         | Dev_or_Path n, arg
7379         | String n, arg
7380         | OptString n, arg ->
7381             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7382         | BufferIn n, arg ->
7383             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7384             pr "    size_t %s_size = %d;\n" n (String.length arg)
7385         | Int _, _
7386         | Int64 _, _
7387         | Bool _, _
7388         | FileIn _, _ | FileOut _, _ -> ()
7389         | StringList n, "" | DeviceList n, "" ->
7390             pr "    const char *const %s[1] = { NULL };\n" n
7391         | StringList n, arg | DeviceList n, arg ->
7392             let strs = string_split " " arg in
7393             iteri (
7394               fun i str ->
7395                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7396             ) strs;
7397             pr "    const char *const %s[] = {\n" n;
7398             iteri (
7399               fun i _ -> pr "      %s_%d,\n" n i
7400             ) strs;
7401             pr "      NULL\n";
7402             pr "    };\n";
7403       ) (List.combine (snd style) args);
7404
7405       let error_code =
7406         match fst style with
7407         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7408         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7409         | RConstString _ | RConstOptString _ ->
7410             pr "    const char *r;\n"; "NULL"
7411         | RString _ -> pr "    char *r;\n"; "NULL"
7412         | RStringList _ | RHashtable _ ->
7413             pr "    char **r;\n";
7414             pr "    int i;\n";
7415             "NULL"
7416         | RStruct (_, typ) ->
7417             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7418         | RStructList (_, typ) ->
7419             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7420         | RBufferOut _ ->
7421             pr "    char *r;\n";
7422             pr "    size_t size;\n";
7423             "NULL" in
7424
7425       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7426       pr "    r = guestfs_%s (g" name;
7427
7428       (* Generate the parameters. *)
7429       List.iter (
7430         function
7431         | OptString _, "NULL" -> pr ", NULL"
7432         | Pathname n, _
7433         | Device n, _ | Dev_or_Path n, _
7434         | String n, _
7435         | OptString n, _ ->
7436             pr ", %s" n
7437         | BufferIn n, _ ->
7438             pr ", %s, %s_size" n n
7439         | FileIn _, arg | FileOut _, arg ->
7440             pr ", \"%s\"" (c_quote arg)
7441         | StringList n, _ | DeviceList n, _ ->
7442             pr ", (char **) %s" n
7443         | Int _, arg ->
7444             let i =
7445               try int_of_string arg
7446               with Failure "int_of_string" ->
7447                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7448             pr ", %d" i
7449         | Int64 _, arg ->
7450             let i =
7451               try Int64.of_string arg
7452               with Failure "int_of_string" ->
7453                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7454             pr ", %Ld" i
7455         | Bool _, arg ->
7456             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7457       ) (List.combine (snd style) args);
7458
7459       (match fst style with
7460        | RBufferOut _ -> pr ", &size"
7461        | _ -> ()
7462       );
7463
7464       pr ");\n";
7465
7466       if not expect_error then
7467         pr "    if (r == %s)\n" error_code
7468       else
7469         pr "    if (r != %s)\n" error_code;
7470       pr "      return -1;\n";
7471
7472       (* Insert the test code. *)
7473       (match test with
7474        | None -> ()
7475        | Some f -> f ()
7476       );
7477
7478       (match fst style with
7479        | RErr | RInt _ | RInt64 _ | RBool _
7480        | RConstString _ | RConstOptString _ -> ()
7481        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7482        | RStringList _ | RHashtable _ ->
7483            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7484            pr "      free (r[i]);\n";
7485            pr "    free (r);\n"
7486        | RStruct (_, typ) ->
7487            pr "    guestfs_free_%s (r);\n" typ
7488        | RStructList (_, typ) ->
7489            pr "    guestfs_free_%s_list (r);\n" typ
7490       );
7491
7492       pr "  }\n"
7493
7494 and c_quote str =
7495   let str = replace_str str "\r" "\\r" in
7496   let str = replace_str str "\n" "\\n" in
7497   let str = replace_str str "\t" "\\t" in
7498   let str = replace_str str "\000" "\\0" in
7499   str
7500
7501 (* Generate a lot of different functions for guestfish. *)
7502 and generate_fish_cmds () =
7503   generate_header CStyle GPLv2plus;
7504
7505   let all_functions =
7506     List.filter (
7507       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7508     ) all_functions in
7509   let all_functions_sorted =
7510     List.filter (
7511       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7512     ) all_functions_sorted in
7513
7514   pr "#include <config.h>\n";
7515   pr "\n";
7516   pr "#include <stdio.h>\n";
7517   pr "#include <stdlib.h>\n";
7518   pr "#include <string.h>\n";
7519   pr "#include <inttypes.h>\n";
7520   pr "\n";
7521   pr "#include <guestfs.h>\n";
7522   pr "#include \"c-ctype.h\"\n";
7523   pr "#include \"full-write.h\"\n";
7524   pr "#include \"xstrtol.h\"\n";
7525   pr "#include \"fish.h\"\n";
7526   pr "\n";
7527   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7528   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7529   pr "\n";
7530
7531   (* list_commands function, which implements guestfish -h *)
7532   pr "void list_commands (void)\n";
7533   pr "{\n";
7534   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7535   pr "  list_builtin_commands ();\n";
7536   List.iter (
7537     fun (name, _, _, flags, _, shortdesc, _) ->
7538       let name = replace_char name '_' '-' in
7539       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7540         name shortdesc
7541   ) all_functions_sorted;
7542   pr "  printf (\"    %%s\\n\",";
7543   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7544   pr "}\n";
7545   pr "\n";
7546
7547   (* display_command function, which implements guestfish -h cmd *)
7548   pr "void display_command (const char *cmd)\n";
7549   pr "{\n";
7550   List.iter (
7551     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7552       let name2 = replace_char name '_' '-' in
7553       let alias =
7554         try find_map (function FishAlias n -> Some n | _ -> None) flags
7555         with Not_found -> name in
7556       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7557       let synopsis =
7558         match snd style with
7559         | [] -> name2
7560         | args ->
7561             sprintf "%s %s"
7562               name2 (String.concat " " (List.map name_of_argt args)) in
7563
7564       let warnings =
7565         if List.mem ProtocolLimitWarning flags then
7566           ("\n\n" ^ protocol_limit_warning)
7567         else "" in
7568
7569       (* For DangerWillRobinson commands, we should probably have
7570        * guestfish prompt before allowing you to use them (especially
7571        * in interactive mode). XXX
7572        *)
7573       let warnings =
7574         warnings ^
7575           if List.mem DangerWillRobinson flags then
7576             ("\n\n" ^ danger_will_robinson)
7577           else "" in
7578
7579       let warnings =
7580         warnings ^
7581           match deprecation_notice flags with
7582           | None -> ""
7583           | Some txt -> "\n\n" ^ txt in
7584
7585       let describe_alias =
7586         if name <> alias then
7587           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7588         else "" in
7589
7590       pr "  if (";
7591       pr "STRCASEEQ (cmd, \"%s\")" name;
7592       if name <> name2 then
7593         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7594       if name <> alias then
7595         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7596       pr ")\n";
7597       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7598         name2 shortdesc
7599         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7600          "=head1 DESCRIPTION\n\n" ^
7601          longdesc ^ warnings ^ describe_alias);
7602       pr "  else\n"
7603   ) all_functions;
7604   pr "    display_builtin_command (cmd);\n";
7605   pr "}\n";
7606   pr "\n";
7607
7608   let emit_print_list_function typ =
7609     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7610       typ typ typ;
7611     pr "{\n";
7612     pr "  unsigned int i;\n";
7613     pr "\n";
7614     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7615     pr "    printf (\"[%%d] = {\\n\", i);\n";
7616     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7617     pr "    printf (\"}\\n\");\n";
7618     pr "  }\n";
7619     pr "}\n";
7620     pr "\n";
7621   in
7622
7623   (* print_* functions *)
7624   List.iter (
7625     fun (typ, cols) ->
7626       let needs_i =
7627         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7628
7629       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7630       pr "{\n";
7631       if needs_i then (
7632         pr "  unsigned int i;\n";
7633         pr "\n"
7634       );
7635       List.iter (
7636         function
7637         | name, FString ->
7638             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7639         | name, FUUID ->
7640             pr "  printf (\"%%s%s: \", indent);\n" name;
7641             pr "  for (i = 0; i < 32; ++i)\n";
7642             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7643             pr "  printf (\"\\n\");\n"
7644         | name, FBuffer ->
7645             pr "  printf (\"%%s%s: \", indent);\n" name;
7646             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7647             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7648             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7649             pr "    else\n";
7650             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7651             pr "  printf (\"\\n\");\n"
7652         | name, (FUInt64|FBytes) ->
7653             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7654               name typ name
7655         | name, FInt64 ->
7656             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7657               name typ name
7658         | name, FUInt32 ->
7659             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7660               name typ name
7661         | name, FInt32 ->
7662             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7663               name typ name
7664         | name, FChar ->
7665             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7666               name typ name
7667         | name, FOptPercent ->
7668             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7669               typ name name typ name;
7670             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7671       ) cols;
7672       pr "}\n";
7673       pr "\n";
7674   ) structs;
7675
7676   (* Emit a print_TYPE_list function definition only if that function is used. *)
7677   List.iter (
7678     function
7679     | typ, (RStructListOnly | RStructAndList) ->
7680         (* generate the function for typ *)
7681         emit_print_list_function typ
7682     | typ, _ -> () (* empty *)
7683   ) (rstructs_used_by all_functions);
7684
7685   (* Emit a print_TYPE function definition only if that function is used. *)
7686   List.iter (
7687     function
7688     | typ, (RStructOnly | RStructAndList) ->
7689         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7690         pr "{\n";
7691         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7692         pr "}\n";
7693         pr "\n";
7694     | typ, _ -> () (* empty *)
7695   ) (rstructs_used_by all_functions);
7696
7697   (* run_<action> actions *)
7698   List.iter (
7699     fun (name, style, _, flags, _, _, _) ->
7700       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7701       pr "{\n";
7702       (match fst style with
7703        | RErr
7704        | RInt _
7705        | RBool _ -> pr "  int r;\n"
7706        | RInt64 _ -> pr "  int64_t r;\n"
7707        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7708        | RString _ -> pr "  char *r;\n"
7709        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7710        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7711        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7712        | RBufferOut _ ->
7713            pr "  char *r;\n";
7714            pr "  size_t size;\n";
7715       );
7716       List.iter (
7717         function
7718         | Device n
7719         | String n
7720         | OptString n -> pr "  const char *%s;\n" n
7721         | Pathname n
7722         | Dev_or_Path n
7723         | FileIn n
7724         | FileOut n -> pr "  char *%s;\n" n
7725         | BufferIn n ->
7726             pr "  const char *%s;\n" n;
7727             pr "  size_t %s_size;\n" n
7728         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7729         | Bool n -> pr "  int %s;\n" n
7730         | Int n -> pr "  int %s;\n" n
7731         | Int64 n -> pr "  int64_t %s;\n" n
7732       ) (snd style);
7733
7734       (* Check and convert parameters. *)
7735       let argc_expected = List.length (snd style) in
7736       pr "  if (argc != %d) {\n" argc_expected;
7737       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7738         argc_expected;
7739       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7740       pr "    return -1;\n";
7741       pr "  }\n";
7742
7743       let parse_integer fn fntyp rtyp range name i =
7744         pr "  {\n";
7745         pr "    strtol_error xerr;\n";
7746         pr "    %s r;\n" fntyp;
7747         pr "\n";
7748         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7749         pr "    if (xerr != LONGINT_OK) {\n";
7750         pr "      fprintf (stderr,\n";
7751         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7752         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7753         pr "      return -1;\n";
7754         pr "    }\n";
7755         (match range with
7756          | None -> ()
7757          | Some (min, max, comment) ->
7758              pr "    /* %s */\n" comment;
7759              pr "    if (r < %s || r > %s) {\n" min max;
7760              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7761                name;
7762              pr "      return -1;\n";
7763              pr "    }\n";
7764              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7765         );
7766         pr "    %s = r;\n" name;
7767         pr "  }\n";
7768       in
7769
7770       iteri (
7771         fun i ->
7772           function
7773           | Device name
7774           | String name ->
7775               pr "  %s = argv[%d];\n" name i
7776           | Pathname name
7777           | Dev_or_Path name ->
7778               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7779               pr "  if (%s == NULL) return -1;\n" name
7780           | OptString name ->
7781               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7782                 name i i
7783           | BufferIn name ->
7784               pr "  %s = argv[%d];\n" name i;
7785               pr "  %s_size = strlen (argv[%d]);\n" name i
7786           | FileIn name ->
7787               pr "  %s = file_in (argv[%d]);\n" name i;
7788               pr "  if (%s == NULL) return -1;\n" name
7789           | FileOut name ->
7790               pr "  %s = file_out (argv[%d]);\n" name i;
7791               pr "  if (%s == NULL) return -1;\n" name
7792           | StringList name | DeviceList name ->
7793               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7794               pr "  if (%s == NULL) return -1;\n" name;
7795           | Bool name ->
7796               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7797           | Int name ->
7798               let range =
7799                 let min = "(-(2LL<<30))"
7800                 and max = "((2LL<<30)-1)"
7801                 and comment =
7802                   "The Int type in the generator is a signed 31 bit int." in
7803                 Some (min, max, comment) in
7804               parse_integer "xstrtoll" "long long" "int" range name i
7805           | Int64 name ->
7806               parse_integer "xstrtoll" "long long" "int64_t" None name i
7807       ) (snd style);
7808
7809       (* Call C API function. *)
7810       pr "  r = guestfs_%s " name;
7811       generate_c_call_args ~handle:"g" style;
7812       pr ";\n";
7813
7814       List.iter (
7815         function
7816         | Device name | String name
7817         | OptString name | Bool name
7818         | Int name | Int64 name
7819         | BufferIn name -> ()
7820         | Pathname name | Dev_or_Path name | FileOut name ->
7821             pr "  free (%s);\n" name
7822         | FileIn name ->
7823             pr "  free_file_in (%s);\n" name
7824         | StringList name | DeviceList name ->
7825             pr "  free_strings (%s);\n" name
7826       ) (snd style);
7827
7828       (* Any output flags? *)
7829       let fish_output =
7830         let flags = filter_map (
7831           function FishOutput flag -> Some flag | _ -> None
7832         ) flags in
7833         match flags with
7834         | [] -> None
7835         | [f] -> Some f
7836         | _ ->
7837             failwithf "%s: more than one FishOutput flag is not allowed" name in
7838
7839       (* Check return value for errors and display command results. *)
7840       (match fst style with
7841        | RErr -> pr "  return r;\n"
7842        | RInt _ ->
7843            pr "  if (r == -1) return -1;\n";
7844            (match fish_output with
7845             | None ->
7846                 pr "  printf (\"%%d\\n\", r);\n";
7847             | Some FishOutputOctal ->
7848                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7849             | Some FishOutputHexadecimal ->
7850                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7851            pr "  return 0;\n"
7852        | RInt64 _ ->
7853            pr "  if (r == -1) return -1;\n";
7854            (match fish_output with
7855             | None ->
7856                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7857             | Some FishOutputOctal ->
7858                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7859             | Some FishOutputHexadecimal ->
7860                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7861            pr "  return 0;\n"
7862        | RBool _ ->
7863            pr "  if (r == -1) return -1;\n";
7864            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7865            pr "  return 0;\n"
7866        | RConstString _ ->
7867            pr "  if (r == NULL) return -1;\n";
7868            pr "  printf (\"%%s\\n\", r);\n";
7869            pr "  return 0;\n"
7870        | RConstOptString _ ->
7871            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7872            pr "  return 0;\n"
7873        | RString _ ->
7874            pr "  if (r == NULL) return -1;\n";
7875            pr "  printf (\"%%s\\n\", r);\n";
7876            pr "  free (r);\n";
7877            pr "  return 0;\n"
7878        | RStringList _ ->
7879            pr "  if (r == NULL) return -1;\n";
7880            pr "  print_strings (r);\n";
7881            pr "  free_strings (r);\n";
7882            pr "  return 0;\n"
7883        | RStruct (_, typ) ->
7884            pr "  if (r == NULL) return -1;\n";
7885            pr "  print_%s (r);\n" typ;
7886            pr "  guestfs_free_%s (r);\n" typ;
7887            pr "  return 0;\n"
7888        | RStructList (_, typ) ->
7889            pr "  if (r == NULL) return -1;\n";
7890            pr "  print_%s_list (r);\n" typ;
7891            pr "  guestfs_free_%s_list (r);\n" typ;
7892            pr "  return 0;\n"
7893        | RHashtable _ ->
7894            pr "  if (r == NULL) return -1;\n";
7895            pr "  print_table (r);\n";
7896            pr "  free_strings (r);\n";
7897            pr "  return 0;\n"
7898        | RBufferOut _ ->
7899            pr "  if (r == NULL) return -1;\n";
7900            pr "  if (full_write (1, r, size) != size) {\n";
7901            pr "    perror (\"write\");\n";
7902            pr "    free (r);\n";
7903            pr "    return -1;\n";
7904            pr "  }\n";
7905            pr "  free (r);\n";
7906            pr "  return 0;\n"
7907       );
7908       pr "}\n";
7909       pr "\n"
7910   ) all_functions;
7911
7912   (* run_action function *)
7913   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7914   pr "{\n";
7915   List.iter (
7916     fun (name, _, _, flags, _, _, _) ->
7917       let name2 = replace_char name '_' '-' in
7918       let alias =
7919         try find_map (function FishAlias n -> Some n | _ -> None) flags
7920         with Not_found -> name in
7921       pr "  if (";
7922       pr "STRCASEEQ (cmd, \"%s\")" name;
7923       if name <> name2 then
7924         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7925       if name <> alias then
7926         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7927       pr ")\n";
7928       pr "    return run_%s (cmd, argc, argv);\n" name;
7929       pr "  else\n";
7930   ) all_functions;
7931   pr "    {\n";
7932   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7933   pr "      if (command_num == 1)\n";
7934   pr "        extended_help_message ();\n";
7935   pr "      return -1;\n";
7936   pr "    }\n";
7937   pr "  return 0;\n";
7938   pr "}\n";
7939   pr "\n"
7940
7941 (* Readline completion for guestfish. *)
7942 and generate_fish_completion () =
7943   generate_header CStyle GPLv2plus;
7944
7945   let all_functions =
7946     List.filter (
7947       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7948     ) all_functions in
7949
7950   pr "\
7951 #include <config.h>
7952
7953 #include <stdio.h>
7954 #include <stdlib.h>
7955 #include <string.h>
7956
7957 #ifdef HAVE_LIBREADLINE
7958 #include <readline/readline.h>
7959 #endif
7960
7961 #include \"fish.h\"
7962
7963 #ifdef HAVE_LIBREADLINE
7964
7965 static const char *const commands[] = {
7966   BUILTIN_COMMANDS_FOR_COMPLETION,
7967 ";
7968
7969   (* Get the commands, including the aliases.  They don't need to be
7970    * sorted - the generator() function just does a dumb linear search.
7971    *)
7972   let commands =
7973     List.map (
7974       fun (name, _, _, flags, _, _, _) ->
7975         let name2 = replace_char name '_' '-' in
7976         let alias =
7977           try find_map (function FishAlias n -> Some n | _ -> None) flags
7978           with Not_found -> name in
7979
7980         if name <> alias then [name2; alias] else [name2]
7981     ) all_functions in
7982   let commands = List.flatten commands in
7983
7984   List.iter (pr "  \"%s\",\n") commands;
7985
7986   pr "  NULL
7987 };
7988
7989 static char *
7990 generator (const char *text, int state)
7991 {
7992   static int index, len;
7993   const char *name;
7994
7995   if (!state) {
7996     index = 0;
7997     len = strlen (text);
7998   }
7999
8000   rl_attempted_completion_over = 1;
8001
8002   while ((name = commands[index]) != NULL) {
8003     index++;
8004     if (STRCASEEQLEN (name, text, len))
8005       return strdup (name);
8006   }
8007
8008   return NULL;
8009 }
8010
8011 #endif /* HAVE_LIBREADLINE */
8012
8013 #ifdef HAVE_RL_COMPLETION_MATCHES
8014 #define RL_COMPLETION_MATCHES rl_completion_matches
8015 #else
8016 #ifdef HAVE_COMPLETION_MATCHES
8017 #define RL_COMPLETION_MATCHES completion_matches
8018 #endif
8019 #endif /* else just fail if we don't have either symbol */
8020
8021 char **
8022 do_completion (const char *text, int start, int end)
8023 {
8024   char **matches = NULL;
8025
8026 #ifdef HAVE_LIBREADLINE
8027   rl_completion_append_character = ' ';
8028
8029   if (start == 0)
8030     matches = RL_COMPLETION_MATCHES (text, generator);
8031   else if (complete_dest_paths)
8032     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8033 #endif
8034
8035   return matches;
8036 }
8037 ";
8038
8039 (* Generate the POD documentation for guestfish. *)
8040 and generate_fish_actions_pod () =
8041   let all_functions_sorted =
8042     List.filter (
8043       fun (_, _, _, flags, _, _, _) ->
8044         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8045     ) all_functions_sorted in
8046
8047   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8048
8049   List.iter (
8050     fun (name, style, _, flags, _, _, longdesc) ->
8051       let longdesc =
8052         Str.global_substitute rex (
8053           fun s ->
8054             let sub =
8055               try Str.matched_group 1 s
8056               with Not_found ->
8057                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8058             "C<" ^ replace_char sub '_' '-' ^ ">"
8059         ) longdesc in
8060       let name = replace_char name '_' '-' in
8061       let alias =
8062         try find_map (function FishAlias n -> Some n | _ -> None) flags
8063         with Not_found -> name in
8064
8065       pr "=head2 %s" name;
8066       if name <> alias then
8067         pr " | %s" alias;
8068       pr "\n";
8069       pr "\n";
8070       pr " %s" name;
8071       List.iter (
8072         function
8073         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8074         | OptString n -> pr " %s" n
8075         | StringList n | DeviceList n -> pr " '%s ...'" n
8076         | Bool _ -> pr " true|false"
8077         | Int n -> pr " %s" n
8078         | Int64 n -> pr " %s" n
8079         | FileIn n | FileOut n -> pr " (%s|-)" n
8080         | BufferIn n -> pr " %s" n
8081       ) (snd style);
8082       pr "\n";
8083       pr "\n";
8084       pr "%s\n\n" longdesc;
8085
8086       if List.exists (function FileIn _ | FileOut _ -> true
8087                       | _ -> false) (snd style) then
8088         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8089
8090       if List.mem ProtocolLimitWarning flags then
8091         pr "%s\n\n" protocol_limit_warning;
8092
8093       if List.mem DangerWillRobinson flags then
8094         pr "%s\n\n" danger_will_robinson;
8095
8096       match deprecation_notice flags with
8097       | None -> ()
8098       | Some txt -> pr "%s\n\n" txt
8099   ) all_functions_sorted
8100
8101 (* Generate a C function prototype. *)
8102 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8103     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8104     ?(prefix = "")
8105     ?handle name style =
8106   if extern then pr "extern ";
8107   if static then pr "static ";
8108   (match fst style with
8109    | RErr -> pr "int "
8110    | RInt _ -> pr "int "
8111    | RInt64 _ -> pr "int64_t "
8112    | RBool _ -> pr "int "
8113    | RConstString _ | RConstOptString _ -> pr "const char *"
8114    | RString _ | RBufferOut _ -> pr "char *"
8115    | RStringList _ | RHashtable _ -> pr "char **"
8116    | RStruct (_, typ) ->
8117        if not in_daemon then pr "struct guestfs_%s *" typ
8118        else pr "guestfs_int_%s *" typ
8119    | RStructList (_, typ) ->
8120        if not in_daemon then pr "struct guestfs_%s_list *" typ
8121        else pr "guestfs_int_%s_list *" typ
8122   );
8123   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8124   pr "%s%s (" prefix name;
8125   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8126     pr "void"
8127   else (
8128     let comma = ref false in
8129     (match handle with
8130      | None -> ()
8131      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8132     );
8133     let next () =
8134       if !comma then (
8135         if single_line then pr ", " else pr ",\n\t\t"
8136       );
8137       comma := true
8138     in
8139     List.iter (
8140       function
8141       | Pathname n
8142       | Device n | Dev_or_Path n
8143       | String n
8144       | OptString n ->
8145           next ();
8146           pr "const char *%s" n
8147       | StringList n | DeviceList n ->
8148           next ();
8149           pr "char *const *%s" n
8150       | Bool n -> next (); pr "int %s" n
8151       | Int n -> next (); pr "int %s" n
8152       | Int64 n -> next (); pr "int64_t %s" n
8153       | FileIn n
8154       | FileOut n ->
8155           if not in_daemon then (next (); pr "const char *%s" n)
8156       | BufferIn n ->
8157           next ();
8158           pr "const char *%s" n;
8159           next ();
8160           pr "size_t %s_size" n
8161     ) (snd style);
8162     if is_RBufferOut then (next (); pr "size_t *size_r");
8163   );
8164   pr ")";
8165   if semicolon then pr ";";
8166   if newline then pr "\n"
8167
8168 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8169 and generate_c_call_args ?handle ?(decl = false) style =
8170   pr "(";
8171   let comma = ref false in
8172   let next () =
8173     if !comma then pr ", ";
8174     comma := true
8175   in
8176   (match handle with
8177    | None -> ()
8178    | Some handle -> pr "%s" handle; comma := true
8179   );
8180   List.iter (
8181     function
8182     | BufferIn n ->
8183         next ();
8184         pr "%s, %s_size" n n
8185     | arg ->
8186         next ();
8187         pr "%s" (name_of_argt arg)
8188   ) (snd style);
8189   (* For RBufferOut calls, add implicit &size parameter. *)
8190   if not decl then (
8191     match fst style with
8192     | RBufferOut _ ->
8193         next ();
8194         pr "&size"
8195     | _ -> ()
8196   );
8197   pr ")"
8198
8199 (* Generate the OCaml bindings interface. *)
8200 and generate_ocaml_mli () =
8201   generate_header OCamlStyle LGPLv2plus;
8202
8203   pr "\
8204 (** For API documentation you should refer to the C API
8205     in the guestfs(3) manual page.  The OCaml API uses almost
8206     exactly the same calls. *)
8207
8208 type t
8209 (** A [guestfs_h] handle. *)
8210
8211 exception Error of string
8212 (** This exception is raised when there is an error. *)
8213
8214 exception Handle_closed of string
8215 (** This exception is raised if you use a {!Guestfs.t} handle
8216     after calling {!close} on it.  The string is the name of
8217     the function. *)
8218
8219 val create : unit -> t
8220 (** Create a {!Guestfs.t} handle. *)
8221
8222 val close : t -> unit
8223 (** Close the {!Guestfs.t} handle and free up all resources used
8224     by it immediately.
8225
8226     Handles are closed by the garbage collector when they become
8227     unreferenced, but callers can call this in order to provide
8228     predictable cleanup. *)
8229
8230 ";
8231   generate_ocaml_structure_decls ();
8232
8233   (* The actions. *)
8234   List.iter (
8235     fun (name, style, _, _, _, shortdesc, _) ->
8236       generate_ocaml_prototype name style;
8237       pr "(** %s *)\n" shortdesc;
8238       pr "\n"
8239   ) all_functions_sorted
8240
8241 (* Generate the OCaml bindings implementation. *)
8242 and generate_ocaml_ml () =
8243   generate_header OCamlStyle LGPLv2plus;
8244
8245   pr "\
8246 type t
8247
8248 exception Error of string
8249 exception Handle_closed of string
8250
8251 external create : unit -> t = \"ocaml_guestfs_create\"
8252 external close : t -> unit = \"ocaml_guestfs_close\"
8253
8254 (* Give the exceptions names, so they can be raised from the C code. *)
8255 let () =
8256   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8257   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8258
8259 ";
8260
8261   generate_ocaml_structure_decls ();
8262
8263   (* The actions. *)
8264   List.iter (
8265     fun (name, style, _, _, _, shortdesc, _) ->
8266       generate_ocaml_prototype ~is_external:true name style;
8267   ) all_functions_sorted
8268
8269 (* Generate the OCaml bindings C implementation. *)
8270 and generate_ocaml_c () =
8271   generate_header CStyle LGPLv2plus;
8272
8273   pr "\
8274 #include <stdio.h>
8275 #include <stdlib.h>
8276 #include <string.h>
8277
8278 #include <caml/config.h>
8279 #include <caml/alloc.h>
8280 #include <caml/callback.h>
8281 #include <caml/fail.h>
8282 #include <caml/memory.h>
8283 #include <caml/mlvalues.h>
8284 #include <caml/signals.h>
8285
8286 #include <guestfs.h>
8287
8288 #include \"guestfs_c.h\"
8289
8290 /* Copy a hashtable of string pairs into an assoc-list.  We return
8291  * the list in reverse order, but hashtables aren't supposed to be
8292  * ordered anyway.
8293  */
8294 static CAMLprim value
8295 copy_table (char * const * argv)
8296 {
8297   CAMLparam0 ();
8298   CAMLlocal5 (rv, pairv, kv, vv, cons);
8299   int i;
8300
8301   rv = Val_int (0);
8302   for (i = 0; argv[i] != NULL; i += 2) {
8303     kv = caml_copy_string (argv[i]);
8304     vv = caml_copy_string (argv[i+1]);
8305     pairv = caml_alloc (2, 0);
8306     Store_field (pairv, 0, kv);
8307     Store_field (pairv, 1, vv);
8308     cons = caml_alloc (2, 0);
8309     Store_field (cons, 1, rv);
8310     rv = cons;
8311     Store_field (cons, 0, pairv);
8312   }
8313
8314   CAMLreturn (rv);
8315 }
8316
8317 ";
8318
8319   (* Struct copy functions. *)
8320
8321   let emit_ocaml_copy_list_function typ =
8322     pr "static CAMLprim value\n";
8323     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8324     pr "{\n";
8325     pr "  CAMLparam0 ();\n";
8326     pr "  CAMLlocal2 (rv, v);\n";
8327     pr "  unsigned int i;\n";
8328     pr "\n";
8329     pr "  if (%ss->len == 0)\n" typ;
8330     pr "    CAMLreturn (Atom (0));\n";
8331     pr "  else {\n";
8332     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8333     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8334     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8335     pr "      caml_modify (&Field (rv, i), v);\n";
8336     pr "    }\n";
8337     pr "    CAMLreturn (rv);\n";
8338     pr "  }\n";
8339     pr "}\n";
8340     pr "\n";
8341   in
8342
8343   List.iter (
8344     fun (typ, cols) ->
8345       let has_optpercent_col =
8346         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8347
8348       pr "static CAMLprim value\n";
8349       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8350       pr "{\n";
8351       pr "  CAMLparam0 ();\n";
8352       if has_optpercent_col then
8353         pr "  CAMLlocal3 (rv, v, v2);\n"
8354       else
8355         pr "  CAMLlocal2 (rv, v);\n";
8356       pr "\n";
8357       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8358       iteri (
8359         fun i col ->
8360           (match col with
8361            | name, FString ->
8362                pr "  v = caml_copy_string (%s->%s);\n" typ name
8363            | name, FBuffer ->
8364                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8365                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8366                  typ name typ name
8367            | name, FUUID ->
8368                pr "  v = caml_alloc_string (32);\n";
8369                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8370            | name, (FBytes|FInt64|FUInt64) ->
8371                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8372            | name, (FInt32|FUInt32) ->
8373                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8374            | name, FOptPercent ->
8375                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8376                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8377                pr "    v = caml_alloc (1, 0);\n";
8378                pr "    Store_field (v, 0, v2);\n";
8379                pr "  } else /* None */\n";
8380                pr "    v = Val_int (0);\n";
8381            | name, FChar ->
8382                pr "  v = Val_int (%s->%s);\n" typ name
8383           );
8384           pr "  Store_field (rv, %d, v);\n" i
8385       ) cols;
8386       pr "  CAMLreturn (rv);\n";
8387       pr "}\n";
8388       pr "\n";
8389   ) structs;
8390
8391   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8392   List.iter (
8393     function
8394     | typ, (RStructListOnly | RStructAndList) ->
8395         (* generate the function for typ *)
8396         emit_ocaml_copy_list_function typ
8397     | typ, _ -> () (* empty *)
8398   ) (rstructs_used_by all_functions);
8399
8400   (* The wrappers. *)
8401   List.iter (
8402     fun (name, style, _, _, _, _, _) ->
8403       pr "/* Automatically generated wrapper for function\n";
8404       pr " * ";
8405       generate_ocaml_prototype name style;
8406       pr " */\n";
8407       pr "\n";
8408
8409       let params =
8410         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8411
8412       let needs_extra_vs =
8413         match fst style with RConstOptString _ -> true | _ -> false in
8414
8415       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8416       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8417       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8418       pr "\n";
8419
8420       pr "CAMLprim value\n";
8421       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8422       List.iter (pr ", value %s") (List.tl params);
8423       pr ")\n";
8424       pr "{\n";
8425
8426       (match params with
8427        | [p1; p2; p3; p4; p5] ->
8428            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8429        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8430            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8431            pr "  CAMLxparam%d (%s);\n"
8432              (List.length rest) (String.concat ", " rest)
8433        | ps ->
8434            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8435       );
8436       if not needs_extra_vs then
8437         pr "  CAMLlocal1 (rv);\n"
8438       else
8439         pr "  CAMLlocal3 (rv, v, v2);\n";
8440       pr "\n";
8441
8442       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8443       pr "  if (g == NULL)\n";
8444       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8445       pr "\n";
8446
8447       List.iter (
8448         function
8449         | Pathname n
8450         | Device n | Dev_or_Path n
8451         | String n
8452         | FileIn n
8453         | FileOut n ->
8454             pr "  const char *%s = String_val (%sv);\n" n n
8455         | OptString n ->
8456             pr "  const char *%s =\n" n;
8457             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8458               n n
8459         | BufferIn n ->
8460             pr "  const char *%s = String_val (%sv);\n" n n;
8461             pr "  size_t %s_size = caml_string_length (%sv);\n" n n
8462         | StringList n | DeviceList n ->
8463             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8464         | Bool n ->
8465             pr "  int %s = Bool_val (%sv);\n" n n
8466         | Int n ->
8467             pr "  int %s = Int_val (%sv);\n" n n
8468         | Int64 n ->
8469             pr "  int64_t %s = Int64_val (%sv);\n" n n
8470       ) (snd style);
8471       let error_code =
8472         match fst style with
8473         | RErr -> pr "  int r;\n"; "-1"
8474         | RInt _ -> pr "  int r;\n"; "-1"
8475         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8476         | RBool _ -> pr "  int r;\n"; "-1"
8477         | RConstString _ | RConstOptString _ ->
8478             pr "  const char *r;\n"; "NULL"
8479         | RString _ -> pr "  char *r;\n"; "NULL"
8480         | RStringList _ ->
8481             pr "  int i;\n";
8482             pr "  char **r;\n";
8483             "NULL"
8484         | RStruct (_, typ) ->
8485             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8486         | RStructList (_, typ) ->
8487             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8488         | RHashtable _ ->
8489             pr "  int i;\n";
8490             pr "  char **r;\n";
8491             "NULL"
8492         | RBufferOut _ ->
8493             pr "  char *r;\n";
8494             pr "  size_t size;\n";
8495             "NULL" in
8496       pr "\n";
8497
8498       pr "  caml_enter_blocking_section ();\n";
8499       pr "  r = guestfs_%s " name;
8500       generate_c_call_args ~handle:"g" style;
8501       pr ";\n";
8502       pr "  caml_leave_blocking_section ();\n";
8503
8504       List.iter (
8505         function
8506         | StringList n | DeviceList n ->
8507             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8508         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8509         | Bool _ | Int _ | Int64 _
8510         | FileIn _ | FileOut _ | BufferIn _ -> ()
8511       ) (snd style);
8512
8513       pr "  if (r == %s)\n" error_code;
8514       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8515       pr "\n";
8516
8517       (match fst style with
8518        | RErr -> pr "  rv = Val_unit;\n"
8519        | RInt _ -> pr "  rv = Val_int (r);\n"
8520        | RInt64 _ ->
8521            pr "  rv = caml_copy_int64 (r);\n"
8522        | RBool _ -> pr "  rv = Val_bool (r);\n"
8523        | RConstString _ ->
8524            pr "  rv = caml_copy_string (r);\n"
8525        | RConstOptString _ ->
8526            pr "  if (r) { /* Some string */\n";
8527            pr "    v = caml_alloc (1, 0);\n";
8528            pr "    v2 = caml_copy_string (r);\n";
8529            pr "    Store_field (v, 0, v2);\n";
8530            pr "  } else /* None */\n";
8531            pr "    v = Val_int (0);\n";
8532        | RString _ ->
8533            pr "  rv = caml_copy_string (r);\n";
8534            pr "  free (r);\n"
8535        | RStringList _ ->
8536            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8537            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8538            pr "  free (r);\n"
8539        | RStruct (_, typ) ->
8540            pr "  rv = copy_%s (r);\n" typ;
8541            pr "  guestfs_free_%s (r);\n" typ;
8542        | RStructList (_, typ) ->
8543            pr "  rv = copy_%s_list (r);\n" typ;
8544            pr "  guestfs_free_%s_list (r);\n" typ;
8545        | RHashtable _ ->
8546            pr "  rv = copy_table (r);\n";
8547            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8548            pr "  free (r);\n";
8549        | RBufferOut _ ->
8550            pr "  rv = caml_alloc_string (size);\n";
8551            pr "  memcpy (String_val (rv), r, size);\n";
8552       );
8553
8554       pr "  CAMLreturn (rv);\n";
8555       pr "}\n";
8556       pr "\n";
8557
8558       if List.length params > 5 then (
8559         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8560         pr "CAMLprim value ";
8561         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8562         pr "CAMLprim value\n";
8563         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8564         pr "{\n";
8565         pr "  return ocaml_guestfs_%s (argv[0]" name;
8566         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8567         pr ");\n";
8568         pr "}\n";
8569         pr "\n"
8570       )
8571   ) all_functions_sorted
8572
8573 and generate_ocaml_structure_decls () =
8574   List.iter (
8575     fun (typ, cols) ->
8576       pr "type %s = {\n" typ;
8577       List.iter (
8578         function
8579         | name, FString -> pr "  %s : string;\n" name
8580         | name, FBuffer -> pr "  %s : string;\n" name
8581         | name, FUUID -> pr "  %s : string;\n" name
8582         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8583         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8584         | name, FChar -> pr "  %s : char;\n" name
8585         | name, FOptPercent -> pr "  %s : float option;\n" name
8586       ) cols;
8587       pr "}\n";
8588       pr "\n"
8589   ) structs
8590
8591 and generate_ocaml_prototype ?(is_external = false) name style =
8592   if is_external then pr "external " else pr "val ";
8593   pr "%s : t -> " name;
8594   List.iter (
8595     function
8596     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8597     | BufferIn _ -> pr "string -> "
8598     | OptString _ -> pr "string option -> "
8599     | StringList _ | DeviceList _ -> pr "string array -> "
8600     | Bool _ -> pr "bool -> "
8601     | Int _ -> pr "int -> "
8602     | Int64 _ -> pr "int64 -> "
8603   ) (snd style);
8604   (match fst style with
8605    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8606    | RInt _ -> pr "int"
8607    | RInt64 _ -> pr "int64"
8608    | RBool _ -> pr "bool"
8609    | RConstString _ -> pr "string"
8610    | RConstOptString _ -> pr "string option"
8611    | RString _ | RBufferOut _ -> pr "string"
8612    | RStringList _ -> pr "string array"
8613    | RStruct (_, typ) -> pr "%s" typ
8614    | RStructList (_, typ) -> pr "%s array" typ
8615    | RHashtable _ -> pr "(string * string) list"
8616   );
8617   if is_external then (
8618     pr " = ";
8619     if List.length (snd style) + 1 > 5 then
8620       pr "\"ocaml_guestfs_%s_byte\" " name;
8621     pr "\"ocaml_guestfs_%s\"" name
8622   );
8623   pr "\n"
8624
8625 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8626 and generate_perl_xs () =
8627   generate_header CStyle LGPLv2plus;
8628
8629   pr "\
8630 #include \"EXTERN.h\"
8631 #include \"perl.h\"
8632 #include \"XSUB.h\"
8633
8634 #include <guestfs.h>
8635
8636 #ifndef PRId64
8637 #define PRId64 \"lld\"
8638 #endif
8639
8640 static SV *
8641 my_newSVll(long long val) {
8642 #ifdef USE_64_BIT_ALL
8643   return newSViv(val);
8644 #else
8645   char buf[100];
8646   int len;
8647   len = snprintf(buf, 100, \"%%\" PRId64, val);
8648   return newSVpv(buf, len);
8649 #endif
8650 }
8651
8652 #ifndef PRIu64
8653 #define PRIu64 \"llu\"
8654 #endif
8655
8656 static SV *
8657 my_newSVull(unsigned long long val) {
8658 #ifdef USE_64_BIT_ALL
8659   return newSVuv(val);
8660 #else
8661   char buf[100];
8662   int len;
8663   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8664   return newSVpv(buf, len);
8665 #endif
8666 }
8667
8668 /* http://www.perlmonks.org/?node_id=680842 */
8669 static char **
8670 XS_unpack_charPtrPtr (SV *arg) {
8671   char **ret;
8672   AV *av;
8673   I32 i;
8674
8675   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8676     croak (\"array reference expected\");
8677
8678   av = (AV *)SvRV (arg);
8679   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8680   if (!ret)
8681     croak (\"malloc failed\");
8682
8683   for (i = 0; i <= av_len (av); i++) {
8684     SV **elem = av_fetch (av, i, 0);
8685
8686     if (!elem || !*elem)
8687       croak (\"missing element in list\");
8688
8689     ret[i] = SvPV_nolen (*elem);
8690   }
8691
8692   ret[i] = NULL;
8693
8694   return ret;
8695 }
8696
8697 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8698
8699 PROTOTYPES: ENABLE
8700
8701 guestfs_h *
8702 _create ()
8703    CODE:
8704       RETVAL = guestfs_create ();
8705       if (!RETVAL)
8706         croak (\"could not create guestfs handle\");
8707       guestfs_set_error_handler (RETVAL, NULL, NULL);
8708  OUTPUT:
8709       RETVAL
8710
8711 void
8712 DESTROY (g)
8713       guestfs_h *g;
8714  PPCODE:
8715       guestfs_close (g);
8716
8717 ";
8718
8719   List.iter (
8720     fun (name, style, _, _, _, _, _) ->
8721       (match fst style with
8722        | RErr -> pr "void\n"
8723        | RInt _ -> pr "SV *\n"
8724        | RInt64 _ -> pr "SV *\n"
8725        | RBool _ -> pr "SV *\n"
8726        | RConstString _ -> pr "SV *\n"
8727        | RConstOptString _ -> pr "SV *\n"
8728        | RString _ -> pr "SV *\n"
8729        | RBufferOut _ -> pr "SV *\n"
8730        | RStringList _
8731        | RStruct _ | RStructList _
8732        | RHashtable _ ->
8733            pr "void\n" (* all lists returned implictly on the stack *)
8734       );
8735       (* Call and arguments. *)
8736       pr "%s (g" name;
8737       List.iter (
8738         fun arg -> pr ", %s" (name_of_argt arg)
8739       ) (snd style);
8740       pr ")\n";
8741       pr "      guestfs_h *g;\n";
8742       iteri (
8743         fun i ->
8744           function
8745           | Pathname n | Device n | Dev_or_Path n | String n
8746           | FileIn n | FileOut n ->
8747               pr "      char *%s;\n" n
8748           | BufferIn n ->
8749               pr "      char *%s;\n" n;
8750               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8751           | OptString n ->
8752               (* http://www.perlmonks.org/?node_id=554277
8753                * Note that the implicit handle argument means we have
8754                * to add 1 to the ST(x) operator.
8755                *)
8756               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8757           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8758           | Bool n -> pr "      int %s;\n" n
8759           | Int n -> pr "      int %s;\n" n
8760           | Int64 n -> pr "      int64_t %s;\n" n
8761       ) (snd style);
8762
8763       let do_cleanups () =
8764         List.iter (
8765           function
8766           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8767           | Bool _ | Int _ | Int64 _
8768           | FileIn _ | FileOut _
8769           | BufferIn _ -> ()
8770           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8771         ) (snd style)
8772       in
8773
8774       (* Code. *)
8775       (match fst style with
8776        | RErr ->
8777            pr "PREINIT:\n";
8778            pr "      int r;\n";
8779            pr " PPCODE:\n";
8780            pr "      r = guestfs_%s " name;
8781            generate_c_call_args ~handle:"g" style;
8782            pr ";\n";
8783            do_cleanups ();
8784            pr "      if (r == -1)\n";
8785            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8786        | RInt n
8787        | RBool n ->
8788            pr "PREINIT:\n";
8789            pr "      int %s;\n" n;
8790            pr "   CODE:\n";
8791            pr "      %s = guestfs_%s " n name;
8792            generate_c_call_args ~handle:"g" style;
8793            pr ";\n";
8794            do_cleanups ();
8795            pr "      if (%s == -1)\n" n;
8796            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8797            pr "      RETVAL = newSViv (%s);\n" n;
8798            pr " OUTPUT:\n";
8799            pr "      RETVAL\n"
8800        | RInt64 n ->
8801            pr "PREINIT:\n";
8802            pr "      int64_t %s;\n" n;
8803            pr "   CODE:\n";
8804            pr "      %s = guestfs_%s " n name;
8805            generate_c_call_args ~handle:"g" style;
8806            pr ";\n";
8807            do_cleanups ();
8808            pr "      if (%s == -1)\n" n;
8809            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8810            pr "      RETVAL = my_newSVll (%s);\n" n;
8811            pr " OUTPUT:\n";
8812            pr "      RETVAL\n"
8813        | RConstString n ->
8814            pr "PREINIT:\n";
8815            pr "      const char *%s;\n" n;
8816            pr "   CODE:\n";
8817            pr "      %s = guestfs_%s " n name;
8818            generate_c_call_args ~handle:"g" style;
8819            pr ";\n";
8820            do_cleanups ();
8821            pr "      if (%s == NULL)\n" n;
8822            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8823            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8824            pr " OUTPUT:\n";
8825            pr "      RETVAL\n"
8826        | RConstOptString n ->
8827            pr "PREINIT:\n";
8828            pr "      const char *%s;\n" n;
8829            pr "   CODE:\n";
8830            pr "      %s = guestfs_%s " n name;
8831            generate_c_call_args ~handle:"g" style;
8832            pr ";\n";
8833            do_cleanups ();
8834            pr "      if (%s == NULL)\n" n;
8835            pr "        RETVAL = &PL_sv_undef;\n";
8836            pr "      else\n";
8837            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8838            pr " OUTPUT:\n";
8839            pr "      RETVAL\n"
8840        | RString n ->
8841            pr "PREINIT:\n";
8842            pr "      char *%s;\n" n;
8843            pr "   CODE:\n";
8844            pr "      %s = guestfs_%s " n name;
8845            generate_c_call_args ~handle:"g" style;
8846            pr ";\n";
8847            do_cleanups ();
8848            pr "      if (%s == NULL)\n" n;
8849            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8850            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8851            pr "      free (%s);\n" n;
8852            pr " OUTPUT:\n";
8853            pr "      RETVAL\n"
8854        | RStringList n | RHashtable n ->
8855            pr "PREINIT:\n";
8856            pr "      char **%s;\n" n;
8857            pr "      int i, n;\n";
8858            pr " PPCODE:\n";
8859            pr "      %s = guestfs_%s " n name;
8860            generate_c_call_args ~handle:"g" style;
8861            pr ";\n";
8862            do_cleanups ();
8863            pr "      if (%s == NULL)\n" n;
8864            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8865            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8866            pr "      EXTEND (SP, n);\n";
8867            pr "      for (i = 0; i < n; ++i) {\n";
8868            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8869            pr "        free (%s[i]);\n" n;
8870            pr "      }\n";
8871            pr "      free (%s);\n" n;
8872        | RStruct (n, typ) ->
8873            let cols = cols_of_struct typ in
8874            generate_perl_struct_code typ cols name style n do_cleanups
8875        | RStructList (n, typ) ->
8876            let cols = cols_of_struct typ in
8877            generate_perl_struct_list_code typ cols name style n do_cleanups
8878        | RBufferOut n ->
8879            pr "PREINIT:\n";
8880            pr "      char *%s;\n" n;
8881            pr "      size_t size;\n";
8882            pr "   CODE:\n";
8883            pr "      %s = guestfs_%s " n name;
8884            generate_c_call_args ~handle:"g" style;
8885            pr ";\n";
8886            do_cleanups ();
8887            pr "      if (%s == NULL)\n" n;
8888            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8889            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8890            pr "      free (%s);\n" n;
8891            pr " OUTPUT:\n";
8892            pr "      RETVAL\n"
8893       );
8894
8895       pr "\n"
8896   ) all_functions
8897
8898 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8899   pr "PREINIT:\n";
8900   pr "      struct guestfs_%s_list *%s;\n" typ n;
8901   pr "      int i;\n";
8902   pr "      HV *hv;\n";
8903   pr " PPCODE:\n";
8904   pr "      %s = guestfs_%s " n name;
8905   generate_c_call_args ~handle:"g" style;
8906   pr ";\n";
8907   do_cleanups ();
8908   pr "      if (%s == NULL)\n" n;
8909   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8910   pr "      EXTEND (SP, %s->len);\n" n;
8911   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8912   pr "        hv = newHV ();\n";
8913   List.iter (
8914     function
8915     | name, FString ->
8916         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8917           name (String.length name) n name
8918     | name, FUUID ->
8919         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8920           name (String.length name) n name
8921     | name, FBuffer ->
8922         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8923           name (String.length name) n name n name
8924     | name, (FBytes|FUInt64) ->
8925         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8926           name (String.length name) n name
8927     | name, FInt64 ->
8928         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8929           name (String.length name) n name
8930     | name, (FInt32|FUInt32) ->
8931         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8932           name (String.length name) n name
8933     | name, FChar ->
8934         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8935           name (String.length name) n name
8936     | name, FOptPercent ->
8937         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8938           name (String.length name) n name
8939   ) cols;
8940   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8941   pr "      }\n";
8942   pr "      guestfs_free_%s_list (%s);\n" typ n
8943
8944 and generate_perl_struct_code typ cols name style n do_cleanups =
8945   pr "PREINIT:\n";
8946   pr "      struct guestfs_%s *%s;\n" typ n;
8947   pr " PPCODE:\n";
8948   pr "      %s = guestfs_%s " n name;
8949   generate_c_call_args ~handle:"g" style;
8950   pr ";\n";
8951   do_cleanups ();
8952   pr "      if (%s == NULL)\n" n;
8953   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8954   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8955   List.iter (
8956     fun ((name, _) as col) ->
8957       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8958
8959       match col with
8960       | name, FString ->
8961           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8962             n name
8963       | name, FBuffer ->
8964           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8965             n name n name
8966       | name, FUUID ->
8967           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8968             n name
8969       | name, (FBytes|FUInt64) ->
8970           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8971             n name
8972       | name, FInt64 ->
8973           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8974             n name
8975       | name, (FInt32|FUInt32) ->
8976           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8977             n name
8978       | name, FChar ->
8979           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8980             n name
8981       | name, FOptPercent ->
8982           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8983             n name
8984   ) cols;
8985   pr "      free (%s);\n" n
8986
8987 (* Generate Sys/Guestfs.pm. *)
8988 and generate_perl_pm () =
8989   generate_header HashStyle LGPLv2plus;
8990
8991   pr "\
8992 =pod
8993
8994 =head1 NAME
8995
8996 Sys::Guestfs - Perl bindings for libguestfs
8997
8998 =head1 SYNOPSIS
8999
9000  use Sys::Guestfs;
9001
9002  my $h = Sys::Guestfs->new ();
9003  $h->add_drive ('guest.img');
9004  $h->launch ();
9005  $h->mount ('/dev/sda1', '/');
9006  $h->touch ('/hello');
9007  $h->sync ();
9008
9009 =head1 DESCRIPTION
9010
9011 The C<Sys::Guestfs> module provides a Perl XS binding to the
9012 libguestfs API for examining and modifying virtual machine
9013 disk images.
9014
9015 Amongst the things this is good for: making batch configuration
9016 changes to guests, getting disk used/free statistics (see also:
9017 virt-df), migrating between virtualization systems (see also:
9018 virt-p2v), performing partial backups, performing partial guest
9019 clones, cloning guests and changing registry/UUID/hostname info, and
9020 much else besides.
9021
9022 Libguestfs uses Linux kernel and qemu code, and can access any type of
9023 guest filesystem that Linux and qemu can, including but not limited
9024 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9025 schemes, qcow, qcow2, vmdk.
9026
9027 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9028 LVs, what filesystem is in each LV, etc.).  It can also run commands
9029 in the context of the guest.  Also you can access filesystems over
9030 FUSE.
9031
9032 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9033 functions for using libguestfs from Perl, including integration
9034 with libvirt.
9035
9036 =head1 ERRORS
9037
9038 All errors turn into calls to C<croak> (see L<Carp(3)>).
9039
9040 =head1 METHODS
9041
9042 =over 4
9043
9044 =cut
9045
9046 package Sys::Guestfs;
9047
9048 use strict;
9049 use warnings;
9050
9051 # This version number changes whenever a new function
9052 # is added to the libguestfs API.  It is not directly
9053 # related to the libguestfs version number.
9054 use vars qw($VERSION);
9055 $VERSION = '0.%d';
9056
9057 require XSLoader;
9058 XSLoader::load ('Sys::Guestfs');
9059
9060 =item $h = Sys::Guestfs->new ();
9061
9062 Create a new guestfs handle.
9063
9064 =cut
9065
9066 sub new {
9067   my $proto = shift;
9068   my $class = ref ($proto) || $proto;
9069
9070   my $self = Sys::Guestfs::_create ();
9071   bless $self, $class;
9072   return $self;
9073 }
9074
9075 " max_proc_nr;
9076
9077   (* Actions.  We only need to print documentation for these as
9078    * they are pulled in from the XS code automatically.
9079    *)
9080   List.iter (
9081     fun (name, style, _, flags, _, _, longdesc) ->
9082       if not (List.mem NotInDocs flags) then (
9083         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9084         pr "=item ";
9085         generate_perl_prototype name style;
9086         pr "\n\n";
9087         pr "%s\n\n" longdesc;
9088         if List.mem ProtocolLimitWarning flags then
9089           pr "%s\n\n" protocol_limit_warning;
9090         if List.mem DangerWillRobinson flags then
9091           pr "%s\n\n" danger_will_robinson;
9092         match deprecation_notice flags with
9093         | None -> ()
9094         | Some txt -> pr "%s\n\n" txt
9095       )
9096   ) all_functions_sorted;
9097
9098   (* End of file. *)
9099   pr "\
9100 =cut
9101
9102 1;
9103
9104 =back
9105
9106 =head1 COPYRIGHT
9107
9108 Copyright (C) %s Red Hat Inc.
9109
9110 =head1 LICENSE
9111
9112 Please see the file COPYING.LIB for the full license.
9113
9114 =head1 SEE ALSO
9115
9116 L<guestfs(3)>,
9117 L<guestfish(1)>,
9118 L<http://libguestfs.org>,
9119 L<Sys::Guestfs::Lib(3)>.
9120
9121 =cut
9122 " copyright_years
9123
9124 and generate_perl_prototype name style =
9125   (match fst style with
9126    | RErr -> ()
9127    | RBool n
9128    | RInt n
9129    | RInt64 n
9130    | RConstString n
9131    | RConstOptString n
9132    | RString n
9133    | RBufferOut n -> pr "$%s = " n
9134    | RStruct (n,_)
9135    | RHashtable n -> pr "%%%s = " n
9136    | RStringList n
9137    | RStructList (n,_) -> pr "@%s = " n
9138   );
9139   pr "$h->%s (" name;
9140   let comma = ref false in
9141   List.iter (
9142     fun arg ->
9143       if !comma then pr ", ";
9144       comma := true;
9145       match arg with
9146       | Pathname n | Device n | Dev_or_Path n | String n
9147       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9148       | BufferIn n ->
9149           pr "$%s" n
9150       | StringList n | DeviceList n ->
9151           pr "\\@%s" n
9152   ) (snd style);
9153   pr ");"
9154
9155 (* Generate Python C module. *)
9156 and generate_python_c () =
9157   generate_header CStyle LGPLv2plus;
9158
9159   pr "\
9160 #define PY_SSIZE_T_CLEAN 1
9161 #include <Python.h>
9162
9163 #if PY_VERSION_HEX < 0x02050000
9164 typedef int Py_ssize_t;
9165 #define PY_SSIZE_T_MAX INT_MAX
9166 #define PY_SSIZE_T_MIN INT_MIN
9167 #endif
9168
9169 #include <stdio.h>
9170 #include <stdlib.h>
9171 #include <assert.h>
9172
9173 #include \"guestfs.h\"
9174
9175 typedef struct {
9176   PyObject_HEAD
9177   guestfs_h *g;
9178 } Pyguestfs_Object;
9179
9180 static guestfs_h *
9181 get_handle (PyObject *obj)
9182 {
9183   assert (obj);
9184   assert (obj != Py_None);
9185   return ((Pyguestfs_Object *) obj)->g;
9186 }
9187
9188 static PyObject *
9189 put_handle (guestfs_h *g)
9190 {
9191   assert (g);
9192   return
9193     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9194 }
9195
9196 /* This list should be freed (but not the strings) after use. */
9197 static char **
9198 get_string_list (PyObject *obj)
9199 {
9200   int i, len;
9201   char **r;
9202
9203   assert (obj);
9204
9205   if (!PyList_Check (obj)) {
9206     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9207     return NULL;
9208   }
9209
9210   len = PyList_Size (obj);
9211   r = malloc (sizeof (char *) * (len+1));
9212   if (r == NULL) {
9213     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9214     return NULL;
9215   }
9216
9217   for (i = 0; i < len; ++i)
9218     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9219   r[len] = NULL;
9220
9221   return r;
9222 }
9223
9224 static PyObject *
9225 put_string_list (char * const * const argv)
9226 {
9227   PyObject *list;
9228   int argc, i;
9229
9230   for (argc = 0; argv[argc] != NULL; ++argc)
9231     ;
9232
9233   list = PyList_New (argc);
9234   for (i = 0; i < argc; ++i)
9235     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9236
9237   return list;
9238 }
9239
9240 static PyObject *
9241 put_table (char * const * const argv)
9242 {
9243   PyObject *list, *item;
9244   int argc, i;
9245
9246   for (argc = 0; argv[argc] != NULL; ++argc)
9247     ;
9248
9249   list = PyList_New (argc >> 1);
9250   for (i = 0; i < argc; i += 2) {
9251     item = PyTuple_New (2);
9252     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9253     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9254     PyList_SetItem (list, i >> 1, item);
9255   }
9256
9257   return list;
9258 }
9259
9260 static void
9261 free_strings (char **argv)
9262 {
9263   int argc;
9264
9265   for (argc = 0; argv[argc] != NULL; ++argc)
9266     free (argv[argc]);
9267   free (argv);
9268 }
9269
9270 static PyObject *
9271 py_guestfs_create (PyObject *self, PyObject *args)
9272 {
9273   guestfs_h *g;
9274
9275   g = guestfs_create ();
9276   if (g == NULL) {
9277     PyErr_SetString (PyExc_RuntimeError,
9278                      \"guestfs.create: failed to allocate handle\");
9279     return NULL;
9280   }
9281   guestfs_set_error_handler (g, NULL, NULL);
9282   return put_handle (g);
9283 }
9284
9285 static PyObject *
9286 py_guestfs_close (PyObject *self, PyObject *args)
9287 {
9288   PyObject *py_g;
9289   guestfs_h *g;
9290
9291   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9292     return NULL;
9293   g = get_handle (py_g);
9294
9295   guestfs_close (g);
9296
9297   Py_INCREF (Py_None);
9298   return Py_None;
9299 }
9300
9301 ";
9302
9303   let emit_put_list_function typ =
9304     pr "static PyObject *\n";
9305     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9306     pr "{\n";
9307     pr "  PyObject *list;\n";
9308     pr "  int i;\n";
9309     pr "\n";
9310     pr "  list = PyList_New (%ss->len);\n" typ;
9311     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9312     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9313     pr "  return list;\n";
9314     pr "};\n";
9315     pr "\n"
9316   in
9317
9318   (* Structures, turned into Python dictionaries. *)
9319   List.iter (
9320     fun (typ, cols) ->
9321       pr "static PyObject *\n";
9322       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9323       pr "{\n";
9324       pr "  PyObject *dict;\n";
9325       pr "\n";
9326       pr "  dict = PyDict_New ();\n";
9327       List.iter (
9328         function
9329         | name, FString ->
9330             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9331             pr "                        PyString_FromString (%s->%s));\n"
9332               typ name
9333         | name, FBuffer ->
9334             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9335             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9336               typ name typ name
9337         | name, FUUID ->
9338             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9339             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9340               typ name
9341         | name, (FBytes|FUInt64) ->
9342             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9343             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9344               typ name
9345         | name, FInt64 ->
9346             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9347             pr "                        PyLong_FromLongLong (%s->%s));\n"
9348               typ name
9349         | name, FUInt32 ->
9350             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9351             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9352               typ name
9353         | name, FInt32 ->
9354             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9355             pr "                        PyLong_FromLong (%s->%s));\n"
9356               typ name
9357         | name, FOptPercent ->
9358             pr "  if (%s->%s >= 0)\n" typ name;
9359             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9360             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9361               typ name;
9362             pr "  else {\n";
9363             pr "    Py_INCREF (Py_None);\n";
9364             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9365             pr "  }\n"
9366         | name, FChar ->
9367             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9368             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9369       ) cols;
9370       pr "  return dict;\n";
9371       pr "};\n";
9372       pr "\n";
9373
9374   ) structs;
9375
9376   (* Emit a put_TYPE_list function definition only if that function is used. *)
9377   List.iter (
9378     function
9379     | typ, (RStructListOnly | RStructAndList) ->
9380         (* generate the function for typ *)
9381         emit_put_list_function typ
9382     | typ, _ -> () (* empty *)
9383   ) (rstructs_used_by all_functions);
9384
9385   (* Python wrapper functions. *)
9386   List.iter (
9387     fun (name, style, _, _, _, _, _) ->
9388       pr "static PyObject *\n";
9389       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9390       pr "{\n";
9391
9392       pr "  PyObject *py_g;\n";
9393       pr "  guestfs_h *g;\n";
9394       pr "  PyObject *py_r;\n";
9395
9396       let error_code =
9397         match fst style with
9398         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9399         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9400         | RConstString _ | RConstOptString _ ->
9401             pr "  const char *r;\n"; "NULL"
9402         | RString _ -> pr "  char *r;\n"; "NULL"
9403         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9404         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9405         | RStructList (_, typ) ->
9406             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9407         | RBufferOut _ ->
9408             pr "  char *r;\n";
9409             pr "  size_t size;\n";
9410             "NULL" in
9411
9412       List.iter (
9413         function
9414         | Pathname n | Device n | Dev_or_Path n | String n
9415         | FileIn n | FileOut n ->
9416             pr "  const char *%s;\n" n
9417         | OptString n -> pr "  const char *%s;\n" n
9418         | BufferIn n ->
9419             pr "  const char *%s;\n" n;
9420             pr "  Py_ssize_t %s_size;\n" n
9421         | StringList n | DeviceList n ->
9422             pr "  PyObject *py_%s;\n" n;
9423             pr "  char **%s;\n" n
9424         | Bool n -> pr "  int %s;\n" n
9425         | Int n -> pr "  int %s;\n" n
9426         | Int64 n -> pr "  long long %s;\n" n
9427       ) (snd style);
9428
9429       pr "\n";
9430
9431       (* Convert the parameters. *)
9432       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9433       List.iter (
9434         function
9435         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9436         | OptString _ -> pr "z"
9437         | StringList _ | DeviceList _ -> pr "O"
9438         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9439         | Int _ -> pr "i"
9440         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9441                              * emulate C's int/long/long long in Python?
9442                              *)
9443         | BufferIn _ -> pr "s#"
9444       ) (snd style);
9445       pr ":guestfs_%s\",\n" name;
9446       pr "                         &py_g";
9447       List.iter (
9448         function
9449         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9450         | OptString n -> pr ", &%s" n
9451         | StringList n | DeviceList n -> pr ", &py_%s" n
9452         | Bool n -> pr ", &%s" n
9453         | Int n -> pr ", &%s" n
9454         | Int64 n -> pr ", &%s" n
9455         | BufferIn n -> pr ", &%s, &%s_size" n n
9456       ) (snd style);
9457
9458       pr "))\n";
9459       pr "    return NULL;\n";
9460
9461       pr "  g = get_handle (py_g);\n";
9462       List.iter (
9463         function
9464         | Pathname _ | Device _ | Dev_or_Path _ | String _
9465         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9466         | BufferIn _ -> ()
9467         | StringList n | DeviceList n ->
9468             pr "  %s = get_string_list (py_%s);\n" n n;
9469             pr "  if (!%s) return NULL;\n" n
9470       ) (snd style);
9471
9472       pr "\n";
9473
9474       pr "  r = guestfs_%s " name;
9475       generate_c_call_args ~handle:"g" style;
9476       pr ";\n";
9477
9478       List.iter (
9479         function
9480         | Pathname _ | Device _ | Dev_or_Path _ | String _
9481         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9482         | BufferIn _ -> ()
9483         | StringList n | DeviceList n ->
9484             pr "  free (%s);\n" n
9485       ) (snd style);
9486
9487       pr "  if (r == %s) {\n" error_code;
9488       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9489       pr "    return NULL;\n";
9490       pr "  }\n";
9491       pr "\n";
9492
9493       (match fst style with
9494        | RErr ->
9495            pr "  Py_INCREF (Py_None);\n";
9496            pr "  py_r = Py_None;\n"
9497        | RInt _
9498        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9499        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9500        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9501        | RConstOptString _ ->
9502            pr "  if (r)\n";
9503            pr "    py_r = PyString_FromString (r);\n";
9504            pr "  else {\n";
9505            pr "    Py_INCREF (Py_None);\n";
9506            pr "    py_r = Py_None;\n";
9507            pr "  }\n"
9508        | RString _ ->
9509            pr "  py_r = PyString_FromString (r);\n";
9510            pr "  free (r);\n"
9511        | RStringList _ ->
9512            pr "  py_r = put_string_list (r);\n";
9513            pr "  free_strings (r);\n"
9514        | RStruct (_, typ) ->
9515            pr "  py_r = put_%s (r);\n" typ;
9516            pr "  guestfs_free_%s (r);\n" typ
9517        | RStructList (_, typ) ->
9518            pr "  py_r = put_%s_list (r);\n" typ;
9519            pr "  guestfs_free_%s_list (r);\n" typ
9520        | RHashtable n ->
9521            pr "  py_r = put_table (r);\n";
9522            pr "  free_strings (r);\n"
9523        | RBufferOut _ ->
9524            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9525            pr "  free (r);\n"
9526       );
9527
9528       pr "  return py_r;\n";
9529       pr "}\n";
9530       pr "\n"
9531   ) all_functions;
9532
9533   (* Table of functions. *)
9534   pr "static PyMethodDef methods[] = {\n";
9535   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9536   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9537   List.iter (
9538     fun (name, _, _, _, _, _, _) ->
9539       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9540         name name
9541   ) all_functions;
9542   pr "  { NULL, NULL, 0, NULL }\n";
9543   pr "};\n";
9544   pr "\n";
9545
9546   (* Init function. *)
9547   pr "\
9548 void
9549 initlibguestfsmod (void)
9550 {
9551   static int initialized = 0;
9552
9553   if (initialized) return;
9554   Py_InitModule ((char *) \"libguestfsmod\", methods);
9555   initialized = 1;
9556 }
9557 "
9558
9559 (* Generate Python module. *)
9560 and generate_python_py () =
9561   generate_header HashStyle LGPLv2plus;
9562
9563   pr "\
9564 u\"\"\"Python bindings for libguestfs
9565
9566 import guestfs
9567 g = guestfs.GuestFS ()
9568 g.add_drive (\"guest.img\")
9569 g.launch ()
9570 parts = g.list_partitions ()
9571
9572 The guestfs module provides a Python binding to the libguestfs API
9573 for examining and modifying virtual machine disk images.
9574
9575 Amongst the things this is good for: making batch configuration
9576 changes to guests, getting disk used/free statistics (see also:
9577 virt-df), migrating between virtualization systems (see also:
9578 virt-p2v), performing partial backups, performing partial guest
9579 clones, cloning guests and changing registry/UUID/hostname info, and
9580 much else besides.
9581
9582 Libguestfs uses Linux kernel and qemu code, and can access any type of
9583 guest filesystem that Linux and qemu can, including but not limited
9584 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9585 schemes, qcow, qcow2, vmdk.
9586
9587 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9588 LVs, what filesystem is in each LV, etc.).  It can also run commands
9589 in the context of the guest.  Also you can access filesystems over
9590 FUSE.
9591
9592 Errors which happen while using the API are turned into Python
9593 RuntimeError exceptions.
9594
9595 To create a guestfs handle you usually have to perform the following
9596 sequence of calls:
9597
9598 # Create the handle, call add_drive at least once, and possibly
9599 # several times if the guest has multiple block devices:
9600 g = guestfs.GuestFS ()
9601 g.add_drive (\"guest.img\")
9602
9603 # Launch the qemu subprocess and wait for it to become ready:
9604 g.launch ()
9605
9606 # Now you can issue commands, for example:
9607 logvols = g.lvs ()
9608
9609 \"\"\"
9610
9611 import libguestfsmod
9612
9613 class GuestFS:
9614     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9615
9616     def __init__ (self):
9617         \"\"\"Create a new libguestfs handle.\"\"\"
9618         self._o = libguestfsmod.create ()
9619
9620     def __del__ (self):
9621         libguestfsmod.close (self._o)
9622
9623 ";
9624
9625   List.iter (
9626     fun (name, style, _, flags, _, _, longdesc) ->
9627       pr "    def %s " name;
9628       generate_py_call_args ~handle:"self" (snd style);
9629       pr ":\n";
9630
9631       if not (List.mem NotInDocs flags) then (
9632         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9633         let doc =
9634           match fst style with
9635           | RErr | RInt _ | RInt64 _ | RBool _
9636           | RConstOptString _ | RConstString _
9637           | RString _ | RBufferOut _ -> doc
9638           | RStringList _ ->
9639               doc ^ "\n\nThis function returns a list of strings."
9640           | RStruct (_, typ) ->
9641               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9642           | RStructList (_, typ) ->
9643               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9644           | RHashtable _ ->
9645               doc ^ "\n\nThis function returns a dictionary." in
9646         let doc =
9647           if List.mem ProtocolLimitWarning flags then
9648             doc ^ "\n\n" ^ protocol_limit_warning
9649           else doc in
9650         let doc =
9651           if List.mem DangerWillRobinson flags then
9652             doc ^ "\n\n" ^ danger_will_robinson
9653           else doc in
9654         let doc =
9655           match deprecation_notice flags with
9656           | None -> doc
9657           | Some txt -> doc ^ "\n\n" ^ txt in
9658         let doc = pod2text ~width:60 name doc in
9659         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9660         let doc = String.concat "\n        " doc in
9661         pr "        u\"\"\"%s\"\"\"\n" doc;
9662       );
9663       pr "        return libguestfsmod.%s " name;
9664       generate_py_call_args ~handle:"self._o" (snd style);
9665       pr "\n";
9666       pr "\n";
9667   ) all_functions
9668
9669 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9670 and generate_py_call_args ~handle args =
9671   pr "(%s" handle;
9672   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9673   pr ")"
9674
9675 (* Useful if you need the longdesc POD text as plain text.  Returns a
9676  * list of lines.
9677  *
9678  * Because this is very slow (the slowest part of autogeneration),
9679  * we memoize the results.
9680  *)
9681 and pod2text ~width name longdesc =
9682   let key = width, name, longdesc in
9683   try Hashtbl.find pod2text_memo key
9684   with Not_found ->
9685     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9686     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9687     close_out chan;
9688     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9689     let chan = open_process_in cmd in
9690     let lines = ref [] in
9691     let rec loop i =
9692       let line = input_line chan in
9693       if i = 1 then             (* discard the first line of output *)
9694         loop (i+1)
9695       else (
9696         let line = triml line in
9697         lines := line :: !lines;
9698         loop (i+1)
9699       ) in
9700     let lines = try loop 1 with End_of_file -> List.rev !lines in
9701     unlink filename;
9702     (match close_process_in chan with
9703      | WEXITED 0 -> ()
9704      | WEXITED i ->
9705          failwithf "pod2text: process exited with non-zero status (%d)" i
9706      | WSIGNALED i | WSTOPPED i ->
9707          failwithf "pod2text: process signalled or stopped by signal %d" i
9708     );
9709     Hashtbl.add pod2text_memo key lines;
9710     pod2text_memo_updated ();
9711     lines
9712
9713 (* Generate ruby bindings. *)
9714 and generate_ruby_c () =
9715   generate_header CStyle LGPLv2plus;
9716
9717   pr "\
9718 #include <stdio.h>
9719 #include <stdlib.h>
9720
9721 #include <ruby.h>
9722
9723 #include \"guestfs.h\"
9724
9725 #include \"extconf.h\"
9726
9727 /* For Ruby < 1.9 */
9728 #ifndef RARRAY_LEN
9729 #define RARRAY_LEN(r) (RARRAY((r))->len)
9730 #endif
9731
9732 static VALUE m_guestfs;                 /* guestfs module */
9733 static VALUE c_guestfs;                 /* guestfs_h handle */
9734 static VALUE e_Error;                   /* used for all errors */
9735
9736 static void ruby_guestfs_free (void *p)
9737 {
9738   if (!p) return;
9739   guestfs_close ((guestfs_h *) p);
9740 }
9741
9742 static VALUE ruby_guestfs_create (VALUE m)
9743 {
9744   guestfs_h *g;
9745
9746   g = guestfs_create ();
9747   if (!g)
9748     rb_raise (e_Error, \"failed to create guestfs handle\");
9749
9750   /* Don't print error messages to stderr by default. */
9751   guestfs_set_error_handler (g, NULL, NULL);
9752
9753   /* Wrap it, and make sure the close function is called when the
9754    * handle goes away.
9755    */
9756   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9757 }
9758
9759 static VALUE ruby_guestfs_close (VALUE gv)
9760 {
9761   guestfs_h *g;
9762   Data_Get_Struct (gv, guestfs_h, g);
9763
9764   ruby_guestfs_free (g);
9765   DATA_PTR (gv) = NULL;
9766
9767   return Qnil;
9768 }
9769
9770 ";
9771
9772   List.iter (
9773     fun (name, style, _, _, _, _, _) ->
9774       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9775       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9776       pr ")\n";
9777       pr "{\n";
9778       pr "  guestfs_h *g;\n";
9779       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9780       pr "  if (!g)\n";
9781       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9782         name;
9783       pr "\n";
9784
9785       List.iter (
9786         function
9787         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9788             pr "  Check_Type (%sv, T_STRING);\n" n;
9789             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9790             pr "  if (!%s)\n" n;
9791             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9792             pr "              \"%s\", \"%s\");\n" n name
9793         | BufferIn n ->
9794             pr "  Check_Type (%sv, T_STRING);\n" n;
9795             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9796             pr "  if (!%s)\n" n;
9797             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9798             pr "              \"%s\", \"%s\");\n" n name;
9799             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9800         | OptString n ->
9801             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9802         | StringList n | DeviceList n ->
9803             pr "  char **%s;\n" n;
9804             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9805             pr "  {\n";
9806             pr "    int i, len;\n";
9807             pr "    len = RARRAY_LEN (%sv);\n" n;
9808             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9809               n;
9810             pr "    for (i = 0; i < len; ++i) {\n";
9811             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9812             pr "      %s[i] = StringValueCStr (v);\n" n;
9813             pr "    }\n";
9814             pr "    %s[len] = NULL;\n" n;
9815             pr "  }\n";
9816         | Bool n ->
9817             pr "  int %s = RTEST (%sv);\n" n n
9818         | Int n ->
9819             pr "  int %s = NUM2INT (%sv);\n" n n
9820         | Int64 n ->
9821             pr "  long long %s = NUM2LL (%sv);\n" n n
9822       ) (snd style);
9823       pr "\n";
9824
9825       let error_code =
9826         match fst style with
9827         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9828         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9829         | RConstString _ | RConstOptString _ ->
9830             pr "  const char *r;\n"; "NULL"
9831         | RString _ -> pr "  char *r;\n"; "NULL"
9832         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9833         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9834         | RStructList (_, typ) ->
9835             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9836         | RBufferOut _ ->
9837             pr "  char *r;\n";
9838             pr "  size_t size;\n";
9839             "NULL" in
9840       pr "\n";
9841
9842       pr "  r = guestfs_%s " name;
9843       generate_c_call_args ~handle:"g" style;
9844       pr ";\n";
9845
9846       List.iter (
9847         function
9848         | Pathname _ | Device _ | Dev_or_Path _ | String _
9849         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9850         | BufferIn _ -> ()
9851         | StringList n | DeviceList n ->
9852             pr "  free (%s);\n" n
9853       ) (snd style);
9854
9855       pr "  if (r == %s)\n" error_code;
9856       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9857       pr "\n";
9858
9859       (match fst style with
9860        | RErr ->
9861            pr "  return Qnil;\n"
9862        | RInt _ | RBool _ ->
9863            pr "  return INT2NUM (r);\n"
9864        | RInt64 _ ->
9865            pr "  return ULL2NUM (r);\n"
9866        | RConstString _ ->
9867            pr "  return rb_str_new2 (r);\n";
9868        | RConstOptString _ ->
9869            pr "  if (r)\n";
9870            pr "    return rb_str_new2 (r);\n";
9871            pr "  else\n";
9872            pr "    return Qnil;\n";
9873        | RString _ ->
9874            pr "  VALUE rv = rb_str_new2 (r);\n";
9875            pr "  free (r);\n";
9876            pr "  return rv;\n";
9877        | RStringList _ ->
9878            pr "  int i, len = 0;\n";
9879            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9880            pr "  VALUE rv = rb_ary_new2 (len);\n";
9881            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9882            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9883            pr "    free (r[i]);\n";
9884            pr "  }\n";
9885            pr "  free (r);\n";
9886            pr "  return rv;\n"
9887        | RStruct (_, typ) ->
9888            let cols = cols_of_struct typ in
9889            generate_ruby_struct_code typ cols
9890        | RStructList (_, typ) ->
9891            let cols = cols_of_struct typ in
9892            generate_ruby_struct_list_code typ cols
9893        | RHashtable _ ->
9894            pr "  VALUE rv = rb_hash_new ();\n";
9895            pr "  int i;\n";
9896            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9897            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9898            pr "    free (r[i]);\n";
9899            pr "    free (r[i+1]);\n";
9900            pr "  }\n";
9901            pr "  free (r);\n";
9902            pr "  return rv;\n"
9903        | RBufferOut _ ->
9904            pr "  VALUE rv = rb_str_new (r, size);\n";
9905            pr "  free (r);\n";
9906            pr "  return rv;\n";
9907       );
9908
9909       pr "}\n";
9910       pr "\n"
9911   ) all_functions;
9912
9913   pr "\
9914 /* Initialize the module. */
9915 void Init__guestfs ()
9916 {
9917   m_guestfs = rb_define_module (\"Guestfs\");
9918   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9919   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9920
9921   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9922   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9923
9924 ";
9925   (* Define the rest of the methods. *)
9926   List.iter (
9927     fun (name, style, _, _, _, _, _) ->
9928       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9929       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9930   ) all_functions;
9931
9932   pr "}\n"
9933
9934 (* Ruby code to return a struct. *)
9935 and generate_ruby_struct_code typ cols =
9936   pr "  VALUE rv = rb_hash_new ();\n";
9937   List.iter (
9938     function
9939     | name, FString ->
9940         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9941     | name, FBuffer ->
9942         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9943     | name, FUUID ->
9944         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9945     | name, (FBytes|FUInt64) ->
9946         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9947     | name, FInt64 ->
9948         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9949     | name, FUInt32 ->
9950         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9951     | name, FInt32 ->
9952         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9953     | name, FOptPercent ->
9954         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9955     | name, FChar -> (* XXX wrong? *)
9956         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9957   ) cols;
9958   pr "  guestfs_free_%s (r);\n" typ;
9959   pr "  return rv;\n"
9960
9961 (* Ruby code to return a struct list. *)
9962 and generate_ruby_struct_list_code typ cols =
9963   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9964   pr "  int i;\n";
9965   pr "  for (i = 0; i < r->len; ++i) {\n";
9966   pr "    VALUE hv = rb_hash_new ();\n";
9967   List.iter (
9968     function
9969     | name, FString ->
9970         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9971     | name, FBuffer ->
9972         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
9973     | name, FUUID ->
9974         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9975     | name, (FBytes|FUInt64) ->
9976         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9977     | name, FInt64 ->
9978         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9979     | name, FUInt32 ->
9980         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9981     | name, FInt32 ->
9982         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9983     | name, FOptPercent ->
9984         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9985     | name, FChar -> (* XXX wrong? *)
9986         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9987   ) cols;
9988   pr "    rb_ary_push (rv, hv);\n";
9989   pr "  }\n";
9990   pr "  guestfs_free_%s_list (r);\n" typ;
9991   pr "  return rv;\n"
9992
9993 (* Generate Java bindings GuestFS.java file. *)
9994 and generate_java_java () =
9995   generate_header CStyle LGPLv2plus;
9996
9997   pr "\
9998 package com.redhat.et.libguestfs;
9999
10000 import java.util.HashMap;
10001 import com.redhat.et.libguestfs.LibGuestFSException;
10002 import com.redhat.et.libguestfs.PV;
10003 import com.redhat.et.libguestfs.VG;
10004 import com.redhat.et.libguestfs.LV;
10005 import com.redhat.et.libguestfs.Stat;
10006 import com.redhat.et.libguestfs.StatVFS;
10007 import com.redhat.et.libguestfs.IntBool;
10008 import com.redhat.et.libguestfs.Dirent;
10009
10010 /**
10011  * The GuestFS object is a libguestfs handle.
10012  *
10013  * @author rjones
10014  */
10015 public class GuestFS {
10016   // Load the native code.
10017   static {
10018     System.loadLibrary (\"guestfs_jni\");
10019   }
10020
10021   /**
10022    * The native guestfs_h pointer.
10023    */
10024   long g;
10025
10026   /**
10027    * Create a libguestfs handle.
10028    *
10029    * @throws LibGuestFSException
10030    */
10031   public GuestFS () throws LibGuestFSException
10032   {
10033     g = _create ();
10034   }
10035   private native long _create () throws LibGuestFSException;
10036
10037   /**
10038    * Close a libguestfs handle.
10039    *
10040    * You can also leave handles to be collected by the garbage
10041    * collector, but this method ensures that the resources used
10042    * by the handle are freed up immediately.  If you call any
10043    * other methods after closing the handle, you will get an
10044    * exception.
10045    *
10046    * @throws LibGuestFSException
10047    */
10048   public void close () throws LibGuestFSException
10049   {
10050     if (g != 0)
10051       _close (g);
10052     g = 0;
10053   }
10054   private native void _close (long g) throws LibGuestFSException;
10055
10056   public void finalize () throws LibGuestFSException
10057   {
10058     close ();
10059   }
10060
10061 ";
10062
10063   List.iter (
10064     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10065       if not (List.mem NotInDocs flags); then (
10066         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10067         let doc =
10068           if List.mem ProtocolLimitWarning flags then
10069             doc ^ "\n\n" ^ protocol_limit_warning
10070           else doc in
10071         let doc =
10072           if List.mem DangerWillRobinson flags then
10073             doc ^ "\n\n" ^ danger_will_robinson
10074           else doc in
10075         let doc =
10076           match deprecation_notice flags with
10077           | None -> doc
10078           | Some txt -> doc ^ "\n\n" ^ txt in
10079         let doc = pod2text ~width:60 name doc in
10080         let doc = List.map (            (* RHBZ#501883 *)
10081           function
10082           | "" -> "<p>"
10083           | nonempty -> nonempty
10084         ) doc in
10085         let doc = String.concat "\n   * " doc in
10086
10087         pr "  /**\n";
10088         pr "   * %s\n" shortdesc;
10089         pr "   * <p>\n";
10090         pr "   * %s\n" doc;
10091         pr "   * @throws LibGuestFSException\n";
10092         pr "   */\n";
10093         pr "  ";
10094       );
10095       generate_java_prototype ~public:true ~semicolon:false name style;
10096       pr "\n";
10097       pr "  {\n";
10098       pr "    if (g == 0)\n";
10099       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10100         name;
10101       pr "    ";
10102       if fst style <> RErr then pr "return ";
10103       pr "_%s " name;
10104       generate_java_call_args ~handle:"g" (snd style);
10105       pr ";\n";
10106       pr "  }\n";
10107       pr "  ";
10108       generate_java_prototype ~privat:true ~native:true name style;
10109       pr "\n";
10110       pr "\n";
10111   ) all_functions;
10112
10113   pr "}\n"
10114
10115 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10116 and generate_java_call_args ~handle args =
10117   pr "(%s" handle;
10118   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10119   pr ")"
10120
10121 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10122     ?(semicolon=true) name style =
10123   if privat then pr "private ";
10124   if public then pr "public ";
10125   if native then pr "native ";
10126
10127   (* return type *)
10128   (match fst style with
10129    | RErr -> pr "void ";
10130    | RInt _ -> pr "int ";
10131    | RInt64 _ -> pr "long ";
10132    | RBool _ -> pr "boolean ";
10133    | RConstString _ | RConstOptString _ | RString _
10134    | RBufferOut _ -> pr "String ";
10135    | RStringList _ -> pr "String[] ";
10136    | RStruct (_, typ) ->
10137        let name = java_name_of_struct typ in
10138        pr "%s " name;
10139    | RStructList (_, typ) ->
10140        let name = java_name_of_struct typ in
10141        pr "%s[] " name;
10142    | RHashtable _ -> pr "HashMap<String,String> ";
10143   );
10144
10145   if native then pr "_%s " name else pr "%s " name;
10146   pr "(";
10147   let needs_comma = ref false in
10148   if native then (
10149     pr "long g";
10150     needs_comma := true
10151   );
10152
10153   (* args *)
10154   List.iter (
10155     fun arg ->
10156       if !needs_comma then pr ", ";
10157       needs_comma := true;
10158
10159       match arg with
10160       | Pathname n
10161       | Device n | Dev_or_Path n
10162       | String n
10163       | OptString n
10164       | FileIn n
10165       | FileOut n ->
10166           pr "String %s" n
10167       | BufferIn n ->
10168           pr "byte[] %s" n
10169       | StringList n | DeviceList n ->
10170           pr "String[] %s" n
10171       | Bool n ->
10172           pr "boolean %s" n
10173       | Int n ->
10174           pr "int %s" n
10175       | Int64 n ->
10176           pr "long %s" n
10177   ) (snd style);
10178
10179   pr ")\n";
10180   pr "    throws LibGuestFSException";
10181   if semicolon then pr ";"
10182
10183 and generate_java_struct jtyp cols () =
10184   generate_header CStyle LGPLv2plus;
10185
10186   pr "\
10187 package com.redhat.et.libguestfs;
10188
10189 /**
10190  * Libguestfs %s structure.
10191  *
10192  * @author rjones
10193  * @see GuestFS
10194  */
10195 public class %s {
10196 " jtyp jtyp;
10197
10198   List.iter (
10199     function
10200     | name, FString
10201     | name, FUUID
10202     | name, FBuffer -> pr "  public String %s;\n" name
10203     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10204     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10205     | name, FChar -> pr "  public char %s;\n" name
10206     | name, FOptPercent ->
10207         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10208         pr "  public float %s;\n" name
10209   ) cols;
10210
10211   pr "}\n"
10212
10213 and generate_java_c () =
10214   generate_header CStyle LGPLv2plus;
10215
10216   pr "\
10217 #include <stdio.h>
10218 #include <stdlib.h>
10219 #include <string.h>
10220
10221 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10222 #include \"guestfs.h\"
10223
10224 /* Note that this function returns.  The exception is not thrown
10225  * until after the wrapper function returns.
10226  */
10227 static void
10228 throw_exception (JNIEnv *env, const char *msg)
10229 {
10230   jclass cl;
10231   cl = (*env)->FindClass (env,
10232                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10233   (*env)->ThrowNew (env, cl, msg);
10234 }
10235
10236 JNIEXPORT jlong JNICALL
10237 Java_com_redhat_et_libguestfs_GuestFS__1create
10238   (JNIEnv *env, jobject obj)
10239 {
10240   guestfs_h *g;
10241
10242   g = guestfs_create ();
10243   if (g == NULL) {
10244     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10245     return 0;
10246   }
10247   guestfs_set_error_handler (g, NULL, NULL);
10248   return (jlong) (long) g;
10249 }
10250
10251 JNIEXPORT void JNICALL
10252 Java_com_redhat_et_libguestfs_GuestFS__1close
10253   (JNIEnv *env, jobject obj, jlong jg)
10254 {
10255   guestfs_h *g = (guestfs_h *) (long) jg;
10256   guestfs_close (g);
10257 }
10258
10259 ";
10260
10261   List.iter (
10262     fun (name, style, _, _, _, _, _) ->
10263       pr "JNIEXPORT ";
10264       (match fst style with
10265        | RErr -> pr "void ";
10266        | RInt _ -> pr "jint ";
10267        | RInt64 _ -> pr "jlong ";
10268        | RBool _ -> pr "jboolean ";
10269        | RConstString _ | RConstOptString _ | RString _
10270        | RBufferOut _ -> pr "jstring ";
10271        | RStruct _ | RHashtable _ ->
10272            pr "jobject ";
10273        | RStringList _ | RStructList _ ->
10274            pr "jobjectArray ";
10275       );
10276       pr "JNICALL\n";
10277       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10278       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10279       pr "\n";
10280       pr "  (JNIEnv *env, jobject obj, jlong jg";
10281       List.iter (
10282         function
10283         | Pathname n
10284         | Device n | Dev_or_Path n
10285         | String n
10286         | OptString n
10287         | FileIn n
10288         | FileOut n ->
10289             pr ", jstring j%s" n
10290         | BufferIn n ->
10291             pr ", jbyteArray j%s" n
10292         | StringList n | DeviceList n ->
10293             pr ", jobjectArray j%s" n
10294         | Bool n ->
10295             pr ", jboolean j%s" n
10296         | Int n ->
10297             pr ", jint j%s" n
10298         | Int64 n ->
10299             pr ", jlong j%s" n
10300       ) (snd style);
10301       pr ")\n";
10302       pr "{\n";
10303       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10304       let error_code, no_ret =
10305         match fst style with
10306         | RErr -> pr "  int r;\n"; "-1", ""
10307         | RBool _
10308         | RInt _ -> pr "  int r;\n"; "-1", "0"
10309         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10310         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10311         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10312         | RString _ ->
10313             pr "  jstring jr;\n";
10314             pr "  char *r;\n"; "NULL", "NULL"
10315         | RStringList _ ->
10316             pr "  jobjectArray jr;\n";
10317             pr "  int r_len;\n";
10318             pr "  jclass cl;\n";
10319             pr "  jstring jstr;\n";
10320             pr "  char **r;\n"; "NULL", "NULL"
10321         | RStruct (_, typ) ->
10322             pr "  jobject jr;\n";
10323             pr "  jclass cl;\n";
10324             pr "  jfieldID fl;\n";
10325             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10326         | RStructList (_, typ) ->
10327             pr "  jobjectArray jr;\n";
10328             pr "  jclass cl;\n";
10329             pr "  jfieldID fl;\n";
10330             pr "  jobject jfl;\n";
10331             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10332         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10333         | RBufferOut _ ->
10334             pr "  jstring jr;\n";
10335             pr "  char *r;\n";
10336             pr "  size_t size;\n";
10337             "NULL", "NULL" in
10338       List.iter (
10339         function
10340         | Pathname n
10341         | Device n | Dev_or_Path n
10342         | String n
10343         | OptString n
10344         | FileIn n
10345         | FileOut n ->
10346             pr "  const char *%s;\n" n
10347         | BufferIn n ->
10348             pr "  jbyte *%s;\n" n;
10349             pr "  size_t %s_size;\n" n
10350         | StringList n | DeviceList n ->
10351             pr "  int %s_len;\n" n;
10352             pr "  const char **%s;\n" n
10353         | Bool n
10354         | Int n ->
10355             pr "  int %s;\n" n
10356         | Int64 n ->
10357             pr "  int64_t %s;\n" n
10358       ) (snd style);
10359
10360       let needs_i =
10361         (match fst style with
10362          | RStringList _ | RStructList _ -> true
10363          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10364          | RConstOptString _
10365          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10366           List.exists (function
10367                        | StringList _ -> true
10368                        | DeviceList _ -> true
10369                        | _ -> false) (snd style) in
10370       if needs_i then
10371         pr "  int i;\n";
10372
10373       pr "\n";
10374
10375       (* Get the parameters. *)
10376       List.iter (
10377         function
10378         | Pathname n
10379         | Device n | Dev_or_Path n
10380         | String n
10381         | FileIn n
10382         | FileOut n ->
10383             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10384         | OptString n ->
10385             (* This is completely undocumented, but Java null becomes
10386              * a NULL parameter.
10387              *)
10388             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10389         | BufferIn n ->
10390             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10391             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10392         | StringList n | DeviceList n ->
10393             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10394             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10395             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10396             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10397               n;
10398             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10399             pr "  }\n";
10400             pr "  %s[%s_len] = NULL;\n" n n;
10401         | Bool n
10402         | Int n
10403         | Int64 n ->
10404             pr "  %s = j%s;\n" n n
10405       ) (snd style);
10406
10407       (* Make the call. *)
10408       pr "  r = guestfs_%s " name;
10409       generate_c_call_args ~handle:"g" style;
10410       pr ";\n";
10411
10412       (* Release the parameters. *)
10413       List.iter (
10414         function
10415         | Pathname n
10416         | Device n | Dev_or_Path n
10417         | String n
10418         | FileIn n
10419         | FileOut n ->
10420             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10421         | OptString n ->
10422             pr "  if (j%s)\n" n;
10423             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10424         | BufferIn n ->
10425             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10426         | StringList n | DeviceList n ->
10427             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10428             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10429               n;
10430             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10431             pr "  }\n";
10432             pr "  free (%s);\n" n
10433         | Bool n
10434         | Int n
10435         | Int64 n -> ()
10436       ) (snd style);
10437
10438       (* Check for errors. *)
10439       pr "  if (r == %s) {\n" error_code;
10440       pr "    throw_exception (env, guestfs_last_error (g));\n";
10441       pr "    return %s;\n" no_ret;
10442       pr "  }\n";
10443
10444       (* Return value. *)
10445       (match fst style with
10446        | RErr -> ()
10447        | RInt _ -> pr "  return (jint) r;\n"
10448        | RBool _ -> pr "  return (jboolean) r;\n"
10449        | RInt64 _ -> pr "  return (jlong) r;\n"
10450        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10451        | RConstOptString _ ->
10452            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10453        | RString _ ->
10454            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10455            pr "  free (r);\n";
10456            pr "  return jr;\n"
10457        | RStringList _ ->
10458            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10459            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10460            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10461            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10462            pr "  for (i = 0; i < r_len; ++i) {\n";
10463            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10464            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10465            pr "    free (r[i]);\n";
10466            pr "  }\n";
10467            pr "  free (r);\n";
10468            pr "  return jr;\n"
10469        | RStruct (_, typ) ->
10470            let jtyp = java_name_of_struct typ in
10471            let cols = cols_of_struct typ in
10472            generate_java_struct_return typ jtyp cols
10473        | RStructList (_, typ) ->
10474            let jtyp = java_name_of_struct typ in
10475            let cols = cols_of_struct typ in
10476            generate_java_struct_list_return typ jtyp cols
10477        | RHashtable _ ->
10478            (* XXX *)
10479            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10480            pr "  return NULL;\n"
10481        | RBufferOut _ ->
10482            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10483            pr "  free (r);\n";
10484            pr "  return jr;\n"
10485       );
10486
10487       pr "}\n";
10488       pr "\n"
10489   ) all_functions
10490
10491 and generate_java_struct_return typ jtyp cols =
10492   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10493   pr "  jr = (*env)->AllocObject (env, cl);\n";
10494   List.iter (
10495     function
10496     | name, FString ->
10497         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10498         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10499     | name, FUUID ->
10500         pr "  {\n";
10501         pr "    char s[33];\n";
10502         pr "    memcpy (s, r->%s, 32);\n" name;
10503         pr "    s[32] = 0;\n";
10504         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10505         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10506         pr "  }\n";
10507     | name, FBuffer ->
10508         pr "  {\n";
10509         pr "    int len = r->%s_len;\n" name;
10510         pr "    char s[len+1];\n";
10511         pr "    memcpy (s, r->%s, len);\n" name;
10512         pr "    s[len] = 0;\n";
10513         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10514         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10515         pr "  }\n";
10516     | name, (FBytes|FUInt64|FInt64) ->
10517         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10518         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10519     | name, (FUInt32|FInt32) ->
10520         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10521         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10522     | name, FOptPercent ->
10523         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10524         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10525     | name, FChar ->
10526         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10527         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10528   ) cols;
10529   pr "  free (r);\n";
10530   pr "  return jr;\n"
10531
10532 and generate_java_struct_list_return typ jtyp cols =
10533   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10534   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10535   pr "  for (i = 0; i < r->len; ++i) {\n";
10536   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10537   List.iter (
10538     function
10539     | name, FString ->
10540         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10541         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10542     | name, FUUID ->
10543         pr "    {\n";
10544         pr "      char s[33];\n";
10545         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10546         pr "      s[32] = 0;\n";
10547         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10548         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10549         pr "    }\n";
10550     | name, FBuffer ->
10551         pr "    {\n";
10552         pr "      int len = r->val[i].%s_len;\n" name;
10553         pr "      char s[len+1];\n";
10554         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10555         pr "      s[len] = 0;\n";
10556         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10557         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10558         pr "    }\n";
10559     | name, (FBytes|FUInt64|FInt64) ->
10560         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10561         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10562     | name, (FUInt32|FInt32) ->
10563         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10564         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10565     | name, FOptPercent ->
10566         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10567         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10568     | name, FChar ->
10569         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10570         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10571   ) cols;
10572   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10573   pr "  }\n";
10574   pr "  guestfs_free_%s_list (r);\n" typ;
10575   pr "  return jr;\n"
10576
10577 and generate_java_makefile_inc () =
10578   generate_header HashStyle GPLv2plus;
10579
10580   pr "java_built_sources = \\\n";
10581   List.iter (
10582     fun (typ, jtyp) ->
10583         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10584   ) java_structs;
10585   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10586
10587 and generate_haskell_hs () =
10588   generate_header HaskellStyle LGPLv2plus;
10589
10590   (* XXX We only know how to generate partial FFI for Haskell
10591    * at the moment.  Please help out!
10592    *)
10593   let can_generate style =
10594     match style with
10595     | RErr, _
10596     | RInt _, _
10597     | RInt64 _, _ -> true
10598     | RBool _, _
10599     | RConstString _, _
10600     | RConstOptString _, _
10601     | RString _, _
10602     | RStringList _, _
10603     | RStruct _, _
10604     | RStructList _, _
10605     | RHashtable _, _
10606     | RBufferOut _, _ -> false in
10607
10608   pr "\
10609 {-# INCLUDE <guestfs.h> #-}
10610 {-# LANGUAGE ForeignFunctionInterface #-}
10611
10612 module Guestfs (
10613   create";
10614
10615   (* List out the names of the actions we want to export. *)
10616   List.iter (
10617     fun (name, style, _, _, _, _, _) ->
10618       if can_generate style then pr ",\n  %s" name
10619   ) all_functions;
10620
10621   pr "
10622   ) where
10623
10624 -- Unfortunately some symbols duplicate ones already present
10625 -- in Prelude.  We don't know which, so we hard-code a list
10626 -- here.
10627 import Prelude hiding (truncate)
10628
10629 import Foreign
10630 import Foreign.C
10631 import Foreign.C.Types
10632 import IO
10633 import Control.Exception
10634 import Data.Typeable
10635
10636 data GuestfsS = GuestfsS            -- represents the opaque C struct
10637 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10638 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10639
10640 -- XXX define properly later XXX
10641 data PV = PV
10642 data VG = VG
10643 data LV = LV
10644 data IntBool = IntBool
10645 data Stat = Stat
10646 data StatVFS = StatVFS
10647 data Hashtable = Hashtable
10648
10649 foreign import ccall unsafe \"guestfs_create\" c_create
10650   :: IO GuestfsP
10651 foreign import ccall unsafe \"&guestfs_close\" c_close
10652   :: FunPtr (GuestfsP -> IO ())
10653 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10654   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10655
10656 create :: IO GuestfsH
10657 create = do
10658   p <- c_create
10659   c_set_error_handler p nullPtr nullPtr
10660   h <- newForeignPtr c_close p
10661   return h
10662
10663 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10664   :: GuestfsP -> IO CString
10665
10666 -- last_error :: GuestfsH -> IO (Maybe String)
10667 -- last_error h = do
10668 --   str <- withForeignPtr h (\\p -> c_last_error p)
10669 --   maybePeek peekCString str
10670
10671 last_error :: GuestfsH -> IO (String)
10672 last_error h = do
10673   str <- withForeignPtr h (\\p -> c_last_error p)
10674   if (str == nullPtr)
10675     then return \"no error\"
10676     else peekCString str
10677
10678 ";
10679
10680   (* Generate wrappers for each foreign function. *)
10681   List.iter (
10682     fun (name, style, _, _, _, _, _) ->
10683       if can_generate style then (
10684         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10685         pr "  :: ";
10686         generate_haskell_prototype ~handle:"GuestfsP" style;
10687         pr "\n";
10688         pr "\n";
10689         pr "%s :: " name;
10690         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10691         pr "\n";
10692         pr "%s %s = do\n" name
10693           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10694         pr "  r <- ";
10695         (* Convert pointer arguments using with* functions. *)
10696         List.iter (
10697           function
10698           | FileIn n
10699           | FileOut n
10700           | Pathname n | Device n | Dev_or_Path n | String n ->
10701               pr "withCString %s $ \\%s -> " n n
10702           | BufferIn n ->
10703               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10704           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10705           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10706           | Bool _ | Int _ | Int64 _ -> ()
10707         ) (snd style);
10708         (* Convert integer arguments. *)
10709         let args =
10710           List.map (
10711             function
10712             | Bool n -> sprintf "(fromBool %s)" n
10713             | Int n -> sprintf "(fromIntegral %s)" n
10714             | Int64 n -> sprintf "(fromIntegral %s)" n
10715             | FileIn n | FileOut n
10716             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10717             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10718           ) (snd style) in
10719         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10720           (String.concat " " ("p" :: args));
10721         (match fst style with
10722          | RErr | RInt _ | RInt64 _ | RBool _ ->
10723              pr "  if (r == -1)\n";
10724              pr "    then do\n";
10725              pr "      err <- last_error h\n";
10726              pr "      fail err\n";
10727          | RConstString _ | RConstOptString _ | RString _
10728          | RStringList _ | RStruct _
10729          | RStructList _ | RHashtable _ | RBufferOut _ ->
10730              pr "  if (r == nullPtr)\n";
10731              pr "    then do\n";
10732              pr "      err <- last_error h\n";
10733              pr "      fail err\n";
10734         );
10735         (match fst style with
10736          | RErr ->
10737              pr "    else return ()\n"
10738          | RInt _ ->
10739              pr "    else return (fromIntegral r)\n"
10740          | RInt64 _ ->
10741              pr "    else return (fromIntegral r)\n"
10742          | RBool _ ->
10743              pr "    else return (toBool r)\n"
10744          | RConstString _
10745          | RConstOptString _
10746          | RString _
10747          | RStringList _
10748          | RStruct _
10749          | RStructList _
10750          | RHashtable _
10751          | RBufferOut _ ->
10752              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10753         );
10754         pr "\n";
10755       )
10756   ) all_functions
10757
10758 and generate_haskell_prototype ~handle ?(hs = false) style =
10759   pr "%s -> " handle;
10760   let string = if hs then "String" else "CString" in
10761   let int = if hs then "Int" else "CInt" in
10762   let bool = if hs then "Bool" else "CInt" in
10763   let int64 = if hs then "Integer" else "Int64" in
10764   List.iter (
10765     fun arg ->
10766       (match arg with
10767        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10768        | BufferIn _ ->
10769            if hs then pr "String"
10770            else pr "CString -> CInt"
10771        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10772        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10773        | Bool _ -> pr "%s" bool
10774        | Int _ -> pr "%s" int
10775        | Int64 _ -> pr "%s" int
10776        | FileIn _ -> pr "%s" string
10777        | FileOut _ -> pr "%s" string
10778       );
10779       pr " -> ";
10780   ) (snd style);
10781   pr "IO (";
10782   (match fst style with
10783    | RErr -> if not hs then pr "CInt"
10784    | RInt _ -> pr "%s" int
10785    | RInt64 _ -> pr "%s" int64
10786    | RBool _ -> pr "%s" bool
10787    | RConstString _ -> pr "%s" string
10788    | RConstOptString _ -> pr "Maybe %s" string
10789    | RString _ -> pr "%s" string
10790    | RStringList _ -> pr "[%s]" string
10791    | RStruct (_, typ) ->
10792        let name = java_name_of_struct typ in
10793        pr "%s" name
10794    | RStructList (_, typ) ->
10795        let name = java_name_of_struct typ in
10796        pr "[%s]" name
10797    | RHashtable _ -> pr "Hashtable"
10798    | RBufferOut _ -> pr "%s" string
10799   );
10800   pr ")"
10801
10802 and generate_csharp () =
10803   generate_header CPlusPlusStyle LGPLv2plus;
10804
10805   (* XXX Make this configurable by the C# assembly users. *)
10806   let library = "libguestfs.so.0" in
10807
10808   pr "\
10809 // These C# bindings are highly experimental at present.
10810 //
10811 // Firstly they only work on Linux (ie. Mono).  In order to get them
10812 // to work on Windows (ie. .Net) you would need to port the library
10813 // itself to Windows first.
10814 //
10815 // The second issue is that some calls are known to be incorrect and
10816 // can cause Mono to segfault.  Particularly: calls which pass or
10817 // return string[], or return any structure value.  This is because
10818 // we haven't worked out the correct way to do this from C#.
10819 //
10820 // The third issue is that when compiling you get a lot of warnings.
10821 // We are not sure whether the warnings are important or not.
10822 //
10823 // Fourthly we do not routinely build or test these bindings as part
10824 // of the make && make check cycle, which means that regressions might
10825 // go unnoticed.
10826 //
10827 // Suggestions and patches are welcome.
10828
10829 // To compile:
10830 //
10831 // gmcs Libguestfs.cs
10832 // mono Libguestfs.exe
10833 //
10834 // (You'll probably want to add a Test class / static main function
10835 // otherwise this won't do anything useful).
10836
10837 using System;
10838 using System.IO;
10839 using System.Runtime.InteropServices;
10840 using System.Runtime.Serialization;
10841 using System.Collections;
10842
10843 namespace Guestfs
10844 {
10845   class Error : System.ApplicationException
10846   {
10847     public Error (string message) : base (message) {}
10848     protected Error (SerializationInfo info, StreamingContext context) {}
10849   }
10850
10851   class Guestfs
10852   {
10853     IntPtr _handle;
10854
10855     [DllImport (\"%s\")]
10856     static extern IntPtr guestfs_create ();
10857
10858     public Guestfs ()
10859     {
10860       _handle = guestfs_create ();
10861       if (_handle == IntPtr.Zero)
10862         throw new Error (\"could not create guestfs handle\");
10863     }
10864
10865     [DllImport (\"%s\")]
10866     static extern void guestfs_close (IntPtr h);
10867
10868     ~Guestfs ()
10869     {
10870       guestfs_close (_handle);
10871     }
10872
10873     [DllImport (\"%s\")]
10874     static extern string guestfs_last_error (IntPtr h);
10875
10876 " library library library;
10877
10878   (* Generate C# structure bindings.  We prefix struct names with
10879    * underscore because C# cannot have conflicting struct names and
10880    * method names (eg. "class stat" and "stat").
10881    *)
10882   List.iter (
10883     fun (typ, cols) ->
10884       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10885       pr "    public class _%s {\n" typ;
10886       List.iter (
10887         function
10888         | name, FChar -> pr "      char %s;\n" name
10889         | name, FString -> pr "      string %s;\n" name
10890         | name, FBuffer ->
10891             pr "      uint %s_len;\n" name;
10892             pr "      string %s;\n" name
10893         | name, FUUID ->
10894             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10895             pr "      string %s;\n" name
10896         | name, FUInt32 -> pr "      uint %s;\n" name
10897         | name, FInt32 -> pr "      int %s;\n" name
10898         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10899         | name, FInt64 -> pr "      long %s;\n" name
10900         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10901       ) cols;
10902       pr "    }\n";
10903       pr "\n"
10904   ) structs;
10905
10906   (* Generate C# function bindings. *)
10907   List.iter (
10908     fun (name, style, _, _, _, shortdesc, _) ->
10909       let rec csharp_return_type () =
10910         match fst style with
10911         | RErr -> "void"
10912         | RBool n -> "bool"
10913         | RInt n -> "int"
10914         | RInt64 n -> "long"
10915         | RConstString n
10916         | RConstOptString n
10917         | RString n
10918         | RBufferOut n -> "string"
10919         | RStruct (_,n) -> "_" ^ n
10920         | RHashtable n -> "Hashtable"
10921         | RStringList n -> "string[]"
10922         | RStructList (_,n) -> sprintf "_%s[]" n
10923
10924       and c_return_type () =
10925         match fst style with
10926         | RErr
10927         | RBool _
10928         | RInt _ -> "int"
10929         | RInt64 _ -> "long"
10930         | RConstString _
10931         | RConstOptString _
10932         | RString _
10933         | RBufferOut _ -> "string"
10934         | RStruct (_,n) -> "_" ^ n
10935         | RHashtable _
10936         | RStringList _ -> "string[]"
10937         | RStructList (_,n) -> sprintf "_%s[]" n
10938
10939       and c_error_comparison () =
10940         match fst style with
10941         | RErr
10942         | RBool _
10943         | RInt _
10944         | RInt64 _ -> "== -1"
10945         | RConstString _
10946         | RConstOptString _
10947         | RString _
10948         | RBufferOut _
10949         | RStruct (_,_)
10950         | RHashtable _
10951         | RStringList _
10952         | RStructList (_,_) -> "== null"
10953
10954       and generate_extern_prototype () =
10955         pr "    static extern %s guestfs_%s (IntPtr h"
10956           (c_return_type ()) name;
10957         List.iter (
10958           function
10959           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10960           | FileIn n | FileOut n
10961           | BufferIn n ->
10962               pr ", [In] string %s" n
10963           | StringList n | DeviceList n ->
10964               pr ", [In] string[] %s" n
10965           | Bool n ->
10966               pr ", bool %s" n
10967           | Int n ->
10968               pr ", int %s" n
10969           | Int64 n ->
10970               pr ", long %s" n
10971         ) (snd style);
10972         pr ");\n"
10973
10974       and generate_public_prototype () =
10975         pr "    public %s %s (" (csharp_return_type ()) name;
10976         let comma = ref false in
10977         let next () =
10978           if !comma then pr ", ";
10979           comma := true
10980         in
10981         List.iter (
10982           function
10983           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10984           | FileIn n | FileOut n
10985           | BufferIn n ->
10986               next (); pr "string %s" n
10987           | StringList n | DeviceList n ->
10988               next (); pr "string[] %s" n
10989           | Bool n ->
10990               next (); pr "bool %s" n
10991           | Int n ->
10992               next (); pr "int %s" n
10993           | Int64 n ->
10994               next (); pr "long %s" n
10995         ) (snd style);
10996         pr ")\n"
10997
10998       and generate_call () =
10999         pr "guestfs_%s (_handle" name;
11000         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11001         pr ");\n";
11002       in
11003
11004       pr "    [DllImport (\"%s\")]\n" library;
11005       generate_extern_prototype ();
11006       pr "\n";
11007       pr "    /// <summary>\n";
11008       pr "    /// %s\n" shortdesc;
11009       pr "    /// </summary>\n";
11010       generate_public_prototype ();
11011       pr "    {\n";
11012       pr "      %s r;\n" (c_return_type ());
11013       pr "      r = ";
11014       generate_call ();
11015       pr "      if (r %s)\n" (c_error_comparison ());
11016       pr "        throw new Error (guestfs_last_error (_handle));\n";
11017       (match fst style with
11018        | RErr -> ()
11019        | RBool _ ->
11020            pr "      return r != 0 ? true : false;\n"
11021        | RHashtable _ ->
11022            pr "      Hashtable rr = new Hashtable ();\n";
11023            pr "      for (int i = 0; i < r.Length; i += 2)\n";
11024            pr "        rr.Add (r[i], r[i+1]);\n";
11025            pr "      return rr;\n"
11026        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11027        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11028        | RStructList _ ->
11029            pr "      return r;\n"
11030       );
11031       pr "    }\n";
11032       pr "\n";
11033   ) all_functions_sorted;
11034
11035   pr "  }
11036 }
11037 "
11038
11039 and generate_bindtests () =
11040   generate_header CStyle LGPLv2plus;
11041
11042   pr "\
11043 #include <stdio.h>
11044 #include <stdlib.h>
11045 #include <inttypes.h>
11046 #include <string.h>
11047
11048 #include \"guestfs.h\"
11049 #include \"guestfs-internal.h\"
11050 #include \"guestfs-internal-actions.h\"
11051 #include \"guestfs_protocol.h\"
11052
11053 #define error guestfs_error
11054 #define safe_calloc guestfs_safe_calloc
11055 #define safe_malloc guestfs_safe_malloc
11056
11057 static void
11058 print_strings (char *const *argv)
11059 {
11060   int argc;
11061
11062   printf (\"[\");
11063   for (argc = 0; argv[argc] != NULL; ++argc) {
11064     if (argc > 0) printf (\", \");
11065     printf (\"\\\"%%s\\\"\", argv[argc]);
11066   }
11067   printf (\"]\\n\");
11068 }
11069
11070 /* The test0 function prints its parameters to stdout. */
11071 ";
11072
11073   let test0, tests =
11074     match test_functions with
11075     | [] -> assert false
11076     | test0 :: tests -> test0, tests in
11077
11078   let () =
11079     let (name, style, _, _, _, _, _) = test0 in
11080     generate_prototype ~extern:false ~semicolon:false ~newline:true
11081       ~handle:"g" ~prefix:"guestfs__" name style;
11082     pr "{\n";
11083     List.iter (
11084       function
11085       | Pathname n
11086       | Device n | Dev_or_Path n
11087       | String n
11088       | FileIn n
11089       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11090       | BufferIn n ->
11091           pr "  {\n";
11092           pr "    size_t i;\n";
11093           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11094           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11095           pr "    printf (\"\\n\");\n";
11096           pr "  }\n";
11097       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11098       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11099       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11100       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11101       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11102     ) (snd style);
11103     pr "  /* Java changes stdout line buffering so we need this: */\n";
11104     pr "  fflush (stdout);\n";
11105     pr "  return 0;\n";
11106     pr "}\n";
11107     pr "\n" in
11108
11109   List.iter (
11110     fun (name, style, _, _, _, _, _) ->
11111       if String.sub name (String.length name - 3) 3 <> "err" then (
11112         pr "/* Test normal return. */\n";
11113         generate_prototype ~extern:false ~semicolon:false ~newline:true
11114           ~handle:"g" ~prefix:"guestfs__" name style;
11115         pr "{\n";
11116         (match fst style with
11117          | RErr ->
11118              pr "  return 0;\n"
11119          | RInt _ ->
11120              pr "  int r;\n";
11121              pr "  sscanf (val, \"%%d\", &r);\n";
11122              pr "  return r;\n"
11123          | RInt64 _ ->
11124              pr "  int64_t r;\n";
11125              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11126              pr "  return r;\n"
11127          | RBool _ ->
11128              pr "  return STREQ (val, \"true\");\n"
11129          | RConstString _
11130          | RConstOptString _ ->
11131              (* Can't return the input string here.  Return a static
11132               * string so we ensure we get a segfault if the caller
11133               * tries to free it.
11134               *)
11135              pr "  return \"static string\";\n"
11136          | RString _ ->
11137              pr "  return strdup (val);\n"
11138          | RStringList _ ->
11139              pr "  char **strs;\n";
11140              pr "  int n, i;\n";
11141              pr "  sscanf (val, \"%%d\", &n);\n";
11142              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11143              pr "  for (i = 0; i < n; ++i) {\n";
11144              pr "    strs[i] = safe_malloc (g, 16);\n";
11145              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11146              pr "  }\n";
11147              pr "  strs[n] = NULL;\n";
11148              pr "  return strs;\n"
11149          | RStruct (_, typ) ->
11150              pr "  struct guestfs_%s *r;\n" typ;
11151              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11152              pr "  return r;\n"
11153          | RStructList (_, typ) ->
11154              pr "  struct guestfs_%s_list *r;\n" typ;
11155              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11156              pr "  sscanf (val, \"%%d\", &r->len);\n";
11157              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11158              pr "  return r;\n"
11159          | RHashtable _ ->
11160              pr "  char **strs;\n";
11161              pr "  int n, i;\n";
11162              pr "  sscanf (val, \"%%d\", &n);\n";
11163              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11164              pr "  for (i = 0; i < n; ++i) {\n";
11165              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11166              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11167              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11168              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11169              pr "  }\n";
11170              pr "  strs[n*2] = NULL;\n";
11171              pr "  return strs;\n"
11172          | RBufferOut _ ->
11173              pr "  return strdup (val);\n"
11174         );
11175         pr "}\n";
11176         pr "\n"
11177       ) else (
11178         pr "/* Test error return. */\n";
11179         generate_prototype ~extern:false ~semicolon:false ~newline:true
11180           ~handle:"g" ~prefix:"guestfs__" name style;
11181         pr "{\n";
11182         pr "  error (g, \"error\");\n";
11183         (match fst style with
11184          | RErr | RInt _ | RInt64 _ | RBool _ ->
11185              pr "  return -1;\n"
11186          | RConstString _ | RConstOptString _
11187          | RString _ | RStringList _ | RStruct _
11188          | RStructList _
11189          | RHashtable _
11190          | RBufferOut _ ->
11191              pr "  return NULL;\n"
11192         );
11193         pr "}\n";
11194         pr "\n"
11195       )
11196   ) tests
11197
11198 and generate_ocaml_bindtests () =
11199   generate_header OCamlStyle GPLv2plus;
11200
11201   pr "\
11202 let () =
11203   let g = Guestfs.create () in
11204 ";
11205
11206   let mkargs args =
11207     String.concat " " (
11208       List.map (
11209         function
11210         | CallString s -> "\"" ^ s ^ "\""
11211         | CallOptString None -> "None"
11212         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11213         | CallStringList xs ->
11214             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11215         | CallInt i when i >= 0 -> string_of_int i
11216         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11217         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11218         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11219         | CallBool b -> string_of_bool b
11220         | CallBuffer s -> sprintf "%S" s
11221       ) args
11222     )
11223   in
11224
11225   generate_lang_bindtests (
11226     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11227   );
11228
11229   pr "print_endline \"EOF\"\n"
11230
11231 and generate_perl_bindtests () =
11232   pr "#!/usr/bin/perl -w\n";
11233   generate_header HashStyle GPLv2plus;
11234
11235   pr "\
11236 use strict;
11237
11238 use Sys::Guestfs;
11239
11240 my $g = Sys::Guestfs->new ();
11241 ";
11242
11243   let mkargs args =
11244     String.concat ", " (
11245       List.map (
11246         function
11247         | CallString s -> "\"" ^ s ^ "\""
11248         | CallOptString None -> "undef"
11249         | CallOptString (Some s) -> sprintf "\"%s\"" s
11250         | CallStringList xs ->
11251             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11252         | CallInt i -> string_of_int i
11253         | CallInt64 i -> Int64.to_string i
11254         | CallBool b -> if b then "1" else "0"
11255         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11256       ) args
11257     )
11258   in
11259
11260   generate_lang_bindtests (
11261     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11262   );
11263
11264   pr "print \"EOF\\n\"\n"
11265
11266 and generate_python_bindtests () =
11267   generate_header HashStyle GPLv2plus;
11268
11269   pr "\
11270 import guestfs
11271
11272 g = guestfs.GuestFS ()
11273 ";
11274
11275   let mkargs args =
11276     String.concat ", " (
11277       List.map (
11278         function
11279         | CallString s -> "\"" ^ s ^ "\""
11280         | CallOptString None -> "None"
11281         | CallOptString (Some s) -> sprintf "\"%s\"" s
11282         | CallStringList xs ->
11283             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11284         | CallInt i -> string_of_int i
11285         | CallInt64 i -> Int64.to_string i
11286         | CallBool b -> if b then "1" else "0"
11287         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11288       ) args
11289     )
11290   in
11291
11292   generate_lang_bindtests (
11293     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11294   );
11295
11296   pr "print \"EOF\"\n"
11297
11298 and generate_ruby_bindtests () =
11299   generate_header HashStyle GPLv2plus;
11300
11301   pr "\
11302 require 'guestfs'
11303
11304 g = Guestfs::create()
11305 ";
11306
11307   let mkargs args =
11308     String.concat ", " (
11309       List.map (
11310         function
11311         | CallString s -> "\"" ^ s ^ "\""
11312         | CallOptString None -> "nil"
11313         | CallOptString (Some s) -> sprintf "\"%s\"" s
11314         | CallStringList xs ->
11315             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11316         | CallInt i -> string_of_int i
11317         | CallInt64 i -> Int64.to_string i
11318         | CallBool b -> string_of_bool b
11319         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11320       ) args
11321     )
11322   in
11323
11324   generate_lang_bindtests (
11325     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11326   );
11327
11328   pr "print \"EOF\\n\"\n"
11329
11330 and generate_java_bindtests () =
11331   generate_header CStyle GPLv2plus;
11332
11333   pr "\
11334 import com.redhat.et.libguestfs.*;
11335
11336 public class Bindtests {
11337     public static void main (String[] argv)
11338     {
11339         try {
11340             GuestFS g = new GuestFS ();
11341 ";
11342
11343   let mkargs args =
11344     String.concat ", " (
11345       List.map (
11346         function
11347         | CallString s -> "\"" ^ s ^ "\""
11348         | CallOptString None -> "null"
11349         | CallOptString (Some s) -> sprintf "\"%s\"" s
11350         | CallStringList xs ->
11351             "new String[]{" ^
11352               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11353         | CallInt i -> string_of_int i
11354         | CallInt64 i -> Int64.to_string i
11355         | CallBool b -> string_of_bool b
11356         | CallBuffer s ->
11357             "new byte[] { " ^ String.concat "," (
11358               map_chars (fun c -> string_of_int (Char.code c)) s
11359             ) ^ " }"
11360       ) args
11361     )
11362   in
11363
11364   generate_lang_bindtests (
11365     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11366   );
11367
11368   pr "
11369             System.out.println (\"EOF\");
11370         }
11371         catch (Exception exn) {
11372             System.err.println (exn);
11373             System.exit (1);
11374         }
11375     }
11376 }
11377 "
11378
11379 and generate_haskell_bindtests () =
11380   generate_header HaskellStyle GPLv2plus;
11381
11382   pr "\
11383 module Bindtests where
11384 import qualified Guestfs
11385
11386 main = do
11387   g <- Guestfs.create
11388 ";
11389
11390   let mkargs args =
11391     String.concat " " (
11392       List.map (
11393         function
11394         | CallString s -> "\"" ^ s ^ "\""
11395         | CallOptString None -> "Nothing"
11396         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11397         | CallStringList xs ->
11398             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11399         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11400         | CallInt i -> string_of_int i
11401         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11402         | CallInt64 i -> Int64.to_string i
11403         | CallBool true -> "True"
11404         | CallBool false -> "False"
11405         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11406       ) args
11407     )
11408   in
11409
11410   generate_lang_bindtests (
11411     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11412   );
11413
11414   pr "  putStrLn \"EOF\"\n"
11415
11416 (* Language-independent bindings tests - we do it this way to
11417  * ensure there is parity in testing bindings across all languages.
11418  *)
11419 and generate_lang_bindtests call =
11420   call "test0" [CallString "abc"; CallOptString (Some "def");
11421                 CallStringList []; CallBool false;
11422                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11423                 CallBuffer "abc\000abc"];
11424   call "test0" [CallString "abc"; CallOptString None;
11425                 CallStringList []; CallBool false;
11426                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11427                 CallBuffer "abc\000abc"];
11428   call "test0" [CallString ""; CallOptString (Some "def");
11429                 CallStringList []; CallBool false;
11430                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11431                 CallBuffer "abc\000abc"];
11432   call "test0" [CallString ""; CallOptString (Some "");
11433                 CallStringList []; CallBool false;
11434                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11435                 CallBuffer "abc\000abc"];
11436   call "test0" [CallString "abc"; CallOptString (Some "def");
11437                 CallStringList ["1"]; CallBool false;
11438                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11439                 CallBuffer "abc\000abc"];
11440   call "test0" [CallString "abc"; CallOptString (Some "def");
11441                 CallStringList ["1"; "2"]; CallBool false;
11442                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11443                 CallBuffer "abc\000abc"];
11444   call "test0" [CallString "abc"; CallOptString (Some "def");
11445                 CallStringList ["1"]; CallBool true;
11446                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11447                 CallBuffer "abc\000abc"];
11448   call "test0" [CallString "abc"; CallOptString (Some "def");
11449                 CallStringList ["1"]; CallBool false;
11450                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11451                 CallBuffer "abc\000abc"];
11452   call "test0" [CallString "abc"; CallOptString (Some "def");
11453                 CallStringList ["1"]; CallBool false;
11454                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11455                 CallBuffer "abc\000abc"];
11456   call "test0" [CallString "abc"; CallOptString (Some "def");
11457                 CallStringList ["1"]; CallBool false;
11458                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11459                 CallBuffer "abc\000abc"];
11460   call "test0" [CallString "abc"; CallOptString (Some "def");
11461                 CallStringList ["1"]; CallBool false;
11462                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11463                 CallBuffer "abc\000abc"];
11464   call "test0" [CallString "abc"; CallOptString (Some "def");
11465                 CallStringList ["1"]; CallBool false;
11466                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11467                 CallBuffer "abc\000abc"];
11468   call "test0" [CallString "abc"; CallOptString (Some "def");
11469                 CallStringList ["1"]; CallBool false;
11470                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11471                 CallBuffer "abc\000abc"]
11472
11473 (* XXX Add here tests of the return and error functions. *)
11474
11475 (* Code to generator bindings for virt-inspector.  Currently only
11476  * implemented for OCaml code (for virt-p2v 2.0).
11477  *)
11478 let rng_input = "inspector/virt-inspector.rng"
11479
11480 (* Read the input file and parse it into internal structures.  This is
11481  * by no means a complete RELAX NG parser, but is just enough to be
11482  * able to parse the specific input file.
11483  *)
11484 type rng =
11485   | Element of string * rng list        (* <element name=name/> *)
11486   | Attribute of string * rng list        (* <attribute name=name/> *)
11487   | Interleave of rng list                (* <interleave/> *)
11488   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11489   | OneOrMore of rng                        (* <oneOrMore/> *)
11490   | Optional of rng                        (* <optional/> *)
11491   | Choice of string list                (* <choice><value/>*</choice> *)
11492   | Value of string                        (* <value>str</value> *)
11493   | Text                                (* <text/> *)
11494
11495 let rec string_of_rng = function
11496   | Element (name, xs) ->
11497       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11498   | Attribute (name, xs) ->
11499       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11500   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11501   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11502   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11503   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11504   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11505   | Value value -> "Value \"" ^ value ^ "\""
11506   | Text -> "Text"
11507
11508 and string_of_rng_list xs =
11509   String.concat ", " (List.map string_of_rng xs)
11510
11511 let rec parse_rng ?defines context = function
11512   | [] -> []
11513   | Xml.Element ("element", ["name", name], children) :: rest ->
11514       Element (name, parse_rng ?defines context children)
11515       :: parse_rng ?defines context rest
11516   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11517       Attribute (name, parse_rng ?defines context children)
11518       :: parse_rng ?defines context rest
11519   | Xml.Element ("interleave", [], children) :: rest ->
11520       Interleave (parse_rng ?defines context children)
11521       :: parse_rng ?defines context rest
11522   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11523       let rng = parse_rng ?defines context [child] in
11524       (match rng with
11525        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11526        | _ ->
11527            failwithf "%s: <zeroOrMore> contains more than one child element"
11528              context
11529       )
11530   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11531       let rng = parse_rng ?defines context [child] in
11532       (match rng with
11533        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11534        | _ ->
11535            failwithf "%s: <oneOrMore> contains more than one child element"
11536              context
11537       )
11538   | Xml.Element ("optional", [], [child]) :: rest ->
11539       let rng = parse_rng ?defines context [child] in
11540       (match rng with
11541        | [child] -> Optional child :: parse_rng ?defines context rest
11542        | _ ->
11543            failwithf "%s: <optional> contains more than one child element"
11544              context
11545       )
11546   | Xml.Element ("choice", [], children) :: rest ->
11547       let values = List.map (
11548         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11549         | _ ->
11550             failwithf "%s: can't handle anything except <value> in <choice>"
11551               context
11552       ) children in
11553       Choice values
11554       :: parse_rng ?defines context rest
11555   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11556       Value value :: parse_rng ?defines context rest
11557   | Xml.Element ("text", [], []) :: rest ->
11558       Text :: parse_rng ?defines context rest
11559   | Xml.Element ("ref", ["name", name], []) :: rest ->
11560       (* Look up the reference.  Because of limitations in this parser,
11561        * we can't handle arbitrarily nested <ref> yet.  You can only
11562        * use <ref> from inside <start>.
11563        *)
11564       (match defines with
11565        | None ->
11566            failwithf "%s: contains <ref>, but no refs are defined yet" context
11567        | Some map ->
11568            let rng = StringMap.find name map in
11569            rng @ parse_rng ?defines context rest
11570       )
11571   | x :: _ ->
11572       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11573
11574 let grammar =
11575   let xml = Xml.parse_file rng_input in
11576   match xml with
11577   | Xml.Element ("grammar", _,
11578                  Xml.Element ("start", _, gram) :: defines) ->
11579       (* The <define/> elements are referenced in the <start> section,
11580        * so build a map of those first.
11581        *)
11582       let defines = List.fold_left (
11583         fun map ->
11584           function Xml.Element ("define", ["name", name], defn) ->
11585             StringMap.add name defn map
11586           | _ ->
11587               failwithf "%s: expected <define name=name/>" rng_input
11588       ) StringMap.empty defines in
11589       let defines = StringMap.mapi parse_rng defines in
11590
11591       (* Parse the <start> clause, passing the defines. *)
11592       parse_rng ~defines "<start>" gram
11593   | _ ->
11594       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11595         rng_input
11596
11597 let name_of_field = function
11598   | Element (name, _) | Attribute (name, _)
11599   | ZeroOrMore (Element (name, _))
11600   | OneOrMore (Element (name, _))
11601   | Optional (Element (name, _)) -> name
11602   | Optional (Attribute (name, _)) -> name
11603   | Text -> (* an unnamed field in an element *)
11604       "data"
11605   | rng ->
11606       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11607
11608 (* At the moment this function only generates OCaml types.  However we
11609  * should parameterize it later so it can generate types/structs in a
11610  * variety of languages.
11611  *)
11612 let generate_types xs =
11613   (* A simple type is one that can be printed out directly, eg.
11614    * "string option".  A complex type is one which has a name and has
11615    * to be defined via another toplevel definition, eg. a struct.
11616    *
11617    * generate_type generates code for either simple or complex types.
11618    * In the simple case, it returns the string ("string option").  In
11619    * the complex case, it returns the name ("mountpoint").  In the
11620    * complex case it has to print out the definition before returning,
11621    * so it should only be called when we are at the beginning of a
11622    * new line (BOL context).
11623    *)
11624   let rec generate_type = function
11625     | Text ->                                (* string *)
11626         "string", true
11627     | Choice values ->                        (* [`val1|`val2|...] *)
11628         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11629     | ZeroOrMore rng ->                        (* <rng> list *)
11630         let t, is_simple = generate_type rng in
11631         t ^ " list (* 0 or more *)", is_simple
11632     | OneOrMore rng ->                        (* <rng> list *)
11633         let t, is_simple = generate_type rng in
11634         t ^ " list (* 1 or more *)", is_simple
11635                                         (* virt-inspector hack: bool *)
11636     | Optional (Attribute (name, [Value "1"])) ->
11637         "bool", true
11638     | Optional rng ->                        (* <rng> list *)
11639         let t, is_simple = generate_type rng in
11640         t ^ " option", is_simple
11641                                         (* type name = { fields ... } *)
11642     | Element (name, fields) when is_attrs_interleave fields ->
11643         generate_type_struct name (get_attrs_interleave fields)
11644     | Element (name, [field])                (* type name = field *)
11645     | Attribute (name, [field]) ->
11646         let t, is_simple = generate_type field in
11647         if is_simple then (t, true)
11648         else (
11649           pr "type %s = %s\n" name t;
11650           name, false
11651         )
11652     | Element (name, fields) ->              (* type name = { fields ... } *)
11653         generate_type_struct name fields
11654     | rng ->
11655         failwithf "generate_type failed at: %s" (string_of_rng rng)
11656
11657   and is_attrs_interleave = function
11658     | [Interleave _] -> true
11659     | Attribute _ :: fields -> is_attrs_interleave fields
11660     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11661     | _ -> false
11662
11663   and get_attrs_interleave = function
11664     | [Interleave fields] -> fields
11665     | ((Attribute _) as field) :: fields
11666     | ((Optional (Attribute _)) as field) :: fields ->
11667         field :: get_attrs_interleave fields
11668     | _ -> assert false
11669
11670   and generate_types xs =
11671     List.iter (fun x -> ignore (generate_type x)) xs
11672
11673   and generate_type_struct name fields =
11674     (* Calculate the types of the fields first.  We have to do this
11675      * before printing anything so we are still in BOL context.
11676      *)
11677     let types = List.map fst (List.map generate_type fields) in
11678
11679     (* Special case of a struct containing just a string and another
11680      * field.  Turn it into an assoc list.
11681      *)
11682     match types with
11683     | ["string"; other] ->
11684         let fname1, fname2 =
11685           match fields with
11686           | [f1; f2] -> name_of_field f1, name_of_field f2
11687           | _ -> assert false in
11688         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11689         name, false
11690
11691     | types ->
11692         pr "type %s = {\n" name;
11693         List.iter (
11694           fun (field, ftype) ->
11695             let fname = name_of_field field in
11696             pr "  %s_%s : %s;\n" name fname ftype
11697         ) (List.combine fields types);
11698         pr "}\n";
11699         (* Return the name of this type, and
11700          * false because it's not a simple type.
11701          *)
11702         name, false
11703   in
11704
11705   generate_types xs
11706
11707 let generate_parsers xs =
11708   (* As for generate_type above, generate_parser makes a parser for
11709    * some type, and returns the name of the parser it has generated.
11710    * Because it (may) need to print something, it should always be
11711    * called in BOL context.
11712    *)
11713   let rec generate_parser = function
11714     | Text ->                                (* string *)
11715         "string_child_or_empty"
11716     | Choice values ->                        (* [`val1|`val2|...] *)
11717         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11718           (String.concat "|"
11719              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11720     | ZeroOrMore rng ->                        (* <rng> list *)
11721         let pa = generate_parser rng in
11722         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11723     | OneOrMore rng ->                        (* <rng> list *)
11724         let pa = generate_parser rng in
11725         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11726                                         (* virt-inspector hack: bool *)
11727     | Optional (Attribute (name, [Value "1"])) ->
11728         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11729     | Optional rng ->                        (* <rng> list *)
11730         let pa = generate_parser rng in
11731         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11732                                         (* type name = { fields ... } *)
11733     | Element (name, fields) when is_attrs_interleave fields ->
11734         generate_parser_struct name (get_attrs_interleave fields)
11735     | Element (name, [field]) ->        (* type name = field *)
11736         let pa = generate_parser field in
11737         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11738         pr "let %s =\n" parser_name;
11739         pr "  %s\n" pa;
11740         pr "let parse_%s = %s\n" name parser_name;
11741         parser_name
11742     | Attribute (name, [field]) ->
11743         let pa = generate_parser field in
11744         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11745         pr "let %s =\n" parser_name;
11746         pr "  %s\n" pa;
11747         pr "let parse_%s = %s\n" name parser_name;
11748         parser_name
11749     | Element (name, fields) ->              (* type name = { fields ... } *)
11750         generate_parser_struct name ([], fields)
11751     | rng ->
11752         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11753
11754   and is_attrs_interleave = function
11755     | [Interleave _] -> true
11756     | Attribute _ :: fields -> is_attrs_interleave fields
11757     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11758     | _ -> false
11759
11760   and get_attrs_interleave = function
11761     | [Interleave fields] -> [], fields
11762     | ((Attribute _) as field) :: fields
11763     | ((Optional (Attribute _)) as field) :: fields ->
11764         let attrs, interleaves = get_attrs_interleave fields in
11765         (field :: attrs), interleaves
11766     | _ -> assert false
11767
11768   and generate_parsers xs =
11769     List.iter (fun x -> ignore (generate_parser x)) xs
11770
11771   and generate_parser_struct name (attrs, interleaves) =
11772     (* Generate parsers for the fields first.  We have to do this
11773      * before printing anything so we are still in BOL context.
11774      *)
11775     let fields = attrs @ interleaves in
11776     let pas = List.map generate_parser fields in
11777
11778     (* Generate an intermediate tuple from all the fields first.
11779      * If the type is just a string + another field, then we will
11780      * return this directly, otherwise it is turned into a record.
11781      *
11782      * RELAX NG note: This code treats <interleave> and plain lists of
11783      * fields the same.  In other words, it doesn't bother enforcing
11784      * any ordering of fields in the XML.
11785      *)
11786     pr "let parse_%s x =\n" name;
11787     pr "  let t = (\n    ";
11788     let comma = ref false in
11789     List.iter (
11790       fun x ->
11791         if !comma then pr ",\n    ";
11792         comma := true;
11793         match x with
11794         | Optional (Attribute (fname, [field])), pa ->
11795             pr "%s x" pa
11796         | Optional (Element (fname, [field])), pa ->
11797             pr "%s (optional_child %S x)" pa fname
11798         | Attribute (fname, [Text]), _ ->
11799             pr "attribute %S x" fname
11800         | (ZeroOrMore _ | OneOrMore _), pa ->
11801             pr "%s x" pa
11802         | Text, pa ->
11803             pr "%s x" pa
11804         | (field, pa) ->
11805             let fname = name_of_field field in
11806             pr "%s (child %S x)" pa fname
11807     ) (List.combine fields pas);
11808     pr "\n  ) in\n";
11809
11810     (match fields with
11811      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11812          pr "  t\n"
11813
11814      | _ ->
11815          pr "  (Obj.magic t : %s)\n" name
11816 (*
11817          List.iter (
11818            function
11819            | (Optional (Attribute (fname, [field])), pa) ->
11820                pr "  %s_%s =\n" name fname;
11821                pr "    %s x;\n" pa
11822            | (Optional (Element (fname, [field])), pa) ->
11823                pr "  %s_%s =\n" name fname;
11824                pr "    (let x = optional_child %S x in\n" fname;
11825                pr "     %s x);\n" pa
11826            | (field, pa) ->
11827                let fname = name_of_field field in
11828                pr "  %s_%s =\n" name fname;
11829                pr "    (let x = child %S x in\n" fname;
11830                pr "     %s x);\n" pa
11831          ) (List.combine fields pas);
11832          pr "}\n"
11833 *)
11834     );
11835     sprintf "parse_%s" name
11836   in
11837
11838   generate_parsers xs
11839
11840 (* Generate ocaml/guestfs_inspector.mli. *)
11841 let generate_ocaml_inspector_mli () =
11842   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11843
11844   pr "\
11845 (** This is an OCaml language binding to the external [virt-inspector]
11846     program.
11847
11848     For more information, please read the man page [virt-inspector(1)].
11849 *)
11850
11851 ";
11852
11853   generate_types grammar;
11854   pr "(** The nested information returned from the {!inspect} function. *)\n";
11855   pr "\n";
11856
11857   pr "\
11858 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11859 (** To inspect a libvirt domain called [name], pass a singleton
11860     list: [inspect [name]].  When using libvirt only, you may
11861     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11862
11863     To inspect a disk image or images, pass a list of the filenames
11864     of the disk images: [inspect filenames]
11865
11866     This function inspects the given guest or disk images and
11867     returns a list of operating system(s) found and a large amount
11868     of information about them.  In the vast majority of cases,
11869     a virtual machine only contains a single operating system.
11870
11871     If the optional [~xml] parameter is given, then this function
11872     skips running the external virt-inspector program and just
11873     parses the given XML directly (which is expected to be XML
11874     produced from a previous run of virt-inspector).  The list of
11875     names and connect URI are ignored in this case.
11876
11877     This function can throw a wide variety of exceptions, for example
11878     if the external virt-inspector program cannot be found, or if
11879     it doesn't generate valid XML.
11880 *)
11881 "
11882
11883 (* Generate ocaml/guestfs_inspector.ml. *)
11884 let generate_ocaml_inspector_ml () =
11885   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11886
11887   pr "open Unix\n";
11888   pr "\n";
11889
11890   generate_types grammar;
11891   pr "\n";
11892
11893   pr "\
11894 (* Misc functions which are used by the parser code below. *)
11895 let first_child = function
11896   | Xml.Element (_, _, c::_) -> c
11897   | Xml.Element (name, _, []) ->
11898       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11899   | Xml.PCData str ->
11900       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11901
11902 let string_child_or_empty = function
11903   | Xml.Element (_, _, [Xml.PCData s]) -> s
11904   | Xml.Element (_, _, []) -> \"\"
11905   | Xml.Element (x, _, _) ->
11906       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11907                 x ^ \" instead\")
11908   | Xml.PCData str ->
11909       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11910
11911 let optional_child name xml =
11912   let children = Xml.children xml in
11913   try
11914     Some (List.find (function
11915                      | Xml.Element (n, _, _) when n = name -> true
11916                      | _ -> false) children)
11917   with
11918     Not_found -> None
11919
11920 let child name xml =
11921   match optional_child name xml with
11922   | Some c -> c
11923   | None ->
11924       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11925
11926 let attribute name xml =
11927   try Xml.attrib xml name
11928   with Xml.No_attribute _ ->
11929     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11930
11931 ";
11932
11933   generate_parsers grammar;
11934   pr "\n";
11935
11936   pr "\
11937 (* Run external virt-inspector, then use parser to parse the XML. *)
11938 let inspect ?connect ?xml names =
11939   let xml =
11940     match xml with
11941     | None ->
11942         if names = [] then invalid_arg \"inspect: no names given\";
11943         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11944           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11945           names in
11946         let cmd = List.map Filename.quote cmd in
11947         let cmd = String.concat \" \" cmd in
11948         let chan = open_process_in cmd in
11949         let xml = Xml.parse_in chan in
11950         (match close_process_in chan with
11951          | WEXITED 0 -> ()
11952          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11953          | WSIGNALED i | WSTOPPED i ->
11954              failwith (\"external virt-inspector command died or stopped on sig \" ^
11955                        string_of_int i)
11956         );
11957         xml
11958     | Some doc ->
11959         Xml.parse_string doc in
11960   parse_operatingsystems xml
11961 "
11962
11963 and generate_max_proc_nr () =
11964   pr "%d\n" max_proc_nr
11965
11966 let output_to filename k =
11967   let filename_new = filename ^ ".new" in
11968   chan := open_out filename_new;
11969   k ();
11970   close_out !chan;
11971   chan := Pervasives.stdout;
11972
11973   (* Is the new file different from the current file? *)
11974   if Sys.file_exists filename && files_equal filename filename_new then
11975     unlink filename_new                 (* same, so skip it *)
11976   else (
11977     (* different, overwrite old one *)
11978     (try chmod filename 0o644 with Unix_error _ -> ());
11979     rename filename_new filename;
11980     chmod filename 0o444;
11981     printf "written %s\n%!" filename;
11982   )
11983
11984 let perror msg = function
11985   | Unix_error (err, _, _) ->
11986       eprintf "%s: %s\n" msg (error_message err)
11987   | exn ->
11988       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11989
11990 (* Main program. *)
11991 let () =
11992   let lock_fd =
11993     try openfile "HACKING" [O_RDWR] 0
11994     with
11995     | Unix_error (ENOENT, _, _) ->
11996         eprintf "\
11997 You are probably running this from the wrong directory.
11998 Run it from the top source directory using the command
11999   src/generator.ml
12000 ";
12001         exit 1
12002     | exn ->
12003         perror "open: HACKING" exn;
12004         exit 1 in
12005
12006   (* Acquire a lock so parallel builds won't try to run the generator
12007    * twice at the same time.  Subsequent builds will wait for the first
12008    * one to finish.  Note the lock is released implicitly when the
12009    * program exits.
12010    *)
12011   (try lockf lock_fd F_LOCK 1
12012    with exn ->
12013      perror "lock: HACKING" exn;
12014      exit 1);
12015
12016   check_functions ();
12017
12018   output_to "src/guestfs_protocol.x" generate_xdr;
12019   output_to "src/guestfs-structs.h" generate_structs_h;
12020   output_to "src/guestfs-actions.h" generate_actions_h;
12021   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12022   output_to "src/guestfs-actions.c" generate_client_actions;
12023   output_to "src/guestfs-bindtests.c" generate_bindtests;
12024   output_to "src/guestfs-structs.pod" generate_structs_pod;
12025   output_to "src/guestfs-actions.pod" generate_actions_pod;
12026   output_to "src/guestfs-availability.pod" generate_availability_pod;
12027   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12028   output_to "src/libguestfs.syms" generate_linker_script;
12029   output_to "daemon/actions.h" generate_daemon_actions_h;
12030   output_to "daemon/stubs.c" generate_daemon_actions;
12031   output_to "daemon/names.c" generate_daemon_names;
12032   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12033   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12034   output_to "capitests/tests.c" generate_tests;
12035   output_to "fish/cmds.c" generate_fish_cmds;
12036   output_to "fish/completion.c" generate_fish_completion;
12037   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12038   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12039   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12040   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12041   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12042   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12043   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12044   output_to "perl/Guestfs.xs" generate_perl_xs;
12045   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12046   output_to "perl/bindtests.pl" generate_perl_bindtests;
12047   output_to "python/guestfs-py.c" generate_python_c;
12048   output_to "python/guestfs.py" generate_python_py;
12049   output_to "python/bindtests.py" generate_python_bindtests;
12050   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12051   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12052   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12053
12054   List.iter (
12055     fun (typ, jtyp) ->
12056       let cols = cols_of_struct typ in
12057       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12058       output_to filename (generate_java_struct jtyp cols);
12059   ) java_structs;
12060
12061   output_to "java/Makefile.inc" generate_java_makefile_inc;
12062   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12063   output_to "java/Bindtests.java" generate_java_bindtests;
12064   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12065   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12066   output_to "csharp/Libguestfs.cs" generate_csharp;
12067
12068   (* Always generate this file last, and unconditionally.  It's used
12069    * by the Makefile to know when we must re-run the generator.
12070    *)
12071   let chan = open_out "src/stamp-generator" in
12072   fprintf chan "1\n";
12073   close_out chan;
12074
12075   printf "generated %d lines of code\n" !lines