620395b7fdc1833bd70cf39a3802399caaf8d03c
[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.  Distro backports makes this unreliable.  Use
814 C<guestfs_available> instead.");
815
816   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
817    [InitNone, Always, TestOutputTrue (
818       [["set_selinux"; "true"];
819        ["get_selinux"]])],
820    "set SELinux enabled or disabled at appliance boot",
821    "\
822 This sets the selinux flag that is passed to the appliance
823 at boot time.  The default is C<selinux=0> (disabled).
824
825 Note that if SELinux is enabled, it is always in
826 Permissive mode (C<enforcing=0>).
827
828 For more information on the architecture of libguestfs,
829 see L<guestfs(3)>.");
830
831   ("get_selinux", (RBool "selinux", []), -1, [],
832    [],
833    "get SELinux enabled flag",
834    "\
835 This returns the current setting of the selinux flag which
836 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
837
838 For more information on the architecture of libguestfs,
839 see L<guestfs(3)>.");
840
841   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
842    [InitNone, Always, TestOutputFalse (
843       [["set_trace"; "false"];
844        ["get_trace"]])],
845    "enable or disable command traces",
846    "\
847 If the command trace flag is set to 1, then commands are
848 printed on stdout before they are executed in a format
849 which is very similar to the one used by guestfish.  In
850 other words, you can run a program with this enabled, and
851 you will get out a script which you can feed to guestfish
852 to perform the same set of actions.
853
854 If you want to trace C API calls into libguestfs (and
855 other libraries) then possibly a better way is to use
856 the external ltrace(1) command.
857
858 Command traces are disabled unless the environment variable
859 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
860
861   ("get_trace", (RBool "trace", []), -1, [],
862    [],
863    "get command trace enabled flag",
864    "\
865 Return the command trace flag.");
866
867   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
868    [InitNone, Always, TestOutputFalse (
869       [["set_direct"; "false"];
870        ["get_direct"]])],
871    "enable or disable direct appliance mode",
872    "\
873 If the direct appliance mode flag is enabled, then stdin and
874 stdout are passed directly through to the appliance once it
875 is launched.
876
877 One consequence of this is that log messages aren't caught
878 by the library and handled by C<guestfs_set_log_message_callback>,
879 but go straight to stdout.
880
881 You probably don't want to use this unless you know what you
882 are doing.
883
884 The default is disabled.");
885
886   ("get_direct", (RBool "direct", []), -1, [],
887    [],
888    "get direct appliance mode flag",
889    "\
890 Return the direct appliance mode flag.");
891
892   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
893    [InitNone, Always, TestOutputTrue (
894       [["set_recovery_proc"; "true"];
895        ["get_recovery_proc"]])],
896    "enable or disable the recovery process",
897    "\
898 If this is called with the parameter C<false> then
899 C<guestfs_launch> does not create a recovery process.  The
900 purpose of the recovery process is to stop runaway qemu
901 processes in the case where the main program aborts abruptly.
902
903 This only has any effect if called before C<guestfs_launch>,
904 and the default is true.
905
906 About the only time when you would want to disable this is
907 if the main process will fork itself into the background
908 (\"daemonize\" itself).  In this case the recovery process
909 thinks that the main program has disappeared and so kills
910 qemu, which is not very helpful.");
911
912   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
913    [],
914    "get recovery process enabled flag",
915    "\
916 Return the recovery process enabled flag.");
917
918   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
919    [],
920    "add a drive specifying the QEMU block emulation to use",
921    "\
922 This is the same as C<guestfs_add_drive> but it allows you
923 to specify the QEMU interface emulation to use at run time.");
924
925   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
926    [],
927    "add a drive read-only specifying the QEMU block emulation to use",
928    "\
929 This is the same as C<guestfs_add_drive_ro> but it allows you
930 to specify the QEMU interface emulation to use at run time.");
931
932 ]
933
934 (* daemon_functions are any functions which cause some action
935  * to take place in the daemon.
936  *)
937
938 let daemon_functions = [
939   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
940    [InitEmpty, Always, TestOutput (
941       [["part_disk"; "/dev/sda"; "mbr"];
942        ["mkfs"; "ext2"; "/dev/sda1"];
943        ["mount"; "/dev/sda1"; "/"];
944        ["write"; "/new"; "new file contents"];
945        ["cat"; "/new"]], "new file contents")],
946    "mount a guest disk at a position in the filesystem",
947    "\
948 Mount a guest disk at a position in the filesystem.  Block devices
949 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
950 the guest.  If those block devices contain partitions, they will have
951 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
952 names can be used.
953
954 The rules are the same as for L<mount(2)>:  A filesystem must
955 first be mounted on C</> before others can be mounted.  Other
956 filesystems can only be mounted on directories which already
957 exist.
958
959 The mounted filesystem is writable, if we have sufficient permissions
960 on the underlying device.
961
962 B<Important note:>
963 When you use this call, the filesystem options C<sync> and C<noatime>
964 are set implicitly.  This was originally done because we thought it
965 would improve reliability, but it turns out that I<-o sync> has a
966 very large negative performance impact and negligible effect on
967 reliability.  Therefore we recommend that you avoid using
968 C<guestfs_mount> in any code that needs performance, and instead
969 use C<guestfs_mount_options> (use an empty string for the first
970 parameter if you don't want any options).");
971
972   ("sync", (RErr, []), 2, [],
973    [ InitEmpty, Always, TestRun [["sync"]]],
974    "sync disks, writes are flushed through to the disk image",
975    "\
976 This syncs the disk, so that any writes are flushed through to the
977 underlying disk image.
978
979 You should always call this if you have modified a disk image, before
980 closing the handle.");
981
982   ("touch", (RErr, [Pathname "path"]), 3, [],
983    [InitBasicFS, Always, TestOutputTrue (
984       [["touch"; "/new"];
985        ["exists"; "/new"]])],
986    "update file timestamps or create a new file",
987    "\
988 Touch acts like the L<touch(1)> command.  It can be used to
989 update the timestamps on a file, or, if the file does not exist,
990 to create a new zero-length file.");
991
992   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
993    [InitISOFS, Always, TestOutput (
994       [["cat"; "/known-2"]], "abcdef\n")],
995    "list the contents of a file",
996    "\
997 Return the contents of the file named C<path>.
998
999 Note that this function cannot correctly handle binary files
1000 (specifically, files containing C<\\0> character which is treated
1001 as end of string).  For those you need to use the C<guestfs_read_file>
1002 or C<guestfs_download> functions which have a more complex interface.");
1003
1004   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1005    [], (* XXX Tricky to test because it depends on the exact format
1006         * of the 'ls -l' command, which changes between F10 and F11.
1007         *)
1008    "list the files in a directory (long format)",
1009    "\
1010 List the files in C<directory> (relative to the root directory,
1011 there is no cwd) in the format of 'ls -la'.
1012
1013 This command is mostly useful for interactive sessions.  It
1014 is I<not> intended that you try to parse the output string.");
1015
1016   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1017    [InitBasicFS, Always, TestOutputList (
1018       [["touch"; "/new"];
1019        ["touch"; "/newer"];
1020        ["touch"; "/newest"];
1021        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1022    "list the files in a directory",
1023    "\
1024 List the files in C<directory> (relative to the root directory,
1025 there is no cwd).  The '.' and '..' entries are not returned, but
1026 hidden files are shown.
1027
1028 This command is mostly useful for interactive sessions.  Programs
1029 should probably use C<guestfs_readdir> instead.");
1030
1031   ("list_devices", (RStringList "devices", []), 7, [],
1032    [InitEmpty, Always, TestOutputListOfDevices (
1033       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1034    "list the block devices",
1035    "\
1036 List all the block devices.
1037
1038 The full block device names are returned, eg. C</dev/sda>");
1039
1040   ("list_partitions", (RStringList "partitions", []), 8, [],
1041    [InitBasicFS, Always, TestOutputListOfDevices (
1042       [["list_partitions"]], ["/dev/sda1"]);
1043     InitEmpty, Always, TestOutputListOfDevices (
1044       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1045        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1046    "list the partitions",
1047    "\
1048 List all the partitions detected on all block devices.
1049
1050 The full partition device names are returned, eg. C</dev/sda1>
1051
1052 This does not return logical volumes.  For that you will need to
1053 call C<guestfs_lvs>.");
1054
1055   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1056    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1057       [["pvs"]], ["/dev/sda1"]);
1058     InitEmpty, Always, TestOutputListOfDevices (
1059       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1060        ["pvcreate"; "/dev/sda1"];
1061        ["pvcreate"; "/dev/sda2"];
1062        ["pvcreate"; "/dev/sda3"];
1063        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1064    "list the LVM physical volumes (PVs)",
1065    "\
1066 List all the physical volumes detected.  This is the equivalent
1067 of the L<pvs(8)> command.
1068
1069 This returns a list of just the device names that contain
1070 PVs (eg. C</dev/sda2>).
1071
1072 See also C<guestfs_pvs_full>.");
1073
1074   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1075    [InitBasicFSonLVM, Always, TestOutputList (
1076       [["vgs"]], ["VG"]);
1077     InitEmpty, Always, TestOutputList (
1078       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1079        ["pvcreate"; "/dev/sda1"];
1080        ["pvcreate"; "/dev/sda2"];
1081        ["pvcreate"; "/dev/sda3"];
1082        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1083        ["vgcreate"; "VG2"; "/dev/sda3"];
1084        ["vgs"]], ["VG1"; "VG2"])],
1085    "list the LVM volume groups (VGs)",
1086    "\
1087 List all the volumes groups detected.  This is the equivalent
1088 of the L<vgs(8)> command.
1089
1090 This returns a list of just the volume group names that were
1091 detected (eg. C<VolGroup00>).
1092
1093 See also C<guestfs_vgs_full>.");
1094
1095   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1096    [InitBasicFSonLVM, Always, TestOutputList (
1097       [["lvs"]], ["/dev/VG/LV"]);
1098     InitEmpty, Always, TestOutputList (
1099       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1100        ["pvcreate"; "/dev/sda1"];
1101        ["pvcreate"; "/dev/sda2"];
1102        ["pvcreate"; "/dev/sda3"];
1103        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1104        ["vgcreate"; "VG2"; "/dev/sda3"];
1105        ["lvcreate"; "LV1"; "VG1"; "50"];
1106        ["lvcreate"; "LV2"; "VG1"; "50"];
1107        ["lvcreate"; "LV3"; "VG2"; "50"];
1108        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1109    "list the LVM logical volumes (LVs)",
1110    "\
1111 List all the logical volumes detected.  This is the equivalent
1112 of the L<lvs(8)> command.
1113
1114 This returns a list of the logical volume device names
1115 (eg. C</dev/VolGroup00/LogVol00>).
1116
1117 See also C<guestfs_lvs_full>.");
1118
1119   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1120    [], (* XXX how to test? *)
1121    "list the LVM physical volumes (PVs)",
1122    "\
1123 List all the physical volumes detected.  This is the equivalent
1124 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1125
1126   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1127    [], (* XXX how to test? *)
1128    "list the LVM volume groups (VGs)",
1129    "\
1130 List all the volumes groups detected.  This is the equivalent
1131 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1132
1133   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1134    [], (* XXX how to test? *)
1135    "list the LVM logical volumes (LVs)",
1136    "\
1137 List all the logical volumes detected.  This is the equivalent
1138 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1139
1140   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1141    [InitISOFS, Always, TestOutputList (
1142       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1143     InitISOFS, Always, TestOutputList (
1144       [["read_lines"; "/empty"]], [])],
1145    "read file as lines",
1146    "\
1147 Return the contents of the file named C<path>.
1148
1149 The file contents are returned as a list of lines.  Trailing
1150 C<LF> and C<CRLF> character sequences are I<not> returned.
1151
1152 Note that this function cannot correctly handle binary files
1153 (specifically, files containing C<\\0> character which is treated
1154 as end of line).  For those you need to use the C<guestfs_read_file>
1155 function which has a more complex interface.");
1156
1157   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1158    [], (* XXX Augeas code needs tests. *)
1159    "create a new Augeas handle",
1160    "\
1161 Create a new Augeas handle for editing configuration files.
1162 If there was any previous Augeas handle associated with this
1163 guestfs session, then it is closed.
1164
1165 You must call this before using any other C<guestfs_aug_*>
1166 commands.
1167
1168 C<root> is the filesystem root.  C<root> must not be NULL,
1169 use C</> instead.
1170
1171 The flags are the same as the flags defined in
1172 E<lt>augeas.hE<gt>, the logical I<or> of the following
1173 integers:
1174
1175 =over 4
1176
1177 =item C<AUG_SAVE_BACKUP> = 1
1178
1179 Keep the original file with a C<.augsave> extension.
1180
1181 =item C<AUG_SAVE_NEWFILE> = 2
1182
1183 Save changes into a file with extension C<.augnew>, and
1184 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1185
1186 =item C<AUG_TYPE_CHECK> = 4
1187
1188 Typecheck lenses (can be expensive).
1189
1190 =item C<AUG_NO_STDINC> = 8
1191
1192 Do not use standard load path for modules.
1193
1194 =item C<AUG_SAVE_NOOP> = 16
1195
1196 Make save a no-op, just record what would have been changed.
1197
1198 =item C<AUG_NO_LOAD> = 32
1199
1200 Do not load the tree in C<guestfs_aug_init>.
1201
1202 =back
1203
1204 To close the handle, you can call C<guestfs_aug_close>.
1205
1206 To find out more about Augeas, see L<http://augeas.net/>.");
1207
1208   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1209    [], (* XXX Augeas code needs tests. *)
1210    "close the current Augeas handle",
1211    "\
1212 Close the current Augeas handle and free up any resources
1213 used by it.  After calling this, you have to call
1214 C<guestfs_aug_init> again before you can use any other
1215 Augeas functions.");
1216
1217   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1218    [], (* XXX Augeas code needs tests. *)
1219    "define an Augeas variable",
1220    "\
1221 Defines an Augeas variable C<name> whose value is the result
1222 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1223 undefined.
1224
1225 On success this returns the number of nodes in C<expr>, or
1226 C<0> if C<expr> evaluates to something which is not a nodeset.");
1227
1228   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1229    [], (* XXX Augeas code needs tests. *)
1230    "define an Augeas node",
1231    "\
1232 Defines a variable C<name> whose value is the result of
1233 evaluating C<expr>.
1234
1235 If C<expr> evaluates to an empty nodeset, a node is created,
1236 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1237 C<name> will be the nodeset containing that single node.
1238
1239 On success this returns a pair containing the
1240 number of nodes in the nodeset, and a boolean flag
1241 if a node was created.");
1242
1243   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1244    [], (* XXX Augeas code needs tests. *)
1245    "look up the value of an Augeas path",
1246    "\
1247 Look up the value associated with C<path>.  If C<path>
1248 matches exactly one node, the C<value> is returned.");
1249
1250   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1251    [], (* XXX Augeas code needs tests. *)
1252    "set Augeas path to value",
1253    "\
1254 Set the value associated with C<path> to C<val>.
1255
1256 In the Augeas API, it is possible to clear a node by setting
1257 the value to NULL.  Due to an oversight in the libguestfs API
1258 you cannot do that with this call.  Instead you must use the
1259 C<guestfs_aug_clear> call.");
1260
1261   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1262    [], (* XXX Augeas code needs tests. *)
1263    "insert a sibling Augeas node",
1264    "\
1265 Create a new sibling C<label> for C<path>, inserting it into
1266 the tree before or after C<path> (depending on the boolean
1267 flag C<before>).
1268
1269 C<path> must match exactly one existing node in the tree, and
1270 C<label> must be a label, ie. not contain C</>, C<*> or end
1271 with a bracketed index C<[N]>.");
1272
1273   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1274    [], (* XXX Augeas code needs tests. *)
1275    "remove an Augeas path",
1276    "\
1277 Remove C<path> and all of its children.
1278
1279 On success this returns the number of entries which were removed.");
1280
1281   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1282    [], (* XXX Augeas code needs tests. *)
1283    "move Augeas node",
1284    "\
1285 Move the node C<src> to C<dest>.  C<src> must match exactly
1286 one node.  C<dest> is overwritten if it exists.");
1287
1288   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1289    [], (* XXX Augeas code needs tests. *)
1290    "return Augeas nodes which match augpath",
1291    "\
1292 Returns a list of paths which match the path expression C<path>.
1293 The returned paths are sufficiently qualified so that they match
1294 exactly one node in the current tree.");
1295
1296   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1297    [], (* XXX Augeas code needs tests. *)
1298    "write all pending Augeas changes to disk",
1299    "\
1300 This writes all pending changes to disk.
1301
1302 The flags which were passed to C<guestfs_aug_init> affect exactly
1303 how files are saved.");
1304
1305   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1306    [], (* XXX Augeas code needs tests. *)
1307    "load files into the tree",
1308    "\
1309 Load files into the tree.
1310
1311 See C<aug_load> in the Augeas documentation for the full gory
1312 details.");
1313
1314   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1315    [], (* XXX Augeas code needs tests. *)
1316    "list Augeas nodes under augpath",
1317    "\
1318 This is just a shortcut for listing C<guestfs_aug_match>
1319 C<path/*> and sorting the resulting nodes into alphabetical order.");
1320
1321   ("rm", (RErr, [Pathname "path"]), 29, [],
1322    [InitBasicFS, Always, TestRun
1323       [["touch"; "/new"];
1324        ["rm"; "/new"]];
1325     InitBasicFS, Always, TestLastFail
1326       [["rm"; "/new"]];
1327     InitBasicFS, Always, TestLastFail
1328       [["mkdir"; "/new"];
1329        ["rm"; "/new"]]],
1330    "remove a file",
1331    "\
1332 Remove the single file C<path>.");
1333
1334   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1335    [InitBasicFS, Always, TestRun
1336       [["mkdir"; "/new"];
1337        ["rmdir"; "/new"]];
1338     InitBasicFS, Always, TestLastFail
1339       [["rmdir"; "/new"]];
1340     InitBasicFS, Always, TestLastFail
1341       [["touch"; "/new"];
1342        ["rmdir"; "/new"]]],
1343    "remove a directory",
1344    "\
1345 Remove the single directory C<path>.");
1346
1347   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1348    [InitBasicFS, Always, TestOutputFalse
1349       [["mkdir"; "/new"];
1350        ["mkdir"; "/new/foo"];
1351        ["touch"; "/new/foo/bar"];
1352        ["rm_rf"; "/new"];
1353        ["exists"; "/new"]]],
1354    "remove a file or directory recursively",
1355    "\
1356 Remove the file or directory C<path>, recursively removing the
1357 contents if its a directory.  This is like the C<rm -rf> shell
1358 command.");
1359
1360   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1361    [InitBasicFS, Always, TestOutputTrue
1362       [["mkdir"; "/new"];
1363        ["is_dir"; "/new"]];
1364     InitBasicFS, Always, TestLastFail
1365       [["mkdir"; "/new/foo/bar"]]],
1366    "create a directory",
1367    "\
1368 Create a directory named C<path>.");
1369
1370   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1371    [InitBasicFS, Always, TestOutputTrue
1372       [["mkdir_p"; "/new/foo/bar"];
1373        ["is_dir"; "/new/foo/bar"]];
1374     InitBasicFS, Always, TestOutputTrue
1375       [["mkdir_p"; "/new/foo/bar"];
1376        ["is_dir"; "/new/foo"]];
1377     InitBasicFS, Always, TestOutputTrue
1378       [["mkdir_p"; "/new/foo/bar"];
1379        ["is_dir"; "/new"]];
1380     (* Regression tests for RHBZ#503133: *)
1381     InitBasicFS, Always, TestRun
1382       [["mkdir"; "/new"];
1383        ["mkdir_p"; "/new"]];
1384     InitBasicFS, Always, TestLastFail
1385       [["touch"; "/new"];
1386        ["mkdir_p"; "/new"]]],
1387    "create a directory and parents",
1388    "\
1389 Create a directory named C<path>, creating any parent directories
1390 as necessary.  This is like the C<mkdir -p> shell command.");
1391
1392   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1393    [], (* XXX Need stat command to test *)
1394    "change file mode",
1395    "\
1396 Change the mode (permissions) of C<path> to C<mode>.  Only
1397 numeric modes are supported.
1398
1399 I<Note>: When using this command from guestfish, C<mode>
1400 by default would be decimal, unless you prefix it with
1401 C<0> to get octal, ie. use C<0700> not C<700>.
1402
1403 The mode actually set is affected by the umask.");
1404
1405   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1406    [], (* XXX Need stat command to test *)
1407    "change file owner and group",
1408    "\
1409 Change the file owner to C<owner> and group to C<group>.
1410
1411 Only numeric uid and gid are supported.  If you want to use
1412 names, you will need to locate and parse the password file
1413 yourself (Augeas support makes this relatively easy).");
1414
1415   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1416    [InitISOFS, Always, TestOutputTrue (
1417       [["exists"; "/empty"]]);
1418     InitISOFS, Always, TestOutputTrue (
1419       [["exists"; "/directory"]])],
1420    "test if file or directory exists",
1421    "\
1422 This returns C<true> if and only if there is a file, directory
1423 (or anything) with the given C<path> name.
1424
1425 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1426
1427   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1428    [InitISOFS, Always, TestOutputTrue (
1429       [["is_file"; "/known-1"]]);
1430     InitISOFS, Always, TestOutputFalse (
1431       [["is_file"; "/directory"]])],
1432    "test if file exists",
1433    "\
1434 This returns C<true> if and only if there is a file
1435 with the given C<path> name.  Note that it returns false for
1436 other objects like directories.
1437
1438 See also C<guestfs_stat>.");
1439
1440   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1441    [InitISOFS, Always, TestOutputFalse (
1442       [["is_dir"; "/known-3"]]);
1443     InitISOFS, Always, TestOutputTrue (
1444       [["is_dir"; "/directory"]])],
1445    "test if file exists",
1446    "\
1447 This returns C<true> if and only if there is a directory
1448 with the given C<path> name.  Note that it returns false for
1449 other objects like files.
1450
1451 See also C<guestfs_stat>.");
1452
1453   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1454    [InitEmpty, Always, TestOutputListOfDevices (
1455       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1456        ["pvcreate"; "/dev/sda1"];
1457        ["pvcreate"; "/dev/sda2"];
1458        ["pvcreate"; "/dev/sda3"];
1459        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1460    "create an LVM physical volume",
1461    "\
1462 This creates an LVM physical volume on the named C<device>,
1463 where C<device> should usually be a partition name such
1464 as C</dev/sda1>.");
1465
1466   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1467    [InitEmpty, Always, TestOutputList (
1468       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1469        ["pvcreate"; "/dev/sda1"];
1470        ["pvcreate"; "/dev/sda2"];
1471        ["pvcreate"; "/dev/sda3"];
1472        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1473        ["vgcreate"; "VG2"; "/dev/sda3"];
1474        ["vgs"]], ["VG1"; "VG2"])],
1475    "create an LVM volume group",
1476    "\
1477 This creates an LVM volume group called C<volgroup>
1478 from the non-empty list of physical volumes C<physvols>.");
1479
1480   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1481    [InitEmpty, Always, TestOutputList (
1482       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1483        ["pvcreate"; "/dev/sda1"];
1484        ["pvcreate"; "/dev/sda2"];
1485        ["pvcreate"; "/dev/sda3"];
1486        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1487        ["vgcreate"; "VG2"; "/dev/sda3"];
1488        ["lvcreate"; "LV1"; "VG1"; "50"];
1489        ["lvcreate"; "LV2"; "VG1"; "50"];
1490        ["lvcreate"; "LV3"; "VG2"; "50"];
1491        ["lvcreate"; "LV4"; "VG2"; "50"];
1492        ["lvcreate"; "LV5"; "VG2"; "50"];
1493        ["lvs"]],
1494       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1495        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1496    "create an LVM logical volume",
1497    "\
1498 This creates an LVM logical volume called C<logvol>
1499 on the volume group C<volgroup>, with C<size> megabytes.");
1500
1501   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1502    [InitEmpty, Always, TestOutput (
1503       [["part_disk"; "/dev/sda"; "mbr"];
1504        ["mkfs"; "ext2"; "/dev/sda1"];
1505        ["mount_options"; ""; "/dev/sda1"; "/"];
1506        ["write"; "/new"; "new file contents"];
1507        ["cat"; "/new"]], "new file contents")],
1508    "make a filesystem",
1509    "\
1510 This creates a filesystem on C<device> (usually a partition
1511 or LVM logical volume).  The filesystem type is C<fstype>, for
1512 example C<ext3>.");
1513
1514   ("sfdisk", (RErr, [Device "device";
1515                      Int "cyls"; Int "heads"; Int "sectors";
1516                      StringList "lines"]), 43, [DangerWillRobinson],
1517    [],
1518    "create partitions on a block device",
1519    "\
1520 This is a direct interface to the L<sfdisk(8)> program for creating
1521 partitions on block devices.
1522
1523 C<device> should be a block device, for example C</dev/sda>.
1524
1525 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1526 and sectors on the device, which are passed directly to sfdisk as
1527 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1528 of these, then the corresponding parameter is omitted.  Usually for
1529 'large' disks, you can just pass C<0> for these, but for small
1530 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1531 out the right geometry and you will need to tell it.
1532
1533 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1534 information refer to the L<sfdisk(8)> manpage.
1535
1536 To create a single partition occupying the whole disk, you would
1537 pass C<lines> as a single element list, when the single element being
1538 the string C<,> (comma).
1539
1540 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1541 C<guestfs_part_init>");
1542
1543   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1544    [],
1545    "create a file",
1546    "\
1547 This call creates a file called C<path>.  The contents of the
1548 file is the string C<content> (which can contain any 8 bit data),
1549 with length C<size>.
1550
1551 As a special case, if C<size> is C<0>
1552 then the length is calculated using C<strlen> (so in this case
1553 the content cannot contain embedded ASCII NULs).
1554
1555 I<NB.> Owing to a bug, writing content containing ASCII NUL
1556 characters does I<not> work, even if the length is specified.");
1557
1558   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1559    [InitEmpty, Always, TestOutputListOfDevices (
1560       [["part_disk"; "/dev/sda"; "mbr"];
1561        ["mkfs"; "ext2"; "/dev/sda1"];
1562        ["mount_options"; ""; "/dev/sda1"; "/"];
1563        ["mounts"]], ["/dev/sda1"]);
1564     InitEmpty, Always, TestOutputList (
1565       [["part_disk"; "/dev/sda"; "mbr"];
1566        ["mkfs"; "ext2"; "/dev/sda1"];
1567        ["mount_options"; ""; "/dev/sda1"; "/"];
1568        ["umount"; "/"];
1569        ["mounts"]], [])],
1570    "unmount a filesystem",
1571    "\
1572 This unmounts the given filesystem.  The filesystem may be
1573 specified either by its mountpoint (path) or the device which
1574 contains the filesystem.");
1575
1576   ("mounts", (RStringList "devices", []), 46, [],
1577    [InitBasicFS, Always, TestOutputListOfDevices (
1578       [["mounts"]], ["/dev/sda1"])],
1579    "show mounted filesystems",
1580    "\
1581 This returns the list of currently mounted filesystems.  It returns
1582 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1583
1584 Some internal mounts are not shown.
1585
1586 See also: C<guestfs_mountpoints>");
1587
1588   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1589    [InitBasicFS, Always, TestOutputList (
1590       [["umount_all"];
1591        ["mounts"]], []);
1592     (* check that umount_all can unmount nested mounts correctly: *)
1593     InitEmpty, Always, TestOutputList (
1594       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1595        ["mkfs"; "ext2"; "/dev/sda1"];
1596        ["mkfs"; "ext2"; "/dev/sda2"];
1597        ["mkfs"; "ext2"; "/dev/sda3"];
1598        ["mount_options"; ""; "/dev/sda1"; "/"];
1599        ["mkdir"; "/mp1"];
1600        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1601        ["mkdir"; "/mp1/mp2"];
1602        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1603        ["mkdir"; "/mp1/mp2/mp3"];
1604        ["umount_all"];
1605        ["mounts"]], [])],
1606    "unmount all filesystems",
1607    "\
1608 This unmounts all mounted filesystems.
1609
1610 Some internal mounts are not unmounted by this call.");
1611
1612   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1613    [],
1614    "remove all LVM LVs, VGs and PVs",
1615    "\
1616 This command removes all LVM logical volumes, volume groups
1617 and physical volumes.");
1618
1619   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1620    [InitISOFS, Always, TestOutput (
1621       [["file"; "/empty"]], "empty");
1622     InitISOFS, Always, TestOutput (
1623       [["file"; "/known-1"]], "ASCII text");
1624     InitISOFS, Always, TestLastFail (
1625       [["file"; "/notexists"]])],
1626    "determine file type",
1627    "\
1628 This call uses the standard L<file(1)> command to determine
1629 the type or contents of the file.  This also works on devices,
1630 for example to find out whether a partition contains a filesystem.
1631
1632 This call will also transparently look inside various types
1633 of compressed file.
1634
1635 The exact command which runs is C<file -zbsL path>.  Note in
1636 particular that the filename is not prepended to the output
1637 (the C<-b> option).");
1638
1639   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1640    [InitBasicFS, Always, TestOutput (
1641       [["upload"; "test-command"; "/test-command"];
1642        ["chmod"; "0o755"; "/test-command"];
1643        ["command"; "/test-command 1"]], "Result1");
1644     InitBasicFS, Always, TestOutput (
1645       [["upload"; "test-command"; "/test-command"];
1646        ["chmod"; "0o755"; "/test-command"];
1647        ["command"; "/test-command 2"]], "Result2\n");
1648     InitBasicFS, Always, TestOutput (
1649       [["upload"; "test-command"; "/test-command"];
1650        ["chmod"; "0o755"; "/test-command"];
1651        ["command"; "/test-command 3"]], "\nResult3");
1652     InitBasicFS, Always, TestOutput (
1653       [["upload"; "test-command"; "/test-command"];
1654        ["chmod"; "0o755"; "/test-command"];
1655        ["command"; "/test-command 4"]], "\nResult4\n");
1656     InitBasicFS, Always, TestOutput (
1657       [["upload"; "test-command"; "/test-command"];
1658        ["chmod"; "0o755"; "/test-command"];
1659        ["command"; "/test-command 5"]], "\nResult5\n\n");
1660     InitBasicFS, Always, TestOutput (
1661       [["upload"; "test-command"; "/test-command"];
1662        ["chmod"; "0o755"; "/test-command"];
1663        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1664     InitBasicFS, Always, TestOutput (
1665       [["upload"; "test-command"; "/test-command"];
1666        ["chmod"; "0o755"; "/test-command"];
1667        ["command"; "/test-command 7"]], "");
1668     InitBasicFS, Always, TestOutput (
1669       [["upload"; "test-command"; "/test-command"];
1670        ["chmod"; "0o755"; "/test-command"];
1671        ["command"; "/test-command 8"]], "\n");
1672     InitBasicFS, Always, TestOutput (
1673       [["upload"; "test-command"; "/test-command"];
1674        ["chmod"; "0o755"; "/test-command"];
1675        ["command"; "/test-command 9"]], "\n\n");
1676     InitBasicFS, Always, TestOutput (
1677       [["upload"; "test-command"; "/test-command"];
1678        ["chmod"; "0o755"; "/test-command"];
1679        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1680     InitBasicFS, Always, TestOutput (
1681       [["upload"; "test-command"; "/test-command"];
1682        ["chmod"; "0o755"; "/test-command"];
1683        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1684     InitBasicFS, Always, TestLastFail (
1685       [["upload"; "test-command"; "/test-command"];
1686        ["chmod"; "0o755"; "/test-command"];
1687        ["command"; "/test-command"]])],
1688    "run a command from the guest filesystem",
1689    "\
1690 This call runs a command from the guest filesystem.  The
1691 filesystem must be mounted, and must contain a compatible
1692 operating system (ie. something Linux, with the same
1693 or compatible processor architecture).
1694
1695 The single parameter is an argv-style list of arguments.
1696 The first element is the name of the program to run.
1697 Subsequent elements are parameters.  The list must be
1698 non-empty (ie. must contain a program name).  Note that
1699 the command runs directly, and is I<not> invoked via
1700 the shell (see C<guestfs_sh>).
1701
1702 The return value is anything printed to I<stdout> by
1703 the command.
1704
1705 If the command returns a non-zero exit status, then
1706 this function returns an error message.  The error message
1707 string is the content of I<stderr> from the command.
1708
1709 The C<$PATH> environment variable will contain at least
1710 C</usr/bin> and C</bin>.  If you require a program from
1711 another location, you should provide the full path in the
1712 first parameter.
1713
1714 Shared libraries and data files required by the program
1715 must be available on filesystems which are mounted in the
1716 correct places.  It is the caller's responsibility to ensure
1717 all filesystems that are needed are mounted at the right
1718 locations.");
1719
1720   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1721    [InitBasicFS, Always, TestOutputList (
1722       [["upload"; "test-command"; "/test-command"];
1723        ["chmod"; "0o755"; "/test-command"];
1724        ["command_lines"; "/test-command 1"]], ["Result1"]);
1725     InitBasicFS, Always, TestOutputList (
1726       [["upload"; "test-command"; "/test-command"];
1727        ["chmod"; "0o755"; "/test-command"];
1728        ["command_lines"; "/test-command 2"]], ["Result2"]);
1729     InitBasicFS, Always, TestOutputList (
1730       [["upload"; "test-command"; "/test-command"];
1731        ["chmod"; "0o755"; "/test-command"];
1732        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1733     InitBasicFS, Always, TestOutputList (
1734       [["upload"; "test-command"; "/test-command"];
1735        ["chmod"; "0o755"; "/test-command"];
1736        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1737     InitBasicFS, Always, TestOutputList (
1738       [["upload"; "test-command"; "/test-command"];
1739        ["chmod"; "0o755"; "/test-command"];
1740        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1741     InitBasicFS, Always, TestOutputList (
1742       [["upload"; "test-command"; "/test-command"];
1743        ["chmod"; "0o755"; "/test-command"];
1744        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1745     InitBasicFS, Always, TestOutputList (
1746       [["upload"; "test-command"; "/test-command"];
1747        ["chmod"; "0o755"; "/test-command"];
1748        ["command_lines"; "/test-command 7"]], []);
1749     InitBasicFS, Always, TestOutputList (
1750       [["upload"; "test-command"; "/test-command"];
1751        ["chmod"; "0o755"; "/test-command"];
1752        ["command_lines"; "/test-command 8"]], [""]);
1753     InitBasicFS, Always, TestOutputList (
1754       [["upload"; "test-command"; "/test-command"];
1755        ["chmod"; "0o755"; "/test-command"];
1756        ["command_lines"; "/test-command 9"]], ["";""]);
1757     InitBasicFS, Always, TestOutputList (
1758       [["upload"; "test-command"; "/test-command"];
1759        ["chmod"; "0o755"; "/test-command"];
1760        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1761     InitBasicFS, Always, TestOutputList (
1762       [["upload"; "test-command"; "/test-command"];
1763        ["chmod"; "0o755"; "/test-command"];
1764        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1765    "run a command, returning lines",
1766    "\
1767 This is the same as C<guestfs_command>, but splits the
1768 result into a list of lines.
1769
1770 See also: C<guestfs_sh_lines>");
1771
1772   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1773    [InitISOFS, Always, TestOutputStruct (
1774       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1775    "get file information",
1776    "\
1777 Returns file information for the given C<path>.
1778
1779 This is the same as the C<stat(2)> system call.");
1780
1781   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1782    [InitISOFS, Always, TestOutputStruct (
1783       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1784    "get file information for a symbolic link",
1785    "\
1786 Returns file information for the given C<path>.
1787
1788 This is the same as C<guestfs_stat> except that if C<path>
1789 is a symbolic link, then the link is stat-ed, not the file it
1790 refers to.
1791
1792 This is the same as the C<lstat(2)> system call.");
1793
1794   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1795    [InitISOFS, Always, TestOutputStruct (
1796       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1797    "get file system statistics",
1798    "\
1799 Returns file system statistics for any mounted file system.
1800 C<path> should be a file or directory in the mounted file system
1801 (typically it is the mount point itself, but it doesn't need to be).
1802
1803 This is the same as the C<statvfs(2)> system call.");
1804
1805   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1806    [], (* XXX test *)
1807    "get ext2/ext3/ext4 superblock details",
1808    "\
1809 This returns the contents of the ext2, ext3 or ext4 filesystem
1810 superblock on C<device>.
1811
1812 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1813 manpage for more details.  The list of fields returned isn't
1814 clearly defined, and depends on both the version of C<tune2fs>
1815 that libguestfs was built against, and the filesystem itself.");
1816
1817   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1818    [InitEmpty, Always, TestOutputTrue (
1819       [["blockdev_setro"; "/dev/sda"];
1820        ["blockdev_getro"; "/dev/sda"]])],
1821    "set block device to read-only",
1822    "\
1823 Sets the block device named C<device> to read-only.
1824
1825 This uses the L<blockdev(8)> command.");
1826
1827   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1828    [InitEmpty, Always, TestOutputFalse (
1829       [["blockdev_setrw"; "/dev/sda"];
1830        ["blockdev_getro"; "/dev/sda"]])],
1831    "set block device to read-write",
1832    "\
1833 Sets the block device named C<device> to read-write.
1834
1835 This uses the L<blockdev(8)> command.");
1836
1837   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1838    [InitEmpty, Always, TestOutputTrue (
1839       [["blockdev_setro"; "/dev/sda"];
1840        ["blockdev_getro"; "/dev/sda"]])],
1841    "is block device set to read-only",
1842    "\
1843 Returns a boolean indicating if the block device is read-only
1844 (true if read-only, false if not).
1845
1846 This uses the L<blockdev(8)> command.");
1847
1848   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1849    [InitEmpty, Always, TestOutputInt (
1850       [["blockdev_getss"; "/dev/sda"]], 512)],
1851    "get sectorsize of block device",
1852    "\
1853 This returns the size of sectors on a block device.
1854 Usually 512, but can be larger for modern devices.
1855
1856 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1857 for that).
1858
1859 This uses the L<blockdev(8)> command.");
1860
1861   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1862    [InitEmpty, Always, TestOutputInt (
1863       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1864    "get blocksize of block device",
1865    "\
1866 This returns the block size of a device.
1867
1868 (Note this is different from both I<size in blocks> and
1869 I<filesystem block size>).
1870
1871 This uses the L<blockdev(8)> command.");
1872
1873   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1874    [], (* XXX test *)
1875    "set blocksize of block device",
1876    "\
1877 This sets the block size of a device.
1878
1879 (Note this is different from both I<size in blocks> and
1880 I<filesystem block size>).
1881
1882 This uses the L<blockdev(8)> command.");
1883
1884   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1885    [InitEmpty, Always, TestOutputInt (
1886       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1887    "get total size of device in 512-byte sectors",
1888    "\
1889 This returns the size of the device in units of 512-byte sectors
1890 (even if the sectorsize isn't 512 bytes ... weird).
1891
1892 See also C<guestfs_blockdev_getss> for the real sector size of
1893 the device, and C<guestfs_blockdev_getsize64> for the more
1894 useful I<size in bytes>.
1895
1896 This uses the L<blockdev(8)> command.");
1897
1898   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1899    [InitEmpty, Always, TestOutputInt (
1900       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1901    "get total size of device in bytes",
1902    "\
1903 This returns the size of the device in bytes.
1904
1905 See also C<guestfs_blockdev_getsz>.
1906
1907 This uses the L<blockdev(8)> command.");
1908
1909   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1910    [InitEmpty, Always, TestRun
1911       [["blockdev_flushbufs"; "/dev/sda"]]],
1912    "flush device buffers",
1913    "\
1914 This tells the kernel to flush internal buffers associated
1915 with C<device>.
1916
1917 This uses the L<blockdev(8)> command.");
1918
1919   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1920    [InitEmpty, Always, TestRun
1921       [["blockdev_rereadpt"; "/dev/sda"]]],
1922    "reread partition table",
1923    "\
1924 Reread the partition table on C<device>.
1925
1926 This uses the L<blockdev(8)> command.");
1927
1928   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1929    [InitBasicFS, Always, TestOutput (
1930       (* Pick a file from cwd which isn't likely to change. *)
1931       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1932        ["checksum"; "md5"; "/COPYING.LIB"]],
1933       Digest.to_hex (Digest.file "COPYING.LIB"))],
1934    "upload a file from the local machine",
1935    "\
1936 Upload local file C<filename> to C<remotefilename> on the
1937 filesystem.
1938
1939 C<filename> can also be a named pipe.
1940
1941 See also C<guestfs_download>.");
1942
1943   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1944    [InitBasicFS, Always, TestOutput (
1945       (* Pick a file from cwd which isn't likely to change. *)
1946       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1947        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1948        ["upload"; "testdownload.tmp"; "/upload"];
1949        ["checksum"; "md5"; "/upload"]],
1950       Digest.to_hex (Digest.file "COPYING.LIB"))],
1951    "download a file to the local machine",
1952    "\
1953 Download file C<remotefilename> and save it as C<filename>
1954 on the local machine.
1955
1956 C<filename> can also be a named pipe.
1957
1958 See also C<guestfs_upload>, C<guestfs_cat>.");
1959
1960   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1961    [InitISOFS, Always, TestOutput (
1962       [["checksum"; "crc"; "/known-3"]], "2891671662");
1963     InitISOFS, Always, TestLastFail (
1964       [["checksum"; "crc"; "/notexists"]]);
1965     InitISOFS, Always, TestOutput (
1966       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1967     InitISOFS, Always, TestOutput (
1968       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1969     InitISOFS, Always, TestOutput (
1970       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1971     InitISOFS, Always, TestOutput (
1972       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1973     InitISOFS, Always, TestOutput (
1974       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1975     InitISOFS, Always, TestOutput (
1976       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1977     (* Test for RHBZ#579608, absolute symbolic links. *)
1978     InitISOFS, Always, TestOutput (
1979       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1980    "compute MD5, SHAx or CRC checksum of file",
1981    "\
1982 This call computes the MD5, SHAx or CRC checksum of the
1983 file named C<path>.
1984
1985 The type of checksum to compute is given by the C<csumtype>
1986 parameter which must have one of the following values:
1987
1988 =over 4
1989
1990 =item C<crc>
1991
1992 Compute the cyclic redundancy check (CRC) specified by POSIX
1993 for the C<cksum> command.
1994
1995 =item C<md5>
1996
1997 Compute the MD5 hash (using the C<md5sum> program).
1998
1999 =item C<sha1>
2000
2001 Compute the SHA1 hash (using the C<sha1sum> program).
2002
2003 =item C<sha224>
2004
2005 Compute the SHA224 hash (using the C<sha224sum> program).
2006
2007 =item C<sha256>
2008
2009 Compute the SHA256 hash (using the C<sha256sum> program).
2010
2011 =item C<sha384>
2012
2013 Compute the SHA384 hash (using the C<sha384sum> program).
2014
2015 =item C<sha512>
2016
2017 Compute the SHA512 hash (using the C<sha512sum> program).
2018
2019 =back
2020
2021 The checksum is returned as a printable string.
2022
2023 To get the checksum for a device, use C<guestfs_checksum_device>.
2024
2025 To get the checksums for many files, use C<guestfs_checksums_out>.");
2026
2027   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2028    [InitBasicFS, Always, TestOutput (
2029       [["tar_in"; "../images/helloworld.tar"; "/"];
2030        ["cat"; "/hello"]], "hello\n")],
2031    "unpack tarfile to directory",
2032    "\
2033 This command uploads and unpacks local file C<tarfile> (an
2034 I<uncompressed> tar file) into C<directory>.
2035
2036 To upload a compressed tarball, use C<guestfs_tgz_in>
2037 or C<guestfs_txz_in>.");
2038
2039   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2040    [],
2041    "pack directory into tarfile",
2042    "\
2043 This command packs the contents of C<directory> and downloads
2044 it to local file C<tarfile>.
2045
2046 To download a compressed tarball, use C<guestfs_tgz_out>
2047 or C<guestfs_txz_out>.");
2048
2049   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2050    [InitBasicFS, Always, TestOutput (
2051       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2052        ["cat"; "/hello"]], "hello\n")],
2053    "unpack compressed tarball to directory",
2054    "\
2055 This command uploads and unpacks local file C<tarball> (a
2056 I<gzip compressed> tar file) into C<directory>.
2057
2058 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2059
2060   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2061    [],
2062    "pack directory into compressed tarball",
2063    "\
2064 This command packs the contents of C<directory> and downloads
2065 it to local file C<tarball>.
2066
2067 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2068
2069   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2070    [InitBasicFS, Always, TestLastFail (
2071       [["umount"; "/"];
2072        ["mount_ro"; "/dev/sda1"; "/"];
2073        ["touch"; "/new"]]);
2074     InitBasicFS, Always, TestOutput (
2075       [["write"; "/new"; "data"];
2076        ["umount"; "/"];
2077        ["mount_ro"; "/dev/sda1"; "/"];
2078        ["cat"; "/new"]], "data")],
2079    "mount a guest disk, read-only",
2080    "\
2081 This is the same as the C<guestfs_mount> command, but it
2082 mounts the filesystem with the read-only (I<-o ro>) flag.");
2083
2084   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2085    [],
2086    "mount a guest disk with mount options",
2087    "\
2088 This is the same as the C<guestfs_mount> command, but it
2089 allows you to set the mount options as for the
2090 L<mount(8)> I<-o> flag.
2091
2092 If the C<options> parameter is an empty string, then
2093 no options are passed (all options default to whatever
2094 the filesystem uses).");
2095
2096   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2097    [],
2098    "mount a guest disk with mount options and vfstype",
2099    "\
2100 This is the same as the C<guestfs_mount> command, but it
2101 allows you to set both the mount options and the vfstype
2102 as for the L<mount(8)> I<-o> and I<-t> flags.");
2103
2104   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2105    [],
2106    "debugging and internals",
2107    "\
2108 The C<guestfs_debug> command exposes some internals of
2109 C<guestfsd> (the guestfs daemon) that runs inside the
2110 qemu subprocess.
2111
2112 There is no comprehensive help for this command.  You have
2113 to look at the file C<daemon/debug.c> in the libguestfs source
2114 to find out what you can do.");
2115
2116   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2117    [InitEmpty, Always, TestOutputList (
2118       [["part_disk"; "/dev/sda"; "mbr"];
2119        ["pvcreate"; "/dev/sda1"];
2120        ["vgcreate"; "VG"; "/dev/sda1"];
2121        ["lvcreate"; "LV1"; "VG"; "50"];
2122        ["lvcreate"; "LV2"; "VG"; "50"];
2123        ["lvremove"; "/dev/VG/LV1"];
2124        ["lvs"]], ["/dev/VG/LV2"]);
2125     InitEmpty, Always, TestOutputList (
2126       [["part_disk"; "/dev/sda"; "mbr"];
2127        ["pvcreate"; "/dev/sda1"];
2128        ["vgcreate"; "VG"; "/dev/sda1"];
2129        ["lvcreate"; "LV1"; "VG"; "50"];
2130        ["lvcreate"; "LV2"; "VG"; "50"];
2131        ["lvremove"; "/dev/VG"];
2132        ["lvs"]], []);
2133     InitEmpty, Always, TestOutputList (
2134       [["part_disk"; "/dev/sda"; "mbr"];
2135        ["pvcreate"; "/dev/sda1"];
2136        ["vgcreate"; "VG"; "/dev/sda1"];
2137        ["lvcreate"; "LV1"; "VG"; "50"];
2138        ["lvcreate"; "LV2"; "VG"; "50"];
2139        ["lvremove"; "/dev/VG"];
2140        ["vgs"]], ["VG"])],
2141    "remove an LVM logical volume",
2142    "\
2143 Remove an LVM logical volume C<device>, where C<device> is
2144 the path to the LV, such as C</dev/VG/LV>.
2145
2146 You can also remove all LVs in a volume group by specifying
2147 the VG name, C</dev/VG>.");
2148
2149   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2150    [InitEmpty, Always, TestOutputList (
2151       [["part_disk"; "/dev/sda"; "mbr"];
2152        ["pvcreate"; "/dev/sda1"];
2153        ["vgcreate"; "VG"; "/dev/sda1"];
2154        ["lvcreate"; "LV1"; "VG"; "50"];
2155        ["lvcreate"; "LV2"; "VG"; "50"];
2156        ["vgremove"; "VG"];
2157        ["lvs"]], []);
2158     InitEmpty, Always, TestOutputList (
2159       [["part_disk"; "/dev/sda"; "mbr"];
2160        ["pvcreate"; "/dev/sda1"];
2161        ["vgcreate"; "VG"; "/dev/sda1"];
2162        ["lvcreate"; "LV1"; "VG"; "50"];
2163        ["lvcreate"; "LV2"; "VG"; "50"];
2164        ["vgremove"; "VG"];
2165        ["vgs"]], [])],
2166    "remove an LVM volume group",
2167    "\
2168 Remove an LVM volume group C<vgname>, (for example C<VG>).
2169
2170 This also forcibly removes all logical volumes in the volume
2171 group (if any).");
2172
2173   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2174    [InitEmpty, Always, TestOutputListOfDevices (
2175       [["part_disk"; "/dev/sda"; "mbr"];
2176        ["pvcreate"; "/dev/sda1"];
2177        ["vgcreate"; "VG"; "/dev/sda1"];
2178        ["lvcreate"; "LV1"; "VG"; "50"];
2179        ["lvcreate"; "LV2"; "VG"; "50"];
2180        ["vgremove"; "VG"];
2181        ["pvremove"; "/dev/sda1"];
2182        ["lvs"]], []);
2183     InitEmpty, Always, TestOutputListOfDevices (
2184       [["part_disk"; "/dev/sda"; "mbr"];
2185        ["pvcreate"; "/dev/sda1"];
2186        ["vgcreate"; "VG"; "/dev/sda1"];
2187        ["lvcreate"; "LV1"; "VG"; "50"];
2188        ["lvcreate"; "LV2"; "VG"; "50"];
2189        ["vgremove"; "VG"];
2190        ["pvremove"; "/dev/sda1"];
2191        ["vgs"]], []);
2192     InitEmpty, Always, TestOutputListOfDevices (
2193       [["part_disk"; "/dev/sda"; "mbr"];
2194        ["pvcreate"; "/dev/sda1"];
2195        ["vgcreate"; "VG"; "/dev/sda1"];
2196        ["lvcreate"; "LV1"; "VG"; "50"];
2197        ["lvcreate"; "LV2"; "VG"; "50"];
2198        ["vgremove"; "VG"];
2199        ["pvremove"; "/dev/sda1"];
2200        ["pvs"]], [])],
2201    "remove an LVM physical volume",
2202    "\
2203 This wipes a physical volume C<device> so that LVM will no longer
2204 recognise it.
2205
2206 The implementation uses the C<pvremove> command which refuses to
2207 wipe physical volumes that contain any volume groups, so you have
2208 to remove those first.");
2209
2210   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2211    [InitBasicFS, Always, TestOutput (
2212       [["set_e2label"; "/dev/sda1"; "testlabel"];
2213        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2214    "set the ext2/3/4 filesystem label",
2215    "\
2216 This sets the ext2/3/4 filesystem label of the filesystem on
2217 C<device> to C<label>.  Filesystem labels are limited to
2218 16 characters.
2219
2220 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2221 to return the existing label on a filesystem.");
2222
2223   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2224    [],
2225    "get the ext2/3/4 filesystem label",
2226    "\
2227 This returns the ext2/3/4 filesystem label of the filesystem on
2228 C<device>.");
2229
2230   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2231    (let uuid = uuidgen () in
2232     [InitBasicFS, Always, TestOutput (
2233        [["set_e2uuid"; "/dev/sda1"; uuid];
2234         ["get_e2uuid"; "/dev/sda1"]], uuid);
2235      InitBasicFS, Always, TestOutput (
2236        [["set_e2uuid"; "/dev/sda1"; "clear"];
2237         ["get_e2uuid"; "/dev/sda1"]], "");
2238      (* We can't predict what UUIDs will be, so just check the commands run. *)
2239      InitBasicFS, Always, TestRun (
2240        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2241      InitBasicFS, Always, TestRun (
2242        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2243    "set the ext2/3/4 filesystem UUID",
2244    "\
2245 This sets the ext2/3/4 filesystem UUID of the filesystem on
2246 C<device> to C<uuid>.  The format of the UUID and alternatives
2247 such as C<clear>, C<random> and C<time> are described in the
2248 L<tune2fs(8)> manpage.
2249
2250 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2251 to return the existing UUID of a filesystem.");
2252
2253   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2254    [],
2255    "get the ext2/3/4 filesystem UUID",
2256    "\
2257 This returns the ext2/3/4 filesystem UUID of the filesystem on
2258 C<device>.");
2259
2260   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2261    [InitBasicFS, Always, TestOutputInt (
2262       [["umount"; "/dev/sda1"];
2263        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2264     InitBasicFS, Always, TestOutputInt (
2265       [["umount"; "/dev/sda1"];
2266        ["zero"; "/dev/sda1"];
2267        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2268    "run the filesystem checker",
2269    "\
2270 This runs the filesystem checker (fsck) on C<device> which
2271 should have filesystem type C<fstype>.
2272
2273 The returned integer is the status.  See L<fsck(8)> for the
2274 list of status codes from C<fsck>.
2275
2276 Notes:
2277
2278 =over 4
2279
2280 =item *
2281
2282 Multiple status codes can be summed together.
2283
2284 =item *
2285
2286 A non-zero return code can mean \"success\", for example if
2287 errors have been corrected on the filesystem.
2288
2289 =item *
2290
2291 Checking or repairing NTFS volumes is not supported
2292 (by linux-ntfs).
2293
2294 =back
2295
2296 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2297
2298   ("zero", (RErr, [Device "device"]), 85, [],
2299    [InitBasicFS, Always, TestOutput (
2300       [["umount"; "/dev/sda1"];
2301        ["zero"; "/dev/sda1"];
2302        ["file"; "/dev/sda1"]], "data")],
2303    "write zeroes to the device",
2304    "\
2305 This command writes zeroes over the first few blocks of C<device>.
2306
2307 How many blocks are zeroed isn't specified (but it's I<not> enough
2308 to securely wipe the device).  It should be sufficient to remove
2309 any partition tables, filesystem superblocks and so on.
2310
2311 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2312
2313   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2314    (* Test disabled because grub-install incompatible with virtio-blk driver.
2315     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2316     *)
2317    [InitBasicFS, Disabled, TestOutputTrue (
2318       [["grub_install"; "/"; "/dev/sda1"];
2319        ["is_dir"; "/boot"]])],
2320    "install GRUB",
2321    "\
2322 This command installs GRUB (the Grand Unified Bootloader) on
2323 C<device>, with the root directory being C<root>.");
2324
2325   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2326    [InitBasicFS, Always, TestOutput (
2327       [["write"; "/old"; "file content"];
2328        ["cp"; "/old"; "/new"];
2329        ["cat"; "/new"]], "file content");
2330     InitBasicFS, Always, TestOutputTrue (
2331       [["write"; "/old"; "file content"];
2332        ["cp"; "/old"; "/new"];
2333        ["is_file"; "/old"]]);
2334     InitBasicFS, Always, TestOutput (
2335       [["write"; "/old"; "file content"];
2336        ["mkdir"; "/dir"];
2337        ["cp"; "/old"; "/dir/new"];
2338        ["cat"; "/dir/new"]], "file content")],
2339    "copy a file",
2340    "\
2341 This copies a file from C<src> to C<dest> where C<dest> is
2342 either a destination filename or destination directory.");
2343
2344   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2345    [InitBasicFS, Always, TestOutput (
2346       [["mkdir"; "/olddir"];
2347        ["mkdir"; "/newdir"];
2348        ["write"; "/olddir/file"; "file content"];
2349        ["cp_a"; "/olddir"; "/newdir"];
2350        ["cat"; "/newdir/olddir/file"]], "file content")],
2351    "copy a file or directory recursively",
2352    "\
2353 This copies a file or directory from C<src> to C<dest>
2354 recursively using the C<cp -a> command.");
2355
2356   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2357    [InitBasicFS, Always, TestOutput (
2358       [["write"; "/old"; "file content"];
2359        ["mv"; "/old"; "/new"];
2360        ["cat"; "/new"]], "file content");
2361     InitBasicFS, Always, TestOutputFalse (
2362       [["write"; "/old"; "file content"];
2363        ["mv"; "/old"; "/new"];
2364        ["is_file"; "/old"]])],
2365    "move a file",
2366    "\
2367 This moves a file from C<src> to C<dest> where C<dest> is
2368 either a destination filename or destination directory.");
2369
2370   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2371    [InitEmpty, Always, TestRun (
2372       [["drop_caches"; "3"]])],
2373    "drop kernel page cache, dentries and inodes",
2374    "\
2375 This instructs the guest kernel to drop its page cache,
2376 and/or dentries and inode caches.  The parameter C<whattodrop>
2377 tells the kernel what precisely to drop, see
2378 L<http://linux-mm.org/Drop_Caches>
2379
2380 Setting C<whattodrop> to 3 should drop everything.
2381
2382 This automatically calls L<sync(2)> before the operation,
2383 so that the maximum guest memory is freed.");
2384
2385   ("dmesg", (RString "kmsgs", []), 91, [],
2386    [InitEmpty, Always, TestRun (
2387       [["dmesg"]])],
2388    "return kernel messages",
2389    "\
2390 This returns the kernel messages (C<dmesg> output) from
2391 the guest kernel.  This is sometimes useful for extended
2392 debugging of problems.
2393
2394 Another way to get the same information is to enable
2395 verbose messages with C<guestfs_set_verbose> or by setting
2396 the environment variable C<LIBGUESTFS_DEBUG=1> before
2397 running the program.");
2398
2399   ("ping_daemon", (RErr, []), 92, [],
2400    [InitEmpty, Always, TestRun (
2401       [["ping_daemon"]])],
2402    "ping the guest daemon",
2403    "\
2404 This is a test probe into the guestfs daemon running inside
2405 the qemu subprocess.  Calling this function checks that the
2406 daemon responds to the ping message, without affecting the daemon
2407 or attached block device(s) in any other way.");
2408
2409   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2410    [InitBasicFS, Always, TestOutputTrue (
2411       [["write"; "/file1"; "contents of a file"];
2412        ["cp"; "/file1"; "/file2"];
2413        ["equal"; "/file1"; "/file2"]]);
2414     InitBasicFS, Always, TestOutputFalse (
2415       [["write"; "/file1"; "contents of a file"];
2416        ["write"; "/file2"; "contents of another file"];
2417        ["equal"; "/file1"; "/file2"]]);
2418     InitBasicFS, Always, TestLastFail (
2419       [["equal"; "/file1"; "/file2"]])],
2420    "test if two files have equal contents",
2421    "\
2422 This compares the two files C<file1> and C<file2> and returns
2423 true if their content is exactly equal, or false otherwise.
2424
2425 The external L<cmp(1)> program is used for the comparison.");
2426
2427   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2428    [InitISOFS, Always, TestOutputList (
2429       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2430     InitISOFS, Always, TestOutputList (
2431       [["strings"; "/empty"]], []);
2432     (* Test for RHBZ#579608, absolute symbolic links. *)
2433     InitISOFS, Always, TestRun (
2434       [["strings"; "/abssymlink"]])],
2435    "print the printable strings in a file",
2436    "\
2437 This runs the L<strings(1)> command on a file and returns
2438 the list of printable strings found.");
2439
2440   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2441    [InitISOFS, Always, TestOutputList (
2442       [["strings_e"; "b"; "/known-5"]], []);
2443     InitBasicFS, Always, TestOutputList (
2444       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2445        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2446    "print the printable strings in a file",
2447    "\
2448 This is like the C<guestfs_strings> command, but allows you to
2449 specify the encoding of strings that are looked for in
2450 the source file C<path>.
2451
2452 Allowed encodings are:
2453
2454 =over 4
2455
2456 =item s
2457
2458 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2459 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2460
2461 =item S
2462
2463 Single 8-bit-byte characters.
2464
2465 =item b
2466
2467 16-bit big endian strings such as those encoded in
2468 UTF-16BE or UCS-2BE.
2469
2470 =item l (lower case letter L)
2471
2472 16-bit little endian such as UTF-16LE and UCS-2LE.
2473 This is useful for examining binaries in Windows guests.
2474
2475 =item B
2476
2477 32-bit big endian such as UCS-4BE.
2478
2479 =item L
2480
2481 32-bit little endian such as UCS-4LE.
2482
2483 =back
2484
2485 The returned strings are transcoded to UTF-8.");
2486
2487   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2488    [InitISOFS, Always, TestOutput (
2489       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2490     (* Test for RHBZ#501888c2 regression which caused large hexdump
2491      * commands to segfault.
2492      *)
2493     InitISOFS, Always, TestRun (
2494       [["hexdump"; "/100krandom"]]);
2495     (* Test for RHBZ#579608, absolute symbolic links. *)
2496     InitISOFS, Always, TestRun (
2497       [["hexdump"; "/abssymlink"]])],
2498    "dump a file in hexadecimal",
2499    "\
2500 This runs C<hexdump -C> on the given C<path>.  The result is
2501 the human-readable, canonical hex dump of the file.");
2502
2503   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2504    [InitNone, Always, TestOutput (
2505       [["part_disk"; "/dev/sda"; "mbr"];
2506        ["mkfs"; "ext3"; "/dev/sda1"];
2507        ["mount_options"; ""; "/dev/sda1"; "/"];
2508        ["write"; "/new"; "test file"];
2509        ["umount"; "/dev/sda1"];
2510        ["zerofree"; "/dev/sda1"];
2511        ["mount_options"; ""; "/dev/sda1"; "/"];
2512        ["cat"; "/new"]], "test file")],
2513    "zero unused inodes and disk blocks on ext2/3 filesystem",
2514    "\
2515 This runs the I<zerofree> program on C<device>.  This program
2516 claims to zero unused inodes and disk blocks on an ext2/3
2517 filesystem, thus making it possible to compress the filesystem
2518 more effectively.
2519
2520 You should B<not> run this program if the filesystem is
2521 mounted.
2522
2523 It is possible that using this program can damage the filesystem
2524 or data on the filesystem.");
2525
2526   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2527    [],
2528    "resize an LVM physical volume",
2529    "\
2530 This resizes (expands or shrinks) an existing LVM physical
2531 volume to match the new size of the underlying device.");
2532
2533   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2534                        Int "cyls"; Int "heads"; Int "sectors";
2535                        String "line"]), 99, [DangerWillRobinson],
2536    [],
2537    "modify a single partition on a block device",
2538    "\
2539 This runs L<sfdisk(8)> option to modify just the single
2540 partition C<n> (note: C<n> counts from 1).
2541
2542 For other parameters, see C<guestfs_sfdisk>.  You should usually
2543 pass C<0> for the cyls/heads/sectors parameters.
2544
2545 See also: C<guestfs_part_add>");
2546
2547   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2548    [],
2549    "display the partition table",
2550    "\
2551 This displays the partition table on C<device>, in the
2552 human-readable output of the L<sfdisk(8)> command.  It is
2553 not intended to be parsed.
2554
2555 See also: C<guestfs_part_list>");
2556
2557   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2558    [],
2559    "display the kernel geometry",
2560    "\
2561 This displays the kernel's idea of the geometry of C<device>.
2562
2563 The result is in human-readable format, and not designed to
2564 be parsed.");
2565
2566   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2567    [],
2568    "display the disk geometry from the partition table",
2569    "\
2570 This displays the disk geometry of C<device> read from the
2571 partition table.  Especially in the case where the underlying
2572 block device has been resized, this can be different from the
2573 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2574
2575 The result is in human-readable format, and not designed to
2576 be parsed.");
2577
2578   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2579    [],
2580    "activate or deactivate all volume groups",
2581    "\
2582 This command activates or (if C<activate> is false) deactivates
2583 all logical volumes in all volume groups.
2584 If activated, then they are made known to the
2585 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2586 then those devices disappear.
2587
2588 This command is the same as running C<vgchange -a y|n>");
2589
2590   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2591    [],
2592    "activate or deactivate some volume groups",
2593    "\
2594 This command activates or (if C<activate> is false) deactivates
2595 all logical volumes in the listed volume groups C<volgroups>.
2596 If activated, then they are made known to the
2597 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2598 then those devices disappear.
2599
2600 This command is the same as running C<vgchange -a y|n volgroups...>
2601
2602 Note that if C<volgroups> is an empty list then B<all> volume groups
2603 are activated or deactivated.");
2604
2605   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2606    [InitNone, Always, TestOutput (
2607       [["part_disk"; "/dev/sda"; "mbr"];
2608        ["pvcreate"; "/dev/sda1"];
2609        ["vgcreate"; "VG"; "/dev/sda1"];
2610        ["lvcreate"; "LV"; "VG"; "10"];
2611        ["mkfs"; "ext2"; "/dev/VG/LV"];
2612        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2613        ["write"; "/new"; "test content"];
2614        ["umount"; "/"];
2615        ["lvresize"; "/dev/VG/LV"; "20"];
2616        ["e2fsck_f"; "/dev/VG/LV"];
2617        ["resize2fs"; "/dev/VG/LV"];
2618        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2619        ["cat"; "/new"]], "test content");
2620     InitNone, Always, TestRun (
2621       (* Make an LV smaller to test RHBZ#587484. *)
2622       [["part_disk"; "/dev/sda"; "mbr"];
2623        ["pvcreate"; "/dev/sda1"];
2624        ["vgcreate"; "VG"; "/dev/sda1"];
2625        ["lvcreate"; "LV"; "VG"; "20"];
2626        ["lvresize"; "/dev/VG/LV"; "10"]])],
2627    "resize an LVM logical volume",
2628    "\
2629 This resizes (expands or shrinks) an existing LVM logical
2630 volume to C<mbytes>.  When reducing, data in the reduced part
2631 is lost.");
2632
2633   ("resize2fs", (RErr, [Device "device"]), 106, [],
2634    [], (* lvresize tests this *)
2635    "resize an ext2/ext3 filesystem",
2636    "\
2637 This resizes an ext2 or ext3 filesystem to match the size of
2638 the underlying device.
2639
2640 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2641 on the C<device> before calling this command.  For unknown reasons
2642 C<resize2fs> sometimes gives an error about this and sometimes not.
2643 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2644 calling this function.");
2645
2646   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2647    [InitBasicFS, Always, TestOutputList (
2648       [["find"; "/"]], ["lost+found"]);
2649     InitBasicFS, Always, TestOutputList (
2650       [["touch"; "/a"];
2651        ["mkdir"; "/b"];
2652        ["touch"; "/b/c"];
2653        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2654     InitBasicFS, Always, TestOutputList (
2655       [["mkdir_p"; "/a/b/c"];
2656        ["touch"; "/a/b/c/d"];
2657        ["find"; "/a/b/"]], ["c"; "c/d"])],
2658    "find all files and directories",
2659    "\
2660 This command lists out all files and directories, recursively,
2661 starting at C<directory>.  It is essentially equivalent to
2662 running the shell command C<find directory -print> but some
2663 post-processing happens on the output, described below.
2664
2665 This returns a list of strings I<without any prefix>.  Thus
2666 if the directory structure was:
2667
2668  /tmp/a
2669  /tmp/b
2670  /tmp/c/d
2671
2672 then the returned list from C<guestfs_find> C</tmp> would be
2673 4 elements:
2674
2675  a
2676  b
2677  c
2678  c/d
2679
2680 If C<directory> is not a directory, then this command returns
2681 an error.
2682
2683 The returned list is sorted.
2684
2685 See also C<guestfs_find0>.");
2686
2687   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2688    [], (* lvresize tests this *)
2689    "check an ext2/ext3 filesystem",
2690    "\
2691 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2692 filesystem checker on C<device>, noninteractively (C<-p>),
2693 even if the filesystem appears to be clean (C<-f>).
2694
2695 This command is only needed because of C<guestfs_resize2fs>
2696 (q.v.).  Normally you should use C<guestfs_fsck>.");
2697
2698   ("sleep", (RErr, [Int "secs"]), 109, [],
2699    [InitNone, Always, TestRun (
2700       [["sleep"; "1"]])],
2701    "sleep for some seconds",
2702    "\
2703 Sleep for C<secs> seconds.");
2704
2705   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2706    [InitNone, Always, TestOutputInt (
2707       [["part_disk"; "/dev/sda"; "mbr"];
2708        ["mkfs"; "ntfs"; "/dev/sda1"];
2709        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2710     InitNone, Always, TestOutputInt (
2711       [["part_disk"; "/dev/sda"; "mbr"];
2712        ["mkfs"; "ext2"; "/dev/sda1"];
2713        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2714    "probe NTFS volume",
2715    "\
2716 This command runs the L<ntfs-3g.probe(8)> command which probes
2717 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2718 be mounted read-write, and some cannot be mounted at all).
2719
2720 C<rw> is a boolean flag.  Set it to true if you want to test
2721 if the volume can be mounted read-write.  Set it to false if
2722 you want to test if the volume can be mounted read-only.
2723
2724 The return value is an integer which C<0> if the operation
2725 would succeed, or some non-zero value documented in the
2726 L<ntfs-3g.probe(8)> manual page.");
2727
2728   ("sh", (RString "output", [String "command"]), 111, [],
2729    [], (* XXX needs tests *)
2730    "run a command via the shell",
2731    "\
2732 This call runs a command from the guest filesystem via the
2733 guest's C</bin/sh>.
2734
2735 This is like C<guestfs_command>, but passes the command to:
2736
2737  /bin/sh -c \"command\"
2738
2739 Depending on the guest's shell, this usually results in
2740 wildcards being expanded, shell expressions being interpolated
2741 and so on.
2742
2743 All the provisos about C<guestfs_command> apply to this call.");
2744
2745   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2746    [], (* XXX needs tests *)
2747    "run a command via the shell returning lines",
2748    "\
2749 This is the same as C<guestfs_sh>, but splits the result
2750 into a list of lines.
2751
2752 See also: C<guestfs_command_lines>");
2753
2754   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2755    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2756     * code in stubs.c, since all valid glob patterns must start with "/".
2757     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2758     *)
2759    [InitBasicFS, Always, TestOutputList (
2760       [["mkdir_p"; "/a/b/c"];
2761        ["touch"; "/a/b/c/d"];
2762        ["touch"; "/a/b/c/e"];
2763        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2764     InitBasicFS, Always, TestOutputList (
2765       [["mkdir_p"; "/a/b/c"];
2766        ["touch"; "/a/b/c/d"];
2767        ["touch"; "/a/b/c/e"];
2768        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2769     InitBasicFS, Always, TestOutputList (
2770       [["mkdir_p"; "/a/b/c"];
2771        ["touch"; "/a/b/c/d"];
2772        ["touch"; "/a/b/c/e"];
2773        ["glob_expand"; "/a/*/x/*"]], [])],
2774    "expand a wildcard path",
2775    "\
2776 This command searches for all the pathnames matching
2777 C<pattern> according to the wildcard expansion rules
2778 used by the shell.
2779
2780 If no paths match, then this returns an empty list
2781 (note: not an error).
2782
2783 It is just a wrapper around the C L<glob(3)> function
2784 with flags C<GLOB_MARK|GLOB_BRACE>.
2785 See that manual page for more details.");
2786
2787   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2788    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2789       [["scrub_device"; "/dev/sdc"]])],
2790    "scrub (securely wipe) a device",
2791    "\
2792 This command writes patterns over C<device> to make data retrieval
2793 more difficult.
2794
2795 It is an interface to the L<scrub(1)> program.  See that
2796 manual page for more details.");
2797
2798   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2799    [InitBasicFS, Always, TestRun (
2800       [["write"; "/file"; "content"];
2801        ["scrub_file"; "/file"]])],
2802    "scrub (securely wipe) a file",
2803    "\
2804 This command writes patterns over a file to make data retrieval
2805 more difficult.
2806
2807 The file is I<removed> after scrubbing.
2808
2809 It is an interface to the L<scrub(1)> program.  See that
2810 manual page for more details.");
2811
2812   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2813    [], (* XXX needs testing *)
2814    "scrub (securely wipe) free space",
2815    "\
2816 This command creates the directory C<dir> and then fills it
2817 with files until the filesystem is full, and scrubs the files
2818 as for C<guestfs_scrub_file>, and deletes them.
2819 The intention is to scrub any free space on the partition
2820 containing C<dir>.
2821
2822 It is an interface to the L<scrub(1)> program.  See that
2823 manual page for more details.");
2824
2825   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2826    [InitBasicFS, Always, TestRun (
2827       [["mkdir"; "/tmp"];
2828        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2829    "create a temporary directory",
2830    "\
2831 This command creates a temporary directory.  The
2832 C<template> parameter should be a full pathname for the
2833 temporary directory name with the final six characters being
2834 \"XXXXXX\".
2835
2836 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2837 the second one being suitable for Windows filesystems.
2838
2839 The name of the temporary directory that was created
2840 is returned.
2841
2842 The temporary directory is created with mode 0700
2843 and is owned by root.
2844
2845 The caller is responsible for deleting the temporary
2846 directory and its contents after use.
2847
2848 See also: L<mkdtemp(3)>");
2849
2850   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2851    [InitISOFS, Always, TestOutputInt (
2852       [["wc_l"; "/10klines"]], 10000);
2853     (* Test for RHBZ#579608, absolute symbolic links. *)
2854     InitISOFS, Always, TestOutputInt (
2855       [["wc_l"; "/abssymlink"]], 10000)],
2856    "count lines in a file",
2857    "\
2858 This command counts the lines in a file, using the
2859 C<wc -l> external command.");
2860
2861   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2862    [InitISOFS, Always, TestOutputInt (
2863       [["wc_w"; "/10klines"]], 10000)],
2864    "count words in a file",
2865    "\
2866 This command counts the words in a file, using the
2867 C<wc -w> external command.");
2868
2869   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2870    [InitISOFS, Always, TestOutputInt (
2871       [["wc_c"; "/100kallspaces"]], 102400)],
2872    "count characters in a file",
2873    "\
2874 This command counts the characters in a file, using the
2875 C<wc -c> external command.");
2876
2877   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2878    [InitISOFS, Always, TestOutputList (
2879       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2880     (* Test for RHBZ#579608, absolute symbolic links. *)
2881     InitISOFS, Always, TestOutputList (
2882       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2883    "return first 10 lines of a file",
2884    "\
2885 This command returns up to the first 10 lines of a file as
2886 a list of strings.");
2887
2888   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2889    [InitISOFS, Always, TestOutputList (
2890       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2891     InitISOFS, Always, TestOutputList (
2892       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2893     InitISOFS, Always, TestOutputList (
2894       [["head_n"; "0"; "/10klines"]], [])],
2895    "return first N lines of a file",
2896    "\
2897 If the parameter C<nrlines> is a positive number, this returns the first
2898 C<nrlines> lines of the file C<path>.
2899
2900 If the parameter C<nrlines> is a negative number, this returns lines
2901 from the file C<path>, excluding the last C<nrlines> lines.
2902
2903 If the parameter C<nrlines> is zero, this returns an empty list.");
2904
2905   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2906    [InitISOFS, Always, TestOutputList (
2907       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2908    "return last 10 lines of a file",
2909    "\
2910 This command returns up to the last 10 lines of a file as
2911 a list of strings.");
2912
2913   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2914    [InitISOFS, Always, TestOutputList (
2915       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2916     InitISOFS, Always, TestOutputList (
2917       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2918     InitISOFS, Always, TestOutputList (
2919       [["tail_n"; "0"; "/10klines"]], [])],
2920    "return last N lines of a file",
2921    "\
2922 If the parameter C<nrlines> is a positive number, this returns the last
2923 C<nrlines> lines of the file C<path>.
2924
2925 If the parameter C<nrlines> is a negative number, this returns lines
2926 from the file C<path>, starting with the C<-nrlines>th line.
2927
2928 If the parameter C<nrlines> is zero, this returns an empty list.");
2929
2930   ("df", (RString "output", []), 125, [],
2931    [], (* XXX Tricky to test because it depends on the exact format
2932         * of the 'df' command and other imponderables.
2933         *)
2934    "report file system disk space usage",
2935    "\
2936 This command runs the C<df> command to report disk space used.
2937
2938 This command is mostly useful for interactive sessions.  It
2939 is I<not> intended that you try to parse the output string.
2940 Use C<statvfs> from programs.");
2941
2942   ("df_h", (RString "output", []), 126, [],
2943    [], (* XXX Tricky to test because it depends on the exact format
2944         * of the 'df' command and other imponderables.
2945         *)
2946    "report file system disk space usage (human readable)",
2947    "\
2948 This command runs the C<df -h> command to report disk space used
2949 in human-readable format.
2950
2951 This command is mostly useful for interactive sessions.  It
2952 is I<not> intended that you try to parse the output string.
2953 Use C<statvfs> from programs.");
2954
2955   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2956    [InitISOFS, Always, TestOutputInt (
2957       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2958    "estimate file space usage",
2959    "\
2960 This command runs the C<du -s> command to estimate file space
2961 usage for C<path>.
2962
2963 C<path> can be a file or a directory.  If C<path> is a directory
2964 then the estimate includes the contents of the directory and all
2965 subdirectories (recursively).
2966
2967 The result is the estimated size in I<kilobytes>
2968 (ie. units of 1024 bytes).");
2969
2970   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2971    [InitISOFS, Always, TestOutputList (
2972       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2973    "list files in an initrd",
2974    "\
2975 This command lists out files contained in an initrd.
2976
2977 The files are listed without any initial C</> character.  The
2978 files are listed in the order they appear (not necessarily
2979 alphabetical).  Directory names are listed as separate items.
2980
2981 Old Linux kernels (2.4 and earlier) used a compressed ext2
2982 filesystem as initrd.  We I<only> support the newer initramfs
2983 format (compressed cpio files).");
2984
2985   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2986    [],
2987    "mount a file using the loop device",
2988    "\
2989 This command lets you mount C<file> (a filesystem image
2990 in a file) on a mount point.  It is entirely equivalent to
2991 the command C<mount -o loop file mountpoint>.");
2992
2993   ("mkswap", (RErr, [Device "device"]), 130, [],
2994    [InitEmpty, Always, TestRun (
2995       [["part_disk"; "/dev/sda"; "mbr"];
2996        ["mkswap"; "/dev/sda1"]])],
2997    "create a swap partition",
2998    "\
2999 Create a swap partition on C<device>.");
3000
3001   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3002    [InitEmpty, Always, TestRun (
3003       [["part_disk"; "/dev/sda"; "mbr"];
3004        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3005    "create a swap partition with a label",
3006    "\
3007 Create a swap partition on C<device> with label C<label>.
3008
3009 Note that you cannot attach a swap label to a block device
3010 (eg. C</dev/sda>), just to a partition.  This appears to be
3011 a limitation of the kernel or swap tools.");
3012
3013   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3014    (let uuid = uuidgen () in
3015     [InitEmpty, Always, TestRun (
3016        [["part_disk"; "/dev/sda"; "mbr"];
3017         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3018    "create a swap partition with an explicit UUID",
3019    "\
3020 Create a swap partition on C<device> with UUID C<uuid>.");
3021
3022   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3023    [InitBasicFS, Always, TestOutputStruct (
3024       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3025        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3026        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3027     InitBasicFS, Always, TestOutputStruct (
3028       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3029        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3030    "make block, character or FIFO devices",
3031    "\
3032 This call creates block or character special devices, or
3033 named pipes (FIFOs).
3034
3035 The C<mode> parameter should be the mode, using the standard
3036 constants.  C<devmajor> and C<devminor> are the
3037 device major and minor numbers, only used when creating block
3038 and character special devices.
3039
3040 Note that, just like L<mknod(2)>, the mode must be bitwise
3041 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3042 just creates a regular file).  These constants are
3043 available in the standard Linux header files, or you can use
3044 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3045 which are wrappers around this command which bitwise OR
3046 in the appropriate constant for you.
3047
3048 The mode actually set is affected by the umask.");
3049
3050   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3051    [InitBasicFS, Always, TestOutputStruct (
3052       [["mkfifo"; "0o777"; "/node"];
3053        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3054    "make FIFO (named pipe)",
3055    "\
3056 This call creates a FIFO (named pipe) called C<path> with
3057 mode C<mode>.  It is just a convenient wrapper around
3058 C<guestfs_mknod>.
3059
3060 The mode actually set is affected by the umask.");
3061
3062   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3063    [InitBasicFS, Always, TestOutputStruct (
3064       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3065        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3066    "make block device node",
3067    "\
3068 This call creates a block device node called C<path> with
3069 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3070 It is just a convenient wrapper around C<guestfs_mknod>.
3071
3072 The mode actually set is affected by the umask.");
3073
3074   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3075    [InitBasicFS, Always, TestOutputStruct (
3076       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3077        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3078    "make char device node",
3079    "\
3080 This call creates a char device node called C<path> with
3081 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3082 It is just a convenient wrapper around C<guestfs_mknod>.
3083
3084 The mode actually set is affected by the umask.");
3085
3086   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3087    [InitEmpty, Always, TestOutputInt (
3088       [["umask"; "0o22"]], 0o22)],
3089    "set file mode creation mask (umask)",
3090    "\
3091 This function sets the mask used for creating new files and
3092 device nodes to C<mask & 0777>.
3093
3094 Typical umask values would be C<022> which creates new files
3095 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3096 C<002> which creates new files with permissions like
3097 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3098
3099 The default umask is C<022>.  This is important because it
3100 means that directories and device nodes will be created with
3101 C<0644> or C<0755> mode even if you specify C<0777>.
3102
3103 See also C<guestfs_get_umask>,
3104 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3105
3106 This call returns the previous umask.");
3107
3108   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3109    [],
3110    "read directories entries",
3111    "\
3112 This returns the list of directory entries in directory C<dir>.
3113
3114 All entries in the directory are returned, including C<.> and
3115 C<..>.  The entries are I<not> sorted, but returned in the same
3116 order as the underlying filesystem.
3117
3118 Also this call returns basic file type information about each
3119 file.  The C<ftyp> field will contain one of the following characters:
3120
3121 =over 4
3122
3123 =item 'b'
3124
3125 Block special
3126
3127 =item 'c'
3128
3129 Char special
3130
3131 =item 'd'
3132
3133 Directory
3134
3135 =item 'f'
3136
3137 FIFO (named pipe)
3138
3139 =item 'l'
3140
3141 Symbolic link
3142
3143 =item 'r'
3144
3145 Regular file
3146
3147 =item 's'
3148
3149 Socket
3150
3151 =item 'u'
3152
3153 Unknown file type
3154
3155 =item '?'
3156
3157 The L<readdir(3)> call returned a C<d_type> field with an
3158 unexpected value
3159
3160 =back
3161
3162 This function is primarily intended for use by programs.  To
3163 get a simple list of names, use C<guestfs_ls>.  To get a printable
3164 directory for human consumption, use C<guestfs_ll>.");
3165
3166   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3167    [],
3168    "create partitions on a block device",
3169    "\
3170 This is a simplified interface to the C<guestfs_sfdisk>
3171 command, where partition sizes are specified in megabytes
3172 only (rounded to the nearest cylinder) and you don't need
3173 to specify the cyls, heads and sectors parameters which
3174 were rarely if ever used anyway.
3175
3176 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3177 and C<guestfs_part_disk>");
3178
3179   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3180    [],
3181    "determine file type inside a compressed file",
3182    "\
3183 This command runs C<file> after first decompressing C<path>
3184 using C<method>.
3185
3186 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3187
3188 Since 1.0.63, use C<guestfs_file> instead which can now
3189 process compressed files.");
3190
3191   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3192    [],
3193    "list extended attributes of a file or directory",
3194    "\
3195 This call lists the extended attributes of the file or directory
3196 C<path>.
3197
3198 At the system call level, this is a combination of the
3199 L<listxattr(2)> and L<getxattr(2)> calls.
3200
3201 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3202
3203   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3204    [],
3205    "list extended attributes of a file or directory",
3206    "\
3207 This is the same as C<guestfs_getxattrs>, but if C<path>
3208 is a symbolic link, then it returns the extended attributes
3209 of the link itself.");
3210
3211   ("setxattr", (RErr, [String "xattr";
3212                        String "val"; Int "vallen"; (* will be BufferIn *)
3213                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3214    [],
3215    "set extended attribute of a file or directory",
3216    "\
3217 This call sets the extended attribute named C<xattr>
3218 of the file C<path> to the value C<val> (of length C<vallen>).
3219 The value is arbitrary 8 bit data.
3220
3221 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3222
3223   ("lsetxattr", (RErr, [String "xattr";
3224                         String "val"; Int "vallen"; (* will be BufferIn *)
3225                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3226    [],
3227    "set extended attribute of a file or directory",
3228    "\
3229 This is the same as C<guestfs_setxattr>, but if C<path>
3230 is a symbolic link, then it sets an extended attribute
3231 of the link itself.");
3232
3233   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3234    [],
3235    "remove extended attribute of a file or directory",
3236    "\
3237 This call removes the extended attribute named C<xattr>
3238 of the file C<path>.
3239
3240 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3241
3242   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3243    [],
3244    "remove extended attribute of a file or directory",
3245    "\
3246 This is the same as C<guestfs_removexattr>, but if C<path>
3247 is a symbolic link, then it removes an extended attribute
3248 of the link itself.");
3249
3250   ("mountpoints", (RHashtable "mps", []), 147, [],
3251    [],
3252    "show mountpoints",
3253    "\
3254 This call is similar to C<guestfs_mounts>.  That call returns
3255 a list of devices.  This one returns a hash table (map) of
3256 device name to directory where the device is mounted.");
3257
3258   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3259    (* This is a special case: while you would expect a parameter
3260     * of type "Pathname", that doesn't work, because it implies
3261     * NEED_ROOT in the generated calling code in stubs.c, and
3262     * this function cannot use NEED_ROOT.
3263     *)
3264    [],
3265    "create a mountpoint",
3266    "\
3267 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3268 specialized calls that can be used to create extra mountpoints
3269 before mounting the first filesystem.
3270
3271 These calls are I<only> necessary in some very limited circumstances,
3272 mainly the case where you want to mount a mix of unrelated and/or
3273 read-only filesystems together.
3274
3275 For example, live CDs often contain a \"Russian doll\" nest of
3276 filesystems, an ISO outer layer, with a squashfs image inside, with
3277 an ext2/3 image inside that.  You can unpack this as follows
3278 in guestfish:
3279
3280  add-ro Fedora-11-i686-Live.iso
3281  run
3282  mkmountpoint /cd
3283  mkmountpoint /squash
3284  mkmountpoint /ext3
3285  mount /dev/sda /cd
3286  mount-loop /cd/LiveOS/squashfs.img /squash
3287  mount-loop /squash/LiveOS/ext3fs.img /ext3
3288
3289 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3290
3291   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3292    [],
3293    "remove a mountpoint",
3294    "\
3295 This calls removes a mountpoint that was previously created
3296 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3297 for full details.");
3298
3299   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3300    [InitISOFS, Always, TestOutputBuffer (
3301       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3302     (* Test various near large, large and too large files (RHBZ#589039). *)
3303     InitBasicFS, Always, TestLastFail (
3304       [["touch"; "/a"];
3305        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3306        ["read_file"; "/a"]]);
3307     InitBasicFS, Always, TestLastFail (
3308       [["touch"; "/a"];
3309        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3310        ["read_file"; "/a"]]);
3311     InitBasicFS, Always, TestLastFail (
3312       [["touch"; "/a"];
3313        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3314        ["read_file"; "/a"]])],
3315    "read a file",
3316    "\
3317 This calls returns the contents of the file C<path> as a
3318 buffer.
3319
3320 Unlike C<guestfs_cat>, this function can correctly
3321 handle files that contain embedded ASCII NUL characters.
3322 However unlike C<guestfs_download>, this function is limited
3323 in the total size of file that can be handled.");
3324
3325   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3326    [InitISOFS, Always, TestOutputList (
3327       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3328     InitISOFS, Always, TestOutputList (
3329       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3330     (* Test for RHBZ#579608, absolute symbolic links. *)
3331     InitISOFS, Always, TestOutputList (
3332       [["grep"; "nomatch"; "/abssymlink"]], [])],
3333    "return lines matching a pattern",
3334    "\
3335 This calls the external C<grep> program and returns the
3336 matching lines.");
3337
3338   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3339    [InitISOFS, Always, TestOutputList (
3340       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3341    "return lines matching a pattern",
3342    "\
3343 This calls the external C<egrep> program and returns the
3344 matching lines.");
3345
3346   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3347    [InitISOFS, Always, TestOutputList (
3348       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3349    "return lines matching a pattern",
3350    "\
3351 This calls the external C<fgrep> program and returns the
3352 matching lines.");
3353
3354   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3355    [InitISOFS, Always, TestOutputList (
3356       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3357    "return lines matching a pattern",
3358    "\
3359 This calls the external C<grep -i> program and returns the
3360 matching lines.");
3361
3362   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3363    [InitISOFS, Always, TestOutputList (
3364       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3365    "return lines matching a pattern",
3366    "\
3367 This calls the external C<egrep -i> program and returns the
3368 matching lines.");
3369
3370   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3371    [InitISOFS, Always, TestOutputList (
3372       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3373    "return lines matching a pattern",
3374    "\
3375 This calls the external C<fgrep -i> program and returns the
3376 matching lines.");
3377
3378   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3379    [InitISOFS, Always, TestOutputList (
3380       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3381    "return lines matching a pattern",
3382    "\
3383 This calls the external C<zgrep> program and returns the
3384 matching lines.");
3385
3386   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3387    [InitISOFS, Always, TestOutputList (
3388       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3389    "return lines matching a pattern",
3390    "\
3391 This calls the external C<zegrep> program and returns the
3392 matching lines.");
3393
3394   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3395    [InitISOFS, Always, TestOutputList (
3396       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3397    "return lines matching a pattern",
3398    "\
3399 This calls the external C<zfgrep> program and returns the
3400 matching lines.");
3401
3402   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3403    [InitISOFS, Always, TestOutputList (
3404       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3405    "return lines matching a pattern",
3406    "\
3407 This calls the external C<zgrep -i> program and returns the
3408 matching lines.");
3409
3410   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3411    [InitISOFS, Always, TestOutputList (
3412       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3413    "return lines matching a pattern",
3414    "\
3415 This calls the external C<zegrep -i> program and returns the
3416 matching lines.");
3417
3418   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3419    [InitISOFS, Always, TestOutputList (
3420       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3421    "return lines matching a pattern",
3422    "\
3423 This calls the external C<zfgrep -i> program and returns the
3424 matching lines.");
3425
3426   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3427    [InitISOFS, Always, TestOutput (
3428       [["realpath"; "/../directory"]], "/directory")],
3429    "canonicalized absolute pathname",
3430    "\
3431 Return the canonicalized absolute pathname of C<path>.  The
3432 returned path has no C<.>, C<..> or symbolic link path elements.");
3433
3434   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3435    [InitBasicFS, Always, TestOutputStruct (
3436       [["touch"; "/a"];
3437        ["ln"; "/a"; "/b"];
3438        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3439    "create a hard link",
3440    "\
3441 This command creates a hard link using the C<ln> command.");
3442
3443   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3444    [InitBasicFS, Always, TestOutputStruct (
3445       [["touch"; "/a"];
3446        ["touch"; "/b"];
3447        ["ln_f"; "/a"; "/b"];
3448        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3449    "create a hard link",
3450    "\
3451 This command creates a hard link using the C<ln -f> command.
3452 The C<-f> option removes the link (C<linkname>) if it exists already.");
3453
3454   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3455    [InitBasicFS, Always, TestOutputStruct (
3456       [["touch"; "/a"];
3457        ["ln_s"; "a"; "/b"];
3458        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3459    "create a symbolic link",
3460    "\
3461 This command creates a symbolic link using the C<ln -s> command.");
3462
3463   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3464    [InitBasicFS, Always, TestOutput (
3465       [["mkdir_p"; "/a/b"];
3466        ["touch"; "/a/b/c"];
3467        ["ln_sf"; "../d"; "/a/b/c"];
3468        ["readlink"; "/a/b/c"]], "../d")],
3469    "create a symbolic link",
3470    "\
3471 This command creates a symbolic link using the C<ln -sf> command,
3472 The C<-f> option removes the link (C<linkname>) if it exists already.");
3473
3474   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3475    [] (* XXX tested above *),
3476    "read the target of a symbolic link",
3477    "\
3478 This command reads the target of a symbolic link.");
3479
3480   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3481    [InitBasicFS, Always, TestOutputStruct (
3482       [["fallocate"; "/a"; "1000000"];
3483        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3484    "preallocate a file in the guest filesystem",
3485    "\
3486 This command preallocates a file (containing zero bytes) named
3487 C<path> of size C<len> bytes.  If the file exists already, it
3488 is overwritten.
3489
3490 Do not confuse this with the guestfish-specific
3491 C<alloc> command which allocates a file in the host and
3492 attaches it as a device.");
3493
3494   ("swapon_device", (RErr, [Device "device"]), 170, [],
3495    [InitPartition, Always, TestRun (
3496       [["mkswap"; "/dev/sda1"];
3497        ["swapon_device"; "/dev/sda1"];
3498        ["swapoff_device"; "/dev/sda1"]])],
3499    "enable swap on device",
3500    "\
3501 This command enables the libguestfs appliance to use the
3502 swap device or partition named C<device>.  The increased
3503 memory is made available for all commands, for example
3504 those run using C<guestfs_command> or C<guestfs_sh>.
3505
3506 Note that you should not swap to existing guest swap
3507 partitions unless you know what you are doing.  They may
3508 contain hibernation information, or other information that
3509 the guest doesn't want you to trash.  You also risk leaking
3510 information about the host to the guest this way.  Instead,
3511 attach a new host device to the guest and swap on that.");
3512
3513   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3514    [], (* XXX tested by swapon_device *)
3515    "disable swap on device",
3516    "\
3517 This command disables the libguestfs appliance swap
3518 device or partition named C<device>.
3519 See C<guestfs_swapon_device>.");
3520
3521   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3522    [InitBasicFS, Always, TestRun (
3523       [["fallocate"; "/swap"; "8388608"];
3524        ["mkswap_file"; "/swap"];
3525        ["swapon_file"; "/swap"];
3526        ["swapoff_file"; "/swap"]])],
3527    "enable swap on file",
3528    "\
3529 This command enables swap to a file.
3530 See C<guestfs_swapon_device> for other notes.");
3531
3532   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3533    [], (* XXX tested by swapon_file *)
3534    "disable swap on file",
3535    "\
3536 This command disables the libguestfs appliance swap on file.");
3537
3538   ("swapon_label", (RErr, [String "label"]), 174, [],
3539    [InitEmpty, Always, TestRun (
3540       [["part_disk"; "/dev/sdb"; "mbr"];
3541        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3542        ["swapon_label"; "swapit"];
3543        ["swapoff_label"; "swapit"];
3544        ["zero"; "/dev/sdb"];
3545        ["blockdev_rereadpt"; "/dev/sdb"]])],
3546    "enable swap on labeled swap partition",
3547    "\
3548 This command enables swap to a labeled swap partition.
3549 See C<guestfs_swapon_device> for other notes.");
3550
3551   ("swapoff_label", (RErr, [String "label"]), 175, [],
3552    [], (* XXX tested by swapon_label *)
3553    "disable swap on labeled swap partition",
3554    "\
3555 This command disables the libguestfs appliance swap on
3556 labeled swap partition.");
3557
3558   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3559    (let uuid = uuidgen () in
3560     [InitEmpty, Always, TestRun (
3561        [["mkswap_U"; uuid; "/dev/sdb"];
3562         ["swapon_uuid"; uuid];
3563         ["swapoff_uuid"; uuid]])]),
3564    "enable swap on swap partition by UUID",
3565    "\
3566 This command enables swap to a swap partition with the given UUID.
3567 See C<guestfs_swapon_device> for other notes.");
3568
3569   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3570    [], (* XXX tested by swapon_uuid *)
3571    "disable swap on swap partition by UUID",
3572    "\
3573 This command disables the libguestfs appliance swap partition
3574 with the given UUID.");
3575
3576   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3577    [InitBasicFS, Always, TestRun (
3578       [["fallocate"; "/swap"; "8388608"];
3579        ["mkswap_file"; "/swap"]])],
3580    "create a swap file",
3581    "\
3582 Create a swap file.
3583
3584 This command just writes a swap file signature to an existing
3585 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3586
3587   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3588    [InitISOFS, Always, TestRun (
3589       [["inotify_init"; "0"]])],
3590    "create an inotify handle",
3591    "\
3592 This command creates a new inotify handle.
3593 The inotify subsystem can be used to notify events which happen to
3594 objects in the guest filesystem.
3595
3596 C<maxevents> is the maximum number of events which will be
3597 queued up between calls to C<guestfs_inotify_read> or
3598 C<guestfs_inotify_files>.
3599 If this is passed as C<0>, then the kernel (or previously set)
3600 default is used.  For Linux 2.6.29 the default was 16384 events.
3601 Beyond this limit, the kernel throws away events, but records
3602 the fact that it threw them away by setting a flag
3603 C<IN_Q_OVERFLOW> in the returned structure list (see
3604 C<guestfs_inotify_read>).
3605
3606 Before any events are generated, you have to add some
3607 watches to the internal watch list.  See:
3608 C<guestfs_inotify_add_watch>,
3609 C<guestfs_inotify_rm_watch> and
3610 C<guestfs_inotify_watch_all>.
3611
3612 Queued up events should be read periodically by calling
3613 C<guestfs_inotify_read>
3614 (or C<guestfs_inotify_files> which is just a helpful
3615 wrapper around C<guestfs_inotify_read>).  If you don't
3616 read the events out often enough then you risk the internal
3617 queue overflowing.
3618
3619 The handle should be closed after use by calling
3620 C<guestfs_inotify_close>.  This also removes any
3621 watches automatically.
3622
3623 See also L<inotify(7)> for an overview of the inotify interface
3624 as exposed by the Linux kernel, which is roughly what we expose
3625 via libguestfs.  Note that there is one global inotify handle
3626 per libguestfs instance.");
3627
3628   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3629    [InitBasicFS, Always, TestOutputList (
3630       [["inotify_init"; "0"];
3631        ["inotify_add_watch"; "/"; "1073741823"];
3632        ["touch"; "/a"];
3633        ["touch"; "/b"];
3634        ["inotify_files"]], ["a"; "b"])],
3635    "add an inotify watch",
3636    "\
3637 Watch C<path> for the events listed in C<mask>.
3638
3639 Note that if C<path> is a directory then events within that
3640 directory are watched, but this does I<not> happen recursively
3641 (in subdirectories).
3642
3643 Note for non-C or non-Linux callers: the inotify events are
3644 defined by the Linux kernel ABI and are listed in
3645 C</usr/include/sys/inotify.h>.");
3646
3647   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3648    [],
3649    "remove an inotify watch",
3650    "\
3651 Remove a previously defined inotify watch.
3652 See C<guestfs_inotify_add_watch>.");
3653
3654   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3655    [],
3656    "return list of inotify events",
3657    "\
3658 Return the complete queue of events that have happened
3659 since the previous read call.
3660
3661 If no events have happened, this returns an empty list.
3662
3663 I<Note>: In order to make sure that all events have been
3664 read, you must call this function repeatedly until it
3665 returns an empty list.  The reason is that the call will
3666 read events up to the maximum appliance-to-host message
3667 size and leave remaining events in the queue.");
3668
3669   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3670    [],
3671    "return list of watched files that had events",
3672    "\
3673 This function is a helpful wrapper around C<guestfs_inotify_read>
3674 which just returns a list of pathnames of objects that were
3675 touched.  The returned pathnames are sorted and deduplicated.");
3676
3677   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3678    [],
3679    "close the inotify handle",
3680    "\
3681 This closes the inotify handle which was previously
3682 opened by inotify_init.  It removes all watches, throws
3683 away any pending events, and deallocates all resources.");
3684
3685   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3686    [],
3687    "set SELinux security context",
3688    "\
3689 This sets the SELinux security context of the daemon
3690 to the string C<context>.
3691
3692 See the documentation about SELINUX in L<guestfs(3)>.");
3693
3694   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3695    [],
3696    "get SELinux security context",
3697    "\
3698 This gets the SELinux security context of the daemon.
3699
3700 See the documentation about SELINUX in L<guestfs(3)>,
3701 and C<guestfs_setcon>");
3702
3703   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3704    [InitEmpty, Always, TestOutput (
3705       [["part_disk"; "/dev/sda"; "mbr"];
3706        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3707        ["mount_options"; ""; "/dev/sda1"; "/"];
3708        ["write"; "/new"; "new file contents"];
3709        ["cat"; "/new"]], "new file contents")],
3710    "make a filesystem with block size",
3711    "\
3712 This call is similar to C<guestfs_mkfs>, but it allows you to
3713 control the block size of the resulting filesystem.  Supported
3714 block sizes depend on the filesystem type, but typically they
3715 are C<1024>, C<2048> or C<4096> only.");
3716
3717   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3718    [InitEmpty, Always, TestOutput (
3719       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3720        ["mke2journal"; "4096"; "/dev/sda1"];
3721        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3722        ["mount_options"; ""; "/dev/sda2"; "/"];
3723        ["write"; "/new"; "new file contents"];
3724        ["cat"; "/new"]], "new file contents")],
3725    "make ext2/3/4 external journal",
3726    "\
3727 This creates an ext2 external journal on C<device>.  It is equivalent
3728 to the command:
3729
3730  mke2fs -O journal_dev -b blocksize device");
3731
3732   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3733    [InitEmpty, Always, TestOutput (
3734       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3735        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3736        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3737        ["mount_options"; ""; "/dev/sda2"; "/"];
3738        ["write"; "/new"; "new file contents"];
3739        ["cat"; "/new"]], "new file contents")],
3740    "make ext2/3/4 external journal with label",
3741    "\
3742 This creates an ext2 external journal on C<device> with label C<label>.");
3743
3744   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3745    (let uuid = uuidgen () in
3746     [InitEmpty, Always, TestOutput (
3747        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3748         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3749         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3750         ["mount_options"; ""; "/dev/sda2"; "/"];
3751         ["write"; "/new"; "new file contents"];
3752         ["cat"; "/new"]], "new file contents")]),
3753    "make ext2/3/4 external journal with UUID",
3754    "\
3755 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3756
3757   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3758    [],
3759    "make ext2/3/4 filesystem with external journal",
3760    "\
3761 This creates an ext2/3/4 filesystem on C<device> with
3762 an external journal on C<journal>.  It is equivalent
3763 to the command:
3764
3765  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3766
3767 See also C<guestfs_mke2journal>.");
3768
3769   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3770    [],
3771    "make ext2/3/4 filesystem with external journal",
3772    "\
3773 This creates an ext2/3/4 filesystem on C<device> with
3774 an external journal on the journal labeled C<label>.
3775
3776 See also C<guestfs_mke2journal_L>.");
3777
3778   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3779    [],
3780    "make ext2/3/4 filesystem with external journal",
3781    "\
3782 This creates an ext2/3/4 filesystem on C<device> with
3783 an external journal on the journal with UUID C<uuid>.
3784
3785 See also C<guestfs_mke2journal_U>.");
3786
3787   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3788    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3789    "load a kernel module",
3790    "\
3791 This loads a kernel module in the appliance.
3792
3793 The kernel module must have been whitelisted when libguestfs
3794 was built (see C<appliance/kmod.whitelist.in> in the source).");
3795
3796   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3797    [InitNone, Always, TestOutput (
3798       [["echo_daemon"; "This is a test"]], "This is a test"
3799     )],
3800    "echo arguments back to the client",
3801    "\
3802 This command concatenates the list of C<words> passed with single spaces
3803 between them and returns the resulting string.
3804
3805 You can use this command to test the connection through to the daemon.
3806
3807 See also C<guestfs_ping_daemon>.");
3808
3809   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3810    [], (* There is a regression test for this. *)
3811    "find all files and directories, returning NUL-separated list",
3812    "\
3813 This command lists out all files and directories, recursively,
3814 starting at C<directory>, placing the resulting list in the
3815 external file called C<files>.
3816
3817 This command works the same way as C<guestfs_find> with the
3818 following exceptions:
3819
3820 =over 4
3821
3822 =item *
3823
3824 The resulting list is written to an external file.
3825
3826 =item *
3827
3828 Items (filenames) in the result are separated
3829 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3830
3831 =item *
3832
3833 This command is not limited in the number of names that it
3834 can return.
3835
3836 =item *
3837
3838 The result list is not sorted.
3839
3840 =back");
3841
3842   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3843    [InitISOFS, Always, TestOutput (
3844       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3845     InitISOFS, Always, TestOutput (
3846       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3847     InitISOFS, Always, TestOutput (
3848       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3849     InitISOFS, Always, TestLastFail (
3850       [["case_sensitive_path"; "/Known-1/"]]);
3851     InitBasicFS, Always, TestOutput (
3852       [["mkdir"; "/a"];
3853        ["mkdir"; "/a/bbb"];
3854        ["touch"; "/a/bbb/c"];
3855        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3856     InitBasicFS, Always, TestOutput (
3857       [["mkdir"; "/a"];
3858        ["mkdir"; "/a/bbb"];
3859        ["touch"; "/a/bbb/c"];
3860        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3861     InitBasicFS, Always, TestLastFail (
3862       [["mkdir"; "/a"];
3863        ["mkdir"; "/a/bbb"];
3864        ["touch"; "/a/bbb/c"];
3865        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3866    "return true path on case-insensitive filesystem",
3867    "\
3868 This can be used to resolve case insensitive paths on
3869 a filesystem which is case sensitive.  The use case is
3870 to resolve paths which you have read from Windows configuration
3871 files or the Windows Registry, to the true path.
3872
3873 The command handles a peculiarity of the Linux ntfs-3g
3874 filesystem driver (and probably others), which is that although
3875 the underlying filesystem is case-insensitive, the driver
3876 exports the filesystem to Linux as case-sensitive.
3877
3878 One consequence of this is that special directories such
3879 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3880 (or other things) depending on the precise details of how
3881 they were created.  In Windows itself this would not be
3882 a problem.
3883
3884 Bug or feature?  You decide:
3885 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3886
3887 This function resolves the true case of each element in the
3888 path and returns the case-sensitive path.
3889
3890 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3891 might return C<\"/WINDOWS/system32\"> (the exact return value
3892 would depend on details of how the directories were originally
3893 created under Windows).
3894
3895 I<Note>:
3896 This function does not handle drive names, backslashes etc.
3897
3898 See also C<guestfs_realpath>.");
3899
3900   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3901    [InitBasicFS, Always, TestOutput (
3902       [["vfs_type"; "/dev/sda1"]], "ext2")],
3903    "get the Linux VFS type corresponding to a mounted device",
3904    "\
3905 This command gets the block device type corresponding to
3906 a mounted device called C<device>.
3907
3908 Usually the result is the name of the Linux VFS module that
3909 is used to mount this device (probably determined automatically
3910 if you used the C<guestfs_mount> call).");
3911
3912   ("truncate", (RErr, [Pathname "path"]), 199, [],
3913    [InitBasicFS, Always, TestOutputStruct (
3914       [["write"; "/test"; "some stuff so size is not zero"];
3915        ["truncate"; "/test"];
3916        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3917    "truncate a file to zero size",
3918    "\
3919 This command truncates C<path> to a zero-length file.  The
3920 file must exist already.");
3921
3922   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3923    [InitBasicFS, Always, TestOutputStruct (
3924       [["touch"; "/test"];
3925        ["truncate_size"; "/test"; "1000"];
3926        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3927    "truncate a file to a particular size",
3928    "\
3929 This command truncates C<path> to size C<size> bytes.  The file
3930 must exist already.
3931
3932 If the current file size is less than C<size> then
3933 the file is extended to the required size with zero bytes.
3934 This creates a sparse file (ie. disk blocks are not allocated
3935 for the file until you write to it).  To create a non-sparse
3936 file of zeroes, use C<guestfs_fallocate64> instead.");
3937
3938   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3939    [InitBasicFS, Always, TestOutputStruct (
3940       [["touch"; "/test"];
3941        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3942        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3943    "set timestamp of a file with nanosecond precision",
3944    "\
3945 This command sets the timestamps of a file with nanosecond
3946 precision.
3947
3948 C<atsecs, atnsecs> are the last access time (atime) in secs and
3949 nanoseconds from the epoch.
3950
3951 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3952 secs and nanoseconds from the epoch.
3953
3954 If the C<*nsecs> field contains the special value C<-1> then
3955 the corresponding timestamp is set to the current time.  (The
3956 C<*secs> field is ignored in this case).
3957
3958 If the C<*nsecs> field contains the special value C<-2> then
3959 the corresponding timestamp is left unchanged.  (The
3960 C<*secs> field is ignored in this case).");
3961
3962   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3963    [InitBasicFS, Always, TestOutputStruct (
3964       [["mkdir_mode"; "/test"; "0o111"];
3965        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3966    "create a directory with a particular mode",
3967    "\
3968 This command creates a directory, setting the initial permissions
3969 of the directory to C<mode>.
3970
3971 For common Linux filesystems, the actual mode which is set will
3972 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3973 interpret the mode in other ways.
3974
3975 See also C<guestfs_mkdir>, C<guestfs_umask>");
3976
3977   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3978    [], (* XXX *)
3979    "change file owner and group",
3980    "\
3981 Change the file owner to C<owner> and group to C<group>.
3982 This is like C<guestfs_chown> but if C<path> is a symlink then
3983 the link itself is changed, not the target.
3984
3985 Only numeric uid and gid are supported.  If you want to use
3986 names, you will need to locate and parse the password file
3987 yourself (Augeas support makes this relatively easy).");
3988
3989   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3990    [], (* XXX *)
3991    "lstat on multiple files",
3992    "\
3993 This call allows you to perform the C<guestfs_lstat> operation
3994 on multiple files, where all files are in the directory C<path>.
3995 C<names> is the list of files from this directory.
3996
3997 On return you get a list of stat structs, with a one-to-one
3998 correspondence to the C<names> list.  If any name did not exist
3999 or could not be lstat'd, then the C<ino> field of that structure
4000 is set to C<-1>.
4001
4002 This call is intended for programs that want to efficiently
4003 list a directory contents without making many round-trips.
4004 See also C<guestfs_lxattrlist> for a similarly efficient call
4005 for getting extended attributes.  Very long directory listings
4006 might cause the protocol message size to be exceeded, causing
4007 this call to fail.  The caller must split up such requests
4008 into smaller groups of names.");
4009
4010   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4011    [], (* XXX *)
4012    "lgetxattr on multiple files",
4013    "\
4014 This call allows you to get the extended attributes
4015 of multiple files, where all files are in the directory C<path>.
4016 C<names> is the list of files from this directory.
4017
4018 On return you get a flat list of xattr structs which must be
4019 interpreted sequentially.  The first xattr struct always has a zero-length
4020 C<attrname>.  C<attrval> in this struct is zero-length
4021 to indicate there was an error doing C<lgetxattr> for this
4022 file, I<or> is a C string which is a decimal number
4023 (the number of following attributes for this file, which could
4024 be C<\"0\">).  Then after the first xattr struct are the
4025 zero or more attributes for the first named file.
4026 This repeats for the second and subsequent files.
4027
4028 This call is intended for programs that want to efficiently
4029 list a directory contents without making many round-trips.
4030 See also C<guestfs_lstatlist> for a similarly efficient call
4031 for getting standard stats.  Very long directory listings
4032 might cause the protocol message size to be exceeded, causing
4033 this call to fail.  The caller must split up such requests
4034 into smaller groups of names.");
4035
4036   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4037    [], (* XXX *)
4038    "readlink on multiple files",
4039    "\
4040 This call allows you to do a C<readlink> operation
4041 on multiple files, where all files are in the directory C<path>.
4042 C<names> is the list of files from this directory.
4043
4044 On return you get a list of strings, with a one-to-one
4045 correspondence to the C<names> list.  Each string is the
4046 value of the symbolic link.
4047
4048 If the C<readlink(2)> operation fails on any name, then
4049 the corresponding result string is the empty string C<\"\">.
4050 However the whole operation is completed even if there
4051 were C<readlink(2)> errors, and so you can call this
4052 function with names where you don't know if they are
4053 symbolic links already (albeit slightly less efficient).
4054
4055 This call is intended for programs that want to efficiently
4056 list a directory contents without making many round-trips.
4057 Very long directory listings might cause the protocol
4058 message size to be exceeded, causing
4059 this call to fail.  The caller must split up such requests
4060 into smaller groups of names.");
4061
4062   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4063    [InitISOFS, Always, TestOutputBuffer (
4064       [["pread"; "/known-4"; "1"; "3"]], "\n");
4065     InitISOFS, Always, TestOutputBuffer (
4066       [["pread"; "/empty"; "0"; "100"]], "")],
4067    "read part of a file",
4068    "\
4069 This command lets you read part of a file.  It reads C<count>
4070 bytes of the file, starting at C<offset>, from file C<path>.
4071
4072 This may read fewer bytes than requested.  For further details
4073 see the L<pread(2)> system call.
4074
4075 See also C<guestfs_pwrite>.");
4076
4077   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4078    [InitEmpty, Always, TestRun (
4079       [["part_init"; "/dev/sda"; "gpt"]])],
4080    "create an empty partition table",
4081    "\
4082 This creates an empty partition table on C<device> of one of the
4083 partition types listed below.  Usually C<parttype> should be
4084 either C<msdos> or C<gpt> (for large disks).
4085
4086 Initially there are no partitions.  Following this, you should
4087 call C<guestfs_part_add> for each partition required.
4088
4089 Possible values for C<parttype> are:
4090
4091 =over 4
4092
4093 =item B<efi> | B<gpt>
4094
4095 Intel EFI / GPT partition table.
4096
4097 This is recommended for >= 2 TB partitions that will be accessed
4098 from Linux and Intel-based Mac OS X.  It also has limited backwards
4099 compatibility with the C<mbr> format.
4100
4101 =item B<mbr> | B<msdos>
4102
4103 The standard PC \"Master Boot Record\" (MBR) format used
4104 by MS-DOS and Windows.  This partition type will B<only> work
4105 for device sizes up to 2 TB.  For large disks we recommend
4106 using C<gpt>.
4107
4108 =back
4109
4110 Other partition table types that may work but are not
4111 supported include:
4112
4113 =over 4
4114
4115 =item B<aix>
4116
4117 AIX disk labels.
4118
4119 =item B<amiga> | B<rdb>
4120
4121 Amiga \"Rigid Disk Block\" format.
4122
4123 =item B<bsd>
4124
4125 BSD disk labels.
4126
4127 =item B<dasd>
4128
4129 DASD, used on IBM mainframes.
4130
4131 =item B<dvh>
4132
4133 MIPS/SGI volumes.
4134
4135 =item B<mac>
4136
4137 Old Mac partition format.  Modern Macs use C<gpt>.
4138
4139 =item B<pc98>
4140
4141 NEC PC-98 format, common in Japan apparently.
4142
4143 =item B<sun>
4144
4145 Sun disk labels.
4146
4147 =back");
4148
4149   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4150    [InitEmpty, Always, TestRun (
4151       [["part_init"; "/dev/sda"; "mbr"];
4152        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4153     InitEmpty, Always, TestRun (
4154       [["part_init"; "/dev/sda"; "gpt"];
4155        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4156        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4157     InitEmpty, Always, TestRun (
4158       [["part_init"; "/dev/sda"; "mbr"];
4159        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4160        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4161        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4162        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4163    "add a partition to the device",
4164    "\
4165 This command adds a partition to C<device>.  If there is no partition
4166 table on the device, call C<guestfs_part_init> first.
4167
4168 The C<prlogex> parameter is the type of partition.  Normally you
4169 should pass C<p> or C<primary> here, but MBR partition tables also
4170 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4171 types.
4172
4173 C<startsect> and C<endsect> are the start and end of the partition
4174 in I<sectors>.  C<endsect> may be negative, which means it counts
4175 backwards from the end of the disk (C<-1> is the last sector).
4176
4177 Creating a partition which covers the whole disk is not so easy.
4178 Use C<guestfs_part_disk> to do that.");
4179
4180   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4181    [InitEmpty, Always, TestRun (
4182       [["part_disk"; "/dev/sda"; "mbr"]]);
4183     InitEmpty, Always, TestRun (
4184       [["part_disk"; "/dev/sda"; "gpt"]])],
4185    "partition whole disk with a single primary partition",
4186    "\
4187 This command is simply a combination of C<guestfs_part_init>
4188 followed by C<guestfs_part_add> to create a single primary partition
4189 covering the whole disk.
4190
4191 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4192 but other possible values are described in C<guestfs_part_init>.");
4193
4194   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4195    [InitEmpty, Always, TestRun (
4196       [["part_disk"; "/dev/sda"; "mbr"];
4197        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4198    "make a partition bootable",
4199    "\
4200 This sets the bootable flag on partition numbered C<partnum> on
4201 device C<device>.  Note that partitions are numbered from 1.
4202
4203 The bootable flag is used by some operating systems (notably
4204 Windows) to determine which partition to boot from.  It is by
4205 no means universally recognized.");
4206
4207   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4208    [InitEmpty, Always, TestRun (
4209       [["part_disk"; "/dev/sda"; "gpt"];
4210        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4211    "set partition name",
4212    "\
4213 This sets the partition name on partition numbered C<partnum> on
4214 device C<device>.  Note that partitions are numbered from 1.
4215
4216 The partition name can only be set on certain types of partition
4217 table.  This works on C<gpt> but not on C<mbr> partitions.");
4218
4219   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4220    [], (* XXX Add a regression test for this. *)
4221    "list partitions on a device",
4222    "\
4223 This command parses the partition table on C<device> and
4224 returns the list of partitions found.
4225
4226 The fields in the returned structure are:
4227
4228 =over 4
4229
4230 =item B<part_num>
4231
4232 Partition number, counting from 1.
4233
4234 =item B<part_start>
4235
4236 Start of the partition I<in bytes>.  To get sectors you have to
4237 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4238
4239 =item B<part_end>
4240
4241 End of the partition in bytes.
4242
4243 =item B<part_size>
4244
4245 Size of the partition in bytes.
4246
4247 =back");
4248
4249   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4250    [InitEmpty, Always, TestOutput (
4251       [["part_disk"; "/dev/sda"; "gpt"];
4252        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4253    "get the partition table type",
4254    "\
4255 This command examines the partition table on C<device> and
4256 returns the partition table type (format) being used.
4257
4258 Common return values include: C<msdos> (a DOS/Windows style MBR
4259 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4260 values are possible, although unusual.  See C<guestfs_part_init>
4261 for a full list.");
4262
4263   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4264    [InitBasicFS, Always, TestOutputBuffer (
4265       [["fill"; "0x63"; "10"; "/test"];
4266        ["read_file"; "/test"]], "cccccccccc")],
4267    "fill a file with octets",
4268    "\
4269 This command creates a new file called C<path>.  The initial
4270 content of the file is C<len> octets of C<c>, where C<c>
4271 must be a number in the range C<[0..255]>.
4272
4273 To fill a file with zero bytes (sparsely), it is
4274 much more efficient to use C<guestfs_truncate_size>.
4275 To create a file with a pattern of repeating bytes
4276 use C<guestfs_fill_pattern>.");
4277
4278   ("available", (RErr, [StringList "groups"]), 216, [],
4279    [InitNone, Always, TestRun [["available"; ""]]],
4280    "test availability of some parts of the API",
4281    "\
4282 This command is used to check the availability of some
4283 groups of functionality in the appliance, which not all builds of
4284 the libguestfs appliance will be able to provide.
4285
4286 The libguestfs groups, and the functions that those
4287 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4288 You can also fetch this list at runtime by calling
4289 C<guestfs_available_all_groups>.
4290
4291 The argument C<groups> is a list of group names, eg:
4292 C<[\"inotify\", \"augeas\"]> would check for the availability of
4293 the Linux inotify functions and Augeas (configuration file
4294 editing) functions.
4295
4296 The command returns no error if I<all> requested groups are available.
4297
4298 It fails with an error if one or more of the requested
4299 groups is unavailable in the appliance.
4300
4301 If an unknown group name is included in the
4302 list of groups then an error is always returned.
4303
4304 I<Notes:>
4305
4306 =over 4
4307
4308 =item *
4309
4310 You must call C<guestfs_launch> before calling this function.
4311
4312 The reason is because we don't know what groups are
4313 supported by the appliance/daemon until it is running and can
4314 be queried.
4315
4316 =item *
4317
4318 If a group of functions is available, this does not necessarily
4319 mean that they will work.  You still have to check for errors
4320 when calling individual API functions even if they are
4321 available.
4322
4323 =item *
4324
4325 It is usually the job of distro packagers to build
4326 complete functionality into the libguestfs appliance.
4327 Upstream libguestfs, if built from source with all
4328 requirements satisfied, will support everything.
4329
4330 =item *
4331
4332 This call was added in version C<1.0.80>.  In previous
4333 versions of libguestfs all you could do would be to speculatively
4334 execute a command to find out if the daemon implemented it.
4335 See also C<guestfs_version>.
4336
4337 =back");
4338
4339   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4340    [InitBasicFS, Always, TestOutputBuffer (
4341       [["write"; "/src"; "hello, world"];
4342        ["dd"; "/src"; "/dest"];
4343        ["read_file"; "/dest"]], "hello, world")],
4344    "copy from source to destination using dd",
4345    "\
4346 This command copies from one source device or file C<src>
4347 to another destination device or file C<dest>.  Normally you
4348 would use this to copy to or from a device or partition, for
4349 example to duplicate a filesystem.
4350
4351 If the destination is a device, it must be as large or larger
4352 than the source file or device, otherwise the copy will fail.
4353 This command cannot do partial copies (see C<guestfs_copy_size>).");
4354
4355   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4356    [InitBasicFS, Always, TestOutputInt (
4357       [["write"; "/file"; "hello, world"];
4358        ["filesize"; "/file"]], 12)],
4359    "return the size of the file in bytes",
4360    "\
4361 This command returns the size of C<file> in bytes.
4362
4363 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4364 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4365 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4366
4367   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4368    [InitBasicFSonLVM, Always, TestOutputList (
4369       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4370        ["lvs"]], ["/dev/VG/LV2"])],
4371    "rename an LVM logical volume",
4372    "\
4373 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4374
4375   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4376    [InitBasicFSonLVM, Always, TestOutputList (
4377       [["umount"; "/"];
4378        ["vg_activate"; "false"; "VG"];
4379        ["vgrename"; "VG"; "VG2"];
4380        ["vg_activate"; "true"; "VG2"];
4381        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4382        ["vgs"]], ["VG2"])],
4383    "rename an LVM volume group",
4384    "\
4385 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4386
4387   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4388    [InitISOFS, Always, TestOutputBuffer (
4389       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4390    "list the contents of a single file in an initrd",
4391    "\
4392 This command unpacks the file C<filename> from the initrd file
4393 called C<initrdpath>.  The filename must be given I<without> the
4394 initial C</> character.
4395
4396 For example, in guestfish you could use the following command
4397 to examine the boot script (usually called C</init>)
4398 contained in a Linux initrd or initramfs image:
4399
4400  initrd-cat /boot/initrd-<version>.img init
4401
4402 See also C<guestfs_initrd_list>.");
4403
4404   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4405    [],
4406    "get the UUID of a physical volume",
4407    "\
4408 This command returns the UUID of the LVM PV C<device>.");
4409
4410   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4411    [],
4412    "get the UUID of a volume group",
4413    "\
4414 This command returns the UUID of the LVM VG named C<vgname>.");
4415
4416   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4417    [],
4418    "get the UUID of a logical volume",
4419    "\
4420 This command returns the UUID of the LVM LV C<device>.");
4421
4422   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4423    [],
4424    "get the PV UUIDs containing the volume group",
4425    "\
4426 Given a VG called C<vgname>, this returns the UUIDs of all
4427 the physical volumes that this volume group resides on.
4428
4429 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4430 calls to associate physical volumes and volume groups.
4431
4432 See also C<guestfs_vglvuuids>.");
4433
4434   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4435    [],
4436    "get the LV UUIDs of all LVs in the volume group",
4437    "\
4438 Given a VG called C<vgname>, this returns the UUIDs of all
4439 the logical volumes created in this volume group.
4440
4441 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4442 calls to associate logical volumes and volume groups.
4443
4444 See also C<guestfs_vgpvuuids>.");
4445
4446   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4447    [InitBasicFS, Always, TestOutputBuffer (
4448       [["write"; "/src"; "hello, world"];
4449        ["copy_size"; "/src"; "/dest"; "5"];
4450        ["read_file"; "/dest"]], "hello")],
4451    "copy size bytes from source to destination using dd",
4452    "\
4453 This command copies exactly C<size> bytes from one source device
4454 or file C<src> to another destination device or file C<dest>.
4455
4456 Note this will fail if the source is too short or if the destination
4457 is not large enough.");
4458
4459   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4460    [InitBasicFSonLVM, Always, TestRun (
4461       [["zero_device"; "/dev/VG/LV"]])],
4462    "write zeroes to an entire device",
4463    "\
4464 This command writes zeroes over the entire C<device>.  Compare
4465 with C<guestfs_zero> which just zeroes the first few blocks of
4466 a device.");
4467
4468   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4469    [InitBasicFS, Always, TestOutput (
4470       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4471        ["cat"; "/hello"]], "hello\n")],
4472    "unpack compressed tarball to directory",
4473    "\
4474 This command uploads and unpacks local file C<tarball> (an
4475 I<xz compressed> tar file) into C<directory>.");
4476
4477   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4478    [],
4479    "pack directory into compressed tarball",
4480    "\
4481 This command packs the contents of C<directory> and downloads
4482 it to local file C<tarball> (as an xz compressed tar archive).");
4483
4484   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4485    [],
4486    "resize an NTFS filesystem",
4487    "\
4488 This command resizes an NTFS filesystem, expanding or
4489 shrinking it to the size of the underlying device.
4490 See also L<ntfsresize(8)>.");
4491
4492   ("vgscan", (RErr, []), 232, [],
4493    [InitEmpty, Always, TestRun (
4494       [["vgscan"]])],
4495    "rescan for LVM physical volumes, volume groups and logical volumes",
4496    "\
4497 This rescans all block devices and rebuilds the list of LVM
4498 physical volumes, volume groups and logical volumes.");
4499
4500   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4501    [InitEmpty, Always, TestRun (
4502       [["part_init"; "/dev/sda"; "mbr"];
4503        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4504        ["part_del"; "/dev/sda"; "1"]])],
4505    "delete a partition",
4506    "\
4507 This command deletes the partition numbered C<partnum> on C<device>.
4508
4509 Note that in the case of MBR partitioning, deleting an
4510 extended partition also deletes any logical partitions
4511 it contains.");
4512
4513   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4514    [InitEmpty, Always, TestOutputTrue (
4515       [["part_init"; "/dev/sda"; "mbr"];
4516        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4517        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4518        ["part_get_bootable"; "/dev/sda"; "1"]])],
4519    "return true if a partition is bootable",
4520    "\
4521 This command returns true if the partition C<partnum> on
4522 C<device> has the bootable flag set.
4523
4524 See also C<guestfs_part_set_bootable>.");
4525
4526   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4527    [InitEmpty, Always, TestOutputInt (
4528       [["part_init"; "/dev/sda"; "mbr"];
4529        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4530        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4531        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4532    "get the MBR type byte (ID byte) from a partition",
4533    "\
4534 Returns the MBR type byte (also known as the ID byte) from
4535 the numbered partition C<partnum>.
4536
4537 Note that only MBR (old DOS-style) partitions have type bytes.
4538 You will get undefined results for other partition table
4539 types (see C<guestfs_part_get_parttype>).");
4540
4541   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4542    [], (* tested by part_get_mbr_id *)
4543    "set the MBR type byte (ID byte) of a partition",
4544    "\
4545 Sets the MBR type byte (also known as the ID byte) of
4546 the numbered partition C<partnum> to C<idbyte>.  Note
4547 that the type bytes quoted in most documentation are
4548 in fact hexadecimal numbers, but usually documented
4549 without any leading \"0x\" which might be confusing.
4550
4551 Note that only MBR (old DOS-style) partitions have type bytes.
4552 You will get undefined results for other partition table
4553 types (see C<guestfs_part_get_parttype>).");
4554
4555   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4556    [InitISOFS, Always, TestOutput (
4557       [["checksum_device"; "md5"; "/dev/sdd"]],
4558       (Digest.to_hex (Digest.file "images/test.iso")))],
4559    "compute MD5, SHAx or CRC checksum of the contents of a device",
4560    "\
4561 This call computes the MD5, SHAx or CRC checksum of the
4562 contents of the device named C<device>.  For the types of
4563 checksums supported see the C<guestfs_checksum> command.");
4564
4565   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4566    [InitNone, Always, TestRun (
4567       [["part_disk"; "/dev/sda"; "mbr"];
4568        ["pvcreate"; "/dev/sda1"];
4569        ["vgcreate"; "VG"; "/dev/sda1"];
4570        ["lvcreate"; "LV"; "VG"; "10"];
4571        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4572    "expand an LV to fill free space",
4573    "\
4574 This expands an existing logical volume C<lv> so that it fills
4575 C<pc>% of the remaining free space in the volume group.  Commonly
4576 you would call this with pc = 100 which expands the logical volume
4577 as much as possible, using all remaining free space in the volume
4578 group.");
4579
4580   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4581    [], (* XXX Augeas code needs tests. *)
4582    "clear Augeas path",
4583    "\
4584 Set the value associated with C<path> to C<NULL>.  This
4585 is the same as the L<augtool(1)> C<clear> command.");
4586
4587   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4588    [InitEmpty, Always, TestOutputInt (
4589       [["get_umask"]], 0o22)],
4590    "get the current umask",
4591    "\
4592 Return the current umask.  By default the umask is C<022>
4593 unless it has been set by calling C<guestfs_umask>.");
4594
4595   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4596    [],
4597    "upload a file to the appliance (internal use only)",
4598    "\
4599 The C<guestfs_debug_upload> command uploads a file to
4600 the libguestfs appliance.
4601
4602 There is no comprehensive help for this command.  You have
4603 to look at the file C<daemon/debug.c> in the libguestfs source
4604 to find out what it is for.");
4605
4606   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4607    [InitBasicFS, Always, TestOutput (
4608       [["base64_in"; "../images/hello.b64"; "/hello"];
4609        ["cat"; "/hello"]], "hello\n")],
4610    "upload base64-encoded data to file",
4611    "\
4612 This command uploads base64-encoded data from C<base64file>
4613 to C<filename>.");
4614
4615   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4616    [],
4617    "download file and encode as base64",
4618    "\
4619 This command downloads the contents of C<filename>, writing
4620 it out to local file C<base64file> encoded as base64.");
4621
4622   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4623    [],
4624    "compute MD5, SHAx or CRC checksum of files in a directory",
4625    "\
4626 This command computes the checksums of all regular files in
4627 C<directory> and then emits a list of those checksums to
4628 the local output file C<sumsfile>.
4629
4630 This can be used for verifying the integrity of a virtual
4631 machine.  However to be properly secure you should pay
4632 attention to the output of the checksum command (it uses
4633 the ones from GNU coreutils).  In particular when the
4634 filename is not printable, coreutils uses a special
4635 backslash syntax.  For more information, see the GNU
4636 coreutils info file.");
4637
4638   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4639    [InitBasicFS, Always, TestOutputBuffer (
4640       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4641        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4642    "fill a file with a repeating pattern of bytes",
4643    "\
4644 This function is like C<guestfs_fill> except that it creates
4645 a new file of length C<len> containing the repeating pattern
4646 of bytes in C<pattern>.  The pattern is truncated if necessary
4647 to ensure the length of the file is exactly C<len> bytes.");
4648
4649   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4650    [InitBasicFS, Always, TestOutput (
4651       [["write"; "/new"; "new file contents"];
4652        ["cat"; "/new"]], "new file contents");
4653     InitBasicFS, Always, TestOutput (
4654       [["write"; "/new"; "\nnew file contents\n"];
4655        ["cat"; "/new"]], "\nnew file contents\n");
4656     InitBasicFS, Always, TestOutput (
4657       [["write"; "/new"; "\n\n"];
4658        ["cat"; "/new"]], "\n\n");
4659     InitBasicFS, Always, TestOutput (
4660       [["write"; "/new"; ""];
4661        ["cat"; "/new"]], "");
4662     InitBasicFS, Always, TestOutput (
4663       [["write"; "/new"; "\n\n\n"];
4664        ["cat"; "/new"]], "\n\n\n");
4665     InitBasicFS, Always, TestOutput (
4666       [["write"; "/new"; "\n"];
4667        ["cat"; "/new"]], "\n")],
4668    "create a new file",
4669    "\
4670 This call creates a file called C<path>.  The content of the
4671 file is the string C<content> (which can contain any 8 bit data).");
4672
4673   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4674    [InitBasicFS, Always, TestOutput (
4675       [["write"; "/new"; "new file contents"];
4676        ["pwrite"; "/new"; "data"; "4"];
4677        ["cat"; "/new"]], "new data contents");
4678     InitBasicFS, Always, TestOutput (
4679       [["write"; "/new"; "new file contents"];
4680        ["pwrite"; "/new"; "is extended"; "9"];
4681        ["cat"; "/new"]], "new file is extended");
4682     InitBasicFS, Always, TestOutput (
4683       [["write"; "/new"; "new file contents"];
4684        ["pwrite"; "/new"; ""; "4"];
4685        ["cat"; "/new"]], "new file contents")],
4686    "write to part of a file",
4687    "\
4688 This command writes to part of a file.  It writes the data
4689 buffer C<content> to the file C<path> starting at offset C<offset>.
4690
4691 This command implements the L<pwrite(2)> system call, and like
4692 that system call it may not write the full data requested.  The
4693 return value is the number of bytes that were actually written
4694 to the file.  This could even be 0, although short writes are
4695 unlikely for regular files in ordinary circumstances.
4696
4697 See also C<guestfs_pread>.");
4698
4699   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4700    [],
4701    "resize an ext2/ext3 filesystem (with size)",
4702    "\
4703 This command is the same as C<guestfs_resize2fs> except that it
4704 allows you to specify the new size (in bytes) explicitly.");
4705
4706   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4707    [],
4708    "resize an LVM physical volume (with size)",
4709    "\
4710 This command is the same as C<guestfs_pvresize> except that it
4711 allows you to specify the new size (in bytes) explicitly.");
4712
4713   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4714    [],
4715    "resize an NTFS filesystem (with size)",
4716    "\
4717 This command is the same as C<guestfs_ntfsresize> except that it
4718 allows you to specify the new size (in bytes) explicitly.");
4719
4720   ("available_all_groups", (RStringList "groups", []), 251, [],
4721    [InitNone, Always, TestRun [["available_all_groups"]]],
4722    "return a list of all optional groups",
4723    "\
4724 This command returns a list of all optional groups that this
4725 daemon knows about.  Note this returns both supported and unsupported
4726 groups.  To find out which ones the daemon can actually support
4727 you have to call C<guestfs_available> on each member of the
4728 returned list.
4729
4730 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4731
4732   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4733    [InitBasicFS, Always, TestOutputStruct (
4734       [["fallocate64"; "/a"; "1000000"];
4735        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4736    "preallocate a file in the guest filesystem",
4737    "\
4738 This command preallocates a file (containing zero bytes) named
4739 C<path> of size C<len> bytes.  If the file exists already, it
4740 is overwritten.
4741
4742 Note that this call allocates disk blocks for the file.
4743 To create a sparse file use C<guestfs_truncate_size> instead.
4744
4745 The deprecated call C<guestfs_fallocate> does the same,
4746 but owing to an oversight it only allowed 30 bit lengths
4747 to be specified, effectively limiting the maximum size
4748 of files created through that call to 1GB.
4749
4750 Do not confuse this with the guestfish-specific
4751 C<alloc> and C<sparse> commands which create
4752 a file in the host and attach it as a device.");
4753
4754 ]
4755
4756 let all_functions = non_daemon_functions @ daemon_functions
4757
4758 (* In some places we want the functions to be displayed sorted
4759  * alphabetically, so this is useful:
4760  *)
4761 let all_functions_sorted =
4762   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4763                compare n1 n2) all_functions
4764
4765 (* This is used to generate the src/MAX_PROC_NR file which
4766  * contains the maximum procedure number, a surrogate for the
4767  * ABI version number.  See src/Makefile.am for the details.
4768  *)
4769 let max_proc_nr =
4770   let proc_nrs = List.map (
4771     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4772   ) daemon_functions in
4773   List.fold_left max 0 proc_nrs
4774
4775 (* Field types for structures. *)
4776 type field =
4777   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4778   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4779   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4780   | FUInt32
4781   | FInt32
4782   | FUInt64
4783   | FInt64
4784   | FBytes                      (* Any int measure that counts bytes. *)
4785   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4786   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4787
4788 (* Because we generate extra parsing code for LVM command line tools,
4789  * we have to pull out the LVM columns separately here.
4790  *)
4791 let lvm_pv_cols = [
4792   "pv_name", FString;
4793   "pv_uuid", FUUID;
4794   "pv_fmt", FString;
4795   "pv_size", FBytes;
4796   "dev_size", FBytes;
4797   "pv_free", FBytes;
4798   "pv_used", FBytes;
4799   "pv_attr", FString (* XXX *);
4800   "pv_pe_count", FInt64;
4801   "pv_pe_alloc_count", FInt64;
4802   "pv_tags", FString;
4803   "pe_start", FBytes;
4804   "pv_mda_count", FInt64;
4805   "pv_mda_free", FBytes;
4806   (* Not in Fedora 10:
4807      "pv_mda_size", FBytes;
4808   *)
4809 ]
4810 let lvm_vg_cols = [
4811   "vg_name", FString;
4812   "vg_uuid", FUUID;
4813   "vg_fmt", FString;
4814   "vg_attr", FString (* XXX *);
4815   "vg_size", FBytes;
4816   "vg_free", FBytes;
4817   "vg_sysid", FString;
4818   "vg_extent_size", FBytes;
4819   "vg_extent_count", FInt64;
4820   "vg_free_count", FInt64;
4821   "max_lv", FInt64;
4822   "max_pv", FInt64;
4823   "pv_count", FInt64;
4824   "lv_count", FInt64;
4825   "snap_count", FInt64;
4826   "vg_seqno", FInt64;
4827   "vg_tags", FString;
4828   "vg_mda_count", FInt64;
4829   "vg_mda_free", FBytes;
4830   (* Not in Fedora 10:
4831      "vg_mda_size", FBytes;
4832   *)
4833 ]
4834 let lvm_lv_cols = [
4835   "lv_name", FString;
4836   "lv_uuid", FUUID;
4837   "lv_attr", FString (* XXX *);
4838   "lv_major", FInt64;
4839   "lv_minor", FInt64;
4840   "lv_kernel_major", FInt64;
4841   "lv_kernel_minor", FInt64;
4842   "lv_size", FBytes;
4843   "seg_count", FInt64;
4844   "origin", FString;
4845   "snap_percent", FOptPercent;
4846   "copy_percent", FOptPercent;
4847   "move_pv", FString;
4848   "lv_tags", FString;
4849   "mirror_log", FString;
4850   "modules", FString;
4851 ]
4852
4853 (* Names and fields in all structures (in RStruct and RStructList)
4854  * that we support.
4855  *)
4856 let structs = [
4857   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4858    * not use this struct in any new code.
4859    *)
4860   "int_bool", [
4861     "i", FInt32;                (* for historical compatibility *)
4862     "b", FInt32;                (* for historical compatibility *)
4863   ];
4864
4865   (* LVM PVs, VGs, LVs. *)
4866   "lvm_pv", lvm_pv_cols;
4867   "lvm_vg", lvm_vg_cols;
4868   "lvm_lv", lvm_lv_cols;
4869
4870   (* Column names and types from stat structures.
4871    * NB. Can't use things like 'st_atime' because glibc header files
4872    * define some of these as macros.  Ugh.
4873    *)
4874   "stat", [
4875     "dev", FInt64;
4876     "ino", FInt64;
4877     "mode", FInt64;
4878     "nlink", FInt64;
4879     "uid", FInt64;
4880     "gid", FInt64;
4881     "rdev", FInt64;
4882     "size", FInt64;
4883     "blksize", FInt64;
4884     "blocks", FInt64;
4885     "atime", FInt64;
4886     "mtime", FInt64;
4887     "ctime", FInt64;
4888   ];
4889   "statvfs", [
4890     "bsize", FInt64;
4891     "frsize", FInt64;
4892     "blocks", FInt64;
4893     "bfree", FInt64;
4894     "bavail", FInt64;
4895     "files", FInt64;
4896     "ffree", FInt64;
4897     "favail", FInt64;
4898     "fsid", FInt64;
4899     "flag", FInt64;
4900     "namemax", FInt64;
4901   ];
4902
4903   (* Column names in dirent structure. *)
4904   "dirent", [
4905     "ino", FInt64;
4906     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4907     "ftyp", FChar;
4908     "name", FString;
4909   ];
4910
4911   (* Version numbers. *)
4912   "version", [
4913     "major", FInt64;
4914     "minor", FInt64;
4915     "release", FInt64;
4916     "extra", FString;
4917   ];
4918
4919   (* Extended attribute. *)
4920   "xattr", [
4921     "attrname", FString;
4922     "attrval", FBuffer;
4923   ];
4924
4925   (* Inotify events. *)
4926   "inotify_event", [
4927     "in_wd", FInt64;
4928     "in_mask", FUInt32;
4929     "in_cookie", FUInt32;
4930     "in_name", FString;
4931   ];
4932
4933   (* Partition table entry. *)
4934   "partition", [
4935     "part_num", FInt32;
4936     "part_start", FBytes;
4937     "part_end", FBytes;
4938     "part_size", FBytes;
4939   ];
4940 ] (* end of structs *)
4941
4942 (* Ugh, Java has to be different ..
4943  * These names are also used by the Haskell bindings.
4944  *)
4945 let java_structs = [
4946   "int_bool", "IntBool";
4947   "lvm_pv", "PV";
4948   "lvm_vg", "VG";
4949   "lvm_lv", "LV";
4950   "stat", "Stat";
4951   "statvfs", "StatVFS";
4952   "dirent", "Dirent";
4953   "version", "Version";
4954   "xattr", "XAttr";
4955   "inotify_event", "INotifyEvent";
4956   "partition", "Partition";
4957 ]
4958
4959 (* What structs are actually returned. *)
4960 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4961
4962 (* Returns a list of RStruct/RStructList structs that are returned
4963  * by any function.  Each element of returned list is a pair:
4964  *
4965  * (structname, RStructOnly)
4966  *    == there exists function which returns RStruct (_, structname)
4967  * (structname, RStructListOnly)
4968  *    == there exists function which returns RStructList (_, structname)
4969  * (structname, RStructAndList)
4970  *    == there are functions returning both RStruct (_, structname)
4971  *                                      and RStructList (_, structname)
4972  *)
4973 let rstructs_used_by functions =
4974   (* ||| is a "logical OR" for rstructs_used_t *)
4975   let (|||) a b =
4976     match a, b with
4977     | RStructAndList, _
4978     | _, RStructAndList -> RStructAndList
4979     | RStructOnly, RStructListOnly
4980     | RStructListOnly, RStructOnly -> RStructAndList
4981     | RStructOnly, RStructOnly -> RStructOnly
4982     | RStructListOnly, RStructListOnly -> RStructListOnly
4983   in
4984
4985   let h = Hashtbl.create 13 in
4986
4987   (* if elem->oldv exists, update entry using ||| operator,
4988    * else just add elem->newv to the hash
4989    *)
4990   let update elem newv =
4991     try  let oldv = Hashtbl.find h elem in
4992          Hashtbl.replace h elem (newv ||| oldv)
4993     with Not_found -> Hashtbl.add h elem newv
4994   in
4995
4996   List.iter (
4997     fun (_, style, _, _, _, _, _) ->
4998       match fst style with
4999       | RStruct (_, structname) -> update structname RStructOnly
5000       | RStructList (_, structname) -> update structname RStructListOnly
5001       | _ -> ()
5002   ) functions;
5003
5004   (* return key->values as a list of (key,value) *)
5005   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5006
5007 (* Used for testing language bindings. *)
5008 type callt =
5009   | CallString of string
5010   | CallOptString of string option
5011   | CallStringList of string list
5012   | CallInt of int
5013   | CallInt64 of int64
5014   | CallBool of bool
5015   | CallBuffer of string
5016
5017 (* Used to memoize the result of pod2text. *)
5018 let pod2text_memo_filename = "src/.pod2text.data"
5019 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5020   try
5021     let chan = open_in pod2text_memo_filename in
5022     let v = input_value chan in
5023     close_in chan;
5024     v
5025   with
5026     _ -> Hashtbl.create 13
5027 let pod2text_memo_updated () =
5028   let chan = open_out pod2text_memo_filename in
5029   output_value chan pod2text_memo;
5030   close_out chan
5031
5032 (* Useful functions.
5033  * Note we don't want to use any external OCaml libraries which
5034  * makes this a bit harder than it should be.
5035  *)
5036 module StringMap = Map.Make (String)
5037
5038 let failwithf fs = ksprintf failwith fs
5039
5040 let unique = let i = ref 0 in fun () -> incr i; !i
5041
5042 let replace_char s c1 c2 =
5043   let s2 = String.copy s in
5044   let r = ref false in
5045   for i = 0 to String.length s2 - 1 do
5046     if String.unsafe_get s2 i = c1 then (
5047       String.unsafe_set s2 i c2;
5048       r := true
5049     )
5050   done;
5051   if not !r then s else s2
5052
5053 let isspace c =
5054   c = ' '
5055   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5056
5057 let triml ?(test = isspace) str =
5058   let i = ref 0 in
5059   let n = ref (String.length str) in
5060   while !n > 0 && test str.[!i]; do
5061     decr n;
5062     incr i
5063   done;
5064   if !i = 0 then str
5065   else String.sub str !i !n
5066
5067 let trimr ?(test = isspace) str =
5068   let n = ref (String.length str) in
5069   while !n > 0 && test str.[!n-1]; do
5070     decr n
5071   done;
5072   if !n = String.length str then str
5073   else String.sub str 0 !n
5074
5075 let trim ?(test = isspace) str =
5076   trimr ~test (triml ~test str)
5077
5078 let rec find s sub =
5079   let len = String.length s in
5080   let sublen = String.length sub in
5081   let rec loop i =
5082     if i <= len-sublen then (
5083       let rec loop2 j =
5084         if j < sublen then (
5085           if s.[i+j] = sub.[j] then loop2 (j+1)
5086           else -1
5087         ) else
5088           i (* found *)
5089       in
5090       let r = loop2 0 in
5091       if r = -1 then loop (i+1) else r
5092     ) else
5093       -1 (* not found *)
5094   in
5095   loop 0
5096
5097 let rec replace_str s s1 s2 =
5098   let len = String.length s in
5099   let sublen = String.length s1 in
5100   let i = find s s1 in
5101   if i = -1 then s
5102   else (
5103     let s' = String.sub s 0 i in
5104     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5105     s' ^ s2 ^ replace_str s'' s1 s2
5106   )
5107
5108 let rec string_split sep str =
5109   let len = String.length str in
5110   let seplen = String.length sep in
5111   let i = find str sep in
5112   if i = -1 then [str]
5113   else (
5114     let s' = String.sub str 0 i in
5115     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5116     s' :: string_split sep s''
5117   )
5118
5119 let files_equal n1 n2 =
5120   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5121   match Sys.command cmd with
5122   | 0 -> true
5123   | 1 -> false
5124   | i -> failwithf "%s: failed with error code %d" cmd i
5125
5126 let rec filter_map f = function
5127   | [] -> []
5128   | x :: xs ->
5129       match f x with
5130       | Some y -> y :: filter_map f xs
5131       | None -> filter_map f xs
5132
5133 let rec find_map f = function
5134   | [] -> raise Not_found
5135   | x :: xs ->
5136       match f x with
5137       | Some y -> y
5138       | None -> find_map f xs
5139
5140 let iteri f xs =
5141   let rec loop i = function
5142     | [] -> ()
5143     | x :: xs -> f i x; loop (i+1) xs
5144   in
5145   loop 0 xs
5146
5147 let mapi f xs =
5148   let rec loop i = function
5149     | [] -> []
5150     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5151   in
5152   loop 0 xs
5153
5154 let count_chars c str =
5155   let count = ref 0 in
5156   for i = 0 to String.length str - 1 do
5157     if c = String.unsafe_get str i then incr count
5158   done;
5159   !count
5160
5161 let explode str =
5162   let r = ref [] in
5163   for i = 0 to String.length str - 1 do
5164     let c = String.unsafe_get str i in
5165     r := c :: !r;
5166   done;
5167   List.rev !r
5168
5169 let map_chars f str =
5170   List.map f (explode str)
5171
5172 let name_of_argt = function
5173   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5174   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5175   | FileIn n | FileOut n | BufferIn n -> n
5176
5177 let java_name_of_struct typ =
5178   try List.assoc typ java_structs
5179   with Not_found ->
5180     failwithf
5181       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5182
5183 let cols_of_struct typ =
5184   try List.assoc typ structs
5185   with Not_found ->
5186     failwithf "cols_of_struct: unknown struct %s" typ
5187
5188 let seq_of_test = function
5189   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5190   | TestOutputListOfDevices (s, _)
5191   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5192   | TestOutputTrue s | TestOutputFalse s
5193   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5194   | TestOutputStruct (s, _)
5195   | TestLastFail s -> s
5196
5197 (* Handling for function flags. *)
5198 let protocol_limit_warning =
5199   "Because of the message protocol, there is a transfer limit
5200 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5201
5202 let danger_will_robinson =
5203   "B<This command is dangerous.  Without careful use you
5204 can easily destroy all your data>."
5205
5206 let deprecation_notice flags =
5207   try
5208     let alt =
5209       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5210     let txt =
5211       sprintf "This function is deprecated.
5212 In new code, use the C<%s> call instead.
5213
5214 Deprecated functions will not be removed from the API, but the
5215 fact that they are deprecated indicates that there are problems
5216 with correct use of these functions." alt in
5217     Some txt
5218   with
5219     Not_found -> None
5220
5221 (* Create list of optional groups. *)
5222 let optgroups =
5223   let h = Hashtbl.create 13 in
5224   List.iter (
5225     fun (name, _, _, flags, _, _, _) ->
5226       List.iter (
5227         function
5228         | Optional group ->
5229             let names = try Hashtbl.find h group with Not_found -> [] in
5230             Hashtbl.replace h group (name :: names)
5231         | _ -> ()
5232       ) flags
5233   ) daemon_functions;
5234   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5235   let groups =
5236     List.map (
5237       fun group -> group, List.sort compare (Hashtbl.find h group)
5238     ) groups in
5239   List.sort (fun x y -> compare (fst x) (fst y)) groups
5240
5241 (* Check function names etc. for consistency. *)
5242 let check_functions () =
5243   let contains_uppercase str =
5244     let len = String.length str in
5245     let rec loop i =
5246       if i >= len then false
5247       else (
5248         let c = str.[i] in
5249         if c >= 'A' && c <= 'Z' then true
5250         else loop (i+1)
5251       )
5252     in
5253     loop 0
5254   in
5255
5256   (* Check function names. *)
5257   List.iter (
5258     fun (name, _, _, _, _, _, _) ->
5259       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5260         failwithf "function name %s does not need 'guestfs' prefix" name;
5261       if name = "" then
5262         failwithf "function name is empty";
5263       if name.[0] < 'a' || name.[0] > 'z' then
5264         failwithf "function name %s must start with lowercase a-z" name;
5265       if String.contains name '-' then
5266         failwithf "function name %s should not contain '-', use '_' instead."
5267           name
5268   ) all_functions;
5269
5270   (* Check function parameter/return names. *)
5271   List.iter (
5272     fun (name, style, _, _, _, _, _) ->
5273       let check_arg_ret_name n =
5274         if contains_uppercase n then
5275           failwithf "%s param/ret %s should not contain uppercase chars"
5276             name n;
5277         if String.contains n '-' || String.contains n '_' then
5278           failwithf "%s param/ret %s should not contain '-' or '_'"
5279             name n;
5280         if n = "value" then
5281           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;
5282         if n = "int" || n = "char" || n = "short" || n = "long" then
5283           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5284         if n = "i" || n = "n" then
5285           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5286         if n = "argv" || n = "args" then
5287           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5288
5289         (* List Haskell, OCaml and C keywords here.
5290          * http://www.haskell.org/haskellwiki/Keywords
5291          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5292          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5293          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5294          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5295          * Omitting _-containing words, since they're handled above.
5296          * Omitting the OCaml reserved word, "val", is ok,
5297          * and saves us from renaming several parameters.
5298          *)
5299         let reserved = [
5300           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5301           "char"; "class"; "const"; "constraint"; "continue"; "data";
5302           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5303           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5304           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5305           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5306           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5307           "interface";
5308           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5309           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5310           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5311           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5312           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5313           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5314           "volatile"; "when"; "where"; "while";
5315           ] in
5316         if List.mem n reserved then
5317           failwithf "%s has param/ret using reserved word %s" name n;
5318       in
5319
5320       (match fst style with
5321        | RErr -> ()
5322        | RInt n | RInt64 n | RBool n
5323        | RConstString n | RConstOptString n | RString n
5324        | RStringList n | RStruct (n, _) | RStructList (n, _)
5325        | RHashtable n | RBufferOut n ->
5326            check_arg_ret_name n
5327       );
5328       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5329   ) all_functions;
5330
5331   (* Check short descriptions. *)
5332   List.iter (
5333     fun (name, _, _, _, _, shortdesc, _) ->
5334       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5335         failwithf "short description of %s should begin with lowercase." name;
5336       let c = shortdesc.[String.length shortdesc-1] in
5337       if c = '\n' || c = '.' then
5338         failwithf "short description of %s should not end with . or \\n." name
5339   ) all_functions;
5340
5341   (* Check long descriptions. *)
5342   List.iter (
5343     fun (name, _, _, _, _, _, longdesc) ->
5344       if longdesc.[String.length longdesc-1] = '\n' then
5345         failwithf "long description of %s should not end with \\n." name
5346   ) all_functions;
5347
5348   (* Check proc_nrs. *)
5349   List.iter (
5350     fun (name, _, proc_nr, _, _, _, _) ->
5351       if proc_nr <= 0 then
5352         failwithf "daemon function %s should have proc_nr > 0" name
5353   ) daemon_functions;
5354
5355   List.iter (
5356     fun (name, _, proc_nr, _, _, _, _) ->
5357       if proc_nr <> -1 then
5358         failwithf "non-daemon function %s should have proc_nr -1" name
5359   ) non_daemon_functions;
5360
5361   let proc_nrs =
5362     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5363       daemon_functions in
5364   let proc_nrs =
5365     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5366   let rec loop = function
5367     | [] -> ()
5368     | [_] -> ()
5369     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5370         loop rest
5371     | (name1,nr1) :: (name2,nr2) :: _ ->
5372         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5373           name1 name2 nr1 nr2
5374   in
5375   loop proc_nrs;
5376
5377   (* Check tests. *)
5378   List.iter (
5379     function
5380       (* Ignore functions that have no tests.  We generate a
5381        * warning when the user does 'make check' instead.
5382        *)
5383     | name, _, _, _, [], _, _ -> ()
5384     | name, _, _, _, tests, _, _ ->
5385         let funcs =
5386           List.map (
5387             fun (_, _, test) ->
5388               match seq_of_test test with
5389               | [] ->
5390                   failwithf "%s has a test containing an empty sequence" name
5391               | cmds -> List.map List.hd cmds
5392           ) tests in
5393         let funcs = List.flatten funcs in
5394
5395         let tested = List.mem name funcs in
5396
5397         if not tested then
5398           failwithf "function %s has tests but does not test itself" name
5399   ) all_functions
5400
5401 (* 'pr' prints to the current output file. *)
5402 let chan = ref Pervasives.stdout
5403 let lines = ref 0
5404 let pr fs =
5405   ksprintf
5406     (fun str ->
5407        let i = count_chars '\n' str in
5408        lines := !lines + i;
5409        output_string !chan str
5410     ) fs
5411
5412 let copyright_years =
5413   let this_year = 1900 + (localtime (time ())).tm_year in
5414   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5415
5416 (* Generate a header block in a number of standard styles. *)
5417 type comment_style =
5418     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5419 type license = GPLv2plus | LGPLv2plus
5420
5421 let generate_header ?(extra_inputs = []) comment license =
5422   let inputs = "src/generator.ml" :: extra_inputs in
5423   let c = match comment with
5424     | CStyle ->         pr "/* "; " *"
5425     | CPlusPlusStyle -> pr "// "; "//"
5426     | HashStyle ->      pr "# ";  "#"
5427     | OCamlStyle ->     pr "(* "; " *"
5428     | HaskellStyle ->   pr "{- "; "  " in
5429   pr "libguestfs generated file\n";
5430   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5431   List.iter (pr "%s   %s\n" c) inputs;
5432   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5433   pr "%s\n" c;
5434   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5435   pr "%s\n" c;
5436   (match license with
5437    | GPLv2plus ->
5438        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5439        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5440        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5441        pr "%s (at your option) any later version.\n" c;
5442        pr "%s\n" c;
5443        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5444        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5445        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5446        pr "%s GNU General Public License for more details.\n" c;
5447        pr "%s\n" c;
5448        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5449        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5450        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5451
5452    | LGPLv2plus ->
5453        pr "%s This library is free software; you can redistribute it and/or\n" c;
5454        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5455        pr "%s License as published by the Free Software Foundation; either\n" c;
5456        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5457        pr "%s\n" c;
5458        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5459        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5460        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5461        pr "%s Lesser General Public License for more details.\n" c;
5462        pr "%s\n" c;
5463        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5464        pr "%s License along with this library; if not, write to the Free Software\n" c;
5465        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5466   );
5467   (match comment with
5468    | CStyle -> pr " */\n"
5469    | CPlusPlusStyle
5470    | HashStyle -> ()
5471    | OCamlStyle -> pr " *)\n"
5472    | HaskellStyle -> pr "-}\n"
5473   );
5474   pr "\n"
5475
5476 (* Start of main code generation functions below this line. *)
5477
5478 (* Generate the pod documentation for the C API. *)
5479 let rec generate_actions_pod () =
5480   List.iter (
5481     fun (shortname, style, _, flags, _, _, longdesc) ->
5482       if not (List.mem NotInDocs flags) then (
5483         let name = "guestfs_" ^ shortname in
5484         pr "=head2 %s\n\n" name;
5485         pr " ";
5486         generate_prototype ~extern:false ~handle:"g" name style;
5487         pr "\n\n";
5488         pr "%s\n\n" longdesc;
5489         (match fst style with
5490          | RErr ->
5491              pr "This function returns 0 on success or -1 on error.\n\n"
5492          | RInt _ ->
5493              pr "On error this function returns -1.\n\n"
5494          | RInt64 _ ->
5495              pr "On error this function returns -1.\n\n"
5496          | RBool _ ->
5497              pr "This function returns a C truth value on success or -1 on error.\n\n"
5498          | RConstString _ ->
5499              pr "This function returns a string, or NULL on error.
5500 The string is owned by the guest handle and must I<not> be freed.\n\n"
5501          | RConstOptString _ ->
5502              pr "This function returns a string which may be NULL.
5503 There is way to return an error from this function.
5504 The string is owned by the guest handle and must I<not> be freed.\n\n"
5505          | RString _ ->
5506              pr "This function returns a string, or NULL on error.
5507 I<The caller must free the returned string after use>.\n\n"
5508          | RStringList _ ->
5509              pr "This function returns a NULL-terminated array of strings
5510 (like L<environ(3)>), or NULL if there was an error.
5511 I<The caller must free the strings and the array after use>.\n\n"
5512          | RStruct (_, typ) ->
5513              pr "This function returns a C<struct guestfs_%s *>,
5514 or NULL if there was an error.
5515 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5516          | RStructList (_, typ) ->
5517              pr "This function returns a C<struct guestfs_%s_list *>
5518 (see E<lt>guestfs-structs.hE<gt>),
5519 or NULL if there was an error.
5520 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5521          | RHashtable _ ->
5522              pr "This function returns a NULL-terminated array of
5523 strings, or NULL if there was an error.
5524 The array of strings will always have length C<2n+1>, where
5525 C<n> keys and values alternate, followed by the trailing NULL entry.
5526 I<The caller must free the strings and the array after use>.\n\n"
5527          | RBufferOut _ ->
5528              pr "This function returns a buffer, or NULL on error.
5529 The size of the returned buffer is written to C<*size_r>.
5530 I<The caller must free the returned buffer after use>.\n\n"
5531         );
5532         if List.mem ProtocolLimitWarning flags then
5533           pr "%s\n\n" protocol_limit_warning;
5534         if List.mem DangerWillRobinson flags then
5535           pr "%s\n\n" danger_will_robinson;
5536         match deprecation_notice flags with
5537         | None -> ()
5538         | Some txt -> pr "%s\n\n" txt
5539       )
5540   ) all_functions_sorted
5541
5542 and generate_structs_pod () =
5543   (* Structs documentation. *)
5544   List.iter (
5545     fun (typ, cols) ->
5546       pr "=head2 guestfs_%s\n" typ;
5547       pr "\n";
5548       pr " struct guestfs_%s {\n" typ;
5549       List.iter (
5550         function
5551         | name, FChar -> pr "   char %s;\n" name
5552         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5553         | name, FInt32 -> pr "   int32_t %s;\n" name
5554         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5555         | name, FInt64 -> pr "   int64_t %s;\n" name
5556         | name, FString -> pr "   char *%s;\n" name
5557         | name, FBuffer ->
5558             pr "   /* The next two fields describe a byte array. */\n";
5559             pr "   uint32_t %s_len;\n" name;
5560             pr "   char *%s;\n" name
5561         | name, FUUID ->
5562             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5563             pr "   char %s[32];\n" name
5564         | name, FOptPercent ->
5565             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5566             pr "   float %s;\n" name
5567       ) cols;
5568       pr " };\n";
5569       pr " \n";
5570       pr " struct guestfs_%s_list {\n" typ;
5571       pr "   uint32_t len; /* Number of elements in list. */\n";
5572       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5573       pr " };\n";
5574       pr " \n";
5575       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5576       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5577         typ typ;
5578       pr "\n"
5579   ) structs
5580
5581 and generate_availability_pod () =
5582   (* Availability documentation. *)
5583   pr "=over 4\n";
5584   pr "\n";
5585   List.iter (
5586     fun (group, functions) ->
5587       pr "=item B<%s>\n" group;
5588       pr "\n";
5589       pr "The following functions:\n";
5590       List.iter (pr "L</guestfs_%s>\n") functions;
5591       pr "\n"
5592   ) optgroups;
5593   pr "=back\n";
5594   pr "\n"
5595
5596 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5597  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5598  *
5599  * We have to use an underscore instead of a dash because otherwise
5600  * rpcgen generates incorrect code.
5601  *
5602  * This header is NOT exported to clients, but see also generate_structs_h.
5603  *)
5604 and generate_xdr () =
5605   generate_header CStyle LGPLv2plus;
5606
5607   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5608   pr "typedef string str<>;\n";
5609   pr "\n";
5610
5611   (* Internal structures. *)
5612   List.iter (
5613     function
5614     | typ, cols ->
5615         pr "struct guestfs_int_%s {\n" typ;
5616         List.iter (function
5617                    | name, FChar -> pr "  char %s;\n" name
5618                    | name, FString -> pr "  string %s<>;\n" name
5619                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5620                    | name, FUUID -> pr "  opaque %s[32];\n" name
5621                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5622                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5623                    | name, FOptPercent -> pr "  float %s;\n" name
5624                   ) cols;
5625         pr "};\n";
5626         pr "\n";
5627         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5628         pr "\n";
5629   ) structs;
5630
5631   List.iter (
5632     fun (shortname, style, _, _, _, _, _) ->
5633       let name = "guestfs_" ^ shortname in
5634
5635       (match snd style with
5636        | [] -> ()
5637        | args ->
5638            pr "struct %s_args {\n" name;
5639            List.iter (
5640              function
5641              | Pathname n | Device n | Dev_or_Path n | String n ->
5642                  pr "  string %s<>;\n" n
5643              | OptString n -> pr "  str *%s;\n" n
5644              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5645              | Bool n -> pr "  bool %s;\n" n
5646              | Int n -> pr "  int %s;\n" n
5647              | Int64 n -> pr "  hyper %s;\n" n
5648              | BufferIn n ->
5649                  pr "  opaque %s<>;\n" n
5650              | FileIn _ | FileOut _ -> ()
5651            ) args;
5652            pr "};\n\n"
5653       );
5654       (match fst style with
5655        | RErr -> ()
5656        | RInt n ->
5657            pr "struct %s_ret {\n" name;
5658            pr "  int %s;\n" n;
5659            pr "};\n\n"
5660        | RInt64 n ->
5661            pr "struct %s_ret {\n" name;
5662            pr "  hyper %s;\n" n;
5663            pr "};\n\n"
5664        | RBool n ->
5665            pr "struct %s_ret {\n" name;
5666            pr "  bool %s;\n" n;
5667            pr "};\n\n"
5668        | RConstString _ | RConstOptString _ ->
5669            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5670        | RString n ->
5671            pr "struct %s_ret {\n" name;
5672            pr "  string %s<>;\n" n;
5673            pr "};\n\n"
5674        | RStringList n ->
5675            pr "struct %s_ret {\n" name;
5676            pr "  str %s<>;\n" n;
5677            pr "};\n\n"
5678        | RStruct (n, typ) ->
5679            pr "struct %s_ret {\n" name;
5680            pr "  guestfs_int_%s %s;\n" typ n;
5681            pr "};\n\n"
5682        | RStructList (n, typ) ->
5683            pr "struct %s_ret {\n" name;
5684            pr "  guestfs_int_%s_list %s;\n" typ n;
5685            pr "};\n\n"
5686        | RHashtable n ->
5687            pr "struct %s_ret {\n" name;
5688            pr "  str %s<>;\n" n;
5689            pr "};\n\n"
5690        | RBufferOut n ->
5691            pr "struct %s_ret {\n" name;
5692            pr "  opaque %s<>;\n" n;
5693            pr "};\n\n"
5694       );
5695   ) daemon_functions;
5696
5697   (* Table of procedure numbers. *)
5698   pr "enum guestfs_procedure {\n";
5699   List.iter (
5700     fun (shortname, _, proc_nr, _, _, _, _) ->
5701       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5702   ) daemon_functions;
5703   pr "  GUESTFS_PROC_NR_PROCS\n";
5704   pr "};\n";
5705   pr "\n";
5706
5707   (* Having to choose a maximum message size is annoying for several
5708    * reasons (it limits what we can do in the API), but it (a) makes
5709    * the protocol a lot simpler, and (b) provides a bound on the size
5710    * of the daemon which operates in limited memory space.
5711    *)
5712   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5713   pr "\n";
5714
5715   (* Message header, etc. *)
5716   pr "\
5717 /* The communication protocol is now documented in the guestfs(3)
5718  * manpage.
5719  */
5720
5721 const GUESTFS_PROGRAM = 0x2000F5F5;
5722 const GUESTFS_PROTOCOL_VERSION = 1;
5723
5724 /* These constants must be larger than any possible message length. */
5725 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5726 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5727
5728 enum guestfs_message_direction {
5729   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5730   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5731 };
5732
5733 enum guestfs_message_status {
5734   GUESTFS_STATUS_OK = 0,
5735   GUESTFS_STATUS_ERROR = 1
5736 };
5737
5738 const GUESTFS_ERROR_LEN = 256;
5739
5740 struct guestfs_message_error {
5741   string error_message<GUESTFS_ERROR_LEN>;
5742 };
5743
5744 struct guestfs_message_header {
5745   unsigned prog;                     /* GUESTFS_PROGRAM */
5746   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5747   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5748   guestfs_message_direction direction;
5749   unsigned serial;                   /* message serial number */
5750   guestfs_message_status status;
5751 };
5752
5753 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5754
5755 struct guestfs_chunk {
5756   int cancel;                        /* if non-zero, transfer is cancelled */
5757   /* data size is 0 bytes if the transfer has finished successfully */
5758   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5759 };
5760 "
5761
5762 (* Generate the guestfs-structs.h file. *)
5763 and generate_structs_h () =
5764   generate_header CStyle LGPLv2plus;
5765
5766   (* This is a public exported header file containing various
5767    * structures.  The structures are carefully written to have
5768    * exactly the same in-memory format as the XDR structures that
5769    * we use on the wire to the daemon.  The reason for creating
5770    * copies of these structures here is just so we don't have to
5771    * export the whole of guestfs_protocol.h (which includes much
5772    * unrelated and XDR-dependent stuff that we don't want to be
5773    * public, or required by clients).
5774    *
5775    * To reiterate, we will pass these structures to and from the
5776    * client with a simple assignment or memcpy, so the format
5777    * must be identical to what rpcgen / the RFC defines.
5778    *)
5779
5780   (* Public structures. *)
5781   List.iter (
5782     fun (typ, cols) ->
5783       pr "struct guestfs_%s {\n" typ;
5784       List.iter (
5785         function
5786         | name, FChar -> pr "  char %s;\n" name
5787         | name, FString -> pr "  char *%s;\n" name
5788         | name, FBuffer ->
5789             pr "  uint32_t %s_len;\n" name;
5790             pr "  char *%s;\n" name
5791         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5792         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5793         | name, FInt32 -> pr "  int32_t %s;\n" name
5794         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5795         | name, FInt64 -> pr "  int64_t %s;\n" name
5796         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5797       ) cols;
5798       pr "};\n";
5799       pr "\n";
5800       pr "struct guestfs_%s_list {\n" typ;
5801       pr "  uint32_t len;\n";
5802       pr "  struct guestfs_%s *val;\n" typ;
5803       pr "};\n";
5804       pr "\n";
5805       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5806       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5807       pr "\n"
5808   ) structs
5809
5810 (* Generate the guestfs-actions.h file. *)
5811 and generate_actions_h () =
5812   generate_header CStyle LGPLv2plus;
5813   List.iter (
5814     fun (shortname, style, _, _, _, _, _) ->
5815       let name = "guestfs_" ^ shortname in
5816       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5817         name style
5818   ) all_functions
5819
5820 (* Generate the guestfs-internal-actions.h file. *)
5821 and generate_internal_actions_h () =
5822   generate_header CStyle LGPLv2plus;
5823   List.iter (
5824     fun (shortname, style, _, _, _, _, _) ->
5825       let name = "guestfs__" ^ shortname in
5826       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5827         name style
5828   ) non_daemon_functions
5829
5830 (* Generate the client-side dispatch stubs. *)
5831 and generate_client_actions () =
5832   generate_header CStyle LGPLv2plus;
5833
5834   pr "\
5835 #include <stdio.h>
5836 #include <stdlib.h>
5837 #include <stdint.h>
5838 #include <string.h>
5839 #include <inttypes.h>
5840
5841 #include \"guestfs.h\"
5842 #include \"guestfs-internal.h\"
5843 #include \"guestfs-internal-actions.h\"
5844 #include \"guestfs_protocol.h\"
5845
5846 #define error guestfs_error
5847 //#define perrorf guestfs_perrorf
5848 #define safe_malloc guestfs_safe_malloc
5849 #define safe_realloc guestfs_safe_realloc
5850 //#define safe_strdup guestfs_safe_strdup
5851 #define safe_memdup guestfs_safe_memdup
5852
5853 /* Check the return message from a call for validity. */
5854 static int
5855 check_reply_header (guestfs_h *g,
5856                     const struct guestfs_message_header *hdr,
5857                     unsigned int proc_nr, unsigned int serial)
5858 {
5859   if (hdr->prog != GUESTFS_PROGRAM) {
5860     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5861     return -1;
5862   }
5863   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5864     error (g, \"wrong protocol version (%%d/%%d)\",
5865            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5866     return -1;
5867   }
5868   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5869     error (g, \"unexpected message direction (%%d/%%d)\",
5870            hdr->direction, GUESTFS_DIRECTION_REPLY);
5871     return -1;
5872   }
5873   if (hdr->proc != proc_nr) {
5874     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5875     return -1;
5876   }
5877   if (hdr->serial != serial) {
5878     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5879     return -1;
5880   }
5881
5882   return 0;
5883 }
5884
5885 /* Check we are in the right state to run a high-level action. */
5886 static int
5887 check_state (guestfs_h *g, const char *caller)
5888 {
5889   if (!guestfs__is_ready (g)) {
5890     if (guestfs__is_config (g) || guestfs__is_launching (g))
5891       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5892         caller);
5893     else
5894       error (g, \"%%s called from the wrong state, %%d != READY\",
5895         caller, guestfs__get_state (g));
5896     return -1;
5897   }
5898   return 0;
5899 }
5900
5901 ";
5902
5903   let error_code_of = function
5904     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5905     | RConstString _ | RConstOptString _
5906     | RString _ | RStringList _
5907     | RStruct _ | RStructList _
5908     | RHashtable _ | RBufferOut _ -> "NULL"
5909   in
5910
5911   (* Generate code to check String-like parameters are not passed in
5912    * as NULL (returning an error if they are).
5913    *)
5914   let check_null_strings shortname style =
5915     let pr_newline = ref false in
5916     List.iter (
5917       function
5918       (* parameters which should not be NULL *)
5919       | String n
5920       | Device n
5921       | Pathname n
5922       | Dev_or_Path n
5923       | FileIn n
5924       | FileOut n
5925       | BufferIn n
5926       | StringList n
5927       | DeviceList n ->
5928           pr "  if (%s == NULL) {\n" n;
5929           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
5930           pr "           \"%s\", \"%s\");\n" shortname n;
5931           pr "    return %s;\n" (error_code_of (fst style));
5932           pr "  }\n";
5933           pr_newline := true
5934
5935       (* can be NULL *)
5936       | OptString _
5937
5938       (* not applicable *)
5939       | Bool _
5940       | Int _
5941       | Int64 _ -> ()
5942     ) (snd style);
5943
5944     if !pr_newline then pr "\n";
5945   in
5946
5947   (* Generate code to generate guestfish call traces. *)
5948   let trace_call shortname style =
5949     pr "  if (guestfs__get_trace (g)) {\n";
5950
5951     let needs_i =
5952       List.exists (function
5953                    | StringList _ | DeviceList _ -> true
5954                    | _ -> false) (snd style) in
5955     if needs_i then (
5956       pr "    int i;\n";
5957       pr "\n"
5958     );
5959
5960     pr "    printf (\"%s\");\n" shortname;
5961     List.iter (
5962       function
5963       | String n                        (* strings *)
5964       | Device n
5965       | Pathname n
5966       | Dev_or_Path n
5967       | FileIn n
5968       | FileOut n
5969       | BufferIn n ->
5970           (* guestfish doesn't support string escaping, so neither do we *)
5971           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5972       | OptString n ->                  (* string option *)
5973           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5974           pr "    else printf (\" null\");\n"
5975       | StringList n
5976       | DeviceList n ->                 (* string list *)
5977           pr "    putchar (' ');\n";
5978           pr "    putchar ('\"');\n";
5979           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5980           pr "      if (i > 0) putchar (' ');\n";
5981           pr "      fputs (%s[i], stdout);\n" n;
5982           pr "    }\n";
5983           pr "    putchar ('\"');\n";
5984       | Bool n ->                       (* boolean *)
5985           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5986       | Int n ->                        (* int *)
5987           pr "    printf (\" %%d\", %s);\n" n
5988       | Int64 n ->
5989           pr "    printf (\" %%\" PRIi64, %s);\n" n
5990     ) (snd style);
5991     pr "    putchar ('\\n');\n";
5992     pr "  }\n";
5993     pr "\n";
5994   in
5995
5996   (* For non-daemon functions, generate a wrapper around each function. *)
5997   List.iter (
5998     fun (shortname, style, _, _, _, _, _) ->
5999       let name = "guestfs_" ^ shortname in
6000
6001       generate_prototype ~extern:false ~semicolon:false ~newline:true
6002         ~handle:"g" name style;
6003       pr "{\n";
6004       check_null_strings shortname style;
6005       trace_call shortname style;
6006       pr "  return guestfs__%s " shortname;
6007       generate_c_call_args ~handle:"g" style;
6008       pr ";\n";
6009       pr "}\n";
6010       pr "\n"
6011   ) non_daemon_functions;
6012
6013   (* Client-side stubs for each function. *)
6014   List.iter (
6015     fun (shortname, style, _, _, _, _, _) ->
6016       let name = "guestfs_" ^ shortname in
6017       let error_code = error_code_of (fst style) in
6018
6019       (* Generate the action stub. *)
6020       generate_prototype ~extern:false ~semicolon:false ~newline:true
6021         ~handle:"g" name style;
6022
6023       pr "{\n";
6024
6025       (match snd style with
6026        | [] -> ()
6027        | _ -> pr "  struct %s_args args;\n" name
6028       );
6029
6030       pr "  guestfs_message_header hdr;\n";
6031       pr "  guestfs_message_error err;\n";
6032       let has_ret =
6033         match fst style with
6034         | RErr -> false
6035         | RConstString _ | RConstOptString _ ->
6036             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6037         | RInt _ | RInt64 _
6038         | RBool _ | RString _ | RStringList _
6039         | RStruct _ | RStructList _
6040         | RHashtable _ | RBufferOut _ ->
6041             pr "  struct %s_ret ret;\n" name;
6042             true in
6043
6044       pr "  int serial;\n";
6045       pr "  int r;\n";
6046       pr "\n";
6047       check_null_strings shortname style;
6048       trace_call shortname style;
6049       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6050         shortname error_code;
6051       pr "  guestfs___set_busy (g);\n";
6052       pr "\n";
6053
6054       (* Send the main header and arguments. *)
6055       (match snd style with
6056        | [] ->
6057            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6058              (String.uppercase shortname)
6059        | args ->
6060            List.iter (
6061              function
6062              | Pathname n | Device n | Dev_or_Path n | String n ->
6063                  pr "  args.%s = (char *) %s;\n" n n
6064              | OptString n ->
6065                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6066              | StringList n | DeviceList n ->
6067                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6068                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6069              | Bool n ->
6070                  pr "  args.%s = %s;\n" n n
6071              | Int n ->
6072                  pr "  args.%s = %s;\n" n n
6073              | Int64 n ->
6074                  pr "  args.%s = %s;\n" n n
6075              | FileIn _ | FileOut _ -> ()
6076              | BufferIn n ->
6077                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6078                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6079                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6080                    shortname;
6081                  pr "    guestfs___end_busy (g);\n";
6082                  pr "    return %s;\n" error_code;
6083                  pr "  }\n";
6084                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6085                  pr "  args.%s.%s_len = %s_size;\n" n n n
6086            ) args;
6087            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6088              (String.uppercase shortname);
6089            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6090              name;
6091       );
6092       pr "  if (serial == -1) {\n";
6093       pr "    guestfs___end_busy (g);\n";
6094       pr "    return %s;\n" error_code;
6095       pr "  }\n";
6096       pr "\n";
6097
6098       (* Send any additional files (FileIn) requested. *)
6099       let need_read_reply_label = ref false in
6100       List.iter (
6101         function
6102         | FileIn n ->
6103             pr "  r = guestfs___send_file (g, %s);\n" n;
6104             pr "  if (r == -1) {\n";
6105             pr "    guestfs___end_busy (g);\n";
6106             pr "    return %s;\n" error_code;
6107             pr "  }\n";
6108             pr "  if (r == -2) /* daemon cancelled */\n";
6109             pr "    goto read_reply;\n";
6110             need_read_reply_label := true;
6111             pr "\n";
6112         | _ -> ()
6113       ) (snd style);
6114
6115       (* Wait for the reply from the remote end. *)
6116       if !need_read_reply_label then pr " read_reply:\n";
6117       pr "  memset (&hdr, 0, sizeof hdr);\n";
6118       pr "  memset (&err, 0, sizeof err);\n";
6119       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6120       pr "\n";
6121       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6122       if not has_ret then
6123         pr "NULL, NULL"
6124       else
6125         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6126       pr ");\n";
6127
6128       pr "  if (r == -1) {\n";
6129       pr "    guestfs___end_busy (g);\n";
6130       pr "    return %s;\n" error_code;
6131       pr "  }\n";
6132       pr "\n";
6133
6134       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6135         (String.uppercase shortname);
6136       pr "    guestfs___end_busy (g);\n";
6137       pr "    return %s;\n" error_code;
6138       pr "  }\n";
6139       pr "\n";
6140
6141       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6142       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6143       pr "    free (err.error_message);\n";
6144       pr "    guestfs___end_busy (g);\n";
6145       pr "    return %s;\n" error_code;
6146       pr "  }\n";
6147       pr "\n";
6148
6149       (* Expecting to receive further files (FileOut)? *)
6150       List.iter (
6151         function
6152         | FileOut n ->
6153             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6154             pr "    guestfs___end_busy (g);\n";
6155             pr "    return %s;\n" error_code;
6156             pr "  }\n";
6157             pr "\n";
6158         | _ -> ()
6159       ) (snd style);
6160
6161       pr "  guestfs___end_busy (g);\n";
6162
6163       (match fst style with
6164        | RErr -> pr "  return 0;\n"
6165        | RInt n | RInt64 n | RBool n ->
6166            pr "  return ret.%s;\n" n
6167        | RConstString _ | RConstOptString _ ->
6168            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6169        | RString n ->
6170            pr "  return ret.%s; /* caller will free */\n" n
6171        | RStringList n | RHashtable n ->
6172            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6173            pr "  ret.%s.%s_val =\n" n n;
6174            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6175            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6176              n n;
6177            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6178            pr "  return ret.%s.%s_val;\n" n n
6179        | RStruct (n, _) ->
6180            pr "  /* caller will free this */\n";
6181            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6182        | RStructList (n, _) ->
6183            pr "  /* caller will free this */\n";
6184            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6185        | RBufferOut n ->
6186            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6187            pr "   * _val might be NULL here.  To make the API saner for\n";
6188            pr "   * callers, we turn this case into a unique pointer (using\n";
6189            pr "   * malloc(1)).\n";
6190            pr "   */\n";
6191            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6192            pr "    *size_r = ret.%s.%s_len;\n" n n;
6193            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6194            pr "  } else {\n";
6195            pr "    free (ret.%s.%s_val);\n" n n;
6196            pr "    char *p = safe_malloc (g, 1);\n";
6197            pr "    *size_r = ret.%s.%s_len;\n" n n;
6198            pr "    return p;\n";
6199            pr "  }\n";
6200       );
6201
6202       pr "}\n\n"
6203   ) daemon_functions;
6204
6205   (* Functions to free structures. *)
6206   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6207   pr " * structure format is identical to the XDR format.  See note in\n";
6208   pr " * generator.ml.\n";
6209   pr " */\n";
6210   pr "\n";
6211
6212   List.iter (
6213     fun (typ, _) ->
6214       pr "void\n";
6215       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6216       pr "{\n";
6217       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6218       pr "  free (x);\n";
6219       pr "}\n";
6220       pr "\n";
6221
6222       pr "void\n";
6223       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6224       pr "{\n";
6225       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6226       pr "  free (x);\n";
6227       pr "}\n";
6228       pr "\n";
6229
6230   ) structs;
6231
6232 (* Generate daemon/actions.h. *)
6233 and generate_daemon_actions_h () =
6234   generate_header CStyle GPLv2plus;
6235
6236   pr "#include \"../src/guestfs_protocol.h\"\n";
6237   pr "\n";
6238
6239   List.iter (
6240     fun (name, style, _, _, _, _, _) ->
6241       generate_prototype
6242         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6243         name style;
6244   ) daemon_functions
6245
6246 (* Generate the linker script which controls the visibility of
6247  * symbols in the public ABI and ensures no other symbols get
6248  * exported accidentally.
6249  *)
6250 and generate_linker_script () =
6251   generate_header HashStyle GPLv2plus;
6252
6253   let globals = [
6254     "guestfs_create";
6255     "guestfs_close";
6256     "guestfs_get_error_handler";
6257     "guestfs_get_out_of_memory_handler";
6258     "guestfs_last_error";
6259     "guestfs_set_error_handler";
6260     "guestfs_set_launch_done_callback";
6261     "guestfs_set_log_message_callback";
6262     "guestfs_set_out_of_memory_handler";
6263     "guestfs_set_subprocess_quit_callback";
6264
6265     (* Unofficial parts of the API: the bindings code use these
6266      * functions, so it is useful to export them.
6267      *)
6268     "guestfs_safe_calloc";
6269     "guestfs_safe_malloc";
6270   ] in
6271   let functions =
6272     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6273       all_functions in
6274   let structs =
6275     List.concat (
6276       List.map (fun (typ, _) ->
6277                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6278         structs
6279     ) in
6280   let globals = List.sort compare (globals @ functions @ structs) in
6281
6282   pr "{\n";
6283   pr "    global:\n";
6284   List.iter (pr "        %s;\n") globals;
6285   pr "\n";
6286
6287   pr "    local:\n";
6288   pr "        *;\n";
6289   pr "};\n"
6290
6291 (* Generate the server-side stubs. *)
6292 and generate_daemon_actions () =
6293   generate_header CStyle GPLv2plus;
6294
6295   pr "#include <config.h>\n";
6296   pr "\n";
6297   pr "#include <stdio.h>\n";
6298   pr "#include <stdlib.h>\n";
6299   pr "#include <string.h>\n";
6300   pr "#include <inttypes.h>\n";
6301   pr "#include <rpc/types.h>\n";
6302   pr "#include <rpc/xdr.h>\n";
6303   pr "\n";
6304   pr "#include \"daemon.h\"\n";
6305   pr "#include \"c-ctype.h\"\n";
6306   pr "#include \"../src/guestfs_protocol.h\"\n";
6307   pr "#include \"actions.h\"\n";
6308   pr "\n";
6309
6310   List.iter (
6311     fun (name, style, _, _, _, _, _) ->
6312       (* Generate server-side stubs. *)
6313       pr "static void %s_stub (XDR *xdr_in)\n" name;
6314       pr "{\n";
6315       let error_code =
6316         match fst style with
6317         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6318         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6319         | RBool _ -> pr "  int r;\n"; "-1"
6320         | RConstString _ | RConstOptString _ ->
6321             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6322         | RString _ -> pr "  char *r;\n"; "NULL"
6323         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6324         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6325         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6326         | RBufferOut _ ->
6327             pr "  size_t size = 1;\n";
6328             pr "  char *r;\n";
6329             "NULL" in
6330
6331       (match snd style with
6332        | [] -> ()
6333        | args ->
6334            pr "  struct guestfs_%s_args args;\n" name;
6335            List.iter (
6336              function
6337              | Device n | Dev_or_Path n
6338              | Pathname n
6339              | String n -> ()
6340              | OptString n -> pr "  char *%s;\n" n
6341              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6342              | Bool n -> pr "  int %s;\n" n
6343              | Int n -> pr "  int %s;\n" n
6344              | Int64 n -> pr "  int64_t %s;\n" n
6345              | FileIn _ | FileOut _ -> ()
6346              | BufferIn n ->
6347                  pr "  const char *%s;\n" n;
6348                  pr "  size_t %s_size;\n" n
6349            ) args
6350       );
6351       pr "\n";
6352
6353       let is_filein =
6354         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6355
6356       (match snd style with
6357        | [] -> ()
6358        | args ->
6359            pr "  memset (&args, 0, sizeof args);\n";
6360            pr "\n";
6361            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6362            if is_filein then
6363              pr "    if (cancel_receive () != -2)\n";
6364            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6365            pr "    goto done;\n";
6366            pr "  }\n";
6367            let pr_args n =
6368              pr "  char *%s = args.%s;\n" n n
6369            in
6370            let pr_list_handling_code n =
6371              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6372              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6373              pr "  if (%s == NULL) {\n" n;
6374              if is_filein then
6375                pr "    if (cancel_receive () != -2)\n";
6376              pr "      reply_with_perror (\"realloc\");\n";
6377              pr "    goto done;\n";
6378              pr "  }\n";
6379              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6380              pr "  args.%s.%s_val = %s;\n" n n n;
6381            in
6382            List.iter (
6383              function
6384              | Pathname n ->
6385                  pr_args n;
6386                  pr "  ABS_PATH (%s, %s, goto done);\n"
6387                    n (if is_filein then "cancel_receive ()" else "0");
6388              | Device n ->
6389                  pr_args n;
6390                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6391                    n (if is_filein then "cancel_receive ()" else "0");
6392              | Dev_or_Path n ->
6393                  pr_args n;
6394                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6395                    n (if is_filein then "cancel_receive ()" else "0");
6396              | String n -> pr_args n
6397              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6398              | StringList n ->
6399                  pr_list_handling_code n;
6400              | DeviceList n ->
6401                  pr_list_handling_code n;
6402                  pr "  /* Ensure that each is a device,\n";
6403                  pr "   * and perform device name translation. */\n";
6404                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6405                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6406                    (if is_filein then "cancel_receive ()" else "0");
6407                  pr "  }\n";
6408              | Bool n -> pr "  %s = args.%s;\n" n n
6409              | Int n -> pr "  %s = args.%s;\n" n n
6410              | Int64 n -> pr "  %s = args.%s;\n" n n
6411              | FileIn _ | FileOut _ -> ()
6412              | BufferIn n ->
6413                  pr "  %s = args.%s.%s_val;\n" n n n;
6414                  pr "  %s_size = args.%s.%s_len;\n" n n n
6415            ) args;
6416            pr "\n"
6417       );
6418
6419       (* this is used at least for do_equal *)
6420       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6421         (* Emit NEED_ROOT just once, even when there are two or
6422            more Pathname args *)
6423         pr "  NEED_ROOT (%s, goto done);\n"
6424           (if is_filein then "cancel_receive ()" else "0");
6425       );
6426
6427       (* Don't want to call the impl with any FileIn or FileOut
6428        * parameters, since these go "outside" the RPC protocol.
6429        *)
6430       let args' =
6431         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6432           (snd style) in
6433       pr "  r = do_%s " name;
6434       generate_c_call_args (fst style, args');
6435       pr ";\n";
6436
6437       (match fst style with
6438        | RErr | RInt _ | RInt64 _ | RBool _
6439        | RConstString _ | RConstOptString _
6440        | RString _ | RStringList _ | RHashtable _
6441        | RStruct (_, _) | RStructList (_, _) ->
6442            pr "  if (r == %s)\n" error_code;
6443            pr "    /* do_%s has already called reply_with_error */\n" name;
6444            pr "    goto done;\n";
6445            pr "\n"
6446        | RBufferOut _ ->
6447            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6448            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6449            pr "   */\n";
6450            pr "  if (size == 1 && r == %s)\n" error_code;
6451            pr "    /* do_%s has already called reply_with_error */\n" name;
6452            pr "    goto done;\n";
6453            pr "\n"
6454       );
6455
6456       (* If there are any FileOut parameters, then the impl must
6457        * send its own reply.
6458        *)
6459       let no_reply =
6460         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6461       if no_reply then
6462         pr "  /* do_%s has already sent a reply */\n" name
6463       else (
6464         match fst style with
6465         | RErr -> pr "  reply (NULL, NULL);\n"
6466         | RInt n | RInt64 n | RBool n ->
6467             pr "  struct guestfs_%s_ret ret;\n" name;
6468             pr "  ret.%s = r;\n" n;
6469             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6470               name
6471         | RConstString _ | RConstOptString _ ->
6472             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6473         | RString n ->
6474             pr "  struct guestfs_%s_ret ret;\n" name;
6475             pr "  ret.%s = r;\n" n;
6476             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6477               name;
6478             pr "  free (r);\n"
6479         | RStringList n | RHashtable n ->
6480             pr "  struct guestfs_%s_ret ret;\n" name;
6481             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6482             pr "  ret.%s.%s_val = r;\n" n n;
6483             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6484               name;
6485             pr "  free_strings (r);\n"
6486         | RStruct (n, _) ->
6487             pr "  struct guestfs_%s_ret ret;\n" name;
6488             pr "  ret.%s = *r;\n" n;
6489             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6490               name;
6491             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6492               name
6493         | RStructList (n, _) ->
6494             pr "  struct guestfs_%s_ret ret;\n" name;
6495             pr "  ret.%s = *r;\n" n;
6496             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6497               name;
6498             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6499               name
6500         | RBufferOut n ->
6501             pr "  struct guestfs_%s_ret ret;\n" name;
6502             pr "  ret.%s.%s_val = r;\n" n n;
6503             pr "  ret.%s.%s_len = size;\n" n n;
6504             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6505               name;
6506             pr "  free (r);\n"
6507       );
6508
6509       (* Free the args. *)
6510       pr "done:\n";
6511       (match snd style with
6512        | [] -> ()
6513        | _ ->
6514            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6515              name
6516       );
6517       pr "  return;\n";
6518       pr "}\n\n";
6519   ) daemon_functions;
6520
6521   (* Dispatch function. *)
6522   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6523   pr "{\n";
6524   pr "  switch (proc_nr) {\n";
6525
6526   List.iter (
6527     fun (name, style, _, _, _, _, _) ->
6528       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6529       pr "      %s_stub (xdr_in);\n" name;
6530       pr "      break;\n"
6531   ) daemon_functions;
6532
6533   pr "    default:\n";
6534   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";
6535   pr "  }\n";
6536   pr "}\n";
6537   pr "\n";
6538
6539   (* LVM columns and tokenization functions. *)
6540   (* XXX This generates crap code.  We should rethink how we
6541    * do this parsing.
6542    *)
6543   List.iter (
6544     function
6545     | typ, cols ->
6546         pr "static const char *lvm_%s_cols = \"%s\";\n"
6547           typ (String.concat "," (List.map fst cols));
6548         pr "\n";
6549
6550         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6551         pr "{\n";
6552         pr "  char *tok, *p, *next;\n";
6553         pr "  int i, j;\n";
6554         pr "\n";
6555         (*
6556           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6557           pr "\n";
6558         *)
6559         pr "  if (!str) {\n";
6560         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6561         pr "    return -1;\n";
6562         pr "  }\n";
6563         pr "  if (!*str || c_isspace (*str)) {\n";
6564         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6565         pr "    return -1;\n";
6566         pr "  }\n";
6567         pr "  tok = str;\n";
6568         List.iter (
6569           fun (name, coltype) ->
6570             pr "  if (!tok) {\n";
6571             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6572             pr "    return -1;\n";
6573             pr "  }\n";
6574             pr "  p = strchrnul (tok, ',');\n";
6575             pr "  if (*p) next = p+1; else next = NULL;\n";
6576             pr "  *p = '\\0';\n";
6577             (match coltype with
6578              | FString ->
6579                  pr "  r->%s = strdup (tok);\n" name;
6580                  pr "  if (r->%s == NULL) {\n" name;
6581                  pr "    perror (\"strdup\");\n";
6582                  pr "    return -1;\n";
6583                  pr "  }\n"
6584              | FUUID ->
6585                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6586                  pr "    if (tok[j] == '\\0') {\n";
6587                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6588                  pr "      return -1;\n";
6589                  pr "    } else if (tok[j] != '-')\n";
6590                  pr "      r->%s[i++] = tok[j];\n" name;
6591                  pr "  }\n";
6592              | FBytes ->
6593                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6594                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6595                  pr "    return -1;\n";
6596                  pr "  }\n";
6597              | FInt64 ->
6598                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6599                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6600                  pr "    return -1;\n";
6601                  pr "  }\n";
6602              | FOptPercent ->
6603                  pr "  if (tok[0] == '\\0')\n";
6604                  pr "    r->%s = -1;\n" name;
6605                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6606                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6607                  pr "    return -1;\n";
6608                  pr "  }\n";
6609              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6610                  assert false (* can never be an LVM column *)
6611             );
6612             pr "  tok = next;\n";
6613         ) cols;
6614
6615         pr "  if (tok != NULL) {\n";
6616         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6617         pr "    return -1;\n";
6618         pr "  }\n";
6619         pr "  return 0;\n";
6620         pr "}\n";
6621         pr "\n";
6622
6623         pr "guestfs_int_lvm_%s_list *\n" typ;
6624         pr "parse_command_line_%ss (void)\n" typ;
6625         pr "{\n";
6626         pr "  char *out, *err;\n";
6627         pr "  char *p, *pend;\n";
6628         pr "  int r, i;\n";
6629         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6630         pr "  void *newp;\n";
6631         pr "\n";
6632         pr "  ret = malloc (sizeof *ret);\n";
6633         pr "  if (!ret) {\n";
6634         pr "    reply_with_perror (\"malloc\");\n";
6635         pr "    return NULL;\n";
6636         pr "  }\n";
6637         pr "\n";
6638         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6639         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6640         pr "\n";
6641         pr "  r = command (&out, &err,\n";
6642         pr "           \"lvm\", \"%ss\",\n" typ;
6643         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6644         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6645         pr "  if (r == -1) {\n";
6646         pr "    reply_with_error (\"%%s\", err);\n";
6647         pr "    free (out);\n";
6648         pr "    free (err);\n";
6649         pr "    free (ret);\n";
6650         pr "    return NULL;\n";
6651         pr "  }\n";
6652         pr "\n";
6653         pr "  free (err);\n";
6654         pr "\n";
6655         pr "  /* Tokenize each line of the output. */\n";
6656         pr "  p = out;\n";
6657         pr "  i = 0;\n";
6658         pr "  while (p) {\n";
6659         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6660         pr "    if (pend) {\n";
6661         pr "      *pend = '\\0';\n";
6662         pr "      pend++;\n";
6663         pr "    }\n";
6664         pr "\n";
6665         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6666         pr "      p++;\n";
6667         pr "\n";
6668         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6669         pr "      p = pend;\n";
6670         pr "      continue;\n";
6671         pr "    }\n";
6672         pr "\n";
6673         pr "    /* Allocate some space to store this next entry. */\n";
6674         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6675         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6676         pr "    if (newp == NULL) {\n";
6677         pr "      reply_with_perror (\"realloc\");\n";
6678         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6679         pr "      free (ret);\n";
6680         pr "      free (out);\n";
6681         pr "      return NULL;\n";
6682         pr "    }\n";
6683         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6684         pr "\n";
6685         pr "    /* Tokenize the next entry. */\n";
6686         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6687         pr "    if (r == -1) {\n";
6688         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6689         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6690         pr "      free (ret);\n";
6691         pr "      free (out);\n";
6692         pr "      return NULL;\n";
6693         pr "    }\n";
6694         pr "\n";
6695         pr "    ++i;\n";
6696         pr "    p = pend;\n";
6697         pr "  }\n";
6698         pr "\n";
6699         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6700         pr "\n";
6701         pr "  free (out);\n";
6702         pr "  return ret;\n";
6703         pr "}\n"
6704
6705   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6706
6707 (* Generate a list of function names, for debugging in the daemon.. *)
6708 and generate_daemon_names () =
6709   generate_header CStyle GPLv2plus;
6710
6711   pr "#include <config.h>\n";
6712   pr "\n";
6713   pr "#include \"daemon.h\"\n";
6714   pr "\n";
6715
6716   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6717   pr "const char *function_names[] = {\n";
6718   List.iter (
6719     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6720   ) daemon_functions;
6721   pr "};\n";
6722
6723 (* Generate the optional groups for the daemon to implement
6724  * guestfs_available.
6725  *)
6726 and generate_daemon_optgroups_c () =
6727   generate_header CStyle GPLv2plus;
6728
6729   pr "#include <config.h>\n";
6730   pr "\n";
6731   pr "#include \"daemon.h\"\n";
6732   pr "#include \"optgroups.h\"\n";
6733   pr "\n";
6734
6735   pr "struct optgroup optgroups[] = {\n";
6736   List.iter (
6737     fun (group, _) ->
6738       pr "  { \"%s\", optgroup_%s_available },\n" group group
6739   ) optgroups;
6740   pr "  { NULL, NULL }\n";
6741   pr "};\n"
6742
6743 and generate_daemon_optgroups_h () =
6744   generate_header CStyle GPLv2plus;
6745
6746   List.iter (
6747     fun (group, _) ->
6748       pr "extern int optgroup_%s_available (void);\n" group
6749   ) optgroups
6750
6751 (* Generate the tests. *)
6752 and generate_tests () =
6753   generate_header CStyle GPLv2plus;
6754
6755   pr "\
6756 #include <stdio.h>
6757 #include <stdlib.h>
6758 #include <string.h>
6759 #include <unistd.h>
6760 #include <sys/types.h>
6761 #include <fcntl.h>
6762
6763 #include \"guestfs.h\"
6764 #include \"guestfs-internal.h\"
6765
6766 static guestfs_h *g;
6767 static int suppress_error = 0;
6768
6769 static void print_error (guestfs_h *g, void *data, const char *msg)
6770 {
6771   if (!suppress_error)
6772     fprintf (stderr, \"%%s\\n\", msg);
6773 }
6774
6775 /* FIXME: nearly identical code appears in fish.c */
6776 static void print_strings (char *const *argv)
6777 {
6778   int argc;
6779
6780   for (argc = 0; argv[argc] != NULL; ++argc)
6781     printf (\"\\t%%s\\n\", argv[argc]);
6782 }
6783
6784 /*
6785 static void print_table (char const *const *argv)
6786 {
6787   int i;
6788
6789   for (i = 0; argv[i] != NULL; i += 2)
6790     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6791 }
6792 */
6793
6794 ";
6795
6796   (* Generate a list of commands which are not tested anywhere. *)
6797   pr "static void no_test_warnings (void)\n";
6798   pr "{\n";
6799
6800   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6801   List.iter (
6802     fun (_, _, _, _, tests, _, _) ->
6803       let tests = filter_map (
6804         function
6805         | (_, (Always|If _|Unless _), test) -> Some test
6806         | (_, Disabled, _) -> None
6807       ) tests in
6808       let seq = List.concat (List.map seq_of_test tests) in
6809       let cmds_tested = List.map List.hd seq in
6810       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6811   ) all_functions;
6812
6813   List.iter (
6814     fun (name, _, _, _, _, _, _) ->
6815       if not (Hashtbl.mem hash name) then
6816         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6817   ) all_functions;
6818
6819   pr "}\n";
6820   pr "\n";
6821
6822   (* Generate the actual tests.  Note that we generate the tests
6823    * in reverse order, deliberately, so that (in general) the
6824    * newest tests run first.  This makes it quicker and easier to
6825    * debug them.
6826    *)
6827   let test_names =
6828     List.map (
6829       fun (name, _, _, flags, tests, _, _) ->
6830         mapi (generate_one_test name flags) tests
6831     ) (List.rev all_functions) in
6832   let test_names = List.concat test_names in
6833   let nr_tests = List.length test_names in
6834
6835   pr "\
6836 int main (int argc, char *argv[])
6837 {
6838   char c = 0;
6839   unsigned long int n_failed = 0;
6840   const char *filename;
6841   int fd;
6842   int nr_tests, test_num = 0;
6843
6844   setbuf (stdout, NULL);
6845
6846   no_test_warnings ();
6847
6848   g = guestfs_create ();
6849   if (g == NULL) {
6850     printf (\"guestfs_create FAILED\\n\");
6851     exit (EXIT_FAILURE);
6852   }
6853
6854   guestfs_set_error_handler (g, print_error, NULL);
6855
6856   guestfs_set_path (g, \"../appliance\");
6857
6858   filename = \"test1.img\";
6859   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6860   if (fd == -1) {
6861     perror (filename);
6862     exit (EXIT_FAILURE);
6863   }
6864   if (lseek (fd, %d, SEEK_SET) == -1) {
6865     perror (\"lseek\");
6866     close (fd);
6867     unlink (filename);
6868     exit (EXIT_FAILURE);
6869   }
6870   if (write (fd, &c, 1) == -1) {
6871     perror (\"write\");
6872     close (fd);
6873     unlink (filename);
6874     exit (EXIT_FAILURE);
6875   }
6876   if (close (fd) == -1) {
6877     perror (filename);
6878     unlink (filename);
6879     exit (EXIT_FAILURE);
6880   }
6881   if (guestfs_add_drive (g, filename) == -1) {
6882     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6883     exit (EXIT_FAILURE);
6884   }
6885
6886   filename = \"test2.img\";
6887   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6888   if (fd == -1) {
6889     perror (filename);
6890     exit (EXIT_FAILURE);
6891   }
6892   if (lseek (fd, %d, SEEK_SET) == -1) {
6893     perror (\"lseek\");
6894     close (fd);
6895     unlink (filename);
6896     exit (EXIT_FAILURE);
6897   }
6898   if (write (fd, &c, 1) == -1) {
6899     perror (\"write\");
6900     close (fd);
6901     unlink (filename);
6902     exit (EXIT_FAILURE);
6903   }
6904   if (close (fd) == -1) {
6905     perror (filename);
6906     unlink (filename);
6907     exit (EXIT_FAILURE);
6908   }
6909   if (guestfs_add_drive (g, filename) == -1) {
6910     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6911     exit (EXIT_FAILURE);
6912   }
6913
6914   filename = \"test3.img\";
6915   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6916   if (fd == -1) {
6917     perror (filename);
6918     exit (EXIT_FAILURE);
6919   }
6920   if (lseek (fd, %d, SEEK_SET) == -1) {
6921     perror (\"lseek\");
6922     close (fd);
6923     unlink (filename);
6924     exit (EXIT_FAILURE);
6925   }
6926   if (write (fd, &c, 1) == -1) {
6927     perror (\"write\");
6928     close (fd);
6929     unlink (filename);
6930     exit (EXIT_FAILURE);
6931   }
6932   if (close (fd) == -1) {
6933     perror (filename);
6934     unlink (filename);
6935     exit (EXIT_FAILURE);
6936   }
6937   if (guestfs_add_drive (g, filename) == -1) {
6938     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6939     exit (EXIT_FAILURE);
6940   }
6941
6942   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6943     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6944     exit (EXIT_FAILURE);
6945   }
6946
6947   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6948   alarm (600);
6949
6950   if (guestfs_launch (g) == -1) {
6951     printf (\"guestfs_launch FAILED\\n\");
6952     exit (EXIT_FAILURE);
6953   }
6954
6955   /* Cancel previous alarm. */
6956   alarm (0);
6957
6958   nr_tests = %d;
6959
6960 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6961
6962   iteri (
6963     fun i test_name ->
6964       pr "  test_num++;\n";
6965       pr "  if (guestfs_get_verbose (g))\n";
6966       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6967       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6968       pr "  if (%s () == -1) {\n" test_name;
6969       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6970       pr "    n_failed++;\n";
6971       pr "  }\n";
6972   ) test_names;
6973   pr "\n";
6974
6975   pr "  guestfs_close (g);\n";
6976   pr "  unlink (\"test1.img\");\n";
6977   pr "  unlink (\"test2.img\");\n";
6978   pr "  unlink (\"test3.img\");\n";
6979   pr "\n";
6980
6981   pr "  if (n_failed > 0) {\n";
6982   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6983   pr "    exit (EXIT_FAILURE);\n";
6984   pr "  }\n";
6985   pr "\n";
6986
6987   pr "  exit (EXIT_SUCCESS);\n";
6988   pr "}\n"
6989
6990 and generate_one_test name flags i (init, prereq, test) =
6991   let test_name = sprintf "test_%s_%d" name i in
6992
6993   pr "\
6994 static int %s_skip (void)
6995 {
6996   const char *str;
6997
6998   str = getenv (\"TEST_ONLY\");
6999   if (str)
7000     return strstr (str, \"%s\") == NULL;
7001   str = getenv (\"SKIP_%s\");
7002   if (str && STREQ (str, \"1\")) return 1;
7003   str = getenv (\"SKIP_TEST_%s\");
7004   if (str && STREQ (str, \"1\")) return 1;
7005   return 0;
7006 }
7007
7008 " test_name name (String.uppercase test_name) (String.uppercase name);
7009
7010   (match prereq with
7011    | Disabled | Always -> ()
7012    | If code | Unless code ->
7013        pr "static int %s_prereq (void)\n" test_name;
7014        pr "{\n";
7015        pr "  %s\n" code;
7016        pr "}\n";
7017        pr "\n";
7018   );
7019
7020   pr "\
7021 static int %s (void)
7022 {
7023   if (%s_skip ()) {
7024     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7025     return 0;
7026   }
7027
7028 " test_name test_name test_name;
7029
7030   (* Optional functions should only be tested if the relevant
7031    * support is available in the daemon.
7032    *)
7033   List.iter (
7034     function
7035     | Optional group ->
7036         pr "  {\n";
7037         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
7038         pr "    int r;\n";
7039         pr "    suppress_error = 1;\n";
7040         pr "    r = guestfs_available (g, (char **) groups);\n";
7041         pr "    suppress_error = 0;\n";
7042         pr "    if (r == -1) {\n";
7043         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
7044         pr "      return 0;\n";
7045         pr "    }\n";
7046         pr "  }\n";
7047     | _ -> ()
7048   ) flags;
7049
7050   (match prereq with
7051    | Disabled ->
7052        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7053    | If _ ->
7054        pr "  if (! %s_prereq ()) {\n" test_name;
7055        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7056        pr "    return 0;\n";
7057        pr "  }\n";
7058        pr "\n";
7059        generate_one_test_body name i test_name init test;
7060    | Unless _ ->
7061        pr "  if (%s_prereq ()) {\n" test_name;
7062        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7063        pr "    return 0;\n";
7064        pr "  }\n";
7065        pr "\n";
7066        generate_one_test_body name i test_name init test;
7067    | Always ->
7068        generate_one_test_body name i test_name init test
7069   );
7070
7071   pr "  return 0;\n";
7072   pr "}\n";
7073   pr "\n";
7074   test_name
7075
7076 and generate_one_test_body name i test_name init test =
7077   (match init with
7078    | InitNone (* XXX at some point, InitNone and InitEmpty became
7079                * folded together as the same thing.  Really we should
7080                * make InitNone do nothing at all, but the tests may
7081                * need to be checked to make sure this is OK.
7082                *)
7083    | InitEmpty ->
7084        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7085        List.iter (generate_test_command_call test_name)
7086          [["blockdev_setrw"; "/dev/sda"];
7087           ["umount_all"];
7088           ["lvm_remove_all"]]
7089    | InitPartition ->
7090        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7091        List.iter (generate_test_command_call test_name)
7092          [["blockdev_setrw"; "/dev/sda"];
7093           ["umount_all"];
7094           ["lvm_remove_all"];
7095           ["part_disk"; "/dev/sda"; "mbr"]]
7096    | InitBasicFS ->
7097        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7098        List.iter (generate_test_command_call test_name)
7099          [["blockdev_setrw"; "/dev/sda"];
7100           ["umount_all"];
7101           ["lvm_remove_all"];
7102           ["part_disk"; "/dev/sda"; "mbr"];
7103           ["mkfs"; "ext2"; "/dev/sda1"];
7104           ["mount_options"; ""; "/dev/sda1"; "/"]]
7105    | InitBasicFSonLVM ->
7106        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7107          test_name;
7108        List.iter (generate_test_command_call test_name)
7109          [["blockdev_setrw"; "/dev/sda"];
7110           ["umount_all"];
7111           ["lvm_remove_all"];
7112           ["part_disk"; "/dev/sda"; "mbr"];
7113           ["pvcreate"; "/dev/sda1"];
7114           ["vgcreate"; "VG"; "/dev/sda1"];
7115           ["lvcreate"; "LV"; "VG"; "8"];
7116           ["mkfs"; "ext2"; "/dev/VG/LV"];
7117           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7118    | InitISOFS ->
7119        pr "  /* InitISOFS for %s */\n" test_name;
7120        List.iter (generate_test_command_call test_name)
7121          [["blockdev_setrw"; "/dev/sda"];
7122           ["umount_all"];
7123           ["lvm_remove_all"];
7124           ["mount_ro"; "/dev/sdd"; "/"]]
7125   );
7126
7127   let get_seq_last = function
7128     | [] ->
7129         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7130           test_name
7131     | seq ->
7132         let seq = List.rev seq in
7133         List.rev (List.tl seq), List.hd seq
7134   in
7135
7136   match test with
7137   | TestRun seq ->
7138       pr "  /* TestRun for %s (%d) */\n" name i;
7139       List.iter (generate_test_command_call test_name) seq
7140   | TestOutput (seq, expected) ->
7141       pr "  /* TestOutput for %s (%d) */\n" name i;
7142       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7143       let seq, last = get_seq_last seq in
7144       let test () =
7145         pr "    if (STRNEQ (r, expected)) {\n";
7146         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7147         pr "      return -1;\n";
7148         pr "    }\n"
7149       in
7150       List.iter (generate_test_command_call test_name) seq;
7151       generate_test_command_call ~test test_name last
7152   | TestOutputList (seq, expected) ->
7153       pr "  /* TestOutputList for %s (%d) */\n" name i;
7154       let seq, last = get_seq_last seq in
7155       let test () =
7156         iteri (
7157           fun i str ->
7158             pr "    if (!r[%d]) {\n" i;
7159             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7160             pr "      print_strings (r);\n";
7161             pr "      return -1;\n";
7162             pr "    }\n";
7163             pr "    {\n";
7164             pr "      const char *expected = \"%s\";\n" (c_quote str);
7165             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7166             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7167             pr "        return -1;\n";
7168             pr "      }\n";
7169             pr "    }\n"
7170         ) expected;
7171         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7172         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7173           test_name;
7174         pr "      print_strings (r);\n";
7175         pr "      return -1;\n";
7176         pr "    }\n"
7177       in
7178       List.iter (generate_test_command_call test_name) seq;
7179       generate_test_command_call ~test test_name last
7180   | TestOutputListOfDevices (seq, expected) ->
7181       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7182       let seq, last = get_seq_last seq in
7183       let test () =
7184         iteri (
7185           fun i str ->
7186             pr "    if (!r[%d]) {\n" i;
7187             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7188             pr "      print_strings (r);\n";
7189             pr "      return -1;\n";
7190             pr "    }\n";
7191             pr "    {\n";
7192             pr "      const char *expected = \"%s\";\n" (c_quote str);
7193             pr "      r[%d][5] = 's';\n" i;
7194             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7195             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7196             pr "        return -1;\n";
7197             pr "      }\n";
7198             pr "    }\n"
7199         ) expected;
7200         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7201         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7202           test_name;
7203         pr "      print_strings (r);\n";
7204         pr "      return -1;\n";
7205         pr "    }\n"
7206       in
7207       List.iter (generate_test_command_call test_name) seq;
7208       generate_test_command_call ~test test_name last
7209   | TestOutputInt (seq, expected) ->
7210       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7211       let seq, last = get_seq_last seq in
7212       let test () =
7213         pr "    if (r != %d) {\n" expected;
7214         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7215           test_name expected;
7216         pr "               (int) r);\n";
7217         pr "      return -1;\n";
7218         pr "    }\n"
7219       in
7220       List.iter (generate_test_command_call test_name) seq;
7221       generate_test_command_call ~test test_name last
7222   | TestOutputIntOp (seq, op, expected) ->
7223       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7224       let seq, last = get_seq_last seq in
7225       let test () =
7226         pr "    if (! (r %s %d)) {\n" op expected;
7227         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7228           test_name op expected;
7229         pr "               (int) r);\n";
7230         pr "      return -1;\n";
7231         pr "    }\n"
7232       in
7233       List.iter (generate_test_command_call test_name) seq;
7234       generate_test_command_call ~test test_name last
7235   | TestOutputTrue seq ->
7236       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7237       let seq, last = get_seq_last seq in
7238       let test () =
7239         pr "    if (!r) {\n";
7240         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7241           test_name;
7242         pr "      return -1;\n";
7243         pr "    }\n"
7244       in
7245       List.iter (generate_test_command_call test_name) seq;
7246       generate_test_command_call ~test test_name last
7247   | TestOutputFalse seq ->
7248       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7249       let seq, last = get_seq_last seq in
7250       let test () =
7251         pr "    if (r) {\n";
7252         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7253           test_name;
7254         pr "      return -1;\n";
7255         pr "    }\n"
7256       in
7257       List.iter (generate_test_command_call test_name) seq;
7258       generate_test_command_call ~test test_name last
7259   | TestOutputLength (seq, expected) ->
7260       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7261       let seq, last = get_seq_last seq in
7262       let test () =
7263         pr "    int j;\n";
7264         pr "    for (j = 0; j < %d; ++j)\n" expected;
7265         pr "      if (r[j] == NULL) {\n";
7266         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7267           test_name;
7268         pr "        print_strings (r);\n";
7269         pr "        return -1;\n";
7270         pr "      }\n";
7271         pr "    if (r[j] != NULL) {\n";
7272         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7273           test_name;
7274         pr "      print_strings (r);\n";
7275         pr "      return -1;\n";
7276         pr "    }\n"
7277       in
7278       List.iter (generate_test_command_call test_name) seq;
7279       generate_test_command_call ~test test_name last
7280   | TestOutputBuffer (seq, expected) ->
7281       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7282       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7283       let seq, last = get_seq_last seq in
7284       let len = String.length expected in
7285       let test () =
7286         pr "    if (size != %d) {\n" len;
7287         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7288         pr "      return -1;\n";
7289         pr "    }\n";
7290         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7291         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7292         pr "      return -1;\n";
7293         pr "    }\n"
7294       in
7295       List.iter (generate_test_command_call test_name) seq;
7296       generate_test_command_call ~test test_name last
7297   | TestOutputStruct (seq, checks) ->
7298       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7299       let seq, last = get_seq_last seq in
7300       let test () =
7301         List.iter (
7302           function
7303           | CompareWithInt (field, expected) ->
7304               pr "    if (r->%s != %d) {\n" field expected;
7305               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7306                 test_name field expected;
7307               pr "               (int) r->%s);\n" field;
7308               pr "      return -1;\n";
7309               pr "    }\n"
7310           | CompareWithIntOp (field, op, expected) ->
7311               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7312               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7313                 test_name field op expected;
7314               pr "               (int) r->%s);\n" field;
7315               pr "      return -1;\n";
7316               pr "    }\n"
7317           | CompareWithString (field, expected) ->
7318               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7319               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7320                 test_name field expected;
7321               pr "               r->%s);\n" field;
7322               pr "      return -1;\n";
7323               pr "    }\n"
7324           | CompareFieldsIntEq (field1, field2) ->
7325               pr "    if (r->%s != r->%s) {\n" field1 field2;
7326               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7327                 test_name field1 field2;
7328               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7329               pr "      return -1;\n";
7330               pr "    }\n"
7331           | CompareFieldsStrEq (field1, field2) ->
7332               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7333               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7334                 test_name field1 field2;
7335               pr "               r->%s, r->%s);\n" field1 field2;
7336               pr "      return -1;\n";
7337               pr "    }\n"
7338         ) checks
7339       in
7340       List.iter (generate_test_command_call test_name) seq;
7341       generate_test_command_call ~test test_name last
7342   | TestLastFail seq ->
7343       pr "  /* TestLastFail for %s (%d) */\n" name i;
7344       let seq, last = get_seq_last seq in
7345       List.iter (generate_test_command_call test_name) seq;
7346       generate_test_command_call test_name ~expect_error:true last
7347
7348 (* Generate the code to run a command, leaving the result in 'r'.
7349  * If you expect to get an error then you should set expect_error:true.
7350  *)
7351 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7352   match cmd with
7353   | [] -> assert false
7354   | name :: args ->
7355       (* Look up the command to find out what args/ret it has. *)
7356       let style =
7357         try
7358           let _, style, _, _, _, _, _ =
7359             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7360           style
7361         with Not_found ->
7362           failwithf "%s: in test, command %s was not found" test_name name in
7363
7364       if List.length (snd style) <> List.length args then
7365         failwithf "%s: in test, wrong number of args given to %s"
7366           test_name name;
7367
7368       pr "  {\n";
7369
7370       List.iter (
7371         function
7372         | OptString n, "NULL" -> ()
7373         | Pathname n, arg
7374         | Device n, arg
7375         | Dev_or_Path n, arg
7376         | String n, arg
7377         | OptString n, arg ->
7378             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7379         | BufferIn n, arg ->
7380             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7381             pr "    size_t %s_size = %d;\n" n (String.length arg)
7382         | Int _, _
7383         | Int64 _, _
7384         | Bool _, _
7385         | FileIn _, _ | FileOut _, _ -> ()
7386         | StringList n, "" | DeviceList n, "" ->
7387             pr "    const char *const %s[1] = { NULL };\n" n
7388         | StringList n, arg | DeviceList n, arg ->
7389             let strs = string_split " " arg in
7390             iteri (
7391               fun i str ->
7392                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7393             ) strs;
7394             pr "    const char *const %s[] = {\n" n;
7395             iteri (
7396               fun i _ -> pr "      %s_%d,\n" n i
7397             ) strs;
7398             pr "      NULL\n";
7399             pr "    };\n";
7400       ) (List.combine (snd style) args);
7401
7402       let error_code =
7403         match fst style with
7404         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7405         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7406         | RConstString _ | RConstOptString _ ->
7407             pr "    const char *r;\n"; "NULL"
7408         | RString _ -> pr "    char *r;\n"; "NULL"
7409         | RStringList _ | RHashtable _ ->
7410             pr "    char **r;\n";
7411             pr "    int i;\n";
7412             "NULL"
7413         | RStruct (_, typ) ->
7414             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7415         | RStructList (_, typ) ->
7416             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7417         | RBufferOut _ ->
7418             pr "    char *r;\n";
7419             pr "    size_t size;\n";
7420             "NULL" in
7421
7422       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7423       pr "    r = guestfs_%s (g" name;
7424
7425       (* Generate the parameters. *)
7426       List.iter (
7427         function
7428         | OptString _, "NULL" -> pr ", NULL"
7429         | Pathname n, _
7430         | Device n, _ | Dev_or_Path n, _
7431         | String n, _
7432         | OptString n, _ ->
7433             pr ", %s" n
7434         | BufferIn n, _ ->
7435             pr ", %s, %s_size" n n
7436         | FileIn _, arg | FileOut _, arg ->
7437             pr ", \"%s\"" (c_quote arg)
7438         | StringList n, _ | DeviceList n, _ ->
7439             pr ", (char **) %s" n
7440         | Int _, arg ->
7441             let i =
7442               try int_of_string arg
7443               with Failure "int_of_string" ->
7444                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7445             pr ", %d" i
7446         | Int64 _, arg ->
7447             let i =
7448               try Int64.of_string arg
7449               with Failure "int_of_string" ->
7450                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7451             pr ", %Ld" i
7452         | Bool _, arg ->
7453             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7454       ) (List.combine (snd style) args);
7455
7456       (match fst style with
7457        | RBufferOut _ -> pr ", &size"
7458        | _ -> ()
7459       );
7460
7461       pr ");\n";
7462
7463       if not expect_error then
7464         pr "    if (r == %s)\n" error_code
7465       else
7466         pr "    if (r != %s)\n" error_code;
7467       pr "      return -1;\n";
7468
7469       (* Insert the test code. *)
7470       (match test with
7471        | None -> ()
7472        | Some f -> f ()
7473       );
7474
7475       (match fst style with
7476        | RErr | RInt _ | RInt64 _ | RBool _
7477        | RConstString _ | RConstOptString _ -> ()
7478        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7479        | RStringList _ | RHashtable _ ->
7480            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7481            pr "      free (r[i]);\n";
7482            pr "    free (r);\n"
7483        | RStruct (_, typ) ->
7484            pr "    guestfs_free_%s (r);\n" typ
7485        | RStructList (_, typ) ->
7486            pr "    guestfs_free_%s_list (r);\n" typ
7487       );
7488
7489       pr "  }\n"
7490
7491 and c_quote str =
7492   let str = replace_str str "\r" "\\r" in
7493   let str = replace_str str "\n" "\\n" in
7494   let str = replace_str str "\t" "\\t" in
7495   let str = replace_str str "\000" "\\0" in
7496   str
7497
7498 (* Generate a lot of different functions for guestfish. *)
7499 and generate_fish_cmds () =
7500   generate_header CStyle GPLv2plus;
7501
7502   let all_functions =
7503     List.filter (
7504       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7505     ) all_functions in
7506   let all_functions_sorted =
7507     List.filter (
7508       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7509     ) all_functions_sorted in
7510
7511   pr "#include <config.h>\n";
7512   pr "\n";
7513   pr "#include <stdio.h>\n";
7514   pr "#include <stdlib.h>\n";
7515   pr "#include <string.h>\n";
7516   pr "#include <inttypes.h>\n";
7517   pr "\n";
7518   pr "#include <guestfs.h>\n";
7519   pr "#include \"c-ctype.h\"\n";
7520   pr "#include \"full-write.h\"\n";
7521   pr "#include \"xstrtol.h\"\n";
7522   pr "#include \"fish.h\"\n";
7523   pr "\n";
7524   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7525   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7526   pr "\n";
7527
7528   (* list_commands function, which implements guestfish -h *)
7529   pr "void list_commands (void)\n";
7530   pr "{\n";
7531   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7532   pr "  list_builtin_commands ();\n";
7533   List.iter (
7534     fun (name, _, _, flags, _, shortdesc, _) ->
7535       let name = replace_char name '_' '-' in
7536       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7537         name shortdesc
7538   ) all_functions_sorted;
7539   pr "  printf (\"    %%s\\n\",";
7540   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7541   pr "}\n";
7542   pr "\n";
7543
7544   (* display_command function, which implements guestfish -h cmd *)
7545   pr "void display_command (const char *cmd)\n";
7546   pr "{\n";
7547   List.iter (
7548     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7549       let name2 = replace_char name '_' '-' in
7550       let alias =
7551         try find_map (function FishAlias n -> Some n | _ -> None) flags
7552         with Not_found -> name in
7553       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7554       let synopsis =
7555         match snd style with
7556         | [] -> name2
7557         | args ->
7558             sprintf "%s %s"
7559               name2 (String.concat " " (List.map name_of_argt args)) in
7560
7561       let warnings =
7562         if List.mem ProtocolLimitWarning flags then
7563           ("\n\n" ^ protocol_limit_warning)
7564         else "" in
7565
7566       (* For DangerWillRobinson commands, we should probably have
7567        * guestfish prompt before allowing you to use them (especially
7568        * in interactive mode). XXX
7569        *)
7570       let warnings =
7571         warnings ^
7572           if List.mem DangerWillRobinson flags then
7573             ("\n\n" ^ danger_will_robinson)
7574           else "" in
7575
7576       let warnings =
7577         warnings ^
7578           match deprecation_notice flags with
7579           | None -> ""
7580           | Some txt -> "\n\n" ^ txt in
7581
7582       let describe_alias =
7583         if name <> alias then
7584           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7585         else "" in
7586
7587       pr "  if (";
7588       pr "STRCASEEQ (cmd, \"%s\")" name;
7589       if name <> name2 then
7590         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7591       if name <> alias then
7592         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7593       pr ")\n";
7594       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7595         name2 shortdesc
7596         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7597          "=head1 DESCRIPTION\n\n" ^
7598          longdesc ^ warnings ^ describe_alias);
7599       pr "  else\n"
7600   ) all_functions;
7601   pr "    display_builtin_command (cmd);\n";
7602   pr "}\n";
7603   pr "\n";
7604
7605   let emit_print_list_function typ =
7606     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7607       typ typ typ;
7608     pr "{\n";
7609     pr "  unsigned int i;\n";
7610     pr "\n";
7611     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7612     pr "    printf (\"[%%d] = {\\n\", i);\n";
7613     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7614     pr "    printf (\"}\\n\");\n";
7615     pr "  }\n";
7616     pr "}\n";
7617     pr "\n";
7618   in
7619
7620   (* print_* functions *)
7621   List.iter (
7622     fun (typ, cols) ->
7623       let needs_i =
7624         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7625
7626       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7627       pr "{\n";
7628       if needs_i then (
7629         pr "  unsigned int i;\n";
7630         pr "\n"
7631       );
7632       List.iter (
7633         function
7634         | name, FString ->
7635             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7636         | name, FUUID ->
7637             pr "  printf (\"%%s%s: \", indent);\n" name;
7638             pr "  for (i = 0; i < 32; ++i)\n";
7639             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7640             pr "  printf (\"\\n\");\n"
7641         | name, FBuffer ->
7642             pr "  printf (\"%%s%s: \", indent);\n" name;
7643             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7644             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7645             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7646             pr "    else\n";
7647             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7648             pr "  printf (\"\\n\");\n"
7649         | name, (FUInt64|FBytes) ->
7650             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7651               name typ name
7652         | name, FInt64 ->
7653             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7654               name typ name
7655         | name, FUInt32 ->
7656             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7657               name typ name
7658         | name, FInt32 ->
7659             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7660               name typ name
7661         | name, FChar ->
7662             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7663               name typ name
7664         | name, FOptPercent ->
7665             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7666               typ name name typ name;
7667             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7668       ) cols;
7669       pr "}\n";
7670       pr "\n";
7671   ) structs;
7672
7673   (* Emit a print_TYPE_list function definition only if that function is used. *)
7674   List.iter (
7675     function
7676     | typ, (RStructListOnly | RStructAndList) ->
7677         (* generate the function for typ *)
7678         emit_print_list_function typ
7679     | typ, _ -> () (* empty *)
7680   ) (rstructs_used_by all_functions);
7681
7682   (* Emit a print_TYPE function definition only if that function is used. *)
7683   List.iter (
7684     function
7685     | typ, (RStructOnly | RStructAndList) ->
7686         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7687         pr "{\n";
7688         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7689         pr "}\n";
7690         pr "\n";
7691     | typ, _ -> () (* empty *)
7692   ) (rstructs_used_by all_functions);
7693
7694   (* run_<action> actions *)
7695   List.iter (
7696     fun (name, style, _, flags, _, _, _) ->
7697       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7698       pr "{\n";
7699       (match fst style with
7700        | RErr
7701        | RInt _
7702        | RBool _ -> pr "  int r;\n"
7703        | RInt64 _ -> pr "  int64_t r;\n"
7704        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7705        | RString _ -> pr "  char *r;\n"
7706        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7707        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7708        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7709        | RBufferOut _ ->
7710            pr "  char *r;\n";
7711            pr "  size_t size;\n";
7712       );
7713       List.iter (
7714         function
7715         | Device n
7716         | String n
7717         | OptString n -> pr "  const char *%s;\n" n
7718         | Pathname n
7719         | Dev_or_Path n
7720         | FileIn n
7721         | FileOut n -> pr "  char *%s;\n" n
7722         | BufferIn n ->
7723             pr "  const char *%s;\n" n;
7724             pr "  size_t %s_size;\n" n
7725         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7726         | Bool n -> pr "  int %s;\n" n
7727         | Int n -> pr "  int %s;\n" n
7728         | Int64 n -> pr "  int64_t %s;\n" n
7729       ) (snd style);
7730
7731       (* Check and convert parameters. *)
7732       let argc_expected = List.length (snd style) in
7733       pr "  if (argc != %d) {\n" argc_expected;
7734       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7735         argc_expected;
7736       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7737       pr "    return -1;\n";
7738       pr "  }\n";
7739
7740       let parse_integer fn fntyp rtyp range name i =
7741         pr "  {\n";
7742         pr "    strtol_error xerr;\n";
7743         pr "    %s r;\n" fntyp;
7744         pr "\n";
7745         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7746         pr "    if (xerr != LONGINT_OK) {\n";
7747         pr "      fprintf (stderr,\n";
7748         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7749         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7750         pr "      return -1;\n";
7751         pr "    }\n";
7752         (match range with
7753          | None -> ()
7754          | Some (min, max, comment) ->
7755              pr "    /* %s */\n" comment;
7756              pr "    if (r < %s || r > %s) {\n" min max;
7757              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7758                name;
7759              pr "      return -1;\n";
7760              pr "    }\n";
7761              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7762         );
7763         pr "    %s = r;\n" name;
7764         pr "  }\n";
7765       in
7766
7767       iteri (
7768         fun i ->
7769           function
7770           | Device name
7771           | String name ->
7772               pr "  %s = argv[%d];\n" name i
7773           | Pathname name
7774           | Dev_or_Path name ->
7775               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7776               pr "  if (%s == NULL) return -1;\n" name
7777           | OptString name ->
7778               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7779                 name i i
7780           | BufferIn name ->
7781               pr "  %s = argv[%d];\n" name i;
7782               pr "  %s_size = strlen (argv[%d]);\n" name i
7783           | FileIn name ->
7784               pr "  %s = file_in (argv[%d]);\n" name i;
7785               pr "  if (%s == NULL) return -1;\n" name
7786           | FileOut name ->
7787               pr "  %s = file_out (argv[%d]);\n" name i;
7788               pr "  if (%s == NULL) return -1;\n" name
7789           | StringList name | DeviceList name ->
7790               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7791               pr "  if (%s == NULL) return -1;\n" name;
7792           | Bool name ->
7793               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7794           | Int name ->
7795               let range =
7796                 let min = "(-(2LL<<30))"
7797                 and max = "((2LL<<30)-1)"
7798                 and comment =
7799                   "The Int type in the generator is a signed 31 bit int." in
7800                 Some (min, max, comment) in
7801               parse_integer "xstrtoll" "long long" "int" range name i
7802           | Int64 name ->
7803               parse_integer "xstrtoll" "long long" "int64_t" None name i
7804       ) (snd style);
7805
7806       (* Call C API function. *)
7807       pr "  r = guestfs_%s " name;
7808       generate_c_call_args ~handle:"g" style;
7809       pr ";\n";
7810
7811       List.iter (
7812         function
7813         | Device name | String name
7814         | OptString name | Bool name
7815         | Int name | Int64 name
7816         | BufferIn name -> ()
7817         | Pathname name | Dev_or_Path name | FileOut name ->
7818             pr "  free (%s);\n" name
7819         | FileIn name ->
7820             pr "  free_file_in (%s);\n" name
7821         | StringList name | DeviceList name ->
7822             pr "  free_strings (%s);\n" name
7823       ) (snd style);
7824
7825       (* Any output flags? *)
7826       let fish_output =
7827         let flags = filter_map (
7828           function FishOutput flag -> Some flag | _ -> None
7829         ) flags in
7830         match flags with
7831         | [] -> None
7832         | [f] -> Some f
7833         | _ ->
7834             failwithf "%s: more than one FishOutput flag is not allowed" name in
7835
7836       (* Check return value for errors and display command results. *)
7837       (match fst style with
7838        | RErr -> pr "  return r;\n"
7839        | RInt _ ->
7840            pr "  if (r == -1) return -1;\n";
7841            (match fish_output with
7842             | None ->
7843                 pr "  printf (\"%%d\\n\", r);\n";
7844             | Some FishOutputOctal ->
7845                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7846             | Some FishOutputHexadecimal ->
7847                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7848            pr "  return 0;\n"
7849        | RInt64 _ ->
7850            pr "  if (r == -1) return -1;\n";
7851            (match fish_output with
7852             | None ->
7853                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7854             | Some FishOutputOctal ->
7855                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7856             | Some FishOutputHexadecimal ->
7857                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7858            pr "  return 0;\n"
7859        | RBool _ ->
7860            pr "  if (r == -1) return -1;\n";
7861            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7862            pr "  return 0;\n"
7863        | RConstString _ ->
7864            pr "  if (r == NULL) return -1;\n";
7865            pr "  printf (\"%%s\\n\", r);\n";
7866            pr "  return 0;\n"
7867        | RConstOptString _ ->
7868            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7869            pr "  return 0;\n"
7870        | RString _ ->
7871            pr "  if (r == NULL) return -1;\n";
7872            pr "  printf (\"%%s\\n\", r);\n";
7873            pr "  free (r);\n";
7874            pr "  return 0;\n"
7875        | RStringList _ ->
7876            pr "  if (r == NULL) return -1;\n";
7877            pr "  print_strings (r);\n";
7878            pr "  free_strings (r);\n";
7879            pr "  return 0;\n"
7880        | RStruct (_, typ) ->
7881            pr "  if (r == NULL) return -1;\n";
7882            pr "  print_%s (r);\n" typ;
7883            pr "  guestfs_free_%s (r);\n" typ;
7884            pr "  return 0;\n"
7885        | RStructList (_, typ) ->
7886            pr "  if (r == NULL) return -1;\n";
7887            pr "  print_%s_list (r);\n" typ;
7888            pr "  guestfs_free_%s_list (r);\n" typ;
7889            pr "  return 0;\n"
7890        | RHashtable _ ->
7891            pr "  if (r == NULL) return -1;\n";
7892            pr "  print_table (r);\n";
7893            pr "  free_strings (r);\n";
7894            pr "  return 0;\n"
7895        | RBufferOut _ ->
7896            pr "  if (r == NULL) return -1;\n";
7897            pr "  if (full_write (1, r, size) != size) {\n";
7898            pr "    perror (\"write\");\n";
7899            pr "    free (r);\n";
7900            pr "    return -1;\n";
7901            pr "  }\n";
7902            pr "  free (r);\n";
7903            pr "  return 0;\n"
7904       );
7905       pr "}\n";
7906       pr "\n"
7907   ) all_functions;
7908
7909   (* run_action function *)
7910   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7911   pr "{\n";
7912   List.iter (
7913     fun (name, _, _, flags, _, _, _) ->
7914       let name2 = replace_char name '_' '-' in
7915       let alias =
7916         try find_map (function FishAlias n -> Some n | _ -> None) flags
7917         with Not_found -> name in
7918       pr "  if (";
7919       pr "STRCASEEQ (cmd, \"%s\")" name;
7920       if name <> name2 then
7921         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7922       if name <> alias then
7923         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7924       pr ")\n";
7925       pr "    return run_%s (cmd, argc, argv);\n" name;
7926       pr "  else\n";
7927   ) all_functions;
7928   pr "    {\n";
7929   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7930   pr "      if (command_num == 1)\n";
7931   pr "        extended_help_message ();\n";
7932   pr "      return -1;\n";
7933   pr "    }\n";
7934   pr "  return 0;\n";
7935   pr "}\n";
7936   pr "\n"
7937
7938 (* Readline completion for guestfish. *)
7939 and generate_fish_completion () =
7940   generate_header CStyle GPLv2plus;
7941
7942   let all_functions =
7943     List.filter (
7944       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7945     ) all_functions in
7946
7947   pr "\
7948 #include <config.h>
7949
7950 #include <stdio.h>
7951 #include <stdlib.h>
7952 #include <string.h>
7953
7954 #ifdef HAVE_LIBREADLINE
7955 #include <readline/readline.h>
7956 #endif
7957
7958 #include \"fish.h\"
7959
7960 #ifdef HAVE_LIBREADLINE
7961
7962 static const char *const commands[] = {
7963   BUILTIN_COMMANDS_FOR_COMPLETION,
7964 ";
7965
7966   (* Get the commands, including the aliases.  They don't need to be
7967    * sorted - the generator() function just does a dumb linear search.
7968    *)
7969   let commands =
7970     List.map (
7971       fun (name, _, _, flags, _, _, _) ->
7972         let name2 = replace_char name '_' '-' in
7973         let alias =
7974           try find_map (function FishAlias n -> Some n | _ -> None) flags
7975           with Not_found -> name in
7976
7977         if name <> alias then [name2; alias] else [name2]
7978     ) all_functions in
7979   let commands = List.flatten commands in
7980
7981   List.iter (pr "  \"%s\",\n") commands;
7982
7983   pr "  NULL
7984 };
7985
7986 static char *
7987 generator (const char *text, int state)
7988 {
7989   static int index, len;
7990   const char *name;
7991
7992   if (!state) {
7993     index = 0;
7994     len = strlen (text);
7995   }
7996
7997   rl_attempted_completion_over = 1;
7998
7999   while ((name = commands[index]) != NULL) {
8000     index++;
8001     if (STRCASEEQLEN (name, text, len))
8002       return strdup (name);
8003   }
8004
8005   return NULL;
8006 }
8007
8008 #endif /* HAVE_LIBREADLINE */
8009
8010 #ifdef HAVE_RL_COMPLETION_MATCHES
8011 #define RL_COMPLETION_MATCHES rl_completion_matches
8012 #else
8013 #ifdef HAVE_COMPLETION_MATCHES
8014 #define RL_COMPLETION_MATCHES completion_matches
8015 #endif
8016 #endif /* else just fail if we don't have either symbol */
8017
8018 char **
8019 do_completion (const char *text, int start, int end)
8020 {
8021   char **matches = NULL;
8022
8023 #ifdef HAVE_LIBREADLINE
8024   rl_completion_append_character = ' ';
8025
8026   if (start == 0)
8027     matches = RL_COMPLETION_MATCHES (text, generator);
8028   else if (complete_dest_paths)
8029     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8030 #endif
8031
8032   return matches;
8033 }
8034 ";
8035
8036 (* Generate the POD documentation for guestfish. *)
8037 and generate_fish_actions_pod () =
8038   let all_functions_sorted =
8039     List.filter (
8040       fun (_, _, _, flags, _, _, _) ->
8041         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8042     ) all_functions_sorted in
8043
8044   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8045
8046   List.iter (
8047     fun (name, style, _, flags, _, _, longdesc) ->
8048       let longdesc =
8049         Str.global_substitute rex (
8050           fun s ->
8051             let sub =
8052               try Str.matched_group 1 s
8053               with Not_found ->
8054                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8055             "C<" ^ replace_char sub '_' '-' ^ ">"
8056         ) longdesc in
8057       let name = replace_char name '_' '-' in
8058       let alias =
8059         try find_map (function FishAlias n -> Some n | _ -> None) flags
8060         with Not_found -> name in
8061
8062       pr "=head2 %s" name;
8063       if name <> alias then
8064         pr " | %s" alias;
8065       pr "\n";
8066       pr "\n";
8067       pr " %s" name;
8068       List.iter (
8069         function
8070         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8071         | OptString n -> pr " %s" n
8072         | StringList n | DeviceList n -> pr " '%s ...'" n
8073         | Bool _ -> pr " true|false"
8074         | Int n -> pr " %s" n
8075         | Int64 n -> pr " %s" n
8076         | FileIn n | FileOut n -> pr " (%s|-)" n
8077         | BufferIn n -> pr " %s" n
8078       ) (snd style);
8079       pr "\n";
8080       pr "\n";
8081       pr "%s\n\n" longdesc;
8082
8083       if List.exists (function FileIn _ | FileOut _ -> true
8084                       | _ -> false) (snd style) then
8085         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8086
8087       if List.mem ProtocolLimitWarning flags then
8088         pr "%s\n\n" protocol_limit_warning;
8089
8090       if List.mem DangerWillRobinson flags then
8091         pr "%s\n\n" danger_will_robinson;
8092
8093       match deprecation_notice flags with
8094       | None -> ()
8095       | Some txt -> pr "%s\n\n" txt
8096   ) all_functions_sorted
8097
8098 (* Generate a C function prototype. *)
8099 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8100     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8101     ?(prefix = "")
8102     ?handle name style =
8103   if extern then pr "extern ";
8104   if static then pr "static ";
8105   (match fst style with
8106    | RErr -> pr "int "
8107    | RInt _ -> pr "int "
8108    | RInt64 _ -> pr "int64_t "
8109    | RBool _ -> pr "int "
8110    | RConstString _ | RConstOptString _ -> pr "const char *"
8111    | RString _ | RBufferOut _ -> pr "char *"
8112    | RStringList _ | RHashtable _ -> pr "char **"
8113    | RStruct (_, typ) ->
8114        if not in_daemon then pr "struct guestfs_%s *" typ
8115        else pr "guestfs_int_%s *" typ
8116    | RStructList (_, typ) ->
8117        if not in_daemon then pr "struct guestfs_%s_list *" typ
8118        else pr "guestfs_int_%s_list *" typ
8119   );
8120   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8121   pr "%s%s (" prefix name;
8122   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8123     pr "void"
8124   else (
8125     let comma = ref false in
8126     (match handle with
8127      | None -> ()
8128      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8129     );
8130     let next () =
8131       if !comma then (
8132         if single_line then pr ", " else pr ",\n\t\t"
8133       );
8134       comma := true
8135     in
8136     List.iter (
8137       function
8138       | Pathname n
8139       | Device n | Dev_or_Path n
8140       | String n
8141       | OptString n ->
8142           next ();
8143           pr "const char *%s" n
8144       | StringList n | DeviceList n ->
8145           next ();
8146           pr "char *const *%s" n
8147       | Bool n -> next (); pr "int %s" n
8148       | Int n -> next (); pr "int %s" n
8149       | Int64 n -> next (); pr "int64_t %s" n
8150       | FileIn n
8151       | FileOut n ->
8152           if not in_daemon then (next (); pr "const char *%s" n)
8153       | BufferIn n ->
8154           next ();
8155           pr "const char *%s" n;
8156           next ();
8157           pr "size_t %s_size" n
8158     ) (snd style);
8159     if is_RBufferOut then (next (); pr "size_t *size_r");
8160   );
8161   pr ")";
8162   if semicolon then pr ";";
8163   if newline then pr "\n"
8164
8165 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8166 and generate_c_call_args ?handle ?(decl = false) style =
8167   pr "(";
8168   let comma = ref false in
8169   let next () =
8170     if !comma then pr ", ";
8171     comma := true
8172   in
8173   (match handle with
8174    | None -> ()
8175    | Some handle -> pr "%s" handle; comma := true
8176   );
8177   List.iter (
8178     function
8179     | BufferIn n ->
8180         next ();
8181         pr "%s, %s_size" n n
8182     | arg ->
8183         next ();
8184         pr "%s" (name_of_argt arg)
8185   ) (snd style);
8186   (* For RBufferOut calls, add implicit &size parameter. *)
8187   if not decl then (
8188     match fst style with
8189     | RBufferOut _ ->
8190         next ();
8191         pr "&size"
8192     | _ -> ()
8193   );
8194   pr ")"
8195
8196 (* Generate the OCaml bindings interface. *)
8197 and generate_ocaml_mli () =
8198   generate_header OCamlStyle LGPLv2plus;
8199
8200   pr "\
8201 (** For API documentation you should refer to the C API
8202     in the guestfs(3) manual page.  The OCaml API uses almost
8203     exactly the same calls. *)
8204
8205 type t
8206 (** A [guestfs_h] handle. *)
8207
8208 exception Error of string
8209 (** This exception is raised when there is an error. *)
8210
8211 exception Handle_closed of string
8212 (** This exception is raised if you use a {!Guestfs.t} handle
8213     after calling {!close} on it.  The string is the name of
8214     the function. *)
8215
8216 val create : unit -> t
8217 (** Create a {!Guestfs.t} handle. *)
8218
8219 val close : t -> unit
8220 (** Close the {!Guestfs.t} handle and free up all resources used
8221     by it immediately.
8222
8223     Handles are closed by the garbage collector when they become
8224     unreferenced, but callers can call this in order to provide
8225     predictable cleanup. *)
8226
8227 ";
8228   generate_ocaml_structure_decls ();
8229
8230   (* The actions. *)
8231   List.iter (
8232     fun (name, style, _, _, _, shortdesc, _) ->
8233       generate_ocaml_prototype name style;
8234       pr "(** %s *)\n" shortdesc;
8235       pr "\n"
8236   ) all_functions_sorted
8237
8238 (* Generate the OCaml bindings implementation. *)
8239 and generate_ocaml_ml () =
8240   generate_header OCamlStyle LGPLv2plus;
8241
8242   pr "\
8243 type t
8244
8245 exception Error of string
8246 exception Handle_closed of string
8247
8248 external create : unit -> t = \"ocaml_guestfs_create\"
8249 external close : t -> unit = \"ocaml_guestfs_close\"
8250
8251 (* Give the exceptions names, so they can be raised from the C code. *)
8252 let () =
8253   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8254   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8255
8256 ";
8257
8258   generate_ocaml_structure_decls ();
8259
8260   (* The actions. *)
8261   List.iter (
8262     fun (name, style, _, _, _, shortdesc, _) ->
8263       generate_ocaml_prototype ~is_external:true name style;
8264   ) all_functions_sorted
8265
8266 (* Generate the OCaml bindings C implementation. *)
8267 and generate_ocaml_c () =
8268   generate_header CStyle LGPLv2plus;
8269
8270   pr "\
8271 #include <stdio.h>
8272 #include <stdlib.h>
8273 #include <string.h>
8274
8275 #include <caml/config.h>
8276 #include <caml/alloc.h>
8277 #include <caml/callback.h>
8278 #include <caml/fail.h>
8279 #include <caml/memory.h>
8280 #include <caml/mlvalues.h>
8281 #include <caml/signals.h>
8282
8283 #include <guestfs.h>
8284
8285 #include \"guestfs_c.h\"
8286
8287 /* Copy a hashtable of string pairs into an assoc-list.  We return
8288  * the list in reverse order, but hashtables aren't supposed to be
8289  * ordered anyway.
8290  */
8291 static CAMLprim value
8292 copy_table (char * const * argv)
8293 {
8294   CAMLparam0 ();
8295   CAMLlocal5 (rv, pairv, kv, vv, cons);
8296   int i;
8297
8298   rv = Val_int (0);
8299   for (i = 0; argv[i] != NULL; i += 2) {
8300     kv = caml_copy_string (argv[i]);
8301     vv = caml_copy_string (argv[i+1]);
8302     pairv = caml_alloc (2, 0);
8303     Store_field (pairv, 0, kv);
8304     Store_field (pairv, 1, vv);
8305     cons = caml_alloc (2, 0);
8306     Store_field (cons, 1, rv);
8307     rv = cons;
8308     Store_field (cons, 0, pairv);
8309   }
8310
8311   CAMLreturn (rv);
8312 }
8313
8314 ";
8315
8316   (* Struct copy functions. *)
8317
8318   let emit_ocaml_copy_list_function typ =
8319     pr "static CAMLprim value\n";
8320     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8321     pr "{\n";
8322     pr "  CAMLparam0 ();\n";
8323     pr "  CAMLlocal2 (rv, v);\n";
8324     pr "  unsigned int i;\n";
8325     pr "\n";
8326     pr "  if (%ss->len == 0)\n" typ;
8327     pr "    CAMLreturn (Atom (0));\n";
8328     pr "  else {\n";
8329     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8330     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8331     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8332     pr "      caml_modify (&Field (rv, i), v);\n";
8333     pr "    }\n";
8334     pr "    CAMLreturn (rv);\n";
8335     pr "  }\n";
8336     pr "}\n";
8337     pr "\n";
8338   in
8339
8340   List.iter (
8341     fun (typ, cols) ->
8342       let has_optpercent_col =
8343         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8344
8345       pr "static CAMLprim value\n";
8346       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8347       pr "{\n";
8348       pr "  CAMLparam0 ();\n";
8349       if has_optpercent_col then
8350         pr "  CAMLlocal3 (rv, v, v2);\n"
8351       else
8352         pr "  CAMLlocal2 (rv, v);\n";
8353       pr "\n";
8354       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8355       iteri (
8356         fun i col ->
8357           (match col with
8358            | name, FString ->
8359                pr "  v = caml_copy_string (%s->%s);\n" typ name
8360            | name, FBuffer ->
8361                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8362                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8363                  typ name typ name
8364            | name, FUUID ->
8365                pr "  v = caml_alloc_string (32);\n";
8366                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8367            | name, (FBytes|FInt64|FUInt64) ->
8368                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8369            | name, (FInt32|FUInt32) ->
8370                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8371            | name, FOptPercent ->
8372                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8373                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8374                pr "    v = caml_alloc (1, 0);\n";
8375                pr "    Store_field (v, 0, v2);\n";
8376                pr "  } else /* None */\n";
8377                pr "    v = Val_int (0);\n";
8378            | name, FChar ->
8379                pr "  v = Val_int (%s->%s);\n" typ name
8380           );
8381           pr "  Store_field (rv, %d, v);\n" i
8382       ) cols;
8383       pr "  CAMLreturn (rv);\n";
8384       pr "}\n";
8385       pr "\n";
8386   ) structs;
8387
8388   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8389   List.iter (
8390     function
8391     | typ, (RStructListOnly | RStructAndList) ->
8392         (* generate the function for typ *)
8393         emit_ocaml_copy_list_function typ
8394     | typ, _ -> () (* empty *)
8395   ) (rstructs_used_by all_functions);
8396
8397   (* The wrappers. *)
8398   List.iter (
8399     fun (name, style, _, _, _, _, _) ->
8400       pr "/* Automatically generated wrapper for function\n";
8401       pr " * ";
8402       generate_ocaml_prototype name style;
8403       pr " */\n";
8404       pr "\n";
8405
8406       let params =
8407         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8408
8409       let needs_extra_vs =
8410         match fst style with RConstOptString _ -> true | _ -> false in
8411
8412       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8413       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8414       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8415       pr "\n";
8416
8417       pr "CAMLprim value\n";
8418       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8419       List.iter (pr ", value %s") (List.tl params);
8420       pr ")\n";
8421       pr "{\n";
8422
8423       (match params with
8424        | [p1; p2; p3; p4; p5] ->
8425            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8426        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8427            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8428            pr "  CAMLxparam%d (%s);\n"
8429              (List.length rest) (String.concat ", " rest)
8430        | ps ->
8431            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8432       );
8433       if not needs_extra_vs then
8434         pr "  CAMLlocal1 (rv);\n"
8435       else
8436         pr "  CAMLlocal3 (rv, v, v2);\n";
8437       pr "\n";
8438
8439       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8440       pr "  if (g == NULL)\n";
8441       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8442       pr "\n";
8443
8444       List.iter (
8445         function
8446         | Pathname n
8447         | Device n | Dev_or_Path n
8448         | String n
8449         | FileIn n
8450         | FileOut n ->
8451             pr "  const char *%s = String_val (%sv);\n" n n
8452         | OptString n ->
8453             pr "  const char *%s =\n" n;
8454             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8455               n n
8456         | BufferIn n ->
8457             pr "  const char *%s = String_val (%sv);\n" n n;
8458             pr "  size_t %s_size = caml_string_length (%sv);\n" n n
8459         | StringList n | DeviceList n ->
8460             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8461         | Bool n ->
8462             pr "  int %s = Bool_val (%sv);\n" n n
8463         | Int n ->
8464             pr "  int %s = Int_val (%sv);\n" n n
8465         | Int64 n ->
8466             pr "  int64_t %s = Int64_val (%sv);\n" n n
8467       ) (snd style);
8468       let error_code =
8469         match fst style with
8470         | RErr -> pr "  int r;\n"; "-1"
8471         | RInt _ -> pr "  int r;\n"; "-1"
8472         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8473         | RBool _ -> pr "  int r;\n"; "-1"
8474         | RConstString _ | RConstOptString _ ->
8475             pr "  const char *r;\n"; "NULL"
8476         | RString _ -> pr "  char *r;\n"; "NULL"
8477         | RStringList _ ->
8478             pr "  int i;\n";
8479             pr "  char **r;\n";
8480             "NULL"
8481         | RStruct (_, typ) ->
8482             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8483         | RStructList (_, typ) ->
8484             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8485         | RHashtable _ ->
8486             pr "  int i;\n";
8487             pr "  char **r;\n";
8488             "NULL"
8489         | RBufferOut _ ->
8490             pr "  char *r;\n";
8491             pr "  size_t size;\n";
8492             "NULL" in
8493       pr "\n";
8494
8495       pr "  caml_enter_blocking_section ();\n";
8496       pr "  r = guestfs_%s " name;
8497       generate_c_call_args ~handle:"g" style;
8498       pr ";\n";
8499       pr "  caml_leave_blocking_section ();\n";
8500
8501       List.iter (
8502         function
8503         | StringList n | DeviceList n ->
8504             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8505         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8506         | Bool _ | Int _ | Int64 _
8507         | FileIn _ | FileOut _ | BufferIn _ -> ()
8508       ) (snd style);
8509
8510       pr "  if (r == %s)\n" error_code;
8511       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8512       pr "\n";
8513
8514       (match fst style with
8515        | RErr -> pr "  rv = Val_unit;\n"
8516        | RInt _ -> pr "  rv = Val_int (r);\n"
8517        | RInt64 _ ->
8518            pr "  rv = caml_copy_int64 (r);\n"
8519        | RBool _ -> pr "  rv = Val_bool (r);\n"
8520        | RConstString _ ->
8521            pr "  rv = caml_copy_string (r);\n"
8522        | RConstOptString _ ->
8523            pr "  if (r) { /* Some string */\n";
8524            pr "    v = caml_alloc (1, 0);\n";
8525            pr "    v2 = caml_copy_string (r);\n";
8526            pr "    Store_field (v, 0, v2);\n";
8527            pr "  } else /* None */\n";
8528            pr "    v = Val_int (0);\n";
8529        | RString _ ->
8530            pr "  rv = caml_copy_string (r);\n";
8531            pr "  free (r);\n"
8532        | RStringList _ ->
8533            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8534            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8535            pr "  free (r);\n"
8536        | RStruct (_, typ) ->
8537            pr "  rv = copy_%s (r);\n" typ;
8538            pr "  guestfs_free_%s (r);\n" typ;
8539        | RStructList (_, typ) ->
8540            pr "  rv = copy_%s_list (r);\n" typ;
8541            pr "  guestfs_free_%s_list (r);\n" typ;
8542        | RHashtable _ ->
8543            pr "  rv = copy_table (r);\n";
8544            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8545            pr "  free (r);\n";
8546        | RBufferOut _ ->
8547            pr "  rv = caml_alloc_string (size);\n";
8548            pr "  memcpy (String_val (rv), r, size);\n";
8549       );
8550
8551       pr "  CAMLreturn (rv);\n";
8552       pr "}\n";
8553       pr "\n";
8554
8555       if List.length params > 5 then (
8556         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8557         pr "CAMLprim value ";
8558         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8559         pr "CAMLprim value\n";
8560         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8561         pr "{\n";
8562         pr "  return ocaml_guestfs_%s (argv[0]" name;
8563         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8564         pr ");\n";
8565         pr "}\n";
8566         pr "\n"
8567       )
8568   ) all_functions_sorted
8569
8570 and generate_ocaml_structure_decls () =
8571   List.iter (
8572     fun (typ, cols) ->
8573       pr "type %s = {\n" typ;
8574       List.iter (
8575         function
8576         | name, FString -> pr "  %s : string;\n" name
8577         | name, FBuffer -> pr "  %s : string;\n" name
8578         | name, FUUID -> pr "  %s : string;\n" name
8579         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8580         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8581         | name, FChar -> pr "  %s : char;\n" name
8582         | name, FOptPercent -> pr "  %s : float option;\n" name
8583       ) cols;
8584       pr "}\n";
8585       pr "\n"
8586   ) structs
8587
8588 and generate_ocaml_prototype ?(is_external = false) name style =
8589   if is_external then pr "external " else pr "val ";
8590   pr "%s : t -> " name;
8591   List.iter (
8592     function
8593     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8594     | BufferIn _ -> pr "string -> "
8595     | OptString _ -> pr "string option -> "
8596     | StringList _ | DeviceList _ -> pr "string array -> "
8597     | Bool _ -> pr "bool -> "
8598     | Int _ -> pr "int -> "
8599     | Int64 _ -> pr "int64 -> "
8600   ) (snd style);
8601   (match fst style with
8602    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8603    | RInt _ -> pr "int"
8604    | RInt64 _ -> pr "int64"
8605    | RBool _ -> pr "bool"
8606    | RConstString _ -> pr "string"
8607    | RConstOptString _ -> pr "string option"
8608    | RString _ | RBufferOut _ -> pr "string"
8609    | RStringList _ -> pr "string array"
8610    | RStruct (_, typ) -> pr "%s" typ
8611    | RStructList (_, typ) -> pr "%s array" typ
8612    | RHashtable _ -> pr "(string * string) list"
8613   );
8614   if is_external then (
8615     pr " = ";
8616     if List.length (snd style) + 1 > 5 then
8617       pr "\"ocaml_guestfs_%s_byte\" " name;
8618     pr "\"ocaml_guestfs_%s\"" name
8619   );
8620   pr "\n"
8621
8622 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8623 and generate_perl_xs () =
8624   generate_header CStyle LGPLv2plus;
8625
8626   pr "\
8627 #include \"EXTERN.h\"
8628 #include \"perl.h\"
8629 #include \"XSUB.h\"
8630
8631 #include <guestfs.h>
8632
8633 #ifndef PRId64
8634 #define PRId64 \"lld\"
8635 #endif
8636
8637 static SV *
8638 my_newSVll(long long val) {
8639 #ifdef USE_64_BIT_ALL
8640   return newSViv(val);
8641 #else
8642   char buf[100];
8643   int len;
8644   len = snprintf(buf, 100, \"%%\" PRId64, val);
8645   return newSVpv(buf, len);
8646 #endif
8647 }
8648
8649 #ifndef PRIu64
8650 #define PRIu64 \"llu\"
8651 #endif
8652
8653 static SV *
8654 my_newSVull(unsigned long long val) {
8655 #ifdef USE_64_BIT_ALL
8656   return newSVuv(val);
8657 #else
8658   char buf[100];
8659   int len;
8660   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8661   return newSVpv(buf, len);
8662 #endif
8663 }
8664
8665 /* http://www.perlmonks.org/?node_id=680842 */
8666 static char **
8667 XS_unpack_charPtrPtr (SV *arg) {
8668   char **ret;
8669   AV *av;
8670   I32 i;
8671
8672   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8673     croak (\"array reference expected\");
8674
8675   av = (AV *)SvRV (arg);
8676   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8677   if (!ret)
8678     croak (\"malloc failed\");
8679
8680   for (i = 0; i <= av_len (av); i++) {
8681     SV **elem = av_fetch (av, i, 0);
8682
8683     if (!elem || !*elem)
8684       croak (\"missing element in list\");
8685
8686     ret[i] = SvPV_nolen (*elem);
8687   }
8688
8689   ret[i] = NULL;
8690
8691   return ret;
8692 }
8693
8694 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8695
8696 PROTOTYPES: ENABLE
8697
8698 guestfs_h *
8699 _create ()
8700    CODE:
8701       RETVAL = guestfs_create ();
8702       if (!RETVAL)
8703         croak (\"could not create guestfs handle\");
8704       guestfs_set_error_handler (RETVAL, NULL, NULL);
8705  OUTPUT:
8706       RETVAL
8707
8708 void
8709 DESTROY (g)
8710       guestfs_h *g;
8711  PPCODE:
8712       guestfs_close (g);
8713
8714 ";
8715
8716   List.iter (
8717     fun (name, style, _, _, _, _, _) ->
8718       (match fst style with
8719        | RErr -> pr "void\n"
8720        | RInt _ -> pr "SV *\n"
8721        | RInt64 _ -> pr "SV *\n"
8722        | RBool _ -> pr "SV *\n"
8723        | RConstString _ -> pr "SV *\n"
8724        | RConstOptString _ -> pr "SV *\n"
8725        | RString _ -> pr "SV *\n"
8726        | RBufferOut _ -> pr "SV *\n"
8727        | RStringList _
8728        | RStruct _ | RStructList _
8729        | RHashtable _ ->
8730            pr "void\n" (* all lists returned implictly on the stack *)
8731       );
8732       (* Call and arguments. *)
8733       pr "%s (g" name;
8734       List.iter (
8735         fun arg -> pr ", %s" (name_of_argt arg)
8736       ) (snd style);
8737       pr ")\n";
8738       pr "      guestfs_h *g;\n";
8739       iteri (
8740         fun i ->
8741           function
8742           | Pathname n | Device n | Dev_or_Path n | String n
8743           | FileIn n | FileOut n ->
8744               pr "      char *%s;\n" n
8745           | BufferIn n ->
8746               pr "      char *%s;\n" n;
8747               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8748           | OptString n ->
8749               (* http://www.perlmonks.org/?node_id=554277
8750                * Note that the implicit handle argument means we have
8751                * to add 1 to the ST(x) operator.
8752                *)
8753               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8754           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8755           | Bool n -> pr "      int %s;\n" n
8756           | Int n -> pr "      int %s;\n" n
8757           | Int64 n -> pr "      int64_t %s;\n" n
8758       ) (snd style);
8759
8760       let do_cleanups () =
8761         List.iter (
8762           function
8763           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8764           | Bool _ | Int _ | Int64 _
8765           | FileIn _ | FileOut _
8766           | BufferIn _ -> ()
8767           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8768         ) (snd style)
8769       in
8770
8771       (* Code. *)
8772       (match fst style with
8773        | RErr ->
8774            pr "PREINIT:\n";
8775            pr "      int r;\n";
8776            pr " PPCODE:\n";
8777            pr "      r = guestfs_%s " name;
8778            generate_c_call_args ~handle:"g" style;
8779            pr ";\n";
8780            do_cleanups ();
8781            pr "      if (r == -1)\n";
8782            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8783        | RInt n
8784        | RBool n ->
8785            pr "PREINIT:\n";
8786            pr "      int %s;\n" n;
8787            pr "   CODE:\n";
8788            pr "      %s = guestfs_%s " n name;
8789            generate_c_call_args ~handle:"g" style;
8790            pr ";\n";
8791            do_cleanups ();
8792            pr "      if (%s == -1)\n" n;
8793            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8794            pr "      RETVAL = newSViv (%s);\n" n;
8795            pr " OUTPUT:\n";
8796            pr "      RETVAL\n"
8797        | RInt64 n ->
8798            pr "PREINIT:\n";
8799            pr "      int64_t %s;\n" n;
8800            pr "   CODE:\n";
8801            pr "      %s = guestfs_%s " n name;
8802            generate_c_call_args ~handle:"g" style;
8803            pr ";\n";
8804            do_cleanups ();
8805            pr "      if (%s == -1)\n" n;
8806            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8807            pr "      RETVAL = my_newSVll (%s);\n" n;
8808            pr " OUTPUT:\n";
8809            pr "      RETVAL\n"
8810        | RConstString n ->
8811            pr "PREINIT:\n";
8812            pr "      const char *%s;\n" n;
8813            pr "   CODE:\n";
8814            pr "      %s = guestfs_%s " n name;
8815            generate_c_call_args ~handle:"g" style;
8816            pr ";\n";
8817            do_cleanups ();
8818            pr "      if (%s == NULL)\n" n;
8819            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8820            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8821            pr " OUTPUT:\n";
8822            pr "      RETVAL\n"
8823        | RConstOptString n ->
8824            pr "PREINIT:\n";
8825            pr "      const char *%s;\n" n;
8826            pr "   CODE:\n";
8827            pr "      %s = guestfs_%s " n name;
8828            generate_c_call_args ~handle:"g" style;
8829            pr ";\n";
8830            do_cleanups ();
8831            pr "      if (%s == NULL)\n" n;
8832            pr "        RETVAL = &PL_sv_undef;\n";
8833            pr "      else\n";
8834            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8835            pr " OUTPUT:\n";
8836            pr "      RETVAL\n"
8837        | RString n ->
8838            pr "PREINIT:\n";
8839            pr "      char *%s;\n" n;
8840            pr "   CODE:\n";
8841            pr "      %s = guestfs_%s " n name;
8842            generate_c_call_args ~handle:"g" style;
8843            pr ";\n";
8844            do_cleanups ();
8845            pr "      if (%s == NULL)\n" n;
8846            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8847            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8848            pr "      free (%s);\n" n;
8849            pr " OUTPUT:\n";
8850            pr "      RETVAL\n"
8851        | RStringList n | RHashtable n ->
8852            pr "PREINIT:\n";
8853            pr "      char **%s;\n" n;
8854            pr "      int i, n;\n";
8855            pr " PPCODE:\n";
8856            pr "      %s = guestfs_%s " n name;
8857            generate_c_call_args ~handle:"g" style;
8858            pr ";\n";
8859            do_cleanups ();
8860            pr "      if (%s == NULL)\n" n;
8861            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8862            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8863            pr "      EXTEND (SP, n);\n";
8864            pr "      for (i = 0; i < n; ++i) {\n";
8865            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8866            pr "        free (%s[i]);\n" n;
8867            pr "      }\n";
8868            pr "      free (%s);\n" n;
8869        | RStruct (n, typ) ->
8870            let cols = cols_of_struct typ in
8871            generate_perl_struct_code typ cols name style n do_cleanups
8872        | RStructList (n, typ) ->
8873            let cols = cols_of_struct typ in
8874            generate_perl_struct_list_code typ cols name style n do_cleanups
8875        | RBufferOut n ->
8876            pr "PREINIT:\n";
8877            pr "      char *%s;\n" n;
8878            pr "      size_t size;\n";
8879            pr "   CODE:\n";
8880            pr "      %s = guestfs_%s " n name;
8881            generate_c_call_args ~handle:"g" style;
8882            pr ";\n";
8883            do_cleanups ();
8884            pr "      if (%s == NULL)\n" n;
8885            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8886            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8887            pr "      free (%s);\n" n;
8888            pr " OUTPUT:\n";
8889            pr "      RETVAL\n"
8890       );
8891
8892       pr "\n"
8893   ) all_functions
8894
8895 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8896   pr "PREINIT:\n";
8897   pr "      struct guestfs_%s_list *%s;\n" typ n;
8898   pr "      int i;\n";
8899   pr "      HV *hv;\n";
8900   pr " PPCODE:\n";
8901   pr "      %s = guestfs_%s " n name;
8902   generate_c_call_args ~handle:"g" style;
8903   pr ";\n";
8904   do_cleanups ();
8905   pr "      if (%s == NULL)\n" n;
8906   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8907   pr "      EXTEND (SP, %s->len);\n" n;
8908   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8909   pr "        hv = newHV ();\n";
8910   List.iter (
8911     function
8912     | name, FString ->
8913         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8914           name (String.length name) n name
8915     | name, FUUID ->
8916         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8917           name (String.length name) n name
8918     | name, FBuffer ->
8919         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8920           name (String.length name) n name n name
8921     | name, (FBytes|FUInt64) ->
8922         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8923           name (String.length name) n name
8924     | name, FInt64 ->
8925         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8926           name (String.length name) n name
8927     | name, (FInt32|FUInt32) ->
8928         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8929           name (String.length name) n name
8930     | name, FChar ->
8931         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8932           name (String.length name) n name
8933     | name, FOptPercent ->
8934         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8935           name (String.length name) n name
8936   ) cols;
8937   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8938   pr "      }\n";
8939   pr "      guestfs_free_%s_list (%s);\n" typ n
8940
8941 and generate_perl_struct_code typ cols name style n do_cleanups =
8942   pr "PREINIT:\n";
8943   pr "      struct guestfs_%s *%s;\n" typ n;
8944   pr " PPCODE:\n";
8945   pr "      %s = guestfs_%s " n name;
8946   generate_c_call_args ~handle:"g" style;
8947   pr ";\n";
8948   do_cleanups ();
8949   pr "      if (%s == NULL)\n" n;
8950   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8951   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8952   List.iter (
8953     fun ((name, _) as col) ->
8954       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8955
8956       match col with
8957       | name, FString ->
8958           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8959             n name
8960       | name, FBuffer ->
8961           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8962             n name n name
8963       | name, FUUID ->
8964           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8965             n name
8966       | name, (FBytes|FUInt64) ->
8967           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8968             n name
8969       | name, FInt64 ->
8970           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8971             n name
8972       | name, (FInt32|FUInt32) ->
8973           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8974             n name
8975       | name, FChar ->
8976           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8977             n name
8978       | name, FOptPercent ->
8979           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8980             n name
8981   ) cols;
8982   pr "      free (%s);\n" n
8983
8984 (* Generate Sys/Guestfs.pm. *)
8985 and generate_perl_pm () =
8986   generate_header HashStyle LGPLv2plus;
8987
8988   pr "\
8989 =pod
8990
8991 =head1 NAME
8992
8993 Sys::Guestfs - Perl bindings for libguestfs
8994
8995 =head1 SYNOPSIS
8996
8997  use Sys::Guestfs;
8998
8999  my $h = Sys::Guestfs->new ();
9000  $h->add_drive ('guest.img');
9001  $h->launch ();
9002  $h->mount ('/dev/sda1', '/');
9003  $h->touch ('/hello');
9004  $h->sync ();
9005
9006 =head1 DESCRIPTION
9007
9008 The C<Sys::Guestfs> module provides a Perl XS binding to the
9009 libguestfs API for examining and modifying virtual machine
9010 disk images.
9011
9012 Amongst the things this is good for: making batch configuration
9013 changes to guests, getting disk used/free statistics (see also:
9014 virt-df), migrating between virtualization systems (see also:
9015 virt-p2v), performing partial backups, performing partial guest
9016 clones, cloning guests and changing registry/UUID/hostname info, and
9017 much else besides.
9018
9019 Libguestfs uses Linux kernel and qemu code, and can access any type of
9020 guest filesystem that Linux and qemu can, including but not limited
9021 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9022 schemes, qcow, qcow2, vmdk.
9023
9024 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9025 LVs, what filesystem is in each LV, etc.).  It can also run commands
9026 in the context of the guest.  Also you can access filesystems over
9027 FUSE.
9028
9029 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9030 functions for using libguestfs from Perl, including integration
9031 with libvirt.
9032
9033 =head1 ERRORS
9034
9035 All errors turn into calls to C<croak> (see L<Carp(3)>).
9036
9037 =head1 METHODS
9038
9039 =over 4
9040
9041 =cut
9042
9043 package Sys::Guestfs;
9044
9045 use strict;
9046 use warnings;
9047
9048 # This version number changes whenever a new function
9049 # is added to the libguestfs API.  It is not directly
9050 # related to the libguestfs version number.
9051 use vars qw($VERSION);
9052 $VERSION = '0.%d';
9053
9054 require XSLoader;
9055 XSLoader::load ('Sys::Guestfs');
9056
9057 =item $h = Sys::Guestfs->new ();
9058
9059 Create a new guestfs handle.
9060
9061 =cut
9062
9063 sub new {
9064   my $proto = shift;
9065   my $class = ref ($proto) || $proto;
9066
9067   my $self = Sys::Guestfs::_create ();
9068   bless $self, $class;
9069   return $self;
9070 }
9071
9072 " max_proc_nr;
9073
9074   (* Actions.  We only need to print documentation for these as
9075    * they are pulled in from the XS code automatically.
9076    *)
9077   List.iter (
9078     fun (name, style, _, flags, _, _, longdesc) ->
9079       if not (List.mem NotInDocs flags) then (
9080         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9081         pr "=item ";
9082         generate_perl_prototype name style;
9083         pr "\n\n";
9084         pr "%s\n\n" longdesc;
9085         if List.mem ProtocolLimitWarning flags then
9086           pr "%s\n\n" protocol_limit_warning;
9087         if List.mem DangerWillRobinson flags then
9088           pr "%s\n\n" danger_will_robinson;
9089         match deprecation_notice flags with
9090         | None -> ()
9091         | Some txt -> pr "%s\n\n" txt
9092       )
9093   ) all_functions_sorted;
9094
9095   (* End of file. *)
9096   pr "\
9097 =cut
9098
9099 1;
9100
9101 =back
9102
9103 =head1 COPYRIGHT
9104
9105 Copyright (C) %s Red Hat Inc.
9106
9107 =head1 LICENSE
9108
9109 Please see the file COPYING.LIB for the full license.
9110
9111 =head1 SEE ALSO
9112
9113 L<guestfs(3)>,
9114 L<guestfish(1)>,
9115 L<http://libguestfs.org>,
9116 L<Sys::Guestfs::Lib(3)>.
9117
9118 =cut
9119 " copyright_years
9120
9121 and generate_perl_prototype name style =
9122   (match fst style with
9123    | RErr -> ()
9124    | RBool n
9125    | RInt n
9126    | RInt64 n
9127    | RConstString n
9128    | RConstOptString n
9129    | RString n
9130    | RBufferOut n -> pr "$%s = " n
9131    | RStruct (n,_)
9132    | RHashtable n -> pr "%%%s = " n
9133    | RStringList n
9134    | RStructList (n,_) -> pr "@%s = " n
9135   );
9136   pr "$h->%s (" name;
9137   let comma = ref false in
9138   List.iter (
9139     fun arg ->
9140       if !comma then pr ", ";
9141       comma := true;
9142       match arg with
9143       | Pathname n | Device n | Dev_or_Path n | String n
9144       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9145       | BufferIn n ->
9146           pr "$%s" n
9147       | StringList n | DeviceList n ->
9148           pr "\\@%s" n
9149   ) (snd style);
9150   pr ");"
9151
9152 (* Generate Python C module. *)
9153 and generate_python_c () =
9154   generate_header CStyle LGPLv2plus;
9155
9156   pr "\
9157 #define PY_SSIZE_T_CLEAN 1
9158 #include <Python.h>
9159
9160 #if PY_VERSION_HEX < 0x02050000
9161 typedef int Py_ssize_t;
9162 #define PY_SSIZE_T_MAX INT_MAX
9163 #define PY_SSIZE_T_MIN INT_MIN
9164 #endif
9165
9166 #include <stdio.h>
9167 #include <stdlib.h>
9168 #include <assert.h>
9169
9170 #include \"guestfs.h\"
9171
9172 typedef struct {
9173   PyObject_HEAD
9174   guestfs_h *g;
9175 } Pyguestfs_Object;
9176
9177 static guestfs_h *
9178 get_handle (PyObject *obj)
9179 {
9180   assert (obj);
9181   assert (obj != Py_None);
9182   return ((Pyguestfs_Object *) obj)->g;
9183 }
9184
9185 static PyObject *
9186 put_handle (guestfs_h *g)
9187 {
9188   assert (g);
9189   return
9190     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9191 }
9192
9193 /* This list should be freed (but not the strings) after use. */
9194 static char **
9195 get_string_list (PyObject *obj)
9196 {
9197   int i, len;
9198   char **r;
9199
9200   assert (obj);
9201
9202   if (!PyList_Check (obj)) {
9203     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9204     return NULL;
9205   }
9206
9207   len = PyList_Size (obj);
9208   r = malloc (sizeof (char *) * (len+1));
9209   if (r == NULL) {
9210     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9211     return NULL;
9212   }
9213
9214   for (i = 0; i < len; ++i)
9215     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9216   r[len] = NULL;
9217
9218   return r;
9219 }
9220
9221 static PyObject *
9222 put_string_list (char * const * const argv)
9223 {
9224   PyObject *list;
9225   int argc, i;
9226
9227   for (argc = 0; argv[argc] != NULL; ++argc)
9228     ;
9229
9230   list = PyList_New (argc);
9231   for (i = 0; i < argc; ++i)
9232     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9233
9234   return list;
9235 }
9236
9237 static PyObject *
9238 put_table (char * const * const argv)
9239 {
9240   PyObject *list, *item;
9241   int argc, i;
9242
9243   for (argc = 0; argv[argc] != NULL; ++argc)
9244     ;
9245
9246   list = PyList_New (argc >> 1);
9247   for (i = 0; i < argc; i += 2) {
9248     item = PyTuple_New (2);
9249     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9250     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9251     PyList_SetItem (list, i >> 1, item);
9252   }
9253
9254   return list;
9255 }
9256
9257 static void
9258 free_strings (char **argv)
9259 {
9260   int argc;
9261
9262   for (argc = 0; argv[argc] != NULL; ++argc)
9263     free (argv[argc]);
9264   free (argv);
9265 }
9266
9267 static PyObject *
9268 py_guestfs_create (PyObject *self, PyObject *args)
9269 {
9270   guestfs_h *g;
9271
9272   g = guestfs_create ();
9273   if (g == NULL) {
9274     PyErr_SetString (PyExc_RuntimeError,
9275                      \"guestfs.create: failed to allocate handle\");
9276     return NULL;
9277   }
9278   guestfs_set_error_handler (g, NULL, NULL);
9279   return put_handle (g);
9280 }
9281
9282 static PyObject *
9283 py_guestfs_close (PyObject *self, PyObject *args)
9284 {
9285   PyObject *py_g;
9286   guestfs_h *g;
9287
9288   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9289     return NULL;
9290   g = get_handle (py_g);
9291
9292   guestfs_close (g);
9293
9294   Py_INCREF (Py_None);
9295   return Py_None;
9296 }
9297
9298 ";
9299
9300   let emit_put_list_function typ =
9301     pr "static PyObject *\n";
9302     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9303     pr "{\n";
9304     pr "  PyObject *list;\n";
9305     pr "  int i;\n";
9306     pr "\n";
9307     pr "  list = PyList_New (%ss->len);\n" typ;
9308     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9309     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9310     pr "  return list;\n";
9311     pr "};\n";
9312     pr "\n"
9313   in
9314
9315   (* Structures, turned into Python dictionaries. *)
9316   List.iter (
9317     fun (typ, cols) ->
9318       pr "static PyObject *\n";
9319       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9320       pr "{\n";
9321       pr "  PyObject *dict;\n";
9322       pr "\n";
9323       pr "  dict = PyDict_New ();\n";
9324       List.iter (
9325         function
9326         | name, FString ->
9327             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9328             pr "                        PyString_FromString (%s->%s));\n"
9329               typ name
9330         | name, FBuffer ->
9331             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9332             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9333               typ name typ name
9334         | name, FUUID ->
9335             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9336             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9337               typ name
9338         | name, (FBytes|FUInt64) ->
9339             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9340             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9341               typ name
9342         | name, FInt64 ->
9343             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9344             pr "                        PyLong_FromLongLong (%s->%s));\n"
9345               typ name
9346         | name, FUInt32 ->
9347             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9348             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9349               typ name
9350         | name, FInt32 ->
9351             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9352             pr "                        PyLong_FromLong (%s->%s));\n"
9353               typ name
9354         | name, FOptPercent ->
9355             pr "  if (%s->%s >= 0)\n" typ name;
9356             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9357             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9358               typ name;
9359             pr "  else {\n";
9360             pr "    Py_INCREF (Py_None);\n";
9361             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9362             pr "  }\n"
9363         | name, FChar ->
9364             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9365             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9366       ) cols;
9367       pr "  return dict;\n";
9368       pr "};\n";
9369       pr "\n";
9370
9371   ) structs;
9372
9373   (* Emit a put_TYPE_list function definition only if that function is used. *)
9374   List.iter (
9375     function
9376     | typ, (RStructListOnly | RStructAndList) ->
9377         (* generate the function for typ *)
9378         emit_put_list_function typ
9379     | typ, _ -> () (* empty *)
9380   ) (rstructs_used_by all_functions);
9381
9382   (* Python wrapper functions. *)
9383   List.iter (
9384     fun (name, style, _, _, _, _, _) ->
9385       pr "static PyObject *\n";
9386       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9387       pr "{\n";
9388
9389       pr "  PyObject *py_g;\n";
9390       pr "  guestfs_h *g;\n";
9391       pr "  PyObject *py_r;\n";
9392
9393       let error_code =
9394         match fst style with
9395         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9396         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9397         | RConstString _ | RConstOptString _ ->
9398             pr "  const char *r;\n"; "NULL"
9399         | RString _ -> pr "  char *r;\n"; "NULL"
9400         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9401         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9402         | RStructList (_, typ) ->
9403             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9404         | RBufferOut _ ->
9405             pr "  char *r;\n";
9406             pr "  size_t size;\n";
9407             "NULL" in
9408
9409       List.iter (
9410         function
9411         | Pathname n | Device n | Dev_or_Path n | String n
9412         | FileIn n | FileOut n ->
9413             pr "  const char *%s;\n" n
9414         | OptString n -> pr "  const char *%s;\n" n
9415         | BufferIn n ->
9416             pr "  const char *%s;\n" n;
9417             pr "  Py_ssize_t %s_size;\n" n
9418         | StringList n | DeviceList n ->
9419             pr "  PyObject *py_%s;\n" n;
9420             pr "  char **%s;\n" n
9421         | Bool n -> pr "  int %s;\n" n
9422         | Int n -> pr "  int %s;\n" n
9423         | Int64 n -> pr "  long long %s;\n" n
9424       ) (snd style);
9425
9426       pr "\n";
9427
9428       (* Convert the parameters. *)
9429       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9430       List.iter (
9431         function
9432         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9433         | OptString _ -> pr "z"
9434         | StringList _ | DeviceList _ -> pr "O"
9435         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9436         | Int _ -> pr "i"
9437         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9438                              * emulate C's int/long/long long in Python?
9439                              *)
9440         | BufferIn _ -> pr "s#"
9441       ) (snd style);
9442       pr ":guestfs_%s\",\n" name;
9443       pr "                         &py_g";
9444       List.iter (
9445         function
9446         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9447         | OptString n -> pr ", &%s" n
9448         | StringList n | DeviceList n -> pr ", &py_%s" n
9449         | Bool n -> pr ", &%s" n
9450         | Int n -> pr ", &%s" n
9451         | Int64 n -> pr ", &%s" n
9452         | BufferIn n -> pr ", &%s, &%s_size" n n
9453       ) (snd style);
9454
9455       pr "))\n";
9456       pr "    return NULL;\n";
9457
9458       pr "  g = get_handle (py_g);\n";
9459       List.iter (
9460         function
9461         | Pathname _ | Device _ | Dev_or_Path _ | String _
9462         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9463         | BufferIn _ -> ()
9464         | StringList n | DeviceList n ->
9465             pr "  %s = get_string_list (py_%s);\n" n n;
9466             pr "  if (!%s) return NULL;\n" n
9467       ) (snd style);
9468
9469       pr "\n";
9470
9471       pr "  r = guestfs_%s " name;
9472       generate_c_call_args ~handle:"g" style;
9473       pr ";\n";
9474
9475       List.iter (
9476         function
9477         | Pathname _ | Device _ | Dev_or_Path _ | String _
9478         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9479         | BufferIn _ -> ()
9480         | StringList n | DeviceList n ->
9481             pr "  free (%s);\n" n
9482       ) (snd style);
9483
9484       pr "  if (r == %s) {\n" error_code;
9485       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9486       pr "    return NULL;\n";
9487       pr "  }\n";
9488       pr "\n";
9489
9490       (match fst style with
9491        | RErr ->
9492            pr "  Py_INCREF (Py_None);\n";
9493            pr "  py_r = Py_None;\n"
9494        | RInt _
9495        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9496        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9497        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9498        | RConstOptString _ ->
9499            pr "  if (r)\n";
9500            pr "    py_r = PyString_FromString (r);\n";
9501            pr "  else {\n";
9502            pr "    Py_INCREF (Py_None);\n";
9503            pr "    py_r = Py_None;\n";
9504            pr "  }\n"
9505        | RString _ ->
9506            pr "  py_r = PyString_FromString (r);\n";
9507            pr "  free (r);\n"
9508        | RStringList _ ->
9509            pr "  py_r = put_string_list (r);\n";
9510            pr "  free_strings (r);\n"
9511        | RStruct (_, typ) ->
9512            pr "  py_r = put_%s (r);\n" typ;
9513            pr "  guestfs_free_%s (r);\n" typ
9514        | RStructList (_, typ) ->
9515            pr "  py_r = put_%s_list (r);\n" typ;
9516            pr "  guestfs_free_%s_list (r);\n" typ
9517        | RHashtable n ->
9518            pr "  py_r = put_table (r);\n";
9519            pr "  free_strings (r);\n"
9520        | RBufferOut _ ->
9521            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9522            pr "  free (r);\n"
9523       );
9524
9525       pr "  return py_r;\n";
9526       pr "}\n";
9527       pr "\n"
9528   ) all_functions;
9529
9530   (* Table of functions. *)
9531   pr "static PyMethodDef methods[] = {\n";
9532   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9533   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9534   List.iter (
9535     fun (name, _, _, _, _, _, _) ->
9536       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9537         name name
9538   ) all_functions;
9539   pr "  { NULL, NULL, 0, NULL }\n";
9540   pr "};\n";
9541   pr "\n";
9542
9543   (* Init function. *)
9544   pr "\
9545 void
9546 initlibguestfsmod (void)
9547 {
9548   static int initialized = 0;
9549
9550   if (initialized) return;
9551   Py_InitModule ((char *) \"libguestfsmod\", methods);
9552   initialized = 1;
9553 }
9554 "
9555
9556 (* Generate Python module. *)
9557 and generate_python_py () =
9558   generate_header HashStyle LGPLv2plus;
9559
9560   pr "\
9561 u\"\"\"Python bindings for libguestfs
9562
9563 import guestfs
9564 g = guestfs.GuestFS ()
9565 g.add_drive (\"guest.img\")
9566 g.launch ()
9567 parts = g.list_partitions ()
9568
9569 The guestfs module provides a Python binding to the libguestfs API
9570 for examining and modifying virtual machine disk images.
9571
9572 Amongst the things this is good for: making batch configuration
9573 changes to guests, getting disk used/free statistics (see also:
9574 virt-df), migrating between virtualization systems (see also:
9575 virt-p2v), performing partial backups, performing partial guest
9576 clones, cloning guests and changing registry/UUID/hostname info, and
9577 much else besides.
9578
9579 Libguestfs uses Linux kernel and qemu code, and can access any type of
9580 guest filesystem that Linux and qemu can, including but not limited
9581 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9582 schemes, qcow, qcow2, vmdk.
9583
9584 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9585 LVs, what filesystem is in each LV, etc.).  It can also run commands
9586 in the context of the guest.  Also you can access filesystems over
9587 FUSE.
9588
9589 Errors which happen while using the API are turned into Python
9590 RuntimeError exceptions.
9591
9592 To create a guestfs handle you usually have to perform the following
9593 sequence of calls:
9594
9595 # Create the handle, call add_drive at least once, and possibly
9596 # several times if the guest has multiple block devices:
9597 g = guestfs.GuestFS ()
9598 g.add_drive (\"guest.img\")
9599
9600 # Launch the qemu subprocess and wait for it to become ready:
9601 g.launch ()
9602
9603 # Now you can issue commands, for example:
9604 logvols = g.lvs ()
9605
9606 \"\"\"
9607
9608 import libguestfsmod
9609
9610 class GuestFS:
9611     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9612
9613     def __init__ (self):
9614         \"\"\"Create a new libguestfs handle.\"\"\"
9615         self._o = libguestfsmod.create ()
9616
9617     def __del__ (self):
9618         libguestfsmod.close (self._o)
9619
9620 ";
9621
9622   List.iter (
9623     fun (name, style, _, flags, _, _, longdesc) ->
9624       pr "    def %s " name;
9625       generate_py_call_args ~handle:"self" (snd style);
9626       pr ":\n";
9627
9628       if not (List.mem NotInDocs flags) then (
9629         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9630         let doc =
9631           match fst style with
9632           | RErr | RInt _ | RInt64 _ | RBool _
9633           | RConstOptString _ | RConstString _
9634           | RString _ | RBufferOut _ -> doc
9635           | RStringList _ ->
9636               doc ^ "\n\nThis function returns a list of strings."
9637           | RStruct (_, typ) ->
9638               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9639           | RStructList (_, typ) ->
9640               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9641           | RHashtable _ ->
9642               doc ^ "\n\nThis function returns a dictionary." in
9643         let doc =
9644           if List.mem ProtocolLimitWarning flags then
9645             doc ^ "\n\n" ^ protocol_limit_warning
9646           else doc in
9647         let doc =
9648           if List.mem DangerWillRobinson flags then
9649             doc ^ "\n\n" ^ danger_will_robinson
9650           else doc in
9651         let doc =
9652           match deprecation_notice flags with
9653           | None -> doc
9654           | Some txt -> doc ^ "\n\n" ^ txt in
9655         let doc = pod2text ~width:60 name doc in
9656         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9657         let doc = String.concat "\n        " doc in
9658         pr "        u\"\"\"%s\"\"\"\n" doc;
9659       );
9660       pr "        return libguestfsmod.%s " name;
9661       generate_py_call_args ~handle:"self._o" (snd style);
9662       pr "\n";
9663       pr "\n";
9664   ) all_functions
9665
9666 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9667 and generate_py_call_args ~handle args =
9668   pr "(%s" handle;
9669   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9670   pr ")"
9671
9672 (* Useful if you need the longdesc POD text as plain text.  Returns a
9673  * list of lines.
9674  *
9675  * Because this is very slow (the slowest part of autogeneration),
9676  * we memoize the results.
9677  *)
9678 and pod2text ~width name longdesc =
9679   let key = width, name, longdesc in
9680   try Hashtbl.find pod2text_memo key
9681   with Not_found ->
9682     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9683     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9684     close_out chan;
9685     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9686     let chan = open_process_in cmd in
9687     let lines = ref [] in
9688     let rec loop i =
9689       let line = input_line chan in
9690       if i = 1 then             (* discard the first line of output *)
9691         loop (i+1)
9692       else (
9693         let line = triml line in
9694         lines := line :: !lines;
9695         loop (i+1)
9696       ) in
9697     let lines = try loop 1 with End_of_file -> List.rev !lines in
9698     unlink filename;
9699     (match close_process_in chan with
9700      | WEXITED 0 -> ()
9701      | WEXITED i ->
9702          failwithf "pod2text: process exited with non-zero status (%d)" i
9703      | WSIGNALED i | WSTOPPED i ->
9704          failwithf "pod2text: process signalled or stopped by signal %d" i
9705     );
9706     Hashtbl.add pod2text_memo key lines;
9707     pod2text_memo_updated ();
9708     lines
9709
9710 (* Generate ruby bindings. *)
9711 and generate_ruby_c () =
9712   generate_header CStyle LGPLv2plus;
9713
9714   pr "\
9715 #include <stdio.h>
9716 #include <stdlib.h>
9717
9718 #include <ruby.h>
9719
9720 #include \"guestfs.h\"
9721
9722 #include \"extconf.h\"
9723
9724 /* For Ruby < 1.9 */
9725 #ifndef RARRAY_LEN
9726 #define RARRAY_LEN(r) (RARRAY((r))->len)
9727 #endif
9728
9729 static VALUE m_guestfs;                 /* guestfs module */
9730 static VALUE c_guestfs;                 /* guestfs_h handle */
9731 static VALUE e_Error;                   /* used for all errors */
9732
9733 static void ruby_guestfs_free (void *p)
9734 {
9735   if (!p) return;
9736   guestfs_close ((guestfs_h *) p);
9737 }
9738
9739 static VALUE ruby_guestfs_create (VALUE m)
9740 {
9741   guestfs_h *g;
9742
9743   g = guestfs_create ();
9744   if (!g)
9745     rb_raise (e_Error, \"failed to create guestfs handle\");
9746
9747   /* Don't print error messages to stderr by default. */
9748   guestfs_set_error_handler (g, NULL, NULL);
9749
9750   /* Wrap it, and make sure the close function is called when the
9751    * handle goes away.
9752    */
9753   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9754 }
9755
9756 static VALUE ruby_guestfs_close (VALUE gv)
9757 {
9758   guestfs_h *g;
9759   Data_Get_Struct (gv, guestfs_h, g);
9760
9761   ruby_guestfs_free (g);
9762   DATA_PTR (gv) = NULL;
9763
9764   return Qnil;
9765 }
9766
9767 ";
9768
9769   List.iter (
9770     fun (name, style, _, _, _, _, _) ->
9771       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9772       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9773       pr ")\n";
9774       pr "{\n";
9775       pr "  guestfs_h *g;\n";
9776       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9777       pr "  if (!g)\n";
9778       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9779         name;
9780       pr "\n";
9781
9782       List.iter (
9783         function
9784         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9785             pr "  Check_Type (%sv, T_STRING);\n" n;
9786             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9787             pr "  if (!%s)\n" n;
9788             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9789             pr "              \"%s\", \"%s\");\n" n name
9790         | BufferIn n ->
9791             pr "  Check_Type (%sv, T_STRING);\n" n;
9792             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9793             pr "  if (!%s)\n" n;
9794             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9795             pr "              \"%s\", \"%s\");\n" n name;
9796             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9797         | OptString n ->
9798             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9799         | StringList n | DeviceList n ->
9800             pr "  char **%s;\n" n;
9801             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9802             pr "  {\n";
9803             pr "    int i, len;\n";
9804             pr "    len = RARRAY_LEN (%sv);\n" n;
9805             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9806               n;
9807             pr "    for (i = 0; i < len; ++i) {\n";
9808             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9809             pr "      %s[i] = StringValueCStr (v);\n" n;
9810             pr "    }\n";
9811             pr "    %s[len] = NULL;\n" n;
9812             pr "  }\n";
9813         | Bool n ->
9814             pr "  int %s = RTEST (%sv);\n" n n
9815         | Int n ->
9816             pr "  int %s = NUM2INT (%sv);\n" n n
9817         | Int64 n ->
9818             pr "  long long %s = NUM2LL (%sv);\n" n n
9819       ) (snd style);
9820       pr "\n";
9821
9822       let error_code =
9823         match fst style with
9824         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9825         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9826         | RConstString _ | RConstOptString _ ->
9827             pr "  const char *r;\n"; "NULL"
9828         | RString _ -> pr "  char *r;\n"; "NULL"
9829         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9830         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9831         | RStructList (_, typ) ->
9832             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9833         | RBufferOut _ ->
9834             pr "  char *r;\n";
9835             pr "  size_t size;\n";
9836             "NULL" in
9837       pr "\n";
9838
9839       pr "  r = guestfs_%s " name;
9840       generate_c_call_args ~handle:"g" style;
9841       pr ";\n";
9842
9843       List.iter (
9844         function
9845         | Pathname _ | Device _ | Dev_or_Path _ | String _
9846         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9847         | BufferIn _ -> ()
9848         | StringList n | DeviceList n ->
9849             pr "  free (%s);\n" n
9850       ) (snd style);
9851
9852       pr "  if (r == %s)\n" error_code;
9853       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9854       pr "\n";
9855
9856       (match fst style with
9857        | RErr ->
9858            pr "  return Qnil;\n"
9859        | RInt _ | RBool _ ->
9860            pr "  return INT2NUM (r);\n"
9861        | RInt64 _ ->
9862            pr "  return ULL2NUM (r);\n"
9863        | RConstString _ ->
9864            pr "  return rb_str_new2 (r);\n";
9865        | RConstOptString _ ->
9866            pr "  if (r)\n";
9867            pr "    return rb_str_new2 (r);\n";
9868            pr "  else\n";
9869            pr "    return Qnil;\n";
9870        | RString _ ->
9871            pr "  VALUE rv = rb_str_new2 (r);\n";
9872            pr "  free (r);\n";
9873            pr "  return rv;\n";
9874        | RStringList _ ->
9875            pr "  int i, len = 0;\n";
9876            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9877            pr "  VALUE rv = rb_ary_new2 (len);\n";
9878            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9879            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9880            pr "    free (r[i]);\n";
9881            pr "  }\n";
9882            pr "  free (r);\n";
9883            pr "  return rv;\n"
9884        | RStruct (_, typ) ->
9885            let cols = cols_of_struct typ in
9886            generate_ruby_struct_code typ cols
9887        | RStructList (_, typ) ->
9888            let cols = cols_of_struct typ in
9889            generate_ruby_struct_list_code typ cols
9890        | RHashtable _ ->
9891            pr "  VALUE rv = rb_hash_new ();\n";
9892            pr "  int i;\n";
9893            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9894            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9895            pr "    free (r[i]);\n";
9896            pr "    free (r[i+1]);\n";
9897            pr "  }\n";
9898            pr "  free (r);\n";
9899            pr "  return rv;\n"
9900        | RBufferOut _ ->
9901            pr "  VALUE rv = rb_str_new (r, size);\n";
9902            pr "  free (r);\n";
9903            pr "  return rv;\n";
9904       );
9905
9906       pr "}\n";
9907       pr "\n"
9908   ) all_functions;
9909
9910   pr "\
9911 /* Initialize the module. */
9912 void Init__guestfs ()
9913 {
9914   m_guestfs = rb_define_module (\"Guestfs\");
9915   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9916   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9917
9918   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9919   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9920
9921 ";
9922   (* Define the rest of the methods. *)
9923   List.iter (
9924     fun (name, style, _, _, _, _, _) ->
9925       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9926       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9927   ) all_functions;
9928
9929   pr "}\n"
9930
9931 (* Ruby code to return a struct. *)
9932 and generate_ruby_struct_code typ cols =
9933   pr "  VALUE rv = rb_hash_new ();\n";
9934   List.iter (
9935     function
9936     | name, FString ->
9937         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9938     | name, FBuffer ->
9939         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9940     | name, FUUID ->
9941         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9942     | name, (FBytes|FUInt64) ->
9943         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9944     | name, FInt64 ->
9945         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9946     | name, FUInt32 ->
9947         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9948     | name, FInt32 ->
9949         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9950     | name, FOptPercent ->
9951         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9952     | name, FChar -> (* XXX wrong? *)
9953         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9954   ) cols;
9955   pr "  guestfs_free_%s (r);\n" typ;
9956   pr "  return rv;\n"
9957
9958 (* Ruby code to return a struct list. *)
9959 and generate_ruby_struct_list_code typ cols =
9960   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9961   pr "  int i;\n";
9962   pr "  for (i = 0; i < r->len; ++i) {\n";
9963   pr "    VALUE hv = rb_hash_new ();\n";
9964   List.iter (
9965     function
9966     | name, FString ->
9967         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9968     | name, FBuffer ->
9969         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
9970     | name, FUUID ->
9971         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9972     | name, (FBytes|FUInt64) ->
9973         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9974     | name, FInt64 ->
9975         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9976     | name, FUInt32 ->
9977         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9978     | name, FInt32 ->
9979         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9980     | name, FOptPercent ->
9981         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9982     | name, FChar -> (* XXX wrong? *)
9983         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9984   ) cols;
9985   pr "    rb_ary_push (rv, hv);\n";
9986   pr "  }\n";
9987   pr "  guestfs_free_%s_list (r);\n" typ;
9988   pr "  return rv;\n"
9989
9990 (* Generate Java bindings GuestFS.java file. *)
9991 and generate_java_java () =
9992   generate_header CStyle LGPLv2plus;
9993
9994   pr "\
9995 package com.redhat.et.libguestfs;
9996
9997 import java.util.HashMap;
9998 import com.redhat.et.libguestfs.LibGuestFSException;
9999 import com.redhat.et.libguestfs.PV;
10000 import com.redhat.et.libguestfs.VG;
10001 import com.redhat.et.libguestfs.LV;
10002 import com.redhat.et.libguestfs.Stat;
10003 import com.redhat.et.libguestfs.StatVFS;
10004 import com.redhat.et.libguestfs.IntBool;
10005 import com.redhat.et.libguestfs.Dirent;
10006
10007 /**
10008  * The GuestFS object is a libguestfs handle.
10009  *
10010  * @author rjones
10011  */
10012 public class GuestFS {
10013   // Load the native code.
10014   static {
10015     System.loadLibrary (\"guestfs_jni\");
10016   }
10017
10018   /**
10019    * The native guestfs_h pointer.
10020    */
10021   long g;
10022
10023   /**
10024    * Create a libguestfs handle.
10025    *
10026    * @throws LibGuestFSException
10027    */
10028   public GuestFS () throws LibGuestFSException
10029   {
10030     g = _create ();
10031   }
10032   private native long _create () throws LibGuestFSException;
10033
10034   /**
10035    * Close a libguestfs handle.
10036    *
10037    * You can also leave handles to be collected by the garbage
10038    * collector, but this method ensures that the resources used
10039    * by the handle are freed up immediately.  If you call any
10040    * other methods after closing the handle, you will get an
10041    * exception.
10042    *
10043    * @throws LibGuestFSException
10044    */
10045   public void close () throws LibGuestFSException
10046   {
10047     if (g != 0)
10048       _close (g);
10049     g = 0;
10050   }
10051   private native void _close (long g) throws LibGuestFSException;
10052
10053   public void finalize () throws LibGuestFSException
10054   {
10055     close ();
10056   }
10057
10058 ";
10059
10060   List.iter (
10061     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10062       if not (List.mem NotInDocs flags); then (
10063         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10064         let doc =
10065           if List.mem ProtocolLimitWarning flags then
10066             doc ^ "\n\n" ^ protocol_limit_warning
10067           else doc in
10068         let doc =
10069           if List.mem DangerWillRobinson flags then
10070             doc ^ "\n\n" ^ danger_will_robinson
10071           else doc in
10072         let doc =
10073           match deprecation_notice flags with
10074           | None -> doc
10075           | Some txt -> doc ^ "\n\n" ^ txt in
10076         let doc = pod2text ~width:60 name doc in
10077         let doc = List.map (            (* RHBZ#501883 *)
10078           function
10079           | "" -> "<p>"
10080           | nonempty -> nonempty
10081         ) doc in
10082         let doc = String.concat "\n   * " doc in
10083
10084         pr "  /**\n";
10085         pr "   * %s\n" shortdesc;
10086         pr "   * <p>\n";
10087         pr "   * %s\n" doc;
10088         pr "   * @throws LibGuestFSException\n";
10089         pr "   */\n";
10090         pr "  ";
10091       );
10092       generate_java_prototype ~public:true ~semicolon:false name style;
10093       pr "\n";
10094       pr "  {\n";
10095       pr "    if (g == 0)\n";
10096       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10097         name;
10098       pr "    ";
10099       if fst style <> RErr then pr "return ";
10100       pr "_%s " name;
10101       generate_java_call_args ~handle:"g" (snd style);
10102       pr ";\n";
10103       pr "  }\n";
10104       pr "  ";
10105       generate_java_prototype ~privat:true ~native:true name style;
10106       pr "\n";
10107       pr "\n";
10108   ) all_functions;
10109
10110   pr "}\n"
10111
10112 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10113 and generate_java_call_args ~handle args =
10114   pr "(%s" handle;
10115   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10116   pr ")"
10117
10118 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10119     ?(semicolon=true) name style =
10120   if privat then pr "private ";
10121   if public then pr "public ";
10122   if native then pr "native ";
10123
10124   (* return type *)
10125   (match fst style with
10126    | RErr -> pr "void ";
10127    | RInt _ -> pr "int ";
10128    | RInt64 _ -> pr "long ";
10129    | RBool _ -> pr "boolean ";
10130    | RConstString _ | RConstOptString _ | RString _
10131    | RBufferOut _ -> pr "String ";
10132    | RStringList _ -> pr "String[] ";
10133    | RStruct (_, typ) ->
10134        let name = java_name_of_struct typ in
10135        pr "%s " name;
10136    | RStructList (_, typ) ->
10137        let name = java_name_of_struct typ in
10138        pr "%s[] " name;
10139    | RHashtable _ -> pr "HashMap<String,String> ";
10140   );
10141
10142   if native then pr "_%s " name else pr "%s " name;
10143   pr "(";
10144   let needs_comma = ref false in
10145   if native then (
10146     pr "long g";
10147     needs_comma := true
10148   );
10149
10150   (* args *)
10151   List.iter (
10152     fun arg ->
10153       if !needs_comma then pr ", ";
10154       needs_comma := true;
10155
10156       match arg with
10157       | Pathname n
10158       | Device n | Dev_or_Path n
10159       | String n
10160       | OptString n
10161       | FileIn n
10162       | FileOut n ->
10163           pr "String %s" n
10164       | BufferIn n ->
10165           pr "byte[] %s" n
10166       | StringList n | DeviceList n ->
10167           pr "String[] %s" n
10168       | Bool n ->
10169           pr "boolean %s" n
10170       | Int n ->
10171           pr "int %s" n
10172       | Int64 n ->
10173           pr "long %s" n
10174   ) (snd style);
10175
10176   pr ")\n";
10177   pr "    throws LibGuestFSException";
10178   if semicolon then pr ";"
10179
10180 and generate_java_struct jtyp cols () =
10181   generate_header CStyle LGPLv2plus;
10182
10183   pr "\
10184 package com.redhat.et.libguestfs;
10185
10186 /**
10187  * Libguestfs %s structure.
10188  *
10189  * @author rjones
10190  * @see GuestFS
10191  */
10192 public class %s {
10193 " jtyp jtyp;
10194
10195   List.iter (
10196     function
10197     | name, FString
10198     | name, FUUID
10199     | name, FBuffer -> pr "  public String %s;\n" name
10200     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10201     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10202     | name, FChar -> pr "  public char %s;\n" name
10203     | name, FOptPercent ->
10204         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10205         pr "  public float %s;\n" name
10206   ) cols;
10207
10208   pr "}\n"
10209
10210 and generate_java_c () =
10211   generate_header CStyle LGPLv2plus;
10212
10213   pr "\
10214 #include <stdio.h>
10215 #include <stdlib.h>
10216 #include <string.h>
10217
10218 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10219 #include \"guestfs.h\"
10220
10221 /* Note that this function returns.  The exception is not thrown
10222  * until after the wrapper function returns.
10223  */
10224 static void
10225 throw_exception (JNIEnv *env, const char *msg)
10226 {
10227   jclass cl;
10228   cl = (*env)->FindClass (env,
10229                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10230   (*env)->ThrowNew (env, cl, msg);
10231 }
10232
10233 JNIEXPORT jlong JNICALL
10234 Java_com_redhat_et_libguestfs_GuestFS__1create
10235   (JNIEnv *env, jobject obj)
10236 {
10237   guestfs_h *g;
10238
10239   g = guestfs_create ();
10240   if (g == NULL) {
10241     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10242     return 0;
10243   }
10244   guestfs_set_error_handler (g, NULL, NULL);
10245   return (jlong) (long) g;
10246 }
10247
10248 JNIEXPORT void JNICALL
10249 Java_com_redhat_et_libguestfs_GuestFS__1close
10250   (JNIEnv *env, jobject obj, jlong jg)
10251 {
10252   guestfs_h *g = (guestfs_h *) (long) jg;
10253   guestfs_close (g);
10254 }
10255
10256 ";
10257
10258   List.iter (
10259     fun (name, style, _, _, _, _, _) ->
10260       pr "JNIEXPORT ";
10261       (match fst style with
10262        | RErr -> pr "void ";
10263        | RInt _ -> pr "jint ";
10264        | RInt64 _ -> pr "jlong ";
10265        | RBool _ -> pr "jboolean ";
10266        | RConstString _ | RConstOptString _ | RString _
10267        | RBufferOut _ -> pr "jstring ";
10268        | RStruct _ | RHashtable _ ->
10269            pr "jobject ";
10270        | RStringList _ | RStructList _ ->
10271            pr "jobjectArray ";
10272       );
10273       pr "JNICALL\n";
10274       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10275       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10276       pr "\n";
10277       pr "  (JNIEnv *env, jobject obj, jlong jg";
10278       List.iter (
10279         function
10280         | Pathname n
10281         | Device n | Dev_or_Path n
10282         | String n
10283         | OptString n
10284         | FileIn n
10285         | FileOut n ->
10286             pr ", jstring j%s" n
10287         | BufferIn n ->
10288             pr ", jbyteArray j%s" n
10289         | StringList n | DeviceList n ->
10290             pr ", jobjectArray j%s" n
10291         | Bool n ->
10292             pr ", jboolean j%s" n
10293         | Int n ->
10294             pr ", jint j%s" n
10295         | Int64 n ->
10296             pr ", jlong j%s" n
10297       ) (snd style);
10298       pr ")\n";
10299       pr "{\n";
10300       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10301       let error_code, no_ret =
10302         match fst style with
10303         | RErr -> pr "  int r;\n"; "-1", ""
10304         | RBool _
10305         | RInt _ -> pr "  int r;\n"; "-1", "0"
10306         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10307         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10308         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10309         | RString _ ->
10310             pr "  jstring jr;\n";
10311             pr "  char *r;\n"; "NULL", "NULL"
10312         | RStringList _ ->
10313             pr "  jobjectArray jr;\n";
10314             pr "  int r_len;\n";
10315             pr "  jclass cl;\n";
10316             pr "  jstring jstr;\n";
10317             pr "  char **r;\n"; "NULL", "NULL"
10318         | RStruct (_, typ) ->
10319             pr "  jobject jr;\n";
10320             pr "  jclass cl;\n";
10321             pr "  jfieldID fl;\n";
10322             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10323         | RStructList (_, typ) ->
10324             pr "  jobjectArray jr;\n";
10325             pr "  jclass cl;\n";
10326             pr "  jfieldID fl;\n";
10327             pr "  jobject jfl;\n";
10328             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10329         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10330         | RBufferOut _ ->
10331             pr "  jstring jr;\n";
10332             pr "  char *r;\n";
10333             pr "  size_t size;\n";
10334             "NULL", "NULL" in
10335       List.iter (
10336         function
10337         | Pathname n
10338         | Device n | Dev_or_Path n
10339         | String n
10340         | OptString n
10341         | FileIn n
10342         | FileOut n ->
10343             pr "  const char *%s;\n" n
10344         | BufferIn n ->
10345             pr "  jbyte *%s;\n" n;
10346             pr "  size_t %s_size;\n" n
10347         | StringList n | DeviceList n ->
10348             pr "  int %s_len;\n" n;
10349             pr "  const char **%s;\n" n
10350         | Bool n
10351         | Int n ->
10352             pr "  int %s;\n" n
10353         | Int64 n ->
10354             pr "  int64_t %s;\n" n
10355       ) (snd style);
10356
10357       let needs_i =
10358         (match fst style with
10359          | RStringList _ | RStructList _ -> true
10360          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10361          | RConstOptString _
10362          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10363           List.exists (function
10364                        | StringList _ -> true
10365                        | DeviceList _ -> true
10366                        | _ -> false) (snd style) in
10367       if needs_i then
10368         pr "  int i;\n";
10369
10370       pr "\n";
10371
10372       (* Get the parameters. *)
10373       List.iter (
10374         function
10375         | Pathname n
10376         | Device n | Dev_or_Path n
10377         | String n
10378         | FileIn n
10379         | FileOut n ->
10380             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10381         | OptString n ->
10382             (* This is completely undocumented, but Java null becomes
10383              * a NULL parameter.
10384              *)
10385             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10386         | BufferIn n ->
10387             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10388             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10389         | StringList n | DeviceList n ->
10390             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10391             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10392             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10393             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10394               n;
10395             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10396             pr "  }\n";
10397             pr "  %s[%s_len] = NULL;\n" n n;
10398         | Bool n
10399         | Int n
10400         | Int64 n ->
10401             pr "  %s = j%s;\n" n n
10402       ) (snd style);
10403
10404       (* Make the call. *)
10405       pr "  r = guestfs_%s " name;
10406       generate_c_call_args ~handle:"g" style;
10407       pr ";\n";
10408
10409       (* Release the parameters. *)
10410       List.iter (
10411         function
10412         | Pathname n
10413         | Device n | Dev_or_Path n
10414         | String n
10415         | FileIn n
10416         | FileOut n ->
10417             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10418         | OptString n ->
10419             pr "  if (j%s)\n" n;
10420             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10421         | BufferIn n ->
10422             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10423         | StringList n | DeviceList n ->
10424             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10425             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10426               n;
10427             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10428             pr "  }\n";
10429             pr "  free (%s);\n" n
10430         | Bool n
10431         | Int n
10432         | Int64 n -> ()
10433       ) (snd style);
10434
10435       (* Check for errors. *)
10436       pr "  if (r == %s) {\n" error_code;
10437       pr "    throw_exception (env, guestfs_last_error (g));\n";
10438       pr "    return %s;\n" no_ret;
10439       pr "  }\n";
10440
10441       (* Return value. *)
10442       (match fst style with
10443        | RErr -> ()
10444        | RInt _ -> pr "  return (jint) r;\n"
10445        | RBool _ -> pr "  return (jboolean) r;\n"
10446        | RInt64 _ -> pr "  return (jlong) r;\n"
10447        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10448        | RConstOptString _ ->
10449            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10450        | RString _ ->
10451            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10452            pr "  free (r);\n";
10453            pr "  return jr;\n"
10454        | RStringList _ ->
10455            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10456            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10457            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10458            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10459            pr "  for (i = 0; i < r_len; ++i) {\n";
10460            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10461            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10462            pr "    free (r[i]);\n";
10463            pr "  }\n";
10464            pr "  free (r);\n";
10465            pr "  return jr;\n"
10466        | RStruct (_, typ) ->
10467            let jtyp = java_name_of_struct typ in
10468            let cols = cols_of_struct typ in
10469            generate_java_struct_return typ jtyp cols
10470        | RStructList (_, typ) ->
10471            let jtyp = java_name_of_struct typ in
10472            let cols = cols_of_struct typ in
10473            generate_java_struct_list_return typ jtyp cols
10474        | RHashtable _ ->
10475            (* XXX *)
10476            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10477            pr "  return NULL;\n"
10478        | RBufferOut _ ->
10479            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10480            pr "  free (r);\n";
10481            pr "  return jr;\n"
10482       );
10483
10484       pr "}\n";
10485       pr "\n"
10486   ) all_functions
10487
10488 and generate_java_struct_return typ jtyp cols =
10489   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10490   pr "  jr = (*env)->AllocObject (env, cl);\n";
10491   List.iter (
10492     function
10493     | name, FString ->
10494         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10495         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10496     | name, FUUID ->
10497         pr "  {\n";
10498         pr "    char s[33];\n";
10499         pr "    memcpy (s, r->%s, 32);\n" name;
10500         pr "    s[32] = 0;\n";
10501         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10502         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10503         pr "  }\n";
10504     | name, FBuffer ->
10505         pr "  {\n";
10506         pr "    int len = r->%s_len;\n" name;
10507         pr "    char s[len+1];\n";
10508         pr "    memcpy (s, r->%s, len);\n" name;
10509         pr "    s[len] = 0;\n";
10510         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10511         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10512         pr "  }\n";
10513     | name, (FBytes|FUInt64|FInt64) ->
10514         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10515         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10516     | name, (FUInt32|FInt32) ->
10517         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10518         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10519     | name, FOptPercent ->
10520         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10521         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10522     | name, FChar ->
10523         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10524         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10525   ) cols;
10526   pr "  free (r);\n";
10527   pr "  return jr;\n"
10528
10529 and generate_java_struct_list_return typ jtyp cols =
10530   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10531   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10532   pr "  for (i = 0; i < r->len; ++i) {\n";
10533   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10534   List.iter (
10535     function
10536     | name, FString ->
10537         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10538         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10539     | name, FUUID ->
10540         pr "    {\n";
10541         pr "      char s[33];\n";
10542         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10543         pr "      s[32] = 0;\n";
10544         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10545         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10546         pr "    }\n";
10547     | name, FBuffer ->
10548         pr "    {\n";
10549         pr "      int len = r->val[i].%s_len;\n" name;
10550         pr "      char s[len+1];\n";
10551         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10552         pr "      s[len] = 0;\n";
10553         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10554         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10555         pr "    }\n";
10556     | name, (FBytes|FUInt64|FInt64) ->
10557         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10558         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10559     | name, (FUInt32|FInt32) ->
10560         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10561         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10562     | name, FOptPercent ->
10563         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10564         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10565     | name, FChar ->
10566         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10567         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10568   ) cols;
10569   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10570   pr "  }\n";
10571   pr "  guestfs_free_%s_list (r);\n" typ;
10572   pr "  return jr;\n"
10573
10574 and generate_java_makefile_inc () =
10575   generate_header HashStyle GPLv2plus;
10576
10577   pr "java_built_sources = \\\n";
10578   List.iter (
10579     fun (typ, jtyp) ->
10580         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10581   ) java_structs;
10582   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10583
10584 and generate_haskell_hs () =
10585   generate_header HaskellStyle LGPLv2plus;
10586
10587   (* XXX We only know how to generate partial FFI for Haskell
10588    * at the moment.  Please help out!
10589    *)
10590   let can_generate style =
10591     match style with
10592     | RErr, _
10593     | RInt _, _
10594     | RInt64 _, _ -> true
10595     | RBool _, _
10596     | RConstString _, _
10597     | RConstOptString _, _
10598     | RString _, _
10599     | RStringList _, _
10600     | RStruct _, _
10601     | RStructList _, _
10602     | RHashtable _, _
10603     | RBufferOut _, _ -> false in
10604
10605   pr "\
10606 {-# INCLUDE <guestfs.h> #-}
10607 {-# LANGUAGE ForeignFunctionInterface #-}
10608
10609 module Guestfs (
10610   create";
10611
10612   (* List out the names of the actions we want to export. *)
10613   List.iter (
10614     fun (name, style, _, _, _, _, _) ->
10615       if can_generate style then pr ",\n  %s" name
10616   ) all_functions;
10617
10618   pr "
10619   ) where
10620
10621 -- Unfortunately some symbols duplicate ones already present
10622 -- in Prelude.  We don't know which, so we hard-code a list
10623 -- here.
10624 import Prelude hiding (truncate)
10625
10626 import Foreign
10627 import Foreign.C
10628 import Foreign.C.Types
10629 import IO
10630 import Control.Exception
10631 import Data.Typeable
10632
10633 data GuestfsS = GuestfsS            -- represents the opaque C struct
10634 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10635 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10636
10637 -- XXX define properly later XXX
10638 data PV = PV
10639 data VG = VG
10640 data LV = LV
10641 data IntBool = IntBool
10642 data Stat = Stat
10643 data StatVFS = StatVFS
10644 data Hashtable = Hashtable
10645
10646 foreign import ccall unsafe \"guestfs_create\" c_create
10647   :: IO GuestfsP
10648 foreign import ccall unsafe \"&guestfs_close\" c_close
10649   :: FunPtr (GuestfsP -> IO ())
10650 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10651   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10652
10653 create :: IO GuestfsH
10654 create = do
10655   p <- c_create
10656   c_set_error_handler p nullPtr nullPtr
10657   h <- newForeignPtr c_close p
10658   return h
10659
10660 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10661   :: GuestfsP -> IO CString
10662
10663 -- last_error :: GuestfsH -> IO (Maybe String)
10664 -- last_error h = do
10665 --   str <- withForeignPtr h (\\p -> c_last_error p)
10666 --   maybePeek peekCString str
10667
10668 last_error :: GuestfsH -> IO (String)
10669 last_error h = do
10670   str <- withForeignPtr h (\\p -> c_last_error p)
10671   if (str == nullPtr)
10672     then return \"no error\"
10673     else peekCString str
10674
10675 ";
10676
10677   (* Generate wrappers for each foreign function. *)
10678   List.iter (
10679     fun (name, style, _, _, _, _, _) ->
10680       if can_generate style then (
10681         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10682         pr "  :: ";
10683         generate_haskell_prototype ~handle:"GuestfsP" style;
10684         pr "\n";
10685         pr "\n";
10686         pr "%s :: " name;
10687         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10688         pr "\n";
10689         pr "%s %s = do\n" name
10690           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10691         pr "  r <- ";
10692         (* Convert pointer arguments using with* functions. *)
10693         List.iter (
10694           function
10695           | FileIn n
10696           | FileOut n
10697           | Pathname n | Device n | Dev_or_Path n | String n ->
10698               pr "withCString %s $ \\%s -> " n n
10699           | BufferIn n ->
10700               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10701           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10702           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10703           | Bool _ | Int _ | Int64 _ -> ()
10704         ) (snd style);
10705         (* Convert integer arguments. *)
10706         let args =
10707           List.map (
10708             function
10709             | Bool n -> sprintf "(fromBool %s)" n
10710             | Int n -> sprintf "(fromIntegral %s)" n
10711             | Int64 n -> sprintf "(fromIntegral %s)" n
10712             | FileIn n | FileOut n
10713             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10714             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10715           ) (snd style) in
10716         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10717           (String.concat " " ("p" :: args));
10718         (match fst style with
10719          | RErr | RInt _ | RInt64 _ | RBool _ ->
10720              pr "  if (r == -1)\n";
10721              pr "    then do\n";
10722              pr "      err <- last_error h\n";
10723              pr "      fail err\n";
10724          | RConstString _ | RConstOptString _ | RString _
10725          | RStringList _ | RStruct _
10726          | RStructList _ | RHashtable _ | RBufferOut _ ->
10727              pr "  if (r == nullPtr)\n";
10728              pr "    then do\n";
10729              pr "      err <- last_error h\n";
10730              pr "      fail err\n";
10731         );
10732         (match fst style with
10733          | RErr ->
10734              pr "    else return ()\n"
10735          | RInt _ ->
10736              pr "    else return (fromIntegral r)\n"
10737          | RInt64 _ ->
10738              pr "    else return (fromIntegral r)\n"
10739          | RBool _ ->
10740              pr "    else return (toBool r)\n"
10741          | RConstString _
10742          | RConstOptString _
10743          | RString _
10744          | RStringList _
10745          | RStruct _
10746          | RStructList _
10747          | RHashtable _
10748          | RBufferOut _ ->
10749              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10750         );
10751         pr "\n";
10752       )
10753   ) all_functions
10754
10755 and generate_haskell_prototype ~handle ?(hs = false) style =
10756   pr "%s -> " handle;
10757   let string = if hs then "String" else "CString" in
10758   let int = if hs then "Int" else "CInt" in
10759   let bool = if hs then "Bool" else "CInt" in
10760   let int64 = if hs then "Integer" else "Int64" in
10761   List.iter (
10762     fun arg ->
10763       (match arg with
10764        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10765        | BufferIn _ ->
10766            if hs then pr "String"
10767            else pr "CString -> CInt"
10768        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10769        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10770        | Bool _ -> pr "%s" bool
10771        | Int _ -> pr "%s" int
10772        | Int64 _ -> pr "%s" int
10773        | FileIn _ -> pr "%s" string
10774        | FileOut _ -> pr "%s" string
10775       );
10776       pr " -> ";
10777   ) (snd style);
10778   pr "IO (";
10779   (match fst style with
10780    | RErr -> if not hs then pr "CInt"
10781    | RInt _ -> pr "%s" int
10782    | RInt64 _ -> pr "%s" int64
10783    | RBool _ -> pr "%s" bool
10784    | RConstString _ -> pr "%s" string
10785    | RConstOptString _ -> pr "Maybe %s" string
10786    | RString _ -> pr "%s" string
10787    | RStringList _ -> pr "[%s]" string
10788    | RStruct (_, typ) ->
10789        let name = java_name_of_struct typ in
10790        pr "%s" name
10791    | RStructList (_, typ) ->
10792        let name = java_name_of_struct typ in
10793        pr "[%s]" name
10794    | RHashtable _ -> pr "Hashtable"
10795    | RBufferOut _ -> pr "%s" string
10796   );
10797   pr ")"
10798
10799 and generate_csharp () =
10800   generate_header CPlusPlusStyle LGPLv2plus;
10801
10802   (* XXX Make this configurable by the C# assembly users. *)
10803   let library = "libguestfs.so.0" in
10804
10805   pr "\
10806 // These C# bindings are highly experimental at present.
10807 //
10808 // Firstly they only work on Linux (ie. Mono).  In order to get them
10809 // to work on Windows (ie. .Net) you would need to port the library
10810 // itself to Windows first.
10811 //
10812 // The second issue is that some calls are known to be incorrect and
10813 // can cause Mono to segfault.  Particularly: calls which pass or
10814 // return string[], or return any structure value.  This is because
10815 // we haven't worked out the correct way to do this from C#.
10816 //
10817 // The third issue is that when compiling you get a lot of warnings.
10818 // We are not sure whether the warnings are important or not.
10819 //
10820 // Fourthly we do not routinely build or test these bindings as part
10821 // of the make && make check cycle, which means that regressions might
10822 // go unnoticed.
10823 //
10824 // Suggestions and patches are welcome.
10825
10826 // To compile:
10827 //
10828 // gmcs Libguestfs.cs
10829 // mono Libguestfs.exe
10830 //
10831 // (You'll probably want to add a Test class / static main function
10832 // otherwise this won't do anything useful).
10833
10834 using System;
10835 using System.IO;
10836 using System.Runtime.InteropServices;
10837 using System.Runtime.Serialization;
10838 using System.Collections;
10839
10840 namespace Guestfs
10841 {
10842   class Error : System.ApplicationException
10843   {
10844     public Error (string message) : base (message) {}
10845     protected Error (SerializationInfo info, StreamingContext context) {}
10846   }
10847
10848   class Guestfs
10849   {
10850     IntPtr _handle;
10851
10852     [DllImport (\"%s\")]
10853     static extern IntPtr guestfs_create ();
10854
10855     public Guestfs ()
10856     {
10857       _handle = guestfs_create ();
10858       if (_handle == IntPtr.Zero)
10859         throw new Error (\"could not create guestfs handle\");
10860     }
10861
10862     [DllImport (\"%s\")]
10863     static extern void guestfs_close (IntPtr h);
10864
10865     ~Guestfs ()
10866     {
10867       guestfs_close (_handle);
10868     }
10869
10870     [DllImport (\"%s\")]
10871     static extern string guestfs_last_error (IntPtr h);
10872
10873 " library library library;
10874
10875   (* Generate C# structure bindings.  We prefix struct names with
10876    * underscore because C# cannot have conflicting struct names and
10877    * method names (eg. "class stat" and "stat").
10878    *)
10879   List.iter (
10880     fun (typ, cols) ->
10881       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10882       pr "    public class _%s {\n" typ;
10883       List.iter (
10884         function
10885         | name, FChar -> pr "      char %s;\n" name
10886         | name, FString -> pr "      string %s;\n" name
10887         | name, FBuffer ->
10888             pr "      uint %s_len;\n" name;
10889             pr "      string %s;\n" name
10890         | name, FUUID ->
10891             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10892             pr "      string %s;\n" name
10893         | name, FUInt32 -> pr "      uint %s;\n" name
10894         | name, FInt32 -> pr "      int %s;\n" name
10895         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10896         | name, FInt64 -> pr "      long %s;\n" name
10897         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10898       ) cols;
10899       pr "    }\n";
10900       pr "\n"
10901   ) structs;
10902
10903   (* Generate C# function bindings. *)
10904   List.iter (
10905     fun (name, style, _, _, _, shortdesc, _) ->
10906       let rec csharp_return_type () =
10907         match fst style with
10908         | RErr -> "void"
10909         | RBool n -> "bool"
10910         | RInt n -> "int"
10911         | RInt64 n -> "long"
10912         | RConstString n
10913         | RConstOptString n
10914         | RString n
10915         | RBufferOut n -> "string"
10916         | RStruct (_,n) -> "_" ^ n
10917         | RHashtable n -> "Hashtable"
10918         | RStringList n -> "string[]"
10919         | RStructList (_,n) -> sprintf "_%s[]" n
10920
10921       and c_return_type () =
10922         match fst style with
10923         | RErr
10924         | RBool _
10925         | RInt _ -> "int"
10926         | RInt64 _ -> "long"
10927         | RConstString _
10928         | RConstOptString _
10929         | RString _
10930         | RBufferOut _ -> "string"
10931         | RStruct (_,n) -> "_" ^ n
10932         | RHashtable _
10933         | RStringList _ -> "string[]"
10934         | RStructList (_,n) -> sprintf "_%s[]" n
10935
10936       and c_error_comparison () =
10937         match fst style with
10938         | RErr
10939         | RBool _
10940         | RInt _
10941         | RInt64 _ -> "== -1"
10942         | RConstString _
10943         | RConstOptString _
10944         | RString _
10945         | RBufferOut _
10946         | RStruct (_,_)
10947         | RHashtable _
10948         | RStringList _
10949         | RStructList (_,_) -> "== null"
10950
10951       and generate_extern_prototype () =
10952         pr "    static extern %s guestfs_%s (IntPtr h"
10953           (c_return_type ()) name;
10954         List.iter (
10955           function
10956           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10957           | FileIn n | FileOut n
10958           | BufferIn n ->
10959               pr ", [In] string %s" n
10960           | StringList n | DeviceList n ->
10961               pr ", [In] string[] %s" n
10962           | Bool n ->
10963               pr ", bool %s" n
10964           | Int n ->
10965               pr ", int %s" n
10966           | Int64 n ->
10967               pr ", long %s" n
10968         ) (snd style);
10969         pr ");\n"
10970
10971       and generate_public_prototype () =
10972         pr "    public %s %s (" (csharp_return_type ()) name;
10973         let comma = ref false in
10974         let next () =
10975           if !comma then pr ", ";
10976           comma := true
10977         in
10978         List.iter (
10979           function
10980           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10981           | FileIn n | FileOut n
10982           | BufferIn n ->
10983               next (); pr "string %s" n
10984           | StringList n | DeviceList n ->
10985               next (); pr "string[] %s" n
10986           | Bool n ->
10987               next (); pr "bool %s" n
10988           | Int n ->
10989               next (); pr "int %s" n
10990           | Int64 n ->
10991               next (); pr "long %s" n
10992         ) (snd style);
10993         pr ")\n"
10994
10995       and generate_call () =
10996         pr "guestfs_%s (_handle" name;
10997         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10998         pr ");\n";
10999       in
11000
11001       pr "    [DllImport (\"%s\")]\n" library;
11002       generate_extern_prototype ();
11003       pr "\n";
11004       pr "    /// <summary>\n";
11005       pr "    /// %s\n" shortdesc;
11006       pr "    /// </summary>\n";
11007       generate_public_prototype ();
11008       pr "    {\n";
11009       pr "      %s r;\n" (c_return_type ());
11010       pr "      r = ";
11011       generate_call ();
11012       pr "      if (r %s)\n" (c_error_comparison ());
11013       pr "        throw new Error (guestfs_last_error (_handle));\n";
11014       (match fst style with
11015        | RErr -> ()
11016        | RBool _ ->
11017            pr "      return r != 0 ? true : false;\n"
11018        | RHashtable _ ->
11019            pr "      Hashtable rr = new Hashtable ();\n";
11020            pr "      for (int i = 0; i < r.Length; i += 2)\n";
11021            pr "        rr.Add (r[i], r[i+1]);\n";
11022            pr "      return rr;\n"
11023        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11024        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11025        | RStructList _ ->
11026            pr "      return r;\n"
11027       );
11028       pr "    }\n";
11029       pr "\n";
11030   ) all_functions_sorted;
11031
11032   pr "  }
11033 }
11034 "
11035
11036 and generate_bindtests () =
11037   generate_header CStyle LGPLv2plus;
11038
11039   pr "\
11040 #include <stdio.h>
11041 #include <stdlib.h>
11042 #include <inttypes.h>
11043 #include <string.h>
11044
11045 #include \"guestfs.h\"
11046 #include \"guestfs-internal.h\"
11047 #include \"guestfs-internal-actions.h\"
11048 #include \"guestfs_protocol.h\"
11049
11050 #define error guestfs_error
11051 #define safe_calloc guestfs_safe_calloc
11052 #define safe_malloc guestfs_safe_malloc
11053
11054 static void
11055 print_strings (char *const *argv)
11056 {
11057   int argc;
11058
11059   printf (\"[\");
11060   for (argc = 0; argv[argc] != NULL; ++argc) {
11061     if (argc > 0) printf (\", \");
11062     printf (\"\\\"%%s\\\"\", argv[argc]);
11063   }
11064   printf (\"]\\n\");
11065 }
11066
11067 /* The test0 function prints its parameters to stdout. */
11068 ";
11069
11070   let test0, tests =
11071     match test_functions with
11072     | [] -> assert false
11073     | test0 :: tests -> test0, tests in
11074
11075   let () =
11076     let (name, style, _, _, _, _, _) = test0 in
11077     generate_prototype ~extern:false ~semicolon:false ~newline:true
11078       ~handle:"g" ~prefix:"guestfs__" name style;
11079     pr "{\n";
11080     List.iter (
11081       function
11082       | Pathname n
11083       | Device n | Dev_or_Path n
11084       | String n
11085       | FileIn n
11086       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11087       | BufferIn n ->
11088           pr "  {\n";
11089           pr "    size_t i;\n";
11090           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11091           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11092           pr "    printf (\"\\n\");\n";
11093           pr "  }\n";
11094       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11095       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11096       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11097       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11098       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11099     ) (snd style);
11100     pr "  /* Java changes stdout line buffering so we need this: */\n";
11101     pr "  fflush (stdout);\n";
11102     pr "  return 0;\n";
11103     pr "}\n";
11104     pr "\n" in
11105
11106   List.iter (
11107     fun (name, style, _, _, _, _, _) ->
11108       if String.sub name (String.length name - 3) 3 <> "err" then (
11109         pr "/* Test normal return. */\n";
11110         generate_prototype ~extern:false ~semicolon:false ~newline:true
11111           ~handle:"g" ~prefix:"guestfs__" name style;
11112         pr "{\n";
11113         (match fst style with
11114          | RErr ->
11115              pr "  return 0;\n"
11116          | RInt _ ->
11117              pr "  int r;\n";
11118              pr "  sscanf (val, \"%%d\", &r);\n";
11119              pr "  return r;\n"
11120          | RInt64 _ ->
11121              pr "  int64_t r;\n";
11122              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11123              pr "  return r;\n"
11124          | RBool _ ->
11125              pr "  return STREQ (val, \"true\");\n"
11126          | RConstString _
11127          | RConstOptString _ ->
11128              (* Can't return the input string here.  Return a static
11129               * string so we ensure we get a segfault if the caller
11130               * tries to free it.
11131               *)
11132              pr "  return \"static string\";\n"
11133          | RString _ ->
11134              pr "  return strdup (val);\n"
11135          | RStringList _ ->
11136              pr "  char **strs;\n";
11137              pr "  int n, i;\n";
11138              pr "  sscanf (val, \"%%d\", &n);\n";
11139              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11140              pr "  for (i = 0; i < n; ++i) {\n";
11141              pr "    strs[i] = safe_malloc (g, 16);\n";
11142              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11143              pr "  }\n";
11144              pr "  strs[n] = NULL;\n";
11145              pr "  return strs;\n"
11146          | RStruct (_, typ) ->
11147              pr "  struct guestfs_%s *r;\n" typ;
11148              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11149              pr "  return r;\n"
11150          | RStructList (_, typ) ->
11151              pr "  struct guestfs_%s_list *r;\n" typ;
11152              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11153              pr "  sscanf (val, \"%%d\", &r->len);\n";
11154              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11155              pr "  return r;\n"
11156          | RHashtable _ ->
11157              pr "  char **strs;\n";
11158              pr "  int n, i;\n";
11159              pr "  sscanf (val, \"%%d\", &n);\n";
11160              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11161              pr "  for (i = 0; i < n; ++i) {\n";
11162              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11163              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11164              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11165              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11166              pr "  }\n";
11167              pr "  strs[n*2] = NULL;\n";
11168              pr "  return strs;\n"
11169          | RBufferOut _ ->
11170              pr "  return strdup (val);\n"
11171         );
11172         pr "}\n";
11173         pr "\n"
11174       ) else (
11175         pr "/* Test error return. */\n";
11176         generate_prototype ~extern:false ~semicolon:false ~newline:true
11177           ~handle:"g" ~prefix:"guestfs__" name style;
11178         pr "{\n";
11179         pr "  error (g, \"error\");\n";
11180         (match fst style with
11181          | RErr | RInt _ | RInt64 _ | RBool _ ->
11182              pr "  return -1;\n"
11183          | RConstString _ | RConstOptString _
11184          | RString _ | RStringList _ | RStruct _
11185          | RStructList _
11186          | RHashtable _
11187          | RBufferOut _ ->
11188              pr "  return NULL;\n"
11189         );
11190         pr "}\n";
11191         pr "\n"
11192       )
11193   ) tests
11194
11195 and generate_ocaml_bindtests () =
11196   generate_header OCamlStyle GPLv2plus;
11197
11198   pr "\
11199 let () =
11200   let g = Guestfs.create () in
11201 ";
11202
11203   let mkargs args =
11204     String.concat " " (
11205       List.map (
11206         function
11207         | CallString s -> "\"" ^ s ^ "\""
11208         | CallOptString None -> "None"
11209         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11210         | CallStringList xs ->
11211             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11212         | CallInt i when i >= 0 -> string_of_int i
11213         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11214         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11215         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11216         | CallBool b -> string_of_bool b
11217         | CallBuffer s -> sprintf "%S" s
11218       ) args
11219     )
11220   in
11221
11222   generate_lang_bindtests (
11223     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11224   );
11225
11226   pr "print_endline \"EOF\"\n"
11227
11228 and generate_perl_bindtests () =
11229   pr "#!/usr/bin/perl -w\n";
11230   generate_header HashStyle GPLv2plus;
11231
11232   pr "\
11233 use strict;
11234
11235 use Sys::Guestfs;
11236
11237 my $g = Sys::Guestfs->new ();
11238 ";
11239
11240   let mkargs args =
11241     String.concat ", " (
11242       List.map (
11243         function
11244         | CallString s -> "\"" ^ s ^ "\""
11245         | CallOptString None -> "undef"
11246         | CallOptString (Some s) -> sprintf "\"%s\"" s
11247         | CallStringList xs ->
11248             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11249         | CallInt i -> string_of_int i
11250         | CallInt64 i -> Int64.to_string i
11251         | CallBool b -> if b then "1" else "0"
11252         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11253       ) args
11254     )
11255   in
11256
11257   generate_lang_bindtests (
11258     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11259   );
11260
11261   pr "print \"EOF\\n\"\n"
11262
11263 and generate_python_bindtests () =
11264   generate_header HashStyle GPLv2plus;
11265
11266   pr "\
11267 import guestfs
11268
11269 g = guestfs.GuestFS ()
11270 ";
11271
11272   let mkargs args =
11273     String.concat ", " (
11274       List.map (
11275         function
11276         | CallString s -> "\"" ^ s ^ "\""
11277         | CallOptString None -> "None"
11278         | CallOptString (Some s) -> sprintf "\"%s\"" s
11279         | CallStringList xs ->
11280             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11281         | CallInt i -> string_of_int i
11282         | CallInt64 i -> Int64.to_string i
11283         | CallBool b -> if b then "1" else "0"
11284         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11285       ) args
11286     )
11287   in
11288
11289   generate_lang_bindtests (
11290     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11291   );
11292
11293   pr "print \"EOF\"\n"
11294
11295 and generate_ruby_bindtests () =
11296   generate_header HashStyle GPLv2plus;
11297
11298   pr "\
11299 require 'guestfs'
11300
11301 g = Guestfs::create()
11302 ";
11303
11304   let mkargs args =
11305     String.concat ", " (
11306       List.map (
11307         function
11308         | CallString s -> "\"" ^ s ^ "\""
11309         | CallOptString None -> "nil"
11310         | CallOptString (Some s) -> sprintf "\"%s\"" s
11311         | CallStringList xs ->
11312             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11313         | CallInt i -> string_of_int i
11314         | CallInt64 i -> Int64.to_string i
11315         | CallBool b -> string_of_bool b
11316         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11317       ) args
11318     )
11319   in
11320
11321   generate_lang_bindtests (
11322     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11323   );
11324
11325   pr "print \"EOF\\n\"\n"
11326
11327 and generate_java_bindtests () =
11328   generate_header CStyle GPLv2plus;
11329
11330   pr "\
11331 import com.redhat.et.libguestfs.*;
11332
11333 public class Bindtests {
11334     public static void main (String[] argv)
11335     {
11336         try {
11337             GuestFS g = new GuestFS ();
11338 ";
11339
11340   let mkargs args =
11341     String.concat ", " (
11342       List.map (
11343         function
11344         | CallString s -> "\"" ^ s ^ "\""
11345         | CallOptString None -> "null"
11346         | CallOptString (Some s) -> sprintf "\"%s\"" s
11347         | CallStringList xs ->
11348             "new String[]{" ^
11349               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11350         | CallInt i -> string_of_int i
11351         | CallInt64 i -> Int64.to_string i
11352         | CallBool b -> string_of_bool b
11353         | CallBuffer s ->
11354             "new byte[] { " ^ String.concat "," (
11355               map_chars (fun c -> string_of_int (Char.code c)) s
11356             ) ^ " }"
11357       ) args
11358     )
11359   in
11360
11361   generate_lang_bindtests (
11362     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11363   );
11364
11365   pr "
11366             System.out.println (\"EOF\");
11367         }
11368         catch (Exception exn) {
11369             System.err.println (exn);
11370             System.exit (1);
11371         }
11372     }
11373 }
11374 "
11375
11376 and generate_haskell_bindtests () =
11377   generate_header HaskellStyle GPLv2plus;
11378
11379   pr "\
11380 module Bindtests where
11381 import qualified Guestfs
11382
11383 main = do
11384   g <- Guestfs.create
11385 ";
11386
11387   let mkargs args =
11388     String.concat " " (
11389       List.map (
11390         function
11391         | CallString s -> "\"" ^ s ^ "\""
11392         | CallOptString None -> "Nothing"
11393         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11394         | CallStringList xs ->
11395             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11396         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11397         | CallInt i -> string_of_int i
11398         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11399         | CallInt64 i -> Int64.to_string i
11400         | CallBool true -> "True"
11401         | CallBool false -> "False"
11402         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11403       ) args
11404     )
11405   in
11406
11407   generate_lang_bindtests (
11408     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11409   );
11410
11411   pr "  putStrLn \"EOF\"\n"
11412
11413 (* Language-independent bindings tests - we do it this way to
11414  * ensure there is parity in testing bindings across all languages.
11415  *)
11416 and generate_lang_bindtests call =
11417   call "test0" [CallString "abc"; CallOptString (Some "def");
11418                 CallStringList []; CallBool false;
11419                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11420                 CallBuffer "abc\000abc"];
11421   call "test0" [CallString "abc"; CallOptString None;
11422                 CallStringList []; CallBool false;
11423                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11424                 CallBuffer "abc\000abc"];
11425   call "test0" [CallString ""; CallOptString (Some "def");
11426                 CallStringList []; CallBool false;
11427                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11428                 CallBuffer "abc\000abc"];
11429   call "test0" [CallString ""; CallOptString (Some "");
11430                 CallStringList []; CallBool false;
11431                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11432                 CallBuffer "abc\000abc"];
11433   call "test0" [CallString "abc"; CallOptString (Some "def");
11434                 CallStringList ["1"]; CallBool false;
11435                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11436                 CallBuffer "abc\000abc"];
11437   call "test0" [CallString "abc"; CallOptString (Some "def");
11438                 CallStringList ["1"; "2"]; CallBool false;
11439                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11440                 CallBuffer "abc\000abc"];
11441   call "test0" [CallString "abc"; CallOptString (Some "def");
11442                 CallStringList ["1"]; CallBool true;
11443                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11444                 CallBuffer "abc\000abc"];
11445   call "test0" [CallString "abc"; CallOptString (Some "def");
11446                 CallStringList ["1"]; CallBool false;
11447                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11448                 CallBuffer "abc\000abc"];
11449   call "test0" [CallString "abc"; CallOptString (Some "def");
11450                 CallStringList ["1"]; CallBool false;
11451                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11452                 CallBuffer "abc\000abc"];
11453   call "test0" [CallString "abc"; CallOptString (Some "def");
11454                 CallStringList ["1"]; CallBool false;
11455                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11456                 CallBuffer "abc\000abc"];
11457   call "test0" [CallString "abc"; CallOptString (Some "def");
11458                 CallStringList ["1"]; CallBool false;
11459                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11460                 CallBuffer "abc\000abc"];
11461   call "test0" [CallString "abc"; CallOptString (Some "def");
11462                 CallStringList ["1"]; CallBool false;
11463                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11464                 CallBuffer "abc\000abc"];
11465   call "test0" [CallString "abc"; CallOptString (Some "def");
11466                 CallStringList ["1"]; CallBool false;
11467                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11468                 CallBuffer "abc\000abc"]
11469
11470 (* XXX Add here tests of the return and error functions. *)
11471
11472 (* Code to generator bindings for virt-inspector.  Currently only
11473  * implemented for OCaml code (for virt-p2v 2.0).
11474  *)
11475 let rng_input = "inspector/virt-inspector.rng"
11476
11477 (* Read the input file and parse it into internal structures.  This is
11478  * by no means a complete RELAX NG parser, but is just enough to be
11479  * able to parse the specific input file.
11480  *)
11481 type rng =
11482   | Element of string * rng list        (* <element name=name/> *)
11483   | Attribute of string * rng list        (* <attribute name=name/> *)
11484   | Interleave of rng list                (* <interleave/> *)
11485   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11486   | OneOrMore of rng                        (* <oneOrMore/> *)
11487   | Optional of rng                        (* <optional/> *)
11488   | Choice of string list                (* <choice><value/>*</choice> *)
11489   | Value of string                        (* <value>str</value> *)
11490   | Text                                (* <text/> *)
11491
11492 let rec string_of_rng = function
11493   | Element (name, xs) ->
11494       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11495   | Attribute (name, xs) ->
11496       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11497   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11498   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11499   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11500   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11501   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11502   | Value value -> "Value \"" ^ value ^ "\""
11503   | Text -> "Text"
11504
11505 and string_of_rng_list xs =
11506   String.concat ", " (List.map string_of_rng xs)
11507
11508 let rec parse_rng ?defines context = function
11509   | [] -> []
11510   | Xml.Element ("element", ["name", name], children) :: rest ->
11511       Element (name, parse_rng ?defines context children)
11512       :: parse_rng ?defines context rest
11513   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11514       Attribute (name, parse_rng ?defines context children)
11515       :: parse_rng ?defines context rest
11516   | Xml.Element ("interleave", [], children) :: rest ->
11517       Interleave (parse_rng ?defines context children)
11518       :: parse_rng ?defines context rest
11519   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11520       let rng = parse_rng ?defines context [child] in
11521       (match rng with
11522        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11523        | _ ->
11524            failwithf "%s: <zeroOrMore> contains more than one child element"
11525              context
11526       )
11527   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11528       let rng = parse_rng ?defines context [child] in
11529       (match rng with
11530        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11531        | _ ->
11532            failwithf "%s: <oneOrMore> contains more than one child element"
11533              context
11534       )
11535   | Xml.Element ("optional", [], [child]) :: rest ->
11536       let rng = parse_rng ?defines context [child] in
11537       (match rng with
11538        | [child] -> Optional child :: parse_rng ?defines context rest
11539        | _ ->
11540            failwithf "%s: <optional> contains more than one child element"
11541              context
11542       )
11543   | Xml.Element ("choice", [], children) :: rest ->
11544       let values = List.map (
11545         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11546         | _ ->
11547             failwithf "%s: can't handle anything except <value> in <choice>"
11548               context
11549       ) children in
11550       Choice values
11551       :: parse_rng ?defines context rest
11552   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11553       Value value :: parse_rng ?defines context rest
11554   | Xml.Element ("text", [], []) :: rest ->
11555       Text :: parse_rng ?defines context rest
11556   | Xml.Element ("ref", ["name", name], []) :: rest ->
11557       (* Look up the reference.  Because of limitations in this parser,
11558        * we can't handle arbitrarily nested <ref> yet.  You can only
11559        * use <ref> from inside <start>.
11560        *)
11561       (match defines with
11562        | None ->
11563            failwithf "%s: contains <ref>, but no refs are defined yet" context
11564        | Some map ->
11565            let rng = StringMap.find name map in
11566            rng @ parse_rng ?defines context rest
11567       )
11568   | x :: _ ->
11569       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11570
11571 let grammar =
11572   let xml = Xml.parse_file rng_input in
11573   match xml with
11574   | Xml.Element ("grammar", _,
11575                  Xml.Element ("start", _, gram) :: defines) ->
11576       (* The <define/> elements are referenced in the <start> section,
11577        * so build a map of those first.
11578        *)
11579       let defines = List.fold_left (
11580         fun map ->
11581           function Xml.Element ("define", ["name", name], defn) ->
11582             StringMap.add name defn map
11583           | _ ->
11584               failwithf "%s: expected <define name=name/>" rng_input
11585       ) StringMap.empty defines in
11586       let defines = StringMap.mapi parse_rng defines in
11587
11588       (* Parse the <start> clause, passing the defines. *)
11589       parse_rng ~defines "<start>" gram
11590   | _ ->
11591       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11592         rng_input
11593
11594 let name_of_field = function
11595   | Element (name, _) | Attribute (name, _)
11596   | ZeroOrMore (Element (name, _))
11597   | OneOrMore (Element (name, _))
11598   | Optional (Element (name, _)) -> name
11599   | Optional (Attribute (name, _)) -> name
11600   | Text -> (* an unnamed field in an element *)
11601       "data"
11602   | rng ->
11603       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11604
11605 (* At the moment this function only generates OCaml types.  However we
11606  * should parameterize it later so it can generate types/structs in a
11607  * variety of languages.
11608  *)
11609 let generate_types xs =
11610   (* A simple type is one that can be printed out directly, eg.
11611    * "string option".  A complex type is one which has a name and has
11612    * to be defined via another toplevel definition, eg. a struct.
11613    *
11614    * generate_type generates code for either simple or complex types.
11615    * In the simple case, it returns the string ("string option").  In
11616    * the complex case, it returns the name ("mountpoint").  In the
11617    * complex case it has to print out the definition before returning,
11618    * so it should only be called when we are at the beginning of a
11619    * new line (BOL context).
11620    *)
11621   let rec generate_type = function
11622     | Text ->                                (* string *)
11623         "string", true
11624     | Choice values ->                        (* [`val1|`val2|...] *)
11625         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11626     | ZeroOrMore rng ->                        (* <rng> list *)
11627         let t, is_simple = generate_type rng in
11628         t ^ " list (* 0 or more *)", is_simple
11629     | OneOrMore rng ->                        (* <rng> list *)
11630         let t, is_simple = generate_type rng in
11631         t ^ " list (* 1 or more *)", is_simple
11632                                         (* virt-inspector hack: bool *)
11633     | Optional (Attribute (name, [Value "1"])) ->
11634         "bool", true
11635     | Optional rng ->                        (* <rng> list *)
11636         let t, is_simple = generate_type rng in
11637         t ^ " option", is_simple
11638                                         (* type name = { fields ... } *)
11639     | Element (name, fields) when is_attrs_interleave fields ->
11640         generate_type_struct name (get_attrs_interleave fields)
11641     | Element (name, [field])                (* type name = field *)
11642     | Attribute (name, [field]) ->
11643         let t, is_simple = generate_type field in
11644         if is_simple then (t, true)
11645         else (
11646           pr "type %s = %s\n" name t;
11647           name, false
11648         )
11649     | Element (name, fields) ->              (* type name = { fields ... } *)
11650         generate_type_struct name fields
11651     | rng ->
11652         failwithf "generate_type failed at: %s" (string_of_rng rng)
11653
11654   and is_attrs_interleave = function
11655     | [Interleave _] -> true
11656     | Attribute _ :: fields -> is_attrs_interleave fields
11657     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11658     | _ -> false
11659
11660   and get_attrs_interleave = function
11661     | [Interleave fields] -> fields
11662     | ((Attribute _) as field) :: fields
11663     | ((Optional (Attribute _)) as field) :: fields ->
11664         field :: get_attrs_interleave fields
11665     | _ -> assert false
11666
11667   and generate_types xs =
11668     List.iter (fun x -> ignore (generate_type x)) xs
11669
11670   and generate_type_struct name fields =
11671     (* Calculate the types of the fields first.  We have to do this
11672      * before printing anything so we are still in BOL context.
11673      *)
11674     let types = List.map fst (List.map generate_type fields) in
11675
11676     (* Special case of a struct containing just a string and another
11677      * field.  Turn it into an assoc list.
11678      *)
11679     match types with
11680     | ["string"; other] ->
11681         let fname1, fname2 =
11682           match fields with
11683           | [f1; f2] -> name_of_field f1, name_of_field f2
11684           | _ -> assert false in
11685         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11686         name, false
11687
11688     | types ->
11689         pr "type %s = {\n" name;
11690         List.iter (
11691           fun (field, ftype) ->
11692             let fname = name_of_field field in
11693             pr "  %s_%s : %s;\n" name fname ftype
11694         ) (List.combine fields types);
11695         pr "}\n";
11696         (* Return the name of this type, and
11697          * false because it's not a simple type.
11698          *)
11699         name, false
11700   in
11701
11702   generate_types xs
11703
11704 let generate_parsers xs =
11705   (* As for generate_type above, generate_parser makes a parser for
11706    * some type, and returns the name of the parser it has generated.
11707    * Because it (may) need to print something, it should always be
11708    * called in BOL context.
11709    *)
11710   let rec generate_parser = function
11711     | Text ->                                (* string *)
11712         "string_child_or_empty"
11713     | Choice values ->                        (* [`val1|`val2|...] *)
11714         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11715           (String.concat "|"
11716              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11717     | ZeroOrMore rng ->                        (* <rng> list *)
11718         let pa = generate_parser rng in
11719         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11720     | OneOrMore rng ->                        (* <rng> list *)
11721         let pa = generate_parser rng in
11722         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11723                                         (* virt-inspector hack: bool *)
11724     | Optional (Attribute (name, [Value "1"])) ->
11725         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11726     | Optional rng ->                        (* <rng> list *)
11727         let pa = generate_parser rng in
11728         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11729                                         (* type name = { fields ... } *)
11730     | Element (name, fields) when is_attrs_interleave fields ->
11731         generate_parser_struct name (get_attrs_interleave fields)
11732     | Element (name, [field]) ->        (* type name = field *)
11733         let pa = generate_parser field in
11734         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11735         pr "let %s =\n" parser_name;
11736         pr "  %s\n" pa;
11737         pr "let parse_%s = %s\n" name parser_name;
11738         parser_name
11739     | Attribute (name, [field]) ->
11740         let pa = generate_parser field in
11741         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11742         pr "let %s =\n" parser_name;
11743         pr "  %s\n" pa;
11744         pr "let parse_%s = %s\n" name parser_name;
11745         parser_name
11746     | Element (name, fields) ->              (* type name = { fields ... } *)
11747         generate_parser_struct name ([], fields)
11748     | rng ->
11749         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11750
11751   and is_attrs_interleave = function
11752     | [Interleave _] -> true
11753     | Attribute _ :: fields -> is_attrs_interleave fields
11754     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11755     | _ -> false
11756
11757   and get_attrs_interleave = function
11758     | [Interleave fields] -> [], fields
11759     | ((Attribute _) as field) :: fields
11760     | ((Optional (Attribute _)) as field) :: fields ->
11761         let attrs, interleaves = get_attrs_interleave fields in
11762         (field :: attrs), interleaves
11763     | _ -> assert false
11764
11765   and generate_parsers xs =
11766     List.iter (fun x -> ignore (generate_parser x)) xs
11767
11768   and generate_parser_struct name (attrs, interleaves) =
11769     (* Generate parsers for the fields first.  We have to do this
11770      * before printing anything so we are still in BOL context.
11771      *)
11772     let fields = attrs @ interleaves in
11773     let pas = List.map generate_parser fields in
11774
11775     (* Generate an intermediate tuple from all the fields first.
11776      * If the type is just a string + another field, then we will
11777      * return this directly, otherwise it is turned into a record.
11778      *
11779      * RELAX NG note: This code treats <interleave> and plain lists of
11780      * fields the same.  In other words, it doesn't bother enforcing
11781      * any ordering of fields in the XML.
11782      *)
11783     pr "let parse_%s x =\n" name;
11784     pr "  let t = (\n    ";
11785     let comma = ref false in
11786     List.iter (
11787       fun x ->
11788         if !comma then pr ",\n    ";
11789         comma := true;
11790         match x with
11791         | Optional (Attribute (fname, [field])), pa ->
11792             pr "%s x" pa
11793         | Optional (Element (fname, [field])), pa ->
11794             pr "%s (optional_child %S x)" pa fname
11795         | Attribute (fname, [Text]), _ ->
11796             pr "attribute %S x" fname
11797         | (ZeroOrMore _ | OneOrMore _), pa ->
11798             pr "%s x" pa
11799         | Text, pa ->
11800             pr "%s x" pa
11801         | (field, pa) ->
11802             let fname = name_of_field field in
11803             pr "%s (child %S x)" pa fname
11804     ) (List.combine fields pas);
11805     pr "\n  ) in\n";
11806
11807     (match fields with
11808      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11809          pr "  t\n"
11810
11811      | _ ->
11812          pr "  (Obj.magic t : %s)\n" name
11813 (*
11814          List.iter (
11815            function
11816            | (Optional (Attribute (fname, [field])), pa) ->
11817                pr "  %s_%s =\n" name fname;
11818                pr "    %s x;\n" pa
11819            | (Optional (Element (fname, [field])), pa) ->
11820                pr "  %s_%s =\n" name fname;
11821                pr "    (let x = optional_child %S x in\n" fname;
11822                pr "     %s x);\n" pa
11823            | (field, pa) ->
11824                let fname = name_of_field field in
11825                pr "  %s_%s =\n" name fname;
11826                pr "    (let x = child %S x in\n" fname;
11827                pr "     %s x);\n" pa
11828          ) (List.combine fields pas);
11829          pr "}\n"
11830 *)
11831     );
11832     sprintf "parse_%s" name
11833   in
11834
11835   generate_parsers xs
11836
11837 (* Generate ocaml/guestfs_inspector.mli. *)
11838 let generate_ocaml_inspector_mli () =
11839   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11840
11841   pr "\
11842 (** This is an OCaml language binding to the external [virt-inspector]
11843     program.
11844
11845     For more information, please read the man page [virt-inspector(1)].
11846 *)
11847
11848 ";
11849
11850   generate_types grammar;
11851   pr "(** The nested information returned from the {!inspect} function. *)\n";
11852   pr "\n";
11853
11854   pr "\
11855 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11856 (** To inspect a libvirt domain called [name], pass a singleton
11857     list: [inspect [name]].  When using libvirt only, you may
11858     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11859
11860     To inspect a disk image or images, pass a list of the filenames
11861     of the disk images: [inspect filenames]
11862
11863     This function inspects the given guest or disk images and
11864     returns a list of operating system(s) found and a large amount
11865     of information about them.  In the vast majority of cases,
11866     a virtual machine only contains a single operating system.
11867
11868     If the optional [~xml] parameter is given, then this function
11869     skips running the external virt-inspector program and just
11870     parses the given XML directly (which is expected to be XML
11871     produced from a previous run of virt-inspector).  The list of
11872     names and connect URI are ignored in this case.
11873
11874     This function can throw a wide variety of exceptions, for example
11875     if the external virt-inspector program cannot be found, or if
11876     it doesn't generate valid XML.
11877 *)
11878 "
11879
11880 (* Generate ocaml/guestfs_inspector.ml. *)
11881 let generate_ocaml_inspector_ml () =
11882   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11883
11884   pr "open Unix\n";
11885   pr "\n";
11886
11887   generate_types grammar;
11888   pr "\n";
11889
11890   pr "\
11891 (* Misc functions which are used by the parser code below. *)
11892 let first_child = function
11893   | Xml.Element (_, _, c::_) -> c
11894   | Xml.Element (name, _, []) ->
11895       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11896   | Xml.PCData str ->
11897       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11898
11899 let string_child_or_empty = function
11900   | Xml.Element (_, _, [Xml.PCData s]) -> s
11901   | Xml.Element (_, _, []) -> \"\"
11902   | Xml.Element (x, _, _) ->
11903       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11904                 x ^ \" instead\")
11905   | Xml.PCData str ->
11906       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11907
11908 let optional_child name xml =
11909   let children = Xml.children xml in
11910   try
11911     Some (List.find (function
11912                      | Xml.Element (n, _, _) when n = name -> true
11913                      | _ -> false) children)
11914   with
11915     Not_found -> None
11916
11917 let child name xml =
11918   match optional_child name xml with
11919   | Some c -> c
11920   | None ->
11921       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11922
11923 let attribute name xml =
11924   try Xml.attrib xml name
11925   with Xml.No_attribute _ ->
11926     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11927
11928 ";
11929
11930   generate_parsers grammar;
11931   pr "\n";
11932
11933   pr "\
11934 (* Run external virt-inspector, then use parser to parse the XML. *)
11935 let inspect ?connect ?xml names =
11936   let xml =
11937     match xml with
11938     | None ->
11939         if names = [] then invalid_arg \"inspect: no names given\";
11940         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11941           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11942           names in
11943         let cmd = List.map Filename.quote cmd in
11944         let cmd = String.concat \" \" cmd in
11945         let chan = open_process_in cmd in
11946         let xml = Xml.parse_in chan in
11947         (match close_process_in chan with
11948          | WEXITED 0 -> ()
11949          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11950          | WSIGNALED i | WSTOPPED i ->
11951              failwith (\"external virt-inspector command died or stopped on sig \" ^
11952                        string_of_int i)
11953         );
11954         xml
11955     | Some doc ->
11956         Xml.parse_string doc in
11957   parse_operatingsystems xml
11958 "
11959
11960 and generate_max_proc_nr () =
11961   pr "%d\n" max_proc_nr
11962
11963 let output_to filename k =
11964   let filename_new = filename ^ ".new" in
11965   chan := open_out filename_new;
11966   k ();
11967   close_out !chan;
11968   chan := Pervasives.stdout;
11969
11970   (* Is the new file different from the current file? *)
11971   if Sys.file_exists filename && files_equal filename filename_new then
11972     unlink filename_new                 (* same, so skip it *)
11973   else (
11974     (* different, overwrite old one *)
11975     (try chmod filename 0o644 with Unix_error _ -> ());
11976     rename filename_new filename;
11977     chmod filename 0o444;
11978     printf "written %s\n%!" filename;
11979   )
11980
11981 let perror msg = function
11982   | Unix_error (err, _, _) ->
11983       eprintf "%s: %s\n" msg (error_message err)
11984   | exn ->
11985       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11986
11987 (* Main program. *)
11988 let () =
11989   let lock_fd =
11990     try openfile "HACKING" [O_RDWR] 0
11991     with
11992     | Unix_error (ENOENT, _, _) ->
11993         eprintf "\
11994 You are probably running this from the wrong directory.
11995 Run it from the top source directory using the command
11996   src/generator.ml
11997 ";
11998         exit 1
11999     | exn ->
12000         perror "open: HACKING" exn;
12001         exit 1 in
12002
12003   (* Acquire a lock so parallel builds won't try to run the generator
12004    * twice at the same time.  Subsequent builds will wait for the first
12005    * one to finish.  Note the lock is released implicitly when the
12006    * program exits.
12007    *)
12008   (try lockf lock_fd F_LOCK 1
12009    with exn ->
12010      perror "lock: HACKING" exn;
12011      exit 1);
12012
12013   check_functions ();
12014
12015   output_to "src/guestfs_protocol.x" generate_xdr;
12016   output_to "src/guestfs-structs.h" generate_structs_h;
12017   output_to "src/guestfs-actions.h" generate_actions_h;
12018   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12019   output_to "src/guestfs-actions.c" generate_client_actions;
12020   output_to "src/guestfs-bindtests.c" generate_bindtests;
12021   output_to "src/guestfs-structs.pod" generate_structs_pod;
12022   output_to "src/guestfs-actions.pod" generate_actions_pod;
12023   output_to "src/guestfs-availability.pod" generate_availability_pod;
12024   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12025   output_to "src/libguestfs.syms" generate_linker_script;
12026   output_to "daemon/actions.h" generate_daemon_actions_h;
12027   output_to "daemon/stubs.c" generate_daemon_actions;
12028   output_to "daemon/names.c" generate_daemon_names;
12029   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12030   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12031   output_to "capitests/tests.c" generate_tests;
12032   output_to "fish/cmds.c" generate_fish_cmds;
12033   output_to "fish/completion.c" generate_fish_completion;
12034   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12035   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12036   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12037   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12038   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12039   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12040   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12041   output_to "perl/Guestfs.xs" generate_perl_xs;
12042   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12043   output_to "perl/bindtests.pl" generate_perl_bindtests;
12044   output_to "python/guestfs-py.c" generate_python_c;
12045   output_to "python/guestfs.py" generate_python_py;
12046   output_to "python/bindtests.py" generate_python_bindtests;
12047   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12048   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12049   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12050
12051   List.iter (
12052     fun (typ, jtyp) ->
12053       let cols = cols_of_struct typ in
12054       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12055       output_to filename (generate_java_struct jtyp cols);
12056   ) java_structs;
12057
12058   output_to "java/Makefile.inc" generate_java_makefile_inc;
12059   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12060   output_to "java/Bindtests.java" generate_java_bindtests;
12061   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12062   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12063   output_to "csharp/Libguestfs.cs" generate_csharp;
12064
12065   (* Always generate this file last, and unconditionally.  It's used
12066    * by the Makefile to know when we must re-run the generator.
12067    *)
12068   let chan = open_out "src/stamp-generator" in
12069   fprintf chan "1\n";
12070   close_out chan;
12071
12072   printf "generated %d lines of code\n" !lines