touch: Restrict touch to regular files only (RHBZ#582484).
[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     (* Run the test only if 'string' is available in the daemon. *)
313   | IfAvailable of string
314
315 (* Some initial scenarios for testing. *)
316 and test_init =
317     (* Do nothing, block devices could contain random stuff including
318      * LVM PVs, and some filesystems might be mounted.  This is usually
319      * a bad idea.
320      *)
321   | InitNone
322
323     (* Block devices are empty and no filesystems are mounted. *)
324   | InitEmpty
325
326     (* /dev/sda contains a single partition /dev/sda1, with random
327      * content.  /dev/sdb and /dev/sdc may have random content.
328      * No LVM.
329      *)
330   | InitPartition
331
332     (* /dev/sda contains a single partition /dev/sda1, which is formatted
333      * as ext2, empty [except for lost+found] and mounted on /.
334      * /dev/sdb and /dev/sdc may have random content.
335      * No LVM.
336      *)
337   | InitBasicFS
338
339     (* /dev/sda:
340      *   /dev/sda1 (is a PV):
341      *     /dev/VG/LV (size 8MB):
342      *       formatted as ext2, empty [except for lost+found], mounted on /
343      * /dev/sdb and /dev/sdc may have random content.
344      *)
345   | InitBasicFSonLVM
346
347     (* /dev/sdd (the ISO, see images/ directory in source)
348      * is mounted on /
349      *)
350   | InitISOFS
351
352 (* Sequence of commands for testing. *)
353 and seq = cmd list
354 and cmd = string list
355
356 (* Note about long descriptions: When referring to another
357  * action, use the format C<guestfs_other> (ie. the full name of
358  * the C function).  This will be replaced as appropriate in other
359  * language bindings.
360  *
361  * Apart from that, long descriptions are just perldoc paragraphs.
362  *)
363
364 (* Generate a random UUID (used in tests). *)
365 let uuidgen () =
366   let chan = open_process_in "uuidgen" in
367   let uuid = input_line chan in
368   (match close_process_in chan with
369    | WEXITED 0 -> ()
370    | WEXITED _ ->
371        failwith "uuidgen: process exited with non-zero status"
372    | WSIGNALED _ | WSTOPPED _ ->
373        failwith "uuidgen: process signalled or stopped by signal"
374   );
375   uuid
376
377 (* These test functions are used in the language binding tests. *)
378
379 let test_all_args = [
380   String "str";
381   OptString "optstr";
382   StringList "strlist";
383   Bool "b";
384   Int "integer";
385   Int64 "integer64";
386   FileIn "filein";
387   FileOut "fileout";
388   BufferIn "bufferin";
389 ]
390
391 let test_all_rets = [
392   (* except for RErr, which is tested thoroughly elsewhere *)
393   "test0rint",         RInt "valout";
394   "test0rint64",       RInt64 "valout";
395   "test0rbool",        RBool "valout";
396   "test0rconststring", RConstString "valout";
397   "test0rconstoptstring", RConstOptString "valout";
398   "test0rstring",      RString "valout";
399   "test0rstringlist",  RStringList "valout";
400   "test0rstruct",      RStruct ("valout", "lvm_pv");
401   "test0rstructlist",  RStructList ("valout", "lvm_pv");
402   "test0rhashtable",   RHashtable "valout";
403 ]
404
405 let test_functions = [
406   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
407    [],
408    "internal test function - do not use",
409    "\
410 This is an internal test function which is used to test whether
411 the automatically generated bindings can handle every possible
412 parameter type correctly.
413
414 It echos the contents of each parameter to stdout.
415
416 You probably don't want to call this function.");
417 ] @ List.flatten (
418   List.map (
419     fun (name, ret) ->
420       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
421         [],
422         "internal test function - do not use",
423         "\
424 This is an internal test function which is used to test whether
425 the automatically generated bindings can handle every possible
426 return type correctly.
427
428 It converts string C<val> to the return type.
429
430 You probably don't want to call this function.");
431        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
432         [],
433         "internal test function - do not use",
434         "\
435 This is an internal test function which is used to test whether
436 the automatically generated bindings can handle every possible
437 return type correctly.
438
439 This function always returns an error.
440
441 You probably don't want to call this function.")]
442   ) test_all_rets
443 )
444
445 (* non_daemon_functions are any functions which don't get processed
446  * in the daemon, eg. functions for setting and getting local
447  * configuration values.
448  *)
449
450 let non_daemon_functions = test_functions @ [
451   ("launch", (RErr, []), -1, [FishAlias "run"],
452    [],
453    "launch the qemu subprocess",
454    "\
455 Internally libguestfs is implemented by running a virtual machine
456 using L<qemu(1)>.
457
458 You should call this after configuring the handle
459 (eg. adding drives) but before performing any actions.");
460
461   ("wait_ready", (RErr, []), -1, [NotInFish],
462    [],
463    "wait until the qemu subprocess launches (no op)",
464    "\
465 This function is a no op.
466
467 In versions of the API E<lt> 1.0.71 you had to call this function
468 just after calling C<guestfs_launch> to wait for the launch
469 to complete.  However this is no longer necessary because
470 C<guestfs_launch> now does the waiting.
471
472 If you see any calls to this function in code then you can just
473 remove them, unless you want to retain compatibility with older
474 versions of the API.");
475
476   ("kill_subprocess", (RErr, []), -1, [],
477    [],
478    "kill the qemu subprocess",
479    "\
480 This kills the qemu subprocess.  You should never need to call this.");
481
482   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
483    [],
484    "add an image to examine or modify",
485    "\
486 This function adds a virtual machine disk image C<filename> to the
487 guest.  The first time you call this function, the disk appears as IDE
488 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
489 so on.
490
491 You don't necessarily need to be root when using libguestfs.  However
492 you obviously do need sufficient permissions to access the filename
493 for whatever operations you want to perform (ie. read access if you
494 just want to read the image or write access if you want to modify the
495 image).
496
497 This is equivalent to the qemu parameter
498 C<-drive file=filename,cache=off,if=...>.
499
500 C<cache=off> is omitted in cases where it is not supported by
501 the underlying filesystem.
502
503 C<if=...> is set at compile time by the configuration option
504 C<./configure --with-drive-if=...>.  In the rare case where you
505 might need to change this at run time, use C<guestfs_add_drive_with_if>
506 or C<guestfs_add_drive_ro_with_if>.
507
508 Note that this call checks for the existence of C<filename>.  This
509 stops you from specifying other types of drive which are supported
510 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
511 the general C<guestfs_config> call instead.");
512
513   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
514    [],
515    "add a CD-ROM disk image to examine",
516    "\
517 This function adds a virtual CD-ROM disk image to the guest.
518
519 This is equivalent to the qemu parameter C<-cdrom filename>.
520
521 Notes:
522
523 =over 4
524
525 =item *
526
527 This call checks for the existence of C<filename>.  This
528 stops you from specifying other types of drive which are supported
529 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
530 the general C<guestfs_config> call instead.
531
532 =item *
533
534 If you just want to add an ISO file (often you use this as an
535 efficient way to transfer large files into the guest), then you
536 should probably use C<guestfs_add_drive_ro> instead.
537
538 =back");
539
540   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
541    [],
542    "add a drive in snapshot mode (read-only)",
543    "\
544 This adds a drive in snapshot mode, making it effectively
545 read-only.
546
547 Note that writes to the device are allowed, and will be seen for
548 the duration of the guestfs handle, but they are written
549 to a temporary file which is discarded as soon as the guestfs
550 handle is closed.  We don't currently have any method to enable
551 changes to be committed, although qemu can support this.
552
553 This is equivalent to the qemu parameter
554 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
555
556 C<if=...> is set at compile time by the configuration option
557 C<./configure --with-drive-if=...>.  In the rare case where you
558 might need to change this at run time, use C<guestfs_add_drive_with_if>
559 or C<guestfs_add_drive_ro_with_if>.
560
561 C<readonly=on> is only added where qemu supports this option.
562
563 Note that this call checks for the existence of C<filename>.  This
564 stops you from specifying other types of drive which are supported
565 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
566 the general C<guestfs_config> call instead.");
567
568   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
569    [],
570    "add qemu parameters",
571    "\
572 This can be used to add arbitrary qemu command line parameters
573 of the form C<-param value>.  Actually it's not quite arbitrary - we
574 prevent you from setting some parameters which would interfere with
575 parameters that we use.
576
577 The first character of C<param> string must be a C<-> (dash).
578
579 C<value> can be NULL.");
580
581   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
582    [],
583    "set the qemu binary",
584    "\
585 Set the qemu binary that we will use.
586
587 The default is chosen when the library was compiled by the
588 configure script.
589
590 You can also override this by setting the C<LIBGUESTFS_QEMU>
591 environment variable.
592
593 Setting C<qemu> to C<NULL> restores the default qemu binary.
594
595 Note that you should call this function as early as possible
596 after creating the handle.  This is because some pre-launch
597 operations depend on testing qemu features (by running C<qemu -help>).
598 If the qemu binary changes, we don't retest features, and
599 so you might see inconsistent results.  Using the environment
600 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
601 the qemu binary at the same time as the handle is created.");
602
603   ("get_qemu", (RConstString "qemu", []), -1, [],
604    [InitNone, Always, TestRun (
605       [["get_qemu"]])],
606    "get the qemu binary",
607    "\
608 Return the current qemu binary.
609
610 This is always non-NULL.  If it wasn't set already, then this will
611 return the default qemu binary name.");
612
613   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
614    [],
615    "set the search path",
616    "\
617 Set the path that libguestfs searches for kernel and initrd.img.
618
619 The default is C<$libdir/guestfs> unless overridden by setting
620 C<LIBGUESTFS_PATH> environment variable.
621
622 Setting C<path> to C<NULL> restores the default path.");
623
624   ("get_path", (RConstString "path", []), -1, [],
625    [InitNone, Always, TestRun (
626       [["get_path"]])],
627    "get the search path",
628    "\
629 Return the current search path.
630
631 This is always non-NULL.  If it wasn't set already, then this will
632 return the default path.");
633
634   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
635    [],
636    "add options to kernel command line",
637    "\
638 This function is used to add additional options to the
639 guest kernel command line.
640
641 The default is C<NULL> unless overridden by setting
642 C<LIBGUESTFS_APPEND> environment variable.
643
644 Setting C<append> to C<NULL> means I<no> additional options
645 are passed (libguestfs always adds a few of its own).");
646
647   ("get_append", (RConstOptString "append", []), -1, [],
648    (* This cannot be tested with the current framework.  The
649     * function can return NULL in normal operations, which the
650     * test framework interprets as an error.
651     *)
652    [],
653    "get the additional kernel options",
654    "\
655 Return the additional kernel options which are added to the
656 guest kernel command line.
657
658 If C<NULL> then no options are added.");
659
660   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
661    [],
662    "set autosync mode",
663    "\
664 If C<autosync> is true, this enables autosync.  Libguestfs will make a
665 best effort attempt to run C<guestfs_umount_all> followed by
666 C<guestfs_sync> when the handle is closed
667 (also if the program exits without closing handles).
668
669 This is disabled by default (except in guestfish where it is
670 enabled by default).");
671
672   ("get_autosync", (RBool "autosync", []), -1, [],
673    [InitNone, Always, TestRun (
674       [["get_autosync"]])],
675    "get autosync mode",
676    "\
677 Get the autosync flag.");
678
679   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
680    [],
681    "set verbose mode",
682    "\
683 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
684
685 Verbose messages are disabled unless the environment variable
686 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
687
688   ("get_verbose", (RBool "verbose", []), -1, [],
689    [],
690    "get verbose mode",
691    "\
692 This returns the verbose messages flag.");
693
694   ("is_ready", (RBool "ready", []), -1, [],
695    [InitNone, Always, TestOutputTrue (
696       [["is_ready"]])],
697    "is ready to accept commands",
698    "\
699 This returns true iff this handle is ready to accept commands
700 (in the C<READY> state).
701
702 For more information on states, see L<guestfs(3)>.");
703
704   ("is_config", (RBool "config", []), -1, [],
705    [InitNone, Always, TestOutputFalse (
706       [["is_config"]])],
707    "is in configuration state",
708    "\
709 This returns true iff this handle is being configured
710 (in the C<CONFIG> state).
711
712 For more information on states, see L<guestfs(3)>.");
713
714   ("is_launching", (RBool "launching", []), -1, [],
715    [InitNone, Always, TestOutputFalse (
716       [["is_launching"]])],
717    "is launching subprocess",
718    "\
719 This returns true iff this handle is launching the subprocess
720 (in the C<LAUNCHING> state).
721
722 For more information on states, see L<guestfs(3)>.");
723
724   ("is_busy", (RBool "busy", []), -1, [],
725    [InitNone, Always, TestOutputFalse (
726       [["is_busy"]])],
727    "is busy processing a command",
728    "\
729 This returns true iff this handle is busy processing a command
730 (in the C<BUSY> state).
731
732 For more information on states, see L<guestfs(3)>.");
733
734   ("get_state", (RInt "state", []), -1, [],
735    [],
736    "get the current state",
737    "\
738 This returns the current state as an opaque integer.  This is
739 only useful for printing debug and internal error messages.
740
741 For more information on states, see L<guestfs(3)>.");
742
743   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
744    [InitNone, Always, TestOutputInt (
745       [["set_memsize"; "500"];
746        ["get_memsize"]], 500)],
747    "set memory allocated to the qemu subprocess",
748    "\
749 This sets the memory size in megabytes allocated to the
750 qemu subprocess.  This only has any effect if called before
751 C<guestfs_launch>.
752
753 You can also change this by setting the environment
754 variable C<LIBGUESTFS_MEMSIZE> before the handle is
755 created.
756
757 For more information on the architecture of libguestfs,
758 see L<guestfs(3)>.");
759
760   ("get_memsize", (RInt "memsize", []), -1, [],
761    [InitNone, Always, TestOutputIntOp (
762       [["get_memsize"]], ">=", 256)],
763    "get memory allocated to the qemu subprocess",
764    "\
765 This gets the memory size in megabytes allocated to the
766 qemu subprocess.
767
768 If C<guestfs_set_memsize> was not called
769 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
770 then this returns the compiled-in default value for memsize.
771
772 For more information on the architecture of libguestfs,
773 see L<guestfs(3)>.");
774
775   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
776    [InitNone, Always, TestOutputIntOp (
777       [["get_pid"]], ">=", 1)],
778    "get PID of qemu subprocess",
779    "\
780 Return the process ID of the qemu subprocess.  If there is no
781 qemu subprocess, then this will return an error.
782
783 This is an internal call used for debugging and testing.");
784
785   ("version", (RStruct ("version", "version"), []), -1, [],
786    [InitNone, Always, TestOutputStruct (
787       [["version"]], [CompareWithInt ("major", 1)])],
788    "get the library version number",
789    "\
790 Return the libguestfs version number that the program is linked
791 against.
792
793 Note that because of dynamic linking this is not necessarily
794 the version of libguestfs that you compiled against.  You can
795 compile the program, and then at runtime dynamically link
796 against a completely different C<libguestfs.so> library.
797
798 This call was added in version C<1.0.58>.  In previous
799 versions of libguestfs there was no way to get the version
800 number.  From C code you can use dynamic linker functions
801 to find out if this symbol exists (if it doesn't, then
802 it's an earlier version).
803
804 The call returns a structure with four elements.  The first
805 three (C<major>, C<minor> and C<release>) are numbers and
806 correspond to the usual version triplet.  The fourth element
807 (C<extra>) is a string and is normally empty, but may be
808 used for distro-specific information.
809
810 To construct the original version string:
811 C<$major.$minor.$release$extra>
812
813 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
814
815 I<Note:> Don't use this call to test for availability
816 of features.  In enterprise distributions we backport
817 features from later versions into earlier versions,
818 making this an unreliable way to test for features.
819 Use C<guestfs_available> instead.");
820
821   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
822    [InitNone, Always, TestOutputTrue (
823       [["set_selinux"; "true"];
824        ["get_selinux"]])],
825    "set SELinux enabled or disabled at appliance boot",
826    "\
827 This sets the selinux flag that is passed to the appliance
828 at boot time.  The default is C<selinux=0> (disabled).
829
830 Note that if SELinux is enabled, it is always in
831 Permissive mode (C<enforcing=0>).
832
833 For more information on the architecture of libguestfs,
834 see L<guestfs(3)>.");
835
836   ("get_selinux", (RBool "selinux", []), -1, [],
837    [],
838    "get SELinux enabled flag",
839    "\
840 This returns the current setting of the selinux flag which
841 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
842
843 For more information on the architecture of libguestfs,
844 see L<guestfs(3)>.");
845
846   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
847    [InitNone, Always, TestOutputFalse (
848       [["set_trace"; "false"];
849        ["get_trace"]])],
850    "enable or disable command traces",
851    "\
852 If the command trace flag is set to 1, then commands are
853 printed on stdout before they are executed in a format
854 which is very similar to the one used by guestfish.  In
855 other words, you can run a program with this enabled, and
856 you will get out a script which you can feed to guestfish
857 to perform the same set of actions.
858
859 If you want to trace C API calls into libguestfs (and
860 other libraries) then possibly a better way is to use
861 the external ltrace(1) command.
862
863 Command traces are disabled unless the environment variable
864 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
865
866   ("get_trace", (RBool "trace", []), -1, [],
867    [],
868    "get command trace enabled flag",
869    "\
870 Return the command trace flag.");
871
872   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
873    [InitNone, Always, TestOutputFalse (
874       [["set_direct"; "false"];
875        ["get_direct"]])],
876    "enable or disable direct appliance mode",
877    "\
878 If the direct appliance mode flag is enabled, then stdin and
879 stdout are passed directly through to the appliance once it
880 is launched.
881
882 One consequence of this is that log messages aren't caught
883 by the library and handled by C<guestfs_set_log_message_callback>,
884 but go straight to stdout.
885
886 You probably don't want to use this unless you know what you
887 are doing.
888
889 The default is disabled.");
890
891   ("get_direct", (RBool "direct", []), -1, [],
892    [],
893    "get direct appliance mode flag",
894    "\
895 Return the direct appliance mode flag.");
896
897   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
898    [InitNone, Always, TestOutputTrue (
899       [["set_recovery_proc"; "true"];
900        ["get_recovery_proc"]])],
901    "enable or disable the recovery process",
902    "\
903 If this is called with the parameter C<false> then
904 C<guestfs_launch> does not create a recovery process.  The
905 purpose of the recovery process is to stop runaway qemu
906 processes in the case where the main program aborts abruptly.
907
908 This only has any effect if called before C<guestfs_launch>,
909 and the default is true.
910
911 About the only time when you would want to disable this is
912 if the main process will fork itself into the background
913 (\"daemonize\" itself).  In this case the recovery process
914 thinks that the main program has disappeared and so kills
915 qemu, which is not very helpful.");
916
917   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
918    [],
919    "get recovery process enabled flag",
920    "\
921 Return the recovery process enabled flag.");
922
923   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
924    [],
925    "add a drive specifying the QEMU block emulation to use",
926    "\
927 This is the same as C<guestfs_add_drive> but it allows you
928 to specify the QEMU interface emulation to use at run time.");
929
930   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
931    [],
932    "add a drive read-only specifying the QEMU block emulation to use",
933    "\
934 This is the same as C<guestfs_add_drive_ro> but it allows you
935 to specify the QEMU interface emulation to use at run time.");
936
937 ]
938
939 (* daemon_functions are any functions which cause some action
940  * to take place in the daemon.
941  *)
942
943 let daemon_functions = [
944   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
945    [InitEmpty, Always, TestOutput (
946       [["part_disk"; "/dev/sda"; "mbr"];
947        ["mkfs"; "ext2"; "/dev/sda1"];
948        ["mount"; "/dev/sda1"; "/"];
949        ["write"; "/new"; "new file contents"];
950        ["cat"; "/new"]], "new file contents")],
951    "mount a guest disk at a position in the filesystem",
952    "\
953 Mount a guest disk at a position in the filesystem.  Block devices
954 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
955 the guest.  If those block devices contain partitions, they will have
956 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
957 names can be used.
958
959 The rules are the same as for L<mount(2)>:  A filesystem must
960 first be mounted on C</> before others can be mounted.  Other
961 filesystems can only be mounted on directories which already
962 exist.
963
964 The mounted filesystem is writable, if we have sufficient permissions
965 on the underlying device.
966
967 B<Important note:>
968 When you use this call, the filesystem options C<sync> and C<noatime>
969 are set implicitly.  This was originally done because we thought it
970 would improve reliability, but it turns out that I<-o sync> has a
971 very large negative performance impact and negligible effect on
972 reliability.  Therefore we recommend that you avoid using
973 C<guestfs_mount> in any code that needs performance, and instead
974 use C<guestfs_mount_options> (use an empty string for the first
975 parameter if you don't want any options).");
976
977   ("sync", (RErr, []), 2, [],
978    [ InitEmpty, Always, TestRun [["sync"]]],
979    "sync disks, writes are flushed through to the disk image",
980    "\
981 This syncs the disk, so that any writes are flushed through to the
982 underlying disk image.
983
984 You should always call this if you have modified a disk image, before
985 closing the handle.");
986
987   ("touch", (RErr, [Pathname "path"]), 3, [],
988    [InitBasicFS, Always, TestOutputTrue (
989       [["touch"; "/new"];
990        ["exists"; "/new"]])],
991    "update file timestamps or create a new file",
992    "\
993 Touch acts like the L<touch(1)> command.  It can be used to
994 update the timestamps on a file, or, if the file does not exist,
995 to create a new zero-length file.
996
997 This command only works on regular files, and will fail on other
998 file types such as directories, symbolic links, block special etc.");
999
1000   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
1001    [InitISOFS, Always, TestOutput (
1002       [["cat"; "/known-2"]], "abcdef\n")],
1003    "list the contents of a file",
1004    "\
1005 Return the contents of the file named C<path>.
1006
1007 Note that this function cannot correctly handle binary files
1008 (specifically, files containing C<\\0> character which is treated
1009 as end of string).  For those you need to use the C<guestfs_read_file>
1010 or C<guestfs_download> functions which have a more complex interface.");
1011
1012   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1013    [], (* XXX Tricky to test because it depends on the exact format
1014         * of the 'ls -l' command, which changes between F10 and F11.
1015         *)
1016    "list the files in a directory (long format)",
1017    "\
1018 List the files in C<directory> (relative to the root directory,
1019 there is no cwd) in the format of 'ls -la'.
1020
1021 This command is mostly useful for interactive sessions.  It
1022 is I<not> intended that you try to parse the output string.");
1023
1024   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1025    [InitBasicFS, Always, TestOutputList (
1026       [["touch"; "/new"];
1027        ["touch"; "/newer"];
1028        ["touch"; "/newest"];
1029        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1030    "list the files in a directory",
1031    "\
1032 List the files in C<directory> (relative to the root directory,
1033 there is no cwd).  The '.' and '..' entries are not returned, but
1034 hidden files are shown.
1035
1036 This command is mostly useful for interactive sessions.  Programs
1037 should probably use C<guestfs_readdir> instead.");
1038
1039   ("list_devices", (RStringList "devices", []), 7, [],
1040    [InitEmpty, Always, TestOutputListOfDevices (
1041       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1042    "list the block devices",
1043    "\
1044 List all the block devices.
1045
1046 The full block device names are returned, eg. C</dev/sda>");
1047
1048   ("list_partitions", (RStringList "partitions", []), 8, [],
1049    [InitBasicFS, Always, TestOutputListOfDevices (
1050       [["list_partitions"]], ["/dev/sda1"]);
1051     InitEmpty, Always, TestOutputListOfDevices (
1052       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1053        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1054    "list the partitions",
1055    "\
1056 List all the partitions detected on all block devices.
1057
1058 The full partition device names are returned, eg. C</dev/sda1>
1059
1060 This does not return logical volumes.  For that you will need to
1061 call C<guestfs_lvs>.");
1062
1063   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1064    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1065       [["pvs"]], ["/dev/sda1"]);
1066     InitEmpty, Always, TestOutputListOfDevices (
1067       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1068        ["pvcreate"; "/dev/sda1"];
1069        ["pvcreate"; "/dev/sda2"];
1070        ["pvcreate"; "/dev/sda3"];
1071        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1072    "list the LVM physical volumes (PVs)",
1073    "\
1074 List all the physical volumes detected.  This is the equivalent
1075 of the L<pvs(8)> command.
1076
1077 This returns a list of just the device names that contain
1078 PVs (eg. C</dev/sda2>).
1079
1080 See also C<guestfs_pvs_full>.");
1081
1082   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1083    [InitBasicFSonLVM, Always, TestOutputList (
1084       [["vgs"]], ["VG"]);
1085     InitEmpty, Always, TestOutputList (
1086       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1087        ["pvcreate"; "/dev/sda1"];
1088        ["pvcreate"; "/dev/sda2"];
1089        ["pvcreate"; "/dev/sda3"];
1090        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1091        ["vgcreate"; "VG2"; "/dev/sda3"];
1092        ["vgs"]], ["VG1"; "VG2"])],
1093    "list the LVM volume groups (VGs)",
1094    "\
1095 List all the volumes groups detected.  This is the equivalent
1096 of the L<vgs(8)> command.
1097
1098 This returns a list of just the volume group names that were
1099 detected (eg. C<VolGroup00>).
1100
1101 See also C<guestfs_vgs_full>.");
1102
1103   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1104    [InitBasicFSonLVM, Always, TestOutputList (
1105       [["lvs"]], ["/dev/VG/LV"]);
1106     InitEmpty, Always, TestOutputList (
1107       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1108        ["pvcreate"; "/dev/sda1"];
1109        ["pvcreate"; "/dev/sda2"];
1110        ["pvcreate"; "/dev/sda3"];
1111        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1112        ["vgcreate"; "VG2"; "/dev/sda3"];
1113        ["lvcreate"; "LV1"; "VG1"; "50"];
1114        ["lvcreate"; "LV2"; "VG1"; "50"];
1115        ["lvcreate"; "LV3"; "VG2"; "50"];
1116        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1117    "list the LVM logical volumes (LVs)",
1118    "\
1119 List all the logical volumes detected.  This is the equivalent
1120 of the L<lvs(8)> command.
1121
1122 This returns a list of the logical volume device names
1123 (eg. C</dev/VolGroup00/LogVol00>).
1124
1125 See also C<guestfs_lvs_full>.");
1126
1127   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1128    [], (* XXX how to test? *)
1129    "list the LVM physical volumes (PVs)",
1130    "\
1131 List all the physical volumes detected.  This is the equivalent
1132 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1133
1134   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1135    [], (* XXX how to test? *)
1136    "list the LVM volume groups (VGs)",
1137    "\
1138 List all the volumes groups detected.  This is the equivalent
1139 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1140
1141   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1142    [], (* XXX how to test? *)
1143    "list the LVM logical volumes (LVs)",
1144    "\
1145 List all the logical volumes detected.  This is the equivalent
1146 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1147
1148   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1149    [InitISOFS, Always, TestOutputList (
1150       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1151     InitISOFS, Always, TestOutputList (
1152       [["read_lines"; "/empty"]], [])],
1153    "read file as lines",
1154    "\
1155 Return the contents of the file named C<path>.
1156
1157 The file contents are returned as a list of lines.  Trailing
1158 C<LF> and C<CRLF> character sequences are I<not> returned.
1159
1160 Note that this function cannot correctly handle binary files
1161 (specifically, files containing C<\\0> character which is treated
1162 as end of line).  For those you need to use the C<guestfs_read_file>
1163 function which has a more complex interface.");
1164
1165   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1166    [], (* XXX Augeas code needs tests. *)
1167    "create a new Augeas handle",
1168    "\
1169 Create a new Augeas handle for editing configuration files.
1170 If there was any previous Augeas handle associated with this
1171 guestfs session, then it is closed.
1172
1173 You must call this before using any other C<guestfs_aug_*>
1174 commands.
1175
1176 C<root> is the filesystem root.  C<root> must not be NULL,
1177 use C</> instead.
1178
1179 The flags are the same as the flags defined in
1180 E<lt>augeas.hE<gt>, the logical I<or> of the following
1181 integers:
1182
1183 =over 4
1184
1185 =item C<AUG_SAVE_BACKUP> = 1
1186
1187 Keep the original file with a C<.augsave> extension.
1188
1189 =item C<AUG_SAVE_NEWFILE> = 2
1190
1191 Save changes into a file with extension C<.augnew>, and
1192 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1193
1194 =item C<AUG_TYPE_CHECK> = 4
1195
1196 Typecheck lenses (can be expensive).
1197
1198 =item C<AUG_NO_STDINC> = 8
1199
1200 Do not use standard load path for modules.
1201
1202 =item C<AUG_SAVE_NOOP> = 16
1203
1204 Make save a no-op, just record what would have been changed.
1205
1206 =item C<AUG_NO_LOAD> = 32
1207
1208 Do not load the tree in C<guestfs_aug_init>.
1209
1210 =back
1211
1212 To close the handle, you can call C<guestfs_aug_close>.
1213
1214 To find out more about Augeas, see L<http://augeas.net/>.");
1215
1216   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1217    [], (* XXX Augeas code needs tests. *)
1218    "close the current Augeas handle",
1219    "\
1220 Close the current Augeas handle and free up any resources
1221 used by it.  After calling this, you have to call
1222 C<guestfs_aug_init> again before you can use any other
1223 Augeas functions.");
1224
1225   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1226    [], (* XXX Augeas code needs tests. *)
1227    "define an Augeas variable",
1228    "\
1229 Defines an Augeas variable C<name> whose value is the result
1230 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1231 undefined.
1232
1233 On success this returns the number of nodes in C<expr>, or
1234 C<0> if C<expr> evaluates to something which is not a nodeset.");
1235
1236   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1237    [], (* XXX Augeas code needs tests. *)
1238    "define an Augeas node",
1239    "\
1240 Defines a variable C<name> whose value is the result of
1241 evaluating C<expr>.
1242
1243 If C<expr> evaluates to an empty nodeset, a node is created,
1244 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1245 C<name> will be the nodeset containing that single node.
1246
1247 On success this returns a pair containing the
1248 number of nodes in the nodeset, and a boolean flag
1249 if a node was created.");
1250
1251   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1252    [], (* XXX Augeas code needs tests. *)
1253    "look up the value of an Augeas path",
1254    "\
1255 Look up the value associated with C<path>.  If C<path>
1256 matches exactly one node, the C<value> is returned.");
1257
1258   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1259    [], (* XXX Augeas code needs tests. *)
1260    "set Augeas path to value",
1261    "\
1262 Set the value associated with C<path> to C<val>.
1263
1264 In the Augeas API, it is possible to clear a node by setting
1265 the value to NULL.  Due to an oversight in the libguestfs API
1266 you cannot do that with this call.  Instead you must use the
1267 C<guestfs_aug_clear> call.");
1268
1269   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1270    [], (* XXX Augeas code needs tests. *)
1271    "insert a sibling Augeas node",
1272    "\
1273 Create a new sibling C<label> for C<path>, inserting it into
1274 the tree before or after C<path> (depending on the boolean
1275 flag C<before>).
1276
1277 C<path> must match exactly one existing node in the tree, and
1278 C<label> must be a label, ie. not contain C</>, C<*> or end
1279 with a bracketed index C<[N]>.");
1280
1281   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1282    [], (* XXX Augeas code needs tests. *)
1283    "remove an Augeas path",
1284    "\
1285 Remove C<path> and all of its children.
1286
1287 On success this returns the number of entries which were removed.");
1288
1289   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1290    [], (* XXX Augeas code needs tests. *)
1291    "move Augeas node",
1292    "\
1293 Move the node C<src> to C<dest>.  C<src> must match exactly
1294 one node.  C<dest> is overwritten if it exists.");
1295
1296   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1297    [], (* XXX Augeas code needs tests. *)
1298    "return Augeas nodes which match augpath",
1299    "\
1300 Returns a list of paths which match the path expression C<path>.
1301 The returned paths are sufficiently qualified so that they match
1302 exactly one node in the current tree.");
1303
1304   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1305    [], (* XXX Augeas code needs tests. *)
1306    "write all pending Augeas changes to disk",
1307    "\
1308 This writes all pending changes to disk.
1309
1310 The flags which were passed to C<guestfs_aug_init> affect exactly
1311 how files are saved.");
1312
1313   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1314    [], (* XXX Augeas code needs tests. *)
1315    "load files into the tree",
1316    "\
1317 Load files into the tree.
1318
1319 See C<aug_load> in the Augeas documentation for the full gory
1320 details.");
1321
1322   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1323    [], (* XXX Augeas code needs tests. *)
1324    "list Augeas nodes under augpath",
1325    "\
1326 This is just a shortcut for listing C<guestfs_aug_match>
1327 C<path/*> and sorting the resulting nodes into alphabetical order.");
1328
1329   ("rm", (RErr, [Pathname "path"]), 29, [],
1330    [InitBasicFS, Always, TestRun
1331       [["touch"; "/new"];
1332        ["rm"; "/new"]];
1333     InitBasicFS, Always, TestLastFail
1334       [["rm"; "/new"]];
1335     InitBasicFS, Always, TestLastFail
1336       [["mkdir"; "/new"];
1337        ["rm"; "/new"]]],
1338    "remove a file",
1339    "\
1340 Remove the single file C<path>.");
1341
1342   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1343    [InitBasicFS, Always, TestRun
1344       [["mkdir"; "/new"];
1345        ["rmdir"; "/new"]];
1346     InitBasicFS, Always, TestLastFail
1347       [["rmdir"; "/new"]];
1348     InitBasicFS, Always, TestLastFail
1349       [["touch"; "/new"];
1350        ["rmdir"; "/new"]]],
1351    "remove a directory",
1352    "\
1353 Remove the single directory C<path>.");
1354
1355   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1356    [InitBasicFS, Always, TestOutputFalse
1357       [["mkdir"; "/new"];
1358        ["mkdir"; "/new/foo"];
1359        ["touch"; "/new/foo/bar"];
1360        ["rm_rf"; "/new"];
1361        ["exists"; "/new"]]],
1362    "remove a file or directory recursively",
1363    "\
1364 Remove the file or directory C<path>, recursively removing the
1365 contents if its a directory.  This is like the C<rm -rf> shell
1366 command.");
1367
1368   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1369    [InitBasicFS, Always, TestOutputTrue
1370       [["mkdir"; "/new"];
1371        ["is_dir"; "/new"]];
1372     InitBasicFS, Always, TestLastFail
1373       [["mkdir"; "/new/foo/bar"]]],
1374    "create a directory",
1375    "\
1376 Create a directory named C<path>.");
1377
1378   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1379    [InitBasicFS, Always, TestOutputTrue
1380       [["mkdir_p"; "/new/foo/bar"];
1381        ["is_dir"; "/new/foo/bar"]];
1382     InitBasicFS, Always, TestOutputTrue
1383       [["mkdir_p"; "/new/foo/bar"];
1384        ["is_dir"; "/new/foo"]];
1385     InitBasicFS, Always, TestOutputTrue
1386       [["mkdir_p"; "/new/foo/bar"];
1387        ["is_dir"; "/new"]];
1388     (* Regression tests for RHBZ#503133: *)
1389     InitBasicFS, Always, TestRun
1390       [["mkdir"; "/new"];
1391        ["mkdir_p"; "/new"]];
1392     InitBasicFS, Always, TestLastFail
1393       [["touch"; "/new"];
1394        ["mkdir_p"; "/new"]]],
1395    "create a directory and parents",
1396    "\
1397 Create a directory named C<path>, creating any parent directories
1398 as necessary.  This is like the C<mkdir -p> shell command.");
1399
1400   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1401    [], (* XXX Need stat command to test *)
1402    "change file mode",
1403    "\
1404 Change the mode (permissions) of C<path> to C<mode>.  Only
1405 numeric modes are supported.
1406
1407 I<Note>: When using this command from guestfish, C<mode>
1408 by default would be decimal, unless you prefix it with
1409 C<0> to get octal, ie. use C<0700> not C<700>.
1410
1411 The mode actually set is affected by the umask.");
1412
1413   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1414    [], (* XXX Need stat command to test *)
1415    "change file owner and group",
1416    "\
1417 Change the file owner to C<owner> and group to C<group>.
1418
1419 Only numeric uid and gid are supported.  If you want to use
1420 names, you will need to locate and parse the password file
1421 yourself (Augeas support makes this relatively easy).");
1422
1423   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1424    [InitISOFS, Always, TestOutputTrue (
1425       [["exists"; "/empty"]]);
1426     InitISOFS, Always, TestOutputTrue (
1427       [["exists"; "/directory"]])],
1428    "test if file or directory exists",
1429    "\
1430 This returns C<true> if and only if there is a file, directory
1431 (or anything) with the given C<path> name.
1432
1433 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1434
1435   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1436    [InitISOFS, Always, TestOutputTrue (
1437       [["is_file"; "/known-1"]]);
1438     InitISOFS, Always, TestOutputFalse (
1439       [["is_file"; "/directory"]])],
1440    "test if file exists",
1441    "\
1442 This returns C<true> if and only if there is a file
1443 with the given C<path> name.  Note that it returns false for
1444 other objects like directories.
1445
1446 See also C<guestfs_stat>.");
1447
1448   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1449    [InitISOFS, Always, TestOutputFalse (
1450       [["is_dir"; "/known-3"]]);
1451     InitISOFS, Always, TestOutputTrue (
1452       [["is_dir"; "/directory"]])],
1453    "test if file exists",
1454    "\
1455 This returns C<true> if and only if there is a directory
1456 with the given C<path> name.  Note that it returns false for
1457 other objects like files.
1458
1459 See also C<guestfs_stat>.");
1460
1461   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1462    [InitEmpty, Always, TestOutputListOfDevices (
1463       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1464        ["pvcreate"; "/dev/sda1"];
1465        ["pvcreate"; "/dev/sda2"];
1466        ["pvcreate"; "/dev/sda3"];
1467        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1468    "create an LVM physical volume",
1469    "\
1470 This creates an LVM physical volume on the named C<device>,
1471 where C<device> should usually be a partition name such
1472 as C</dev/sda1>.");
1473
1474   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1475    [InitEmpty, Always, TestOutputList (
1476       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1477        ["pvcreate"; "/dev/sda1"];
1478        ["pvcreate"; "/dev/sda2"];
1479        ["pvcreate"; "/dev/sda3"];
1480        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1481        ["vgcreate"; "VG2"; "/dev/sda3"];
1482        ["vgs"]], ["VG1"; "VG2"])],
1483    "create an LVM volume group",
1484    "\
1485 This creates an LVM volume group called C<volgroup>
1486 from the non-empty list of physical volumes C<physvols>.");
1487
1488   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1489    [InitEmpty, Always, TestOutputList (
1490       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1491        ["pvcreate"; "/dev/sda1"];
1492        ["pvcreate"; "/dev/sda2"];
1493        ["pvcreate"; "/dev/sda3"];
1494        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1495        ["vgcreate"; "VG2"; "/dev/sda3"];
1496        ["lvcreate"; "LV1"; "VG1"; "50"];
1497        ["lvcreate"; "LV2"; "VG1"; "50"];
1498        ["lvcreate"; "LV3"; "VG2"; "50"];
1499        ["lvcreate"; "LV4"; "VG2"; "50"];
1500        ["lvcreate"; "LV5"; "VG2"; "50"];
1501        ["lvs"]],
1502       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1503        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1504    "create an LVM logical volume",
1505    "\
1506 This creates an LVM logical volume called C<logvol>
1507 on the volume group C<volgroup>, with C<size> megabytes.");
1508
1509   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1510    [InitEmpty, Always, TestOutput (
1511       [["part_disk"; "/dev/sda"; "mbr"];
1512        ["mkfs"; "ext2"; "/dev/sda1"];
1513        ["mount_options"; ""; "/dev/sda1"; "/"];
1514        ["write"; "/new"; "new file contents"];
1515        ["cat"; "/new"]], "new file contents")],
1516    "make a filesystem",
1517    "\
1518 This creates a filesystem on C<device> (usually a partition
1519 or LVM logical volume).  The filesystem type is C<fstype>, for
1520 example C<ext3>.");
1521
1522   ("sfdisk", (RErr, [Device "device";
1523                      Int "cyls"; Int "heads"; Int "sectors";
1524                      StringList "lines"]), 43, [DangerWillRobinson],
1525    [],
1526    "create partitions on a block device",
1527    "\
1528 This is a direct interface to the L<sfdisk(8)> program for creating
1529 partitions on block devices.
1530
1531 C<device> should be a block device, for example C</dev/sda>.
1532
1533 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1534 and sectors on the device, which are passed directly to sfdisk as
1535 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1536 of these, then the corresponding parameter is omitted.  Usually for
1537 'large' disks, you can just pass C<0> for these, but for small
1538 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1539 out the right geometry and you will need to tell it.
1540
1541 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1542 information refer to the L<sfdisk(8)> manpage.
1543
1544 To create a single partition occupying the whole disk, you would
1545 pass C<lines> as a single element list, when the single element being
1546 the string C<,> (comma).
1547
1548 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1549 C<guestfs_part_init>");
1550
1551   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1552    (* Regression test for RHBZ#597135. *)
1553    [InitBasicFS, Always, TestLastFail
1554       [["write_file"; "/new"; "abc"; "10000"]]],
1555    "create a file",
1556    "\
1557 This call creates a file called C<path>.  The contents of the
1558 file is the string C<content> (which can contain any 8 bit data),
1559 with length C<size>.
1560
1561 As a special case, if C<size> is C<0>
1562 then the length is calculated using C<strlen> (so in this case
1563 the content cannot contain embedded ASCII NULs).
1564
1565 I<NB.> Owing to a bug, writing content containing ASCII NUL
1566 characters does I<not> work, even if the length is specified.");
1567
1568   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1569    [InitEmpty, Always, TestOutputListOfDevices (
1570       [["part_disk"; "/dev/sda"; "mbr"];
1571        ["mkfs"; "ext2"; "/dev/sda1"];
1572        ["mount_options"; ""; "/dev/sda1"; "/"];
1573        ["mounts"]], ["/dev/sda1"]);
1574     InitEmpty, Always, TestOutputList (
1575       [["part_disk"; "/dev/sda"; "mbr"];
1576        ["mkfs"; "ext2"; "/dev/sda1"];
1577        ["mount_options"; ""; "/dev/sda1"; "/"];
1578        ["umount"; "/"];
1579        ["mounts"]], [])],
1580    "unmount a filesystem",
1581    "\
1582 This unmounts the given filesystem.  The filesystem may be
1583 specified either by its mountpoint (path) or the device which
1584 contains the filesystem.");
1585
1586   ("mounts", (RStringList "devices", []), 46, [],
1587    [InitBasicFS, Always, TestOutputListOfDevices (
1588       [["mounts"]], ["/dev/sda1"])],
1589    "show mounted filesystems",
1590    "\
1591 This returns the list of currently mounted filesystems.  It returns
1592 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1593
1594 Some internal mounts are not shown.
1595
1596 See also: C<guestfs_mountpoints>");
1597
1598   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1599    [InitBasicFS, Always, TestOutputList (
1600       [["umount_all"];
1601        ["mounts"]], []);
1602     (* check that umount_all can unmount nested mounts correctly: *)
1603     InitEmpty, Always, TestOutputList (
1604       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1605        ["mkfs"; "ext2"; "/dev/sda1"];
1606        ["mkfs"; "ext2"; "/dev/sda2"];
1607        ["mkfs"; "ext2"; "/dev/sda3"];
1608        ["mount_options"; ""; "/dev/sda1"; "/"];
1609        ["mkdir"; "/mp1"];
1610        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1611        ["mkdir"; "/mp1/mp2"];
1612        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1613        ["mkdir"; "/mp1/mp2/mp3"];
1614        ["umount_all"];
1615        ["mounts"]], [])],
1616    "unmount all filesystems",
1617    "\
1618 This unmounts all mounted filesystems.
1619
1620 Some internal mounts are not unmounted by this call.");
1621
1622   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1623    [],
1624    "remove all LVM LVs, VGs and PVs",
1625    "\
1626 This command removes all LVM logical volumes, volume groups
1627 and physical volumes.");
1628
1629   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1630    [InitISOFS, Always, TestOutput (
1631       [["file"; "/empty"]], "empty");
1632     InitISOFS, Always, TestOutput (
1633       [["file"; "/known-1"]], "ASCII text");
1634     InitISOFS, Always, TestLastFail (
1635       [["file"; "/notexists"]])],
1636    "determine file type",
1637    "\
1638 This call uses the standard L<file(1)> command to determine
1639 the type or contents of the file.  This also works on devices,
1640 for example to find out whether a partition contains a filesystem.
1641
1642 This call will also transparently look inside various types
1643 of compressed file.
1644
1645 The exact command which runs is C<file -zbsL path>.  Note in
1646 particular that the filename is not prepended to the output
1647 (the C<-b> option).");
1648
1649   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1650    [InitBasicFS, Always, TestOutput (
1651       [["upload"; "test-command"; "/test-command"];
1652        ["chmod"; "0o755"; "/test-command"];
1653        ["command"; "/test-command 1"]], "Result1");
1654     InitBasicFS, Always, TestOutput (
1655       [["upload"; "test-command"; "/test-command"];
1656        ["chmod"; "0o755"; "/test-command"];
1657        ["command"; "/test-command 2"]], "Result2\n");
1658     InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 3"]], "\nResult3");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 4"]], "\nResult4\n");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 5"]], "\nResult5\n\n");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 7"]], "");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 8"]], "\n");
1682     InitBasicFS, Always, TestOutput (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command 9"]], "\n\n");
1686     InitBasicFS, Always, TestOutput (
1687       [["upload"; "test-command"; "/test-command"];
1688        ["chmod"; "0o755"; "/test-command"];
1689        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1690     InitBasicFS, Always, TestOutput (
1691       [["upload"; "test-command"; "/test-command"];
1692        ["chmod"; "0o755"; "/test-command"];
1693        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1694     InitBasicFS, Always, TestLastFail (
1695       [["upload"; "test-command"; "/test-command"];
1696        ["chmod"; "0o755"; "/test-command"];
1697        ["command"; "/test-command"]])],
1698    "run a command from the guest filesystem",
1699    "\
1700 This call runs a command from the guest filesystem.  The
1701 filesystem must be mounted, and must contain a compatible
1702 operating system (ie. something Linux, with the same
1703 or compatible processor architecture).
1704
1705 The single parameter is an argv-style list of arguments.
1706 The first element is the name of the program to run.
1707 Subsequent elements are parameters.  The list must be
1708 non-empty (ie. must contain a program name).  Note that
1709 the command runs directly, and is I<not> invoked via
1710 the shell (see C<guestfs_sh>).
1711
1712 The return value is anything printed to I<stdout> by
1713 the command.
1714
1715 If the command returns a non-zero exit status, then
1716 this function returns an error message.  The error message
1717 string is the content of I<stderr> from the command.
1718
1719 The C<$PATH> environment variable will contain at least
1720 C</usr/bin> and C</bin>.  If you require a program from
1721 another location, you should provide the full path in the
1722 first parameter.
1723
1724 Shared libraries and data files required by the program
1725 must be available on filesystems which are mounted in the
1726 correct places.  It is the caller's responsibility to ensure
1727 all filesystems that are needed are mounted at the right
1728 locations.");
1729
1730   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1731    [InitBasicFS, Always, TestOutputList (
1732       [["upload"; "test-command"; "/test-command"];
1733        ["chmod"; "0o755"; "/test-command"];
1734        ["command_lines"; "/test-command 1"]], ["Result1"]);
1735     InitBasicFS, Always, TestOutputList (
1736       [["upload"; "test-command"; "/test-command"];
1737        ["chmod"; "0o755"; "/test-command"];
1738        ["command_lines"; "/test-command 2"]], ["Result2"]);
1739     InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 7"]], []);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 8"]], [""]);
1763     InitBasicFS, Always, TestOutputList (
1764       [["upload"; "test-command"; "/test-command"];
1765        ["chmod"; "0o755"; "/test-command"];
1766        ["command_lines"; "/test-command 9"]], ["";""]);
1767     InitBasicFS, Always, TestOutputList (
1768       [["upload"; "test-command"; "/test-command"];
1769        ["chmod"; "0o755"; "/test-command"];
1770        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1771     InitBasicFS, Always, TestOutputList (
1772       [["upload"; "test-command"; "/test-command"];
1773        ["chmod"; "0o755"; "/test-command"];
1774        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1775    "run a command, returning lines",
1776    "\
1777 This is the same as C<guestfs_command>, but splits the
1778 result into a list of lines.
1779
1780 See also: C<guestfs_sh_lines>");
1781
1782   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1783    [InitISOFS, Always, TestOutputStruct (
1784       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1785    "get file information",
1786    "\
1787 Returns file information for the given C<path>.
1788
1789 This is the same as the C<stat(2)> system call.");
1790
1791   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1792    [InitISOFS, Always, TestOutputStruct (
1793       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1794    "get file information for a symbolic link",
1795    "\
1796 Returns file information for the given C<path>.
1797
1798 This is the same as C<guestfs_stat> except that if C<path>
1799 is a symbolic link, then the link is stat-ed, not the file it
1800 refers to.
1801
1802 This is the same as the C<lstat(2)> system call.");
1803
1804   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1805    [InitISOFS, Always, TestOutputStruct (
1806       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1807    "get file system statistics",
1808    "\
1809 Returns file system statistics for any mounted file system.
1810 C<path> should be a file or directory in the mounted file system
1811 (typically it is the mount point itself, but it doesn't need to be).
1812
1813 This is the same as the C<statvfs(2)> system call.");
1814
1815   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1816    [], (* XXX test *)
1817    "get ext2/ext3/ext4 superblock details",
1818    "\
1819 This returns the contents of the ext2, ext3 or ext4 filesystem
1820 superblock on C<device>.
1821
1822 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1823 manpage for more details.  The list of fields returned isn't
1824 clearly defined, and depends on both the version of C<tune2fs>
1825 that libguestfs was built against, and the filesystem itself.");
1826
1827   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1828    [InitEmpty, Always, TestOutputTrue (
1829       [["blockdev_setro"; "/dev/sda"];
1830        ["blockdev_getro"; "/dev/sda"]])],
1831    "set block device to read-only",
1832    "\
1833 Sets the block device named C<device> to read-only.
1834
1835 This uses the L<blockdev(8)> command.");
1836
1837   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1838    [InitEmpty, Always, TestOutputFalse (
1839       [["blockdev_setrw"; "/dev/sda"];
1840        ["blockdev_getro"; "/dev/sda"]])],
1841    "set block device to read-write",
1842    "\
1843 Sets the block device named C<device> to read-write.
1844
1845 This uses the L<blockdev(8)> command.");
1846
1847   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1848    [InitEmpty, Always, TestOutputTrue (
1849       [["blockdev_setro"; "/dev/sda"];
1850        ["blockdev_getro"; "/dev/sda"]])],
1851    "is block device set to read-only",
1852    "\
1853 Returns a boolean indicating if the block device is read-only
1854 (true if read-only, false if not).
1855
1856 This uses the L<blockdev(8)> command.");
1857
1858   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1859    [InitEmpty, Always, TestOutputInt (
1860       [["blockdev_getss"; "/dev/sda"]], 512)],
1861    "get sectorsize of block device",
1862    "\
1863 This returns the size of sectors on a block device.
1864 Usually 512, but can be larger for modern devices.
1865
1866 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1867 for that).
1868
1869 This uses the L<blockdev(8)> command.");
1870
1871   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1872    [InitEmpty, Always, TestOutputInt (
1873       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1874    "get blocksize of block device",
1875    "\
1876 This returns the block size of a device.
1877
1878 (Note this is different from both I<size in blocks> and
1879 I<filesystem block size>).
1880
1881 This uses the L<blockdev(8)> command.");
1882
1883   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1884    [], (* XXX test *)
1885    "set blocksize of block device",
1886    "\
1887 This sets the block size of a device.
1888
1889 (Note this is different from both I<size in blocks> and
1890 I<filesystem block size>).
1891
1892 This uses the L<blockdev(8)> command.");
1893
1894   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1895    [InitEmpty, Always, TestOutputInt (
1896       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1897    "get total size of device in 512-byte sectors",
1898    "\
1899 This returns the size of the device in units of 512-byte sectors
1900 (even if the sectorsize isn't 512 bytes ... weird).
1901
1902 See also C<guestfs_blockdev_getss> for the real sector size of
1903 the device, and C<guestfs_blockdev_getsize64> for the more
1904 useful I<size in bytes>.
1905
1906 This uses the L<blockdev(8)> command.");
1907
1908   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1909    [InitEmpty, Always, TestOutputInt (
1910       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1911    "get total size of device in bytes",
1912    "\
1913 This returns the size of the device in bytes.
1914
1915 See also C<guestfs_blockdev_getsz>.
1916
1917 This uses the L<blockdev(8)> command.");
1918
1919   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1920    [InitEmpty, Always, TestRun
1921       [["blockdev_flushbufs"; "/dev/sda"]]],
1922    "flush device buffers",
1923    "\
1924 This tells the kernel to flush internal buffers associated
1925 with C<device>.
1926
1927 This uses the L<blockdev(8)> command.");
1928
1929   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1930    [InitEmpty, Always, TestRun
1931       [["blockdev_rereadpt"; "/dev/sda"]]],
1932    "reread partition table",
1933    "\
1934 Reread the partition table on C<device>.
1935
1936 This uses the L<blockdev(8)> command.");
1937
1938   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1939    [InitBasicFS, Always, TestOutput (
1940       (* Pick a file from cwd which isn't likely to change. *)
1941       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1942        ["checksum"; "md5"; "/COPYING.LIB"]],
1943       Digest.to_hex (Digest.file "COPYING.LIB"))],
1944    "upload a file from the local machine",
1945    "\
1946 Upload local file C<filename> to C<remotefilename> on the
1947 filesystem.
1948
1949 C<filename> can also be a named pipe.
1950
1951 See also C<guestfs_download>.");
1952
1953   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1954    [InitBasicFS, Always, TestOutput (
1955       (* Pick a file from cwd which isn't likely to change. *)
1956       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1957        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1958        ["upload"; "testdownload.tmp"; "/upload"];
1959        ["checksum"; "md5"; "/upload"]],
1960       Digest.to_hex (Digest.file "COPYING.LIB"))],
1961    "download a file to the local machine",
1962    "\
1963 Download file C<remotefilename> and save it as C<filename>
1964 on the local machine.
1965
1966 C<filename> can also be a named pipe.
1967
1968 See also C<guestfs_upload>, C<guestfs_cat>.");
1969
1970   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1971    [InitISOFS, Always, TestOutput (
1972       [["checksum"; "crc"; "/known-3"]], "2891671662");
1973     InitISOFS, Always, TestLastFail (
1974       [["checksum"; "crc"; "/notexists"]]);
1975     InitISOFS, Always, TestOutput (
1976       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1977     InitISOFS, Always, TestOutput (
1978       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1979     InitISOFS, Always, TestOutput (
1980       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1981     InitISOFS, Always, TestOutput (
1982       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1983     InitISOFS, Always, TestOutput (
1984       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1985     InitISOFS, Always, TestOutput (
1986       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1987     (* Test for RHBZ#579608, absolute symbolic links. *)
1988     InitISOFS, Always, TestOutput (
1989       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1990    "compute MD5, SHAx or CRC checksum of file",
1991    "\
1992 This call computes the MD5, SHAx or CRC checksum of the
1993 file named C<path>.
1994
1995 The type of checksum to compute is given by the C<csumtype>
1996 parameter which must have one of the following values:
1997
1998 =over 4
1999
2000 =item C<crc>
2001
2002 Compute the cyclic redundancy check (CRC) specified by POSIX
2003 for the C<cksum> command.
2004
2005 =item C<md5>
2006
2007 Compute the MD5 hash (using the C<md5sum> program).
2008
2009 =item C<sha1>
2010
2011 Compute the SHA1 hash (using the C<sha1sum> program).
2012
2013 =item C<sha224>
2014
2015 Compute the SHA224 hash (using the C<sha224sum> program).
2016
2017 =item C<sha256>
2018
2019 Compute the SHA256 hash (using the C<sha256sum> program).
2020
2021 =item C<sha384>
2022
2023 Compute the SHA384 hash (using the C<sha384sum> program).
2024
2025 =item C<sha512>
2026
2027 Compute the SHA512 hash (using the C<sha512sum> program).
2028
2029 =back
2030
2031 The checksum is returned as a printable string.
2032
2033 To get the checksum for a device, use C<guestfs_checksum_device>.
2034
2035 To get the checksums for many files, use C<guestfs_checksums_out>.");
2036
2037   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2038    [InitBasicFS, Always, TestOutput (
2039       [["tar_in"; "../images/helloworld.tar"; "/"];
2040        ["cat"; "/hello"]], "hello\n")],
2041    "unpack tarfile to directory",
2042    "\
2043 This command uploads and unpacks local file C<tarfile> (an
2044 I<uncompressed> tar file) into C<directory>.
2045
2046 To upload a compressed tarball, use C<guestfs_tgz_in>
2047 or C<guestfs_txz_in>.");
2048
2049   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2050    [],
2051    "pack directory into tarfile",
2052    "\
2053 This command packs the contents of C<directory> and downloads
2054 it to local file C<tarfile>.
2055
2056 To download a compressed tarball, use C<guestfs_tgz_out>
2057 or C<guestfs_txz_out>.");
2058
2059   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2060    [InitBasicFS, Always, TestOutput (
2061       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2062        ["cat"; "/hello"]], "hello\n")],
2063    "unpack compressed tarball to directory",
2064    "\
2065 This command uploads and unpacks local file C<tarball> (a
2066 I<gzip compressed> tar file) into C<directory>.
2067
2068 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2069
2070   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2071    [],
2072    "pack directory into compressed tarball",
2073    "\
2074 This command packs the contents of C<directory> and downloads
2075 it to local file C<tarball>.
2076
2077 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2078
2079   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2080    [InitBasicFS, Always, TestLastFail (
2081       [["umount"; "/"];
2082        ["mount_ro"; "/dev/sda1"; "/"];
2083        ["touch"; "/new"]]);
2084     InitBasicFS, Always, TestOutput (
2085       [["write"; "/new"; "data"];
2086        ["umount"; "/"];
2087        ["mount_ro"; "/dev/sda1"; "/"];
2088        ["cat"; "/new"]], "data")],
2089    "mount a guest disk, read-only",
2090    "\
2091 This is the same as the C<guestfs_mount> command, but it
2092 mounts the filesystem with the read-only (I<-o ro>) flag.");
2093
2094   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2095    [],
2096    "mount a guest disk with mount options",
2097    "\
2098 This is the same as the C<guestfs_mount> command, but it
2099 allows you to set the mount options as for the
2100 L<mount(8)> I<-o> flag.
2101
2102 If the C<options> parameter is an empty string, then
2103 no options are passed (all options default to whatever
2104 the filesystem uses).");
2105
2106   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2107    [],
2108    "mount a guest disk with mount options and vfstype",
2109    "\
2110 This is the same as the C<guestfs_mount> command, but it
2111 allows you to set both the mount options and the vfstype
2112 as for the L<mount(8)> I<-o> and I<-t> flags.");
2113
2114   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2115    [],
2116    "debugging and internals",
2117    "\
2118 The C<guestfs_debug> command exposes some internals of
2119 C<guestfsd> (the guestfs daemon) that runs inside the
2120 qemu subprocess.
2121
2122 There is no comprehensive help for this command.  You have
2123 to look at the file C<daemon/debug.c> in the libguestfs source
2124 to find out what you can do.");
2125
2126   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2127    [InitEmpty, Always, TestOutputList (
2128       [["part_disk"; "/dev/sda"; "mbr"];
2129        ["pvcreate"; "/dev/sda1"];
2130        ["vgcreate"; "VG"; "/dev/sda1"];
2131        ["lvcreate"; "LV1"; "VG"; "50"];
2132        ["lvcreate"; "LV2"; "VG"; "50"];
2133        ["lvremove"; "/dev/VG/LV1"];
2134        ["lvs"]], ["/dev/VG/LV2"]);
2135     InitEmpty, Always, TestOutputList (
2136       [["part_disk"; "/dev/sda"; "mbr"];
2137        ["pvcreate"; "/dev/sda1"];
2138        ["vgcreate"; "VG"; "/dev/sda1"];
2139        ["lvcreate"; "LV1"; "VG"; "50"];
2140        ["lvcreate"; "LV2"; "VG"; "50"];
2141        ["lvremove"; "/dev/VG"];
2142        ["lvs"]], []);
2143     InitEmpty, Always, TestOutputList (
2144       [["part_disk"; "/dev/sda"; "mbr"];
2145        ["pvcreate"; "/dev/sda1"];
2146        ["vgcreate"; "VG"; "/dev/sda1"];
2147        ["lvcreate"; "LV1"; "VG"; "50"];
2148        ["lvcreate"; "LV2"; "VG"; "50"];
2149        ["lvremove"; "/dev/VG"];
2150        ["vgs"]], ["VG"])],
2151    "remove an LVM logical volume",
2152    "\
2153 Remove an LVM logical volume C<device>, where C<device> is
2154 the path to the LV, such as C</dev/VG/LV>.
2155
2156 You can also remove all LVs in a volume group by specifying
2157 the VG name, C</dev/VG>.");
2158
2159   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2160    [InitEmpty, Always, TestOutputList (
2161       [["part_disk"; "/dev/sda"; "mbr"];
2162        ["pvcreate"; "/dev/sda1"];
2163        ["vgcreate"; "VG"; "/dev/sda1"];
2164        ["lvcreate"; "LV1"; "VG"; "50"];
2165        ["lvcreate"; "LV2"; "VG"; "50"];
2166        ["vgremove"; "VG"];
2167        ["lvs"]], []);
2168     InitEmpty, Always, TestOutputList (
2169       [["part_disk"; "/dev/sda"; "mbr"];
2170        ["pvcreate"; "/dev/sda1"];
2171        ["vgcreate"; "VG"; "/dev/sda1"];
2172        ["lvcreate"; "LV1"; "VG"; "50"];
2173        ["lvcreate"; "LV2"; "VG"; "50"];
2174        ["vgremove"; "VG"];
2175        ["vgs"]], [])],
2176    "remove an LVM volume group",
2177    "\
2178 Remove an LVM volume group C<vgname>, (for example C<VG>).
2179
2180 This also forcibly removes all logical volumes in the volume
2181 group (if any).");
2182
2183   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2184    [InitEmpty, Always, TestOutputListOfDevices (
2185       [["part_disk"; "/dev/sda"; "mbr"];
2186        ["pvcreate"; "/dev/sda1"];
2187        ["vgcreate"; "VG"; "/dev/sda1"];
2188        ["lvcreate"; "LV1"; "VG"; "50"];
2189        ["lvcreate"; "LV2"; "VG"; "50"];
2190        ["vgremove"; "VG"];
2191        ["pvremove"; "/dev/sda1"];
2192        ["lvs"]], []);
2193     InitEmpty, Always, TestOutputListOfDevices (
2194       [["part_disk"; "/dev/sda"; "mbr"];
2195        ["pvcreate"; "/dev/sda1"];
2196        ["vgcreate"; "VG"; "/dev/sda1"];
2197        ["lvcreate"; "LV1"; "VG"; "50"];
2198        ["lvcreate"; "LV2"; "VG"; "50"];
2199        ["vgremove"; "VG"];
2200        ["pvremove"; "/dev/sda1"];
2201        ["vgs"]], []);
2202     InitEmpty, Always, TestOutputListOfDevices (
2203       [["part_disk"; "/dev/sda"; "mbr"];
2204        ["pvcreate"; "/dev/sda1"];
2205        ["vgcreate"; "VG"; "/dev/sda1"];
2206        ["lvcreate"; "LV1"; "VG"; "50"];
2207        ["lvcreate"; "LV2"; "VG"; "50"];
2208        ["vgremove"; "VG"];
2209        ["pvremove"; "/dev/sda1"];
2210        ["pvs"]], [])],
2211    "remove an LVM physical volume",
2212    "\
2213 This wipes a physical volume C<device> so that LVM will no longer
2214 recognise it.
2215
2216 The implementation uses the C<pvremove> command which refuses to
2217 wipe physical volumes that contain any volume groups, so you have
2218 to remove those first.");
2219
2220   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2221    [InitBasicFS, Always, TestOutput (
2222       [["set_e2label"; "/dev/sda1"; "testlabel"];
2223        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2224    "set the ext2/3/4 filesystem label",
2225    "\
2226 This sets the ext2/3/4 filesystem label of the filesystem on
2227 C<device> to C<label>.  Filesystem labels are limited to
2228 16 characters.
2229
2230 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2231 to return the existing label on a filesystem.");
2232
2233   ("get_e2label", (RString "label", [Device "device"]), 81, [DeprecatedBy "vfs_label"],
2234    [],
2235    "get the ext2/3/4 filesystem label",
2236    "\
2237 This returns the ext2/3/4 filesystem label of the filesystem on
2238 C<device>.");
2239
2240   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2241    (let uuid = uuidgen () in
2242     [InitBasicFS, Always, TestOutput (
2243        [["set_e2uuid"; "/dev/sda1"; uuid];
2244         ["get_e2uuid"; "/dev/sda1"]], uuid);
2245      InitBasicFS, Always, TestOutput (
2246        [["set_e2uuid"; "/dev/sda1"; "clear"];
2247         ["get_e2uuid"; "/dev/sda1"]], "");
2248      (* We can't predict what UUIDs will be, so just check the commands run. *)
2249      InitBasicFS, Always, TestRun (
2250        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2251      InitBasicFS, Always, TestRun (
2252        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2253    "set the ext2/3/4 filesystem UUID",
2254    "\
2255 This sets the ext2/3/4 filesystem UUID of the filesystem on
2256 C<device> to C<uuid>.  The format of the UUID and alternatives
2257 such as C<clear>, C<random> and C<time> are described in the
2258 L<tune2fs(8)> manpage.
2259
2260 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2261 to return the existing UUID of a filesystem.");
2262
2263   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [DeprecatedBy "vfs_uuid"],
2264    (* Regression test for RHBZ#597112. *)
2265    (let uuid = uuidgen () in
2266     [InitBasicFS, Always, TestOutput (
2267        [["mke2journal"; "1024"; "/dev/sdb"];
2268         ["set_e2uuid"; "/dev/sdb"; uuid];
2269         ["get_e2uuid"; "/dev/sdb"]], uuid)]),
2270    "get the ext2/3/4 filesystem UUID",
2271    "\
2272 This returns the ext2/3/4 filesystem UUID of the filesystem on
2273 C<device>.");
2274
2275   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2276    [InitBasicFS, Always, TestOutputInt (
2277       [["umount"; "/dev/sda1"];
2278        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2279     InitBasicFS, Always, TestOutputInt (
2280       [["umount"; "/dev/sda1"];
2281        ["zero"; "/dev/sda1"];
2282        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2283    "run the filesystem checker",
2284    "\
2285 This runs the filesystem checker (fsck) on C<device> which
2286 should have filesystem type C<fstype>.
2287
2288 The returned integer is the status.  See L<fsck(8)> for the
2289 list of status codes from C<fsck>.
2290
2291 Notes:
2292
2293 =over 4
2294
2295 =item *
2296
2297 Multiple status codes can be summed together.
2298
2299 =item *
2300
2301 A non-zero return code can mean \"success\", for example if
2302 errors have been corrected on the filesystem.
2303
2304 =item *
2305
2306 Checking or repairing NTFS volumes is not supported
2307 (by linux-ntfs).
2308
2309 =back
2310
2311 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2312
2313   ("zero", (RErr, [Device "device"]), 85, [],
2314    [InitBasicFS, Always, TestOutput (
2315       [["umount"; "/dev/sda1"];
2316        ["zero"; "/dev/sda1"];
2317        ["file"; "/dev/sda1"]], "data")],
2318    "write zeroes to the device",
2319    "\
2320 This command writes zeroes over the first few blocks of C<device>.
2321
2322 How many blocks are zeroed isn't specified (but it's I<not> enough
2323 to securely wipe the device).  It should be sufficient to remove
2324 any partition tables, filesystem superblocks and so on.
2325
2326 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2327
2328   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2329    (* See:
2330     * https://bugzilla.redhat.com/show_bug.cgi?id=484986
2331     * https://bugzilla.redhat.com/show_bug.cgi?id=479760
2332     *)
2333    [InitBasicFS, Always, TestOutputTrue (
2334       [["mkdir_p"; "/boot/grub"];
2335        ["write"; "/boot/grub/device.map"; "(hd0) /dev/vda"];
2336        ["grub_install"; "/"; "/dev/vda"];
2337        ["is_dir"; "/boot"]])],
2338    "install GRUB",
2339    "\
2340 This command installs GRUB (the Grand Unified Bootloader) on
2341 C<device>, with the root directory being C<root>.
2342
2343 Note: If grub-install reports the error
2344 \"No suitable drive was found in the generated device map.\"
2345 it may be that you need to create a C</boot/grub/device.map>
2346 file first that contains the mapping between grub device names
2347 and Linux device names.  It is usually sufficient to create
2348 a file containing:
2349
2350  (hd0) /dev/vda
2351
2352 replacing C</dev/vda> with the name of the installation device.");
2353
2354   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2355    [InitBasicFS, Always, TestOutput (
2356       [["write"; "/old"; "file content"];
2357        ["cp"; "/old"; "/new"];
2358        ["cat"; "/new"]], "file content");
2359     InitBasicFS, Always, TestOutputTrue (
2360       [["write"; "/old"; "file content"];
2361        ["cp"; "/old"; "/new"];
2362        ["is_file"; "/old"]]);
2363     InitBasicFS, Always, TestOutput (
2364       [["write"; "/old"; "file content"];
2365        ["mkdir"; "/dir"];
2366        ["cp"; "/old"; "/dir/new"];
2367        ["cat"; "/dir/new"]], "file content")],
2368    "copy a file",
2369    "\
2370 This copies a file from C<src> to C<dest> where C<dest> is
2371 either a destination filename or destination directory.");
2372
2373   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2374    [InitBasicFS, Always, TestOutput (
2375       [["mkdir"; "/olddir"];
2376        ["mkdir"; "/newdir"];
2377        ["write"; "/olddir/file"; "file content"];
2378        ["cp_a"; "/olddir"; "/newdir"];
2379        ["cat"; "/newdir/olddir/file"]], "file content")],
2380    "copy a file or directory recursively",
2381    "\
2382 This copies a file or directory from C<src> to C<dest>
2383 recursively using the C<cp -a> command.");
2384
2385   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2386    [InitBasicFS, Always, TestOutput (
2387       [["write"; "/old"; "file content"];
2388        ["mv"; "/old"; "/new"];
2389        ["cat"; "/new"]], "file content");
2390     InitBasicFS, Always, TestOutputFalse (
2391       [["write"; "/old"; "file content"];
2392        ["mv"; "/old"; "/new"];
2393        ["is_file"; "/old"]])],
2394    "move a file",
2395    "\
2396 This moves a file from C<src> to C<dest> where C<dest> is
2397 either a destination filename or destination directory.");
2398
2399   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2400    [InitEmpty, Always, TestRun (
2401       [["drop_caches"; "3"]])],
2402    "drop kernel page cache, dentries and inodes",
2403    "\
2404 This instructs the guest kernel to drop its page cache,
2405 and/or dentries and inode caches.  The parameter C<whattodrop>
2406 tells the kernel what precisely to drop, see
2407 L<http://linux-mm.org/Drop_Caches>
2408
2409 Setting C<whattodrop> to 3 should drop everything.
2410
2411 This automatically calls L<sync(2)> before the operation,
2412 so that the maximum guest memory is freed.");
2413
2414   ("dmesg", (RString "kmsgs", []), 91, [],
2415    [InitEmpty, Always, TestRun (
2416       [["dmesg"]])],
2417    "return kernel messages",
2418    "\
2419 This returns the kernel messages (C<dmesg> output) from
2420 the guest kernel.  This is sometimes useful for extended
2421 debugging of problems.
2422
2423 Another way to get the same information is to enable
2424 verbose messages with C<guestfs_set_verbose> or by setting
2425 the environment variable C<LIBGUESTFS_DEBUG=1> before
2426 running the program.");
2427
2428   ("ping_daemon", (RErr, []), 92, [],
2429    [InitEmpty, Always, TestRun (
2430       [["ping_daemon"]])],
2431    "ping the guest daemon",
2432    "\
2433 This is a test probe into the guestfs daemon running inside
2434 the qemu subprocess.  Calling this function checks that the
2435 daemon responds to the ping message, without affecting the daemon
2436 or attached block device(s) in any other way.");
2437
2438   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2439    [InitBasicFS, Always, TestOutputTrue (
2440       [["write"; "/file1"; "contents of a file"];
2441        ["cp"; "/file1"; "/file2"];
2442        ["equal"; "/file1"; "/file2"]]);
2443     InitBasicFS, Always, TestOutputFalse (
2444       [["write"; "/file1"; "contents of a file"];
2445        ["write"; "/file2"; "contents of another file"];
2446        ["equal"; "/file1"; "/file2"]]);
2447     InitBasicFS, Always, TestLastFail (
2448       [["equal"; "/file1"; "/file2"]])],
2449    "test if two files have equal contents",
2450    "\
2451 This compares the two files C<file1> and C<file2> and returns
2452 true if their content is exactly equal, or false otherwise.
2453
2454 The external L<cmp(1)> program is used for the comparison.");
2455
2456   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2457    [InitISOFS, Always, TestOutputList (
2458       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2459     InitISOFS, Always, TestOutputList (
2460       [["strings"; "/empty"]], []);
2461     (* Test for RHBZ#579608, absolute symbolic links. *)
2462     InitISOFS, Always, TestRun (
2463       [["strings"; "/abssymlink"]])],
2464    "print the printable strings in a file",
2465    "\
2466 This runs the L<strings(1)> command on a file and returns
2467 the list of printable strings found.");
2468
2469   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2470    [InitISOFS, Always, TestOutputList (
2471       [["strings_e"; "b"; "/known-5"]], []);
2472     InitBasicFS, Always, TestOutputList (
2473       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2474        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2475    "print the printable strings in a file",
2476    "\
2477 This is like the C<guestfs_strings> command, but allows you to
2478 specify the encoding of strings that are looked for in
2479 the source file C<path>.
2480
2481 Allowed encodings are:
2482
2483 =over 4
2484
2485 =item s
2486
2487 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2488 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2489
2490 =item S
2491
2492 Single 8-bit-byte characters.
2493
2494 =item b
2495
2496 16-bit big endian strings such as those encoded in
2497 UTF-16BE or UCS-2BE.
2498
2499 =item l (lower case letter L)
2500
2501 16-bit little endian such as UTF-16LE and UCS-2LE.
2502 This is useful for examining binaries in Windows guests.
2503
2504 =item B
2505
2506 32-bit big endian such as UCS-4BE.
2507
2508 =item L
2509
2510 32-bit little endian such as UCS-4LE.
2511
2512 =back
2513
2514 The returned strings are transcoded to UTF-8.");
2515
2516   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2517    [InitISOFS, Always, TestOutput (
2518       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2519     (* Test for RHBZ#501888c2 regression which caused large hexdump
2520      * commands to segfault.
2521      *)
2522     InitISOFS, Always, TestRun (
2523       [["hexdump"; "/100krandom"]]);
2524     (* Test for RHBZ#579608, absolute symbolic links. *)
2525     InitISOFS, Always, TestRun (
2526       [["hexdump"; "/abssymlink"]])],
2527    "dump a file in hexadecimal",
2528    "\
2529 This runs C<hexdump -C> on the given C<path>.  The result is
2530 the human-readable, canonical hex dump of the file.");
2531
2532   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2533    [InitNone, Always, TestOutput (
2534       [["part_disk"; "/dev/sda"; "mbr"];
2535        ["mkfs"; "ext3"; "/dev/sda1"];
2536        ["mount_options"; ""; "/dev/sda1"; "/"];
2537        ["write"; "/new"; "test file"];
2538        ["umount"; "/dev/sda1"];
2539        ["zerofree"; "/dev/sda1"];
2540        ["mount_options"; ""; "/dev/sda1"; "/"];
2541        ["cat"; "/new"]], "test file")],
2542    "zero unused inodes and disk blocks on ext2/3 filesystem",
2543    "\
2544 This runs the I<zerofree> program on C<device>.  This program
2545 claims to zero unused inodes and disk blocks on an ext2/3
2546 filesystem, thus making it possible to compress the filesystem
2547 more effectively.
2548
2549 You should B<not> run this program if the filesystem is
2550 mounted.
2551
2552 It is possible that using this program can damage the filesystem
2553 or data on the filesystem.");
2554
2555   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2556    [],
2557    "resize an LVM physical volume",
2558    "\
2559 This resizes (expands or shrinks) an existing LVM physical
2560 volume to match the new size of the underlying device.");
2561
2562   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2563                        Int "cyls"; Int "heads"; Int "sectors";
2564                        String "line"]), 99, [DangerWillRobinson],
2565    [],
2566    "modify a single partition on a block device",
2567    "\
2568 This runs L<sfdisk(8)> option to modify just the single
2569 partition C<n> (note: C<n> counts from 1).
2570
2571 For other parameters, see C<guestfs_sfdisk>.  You should usually
2572 pass C<0> for the cyls/heads/sectors parameters.
2573
2574 See also: C<guestfs_part_add>");
2575
2576   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2577    [],
2578    "display the partition table",
2579    "\
2580 This displays the partition table on C<device>, in the
2581 human-readable output of the L<sfdisk(8)> command.  It is
2582 not intended to be parsed.
2583
2584 See also: C<guestfs_part_list>");
2585
2586   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2587    [],
2588    "display the kernel geometry",
2589    "\
2590 This displays the kernel's idea of the geometry of C<device>.
2591
2592 The result is in human-readable format, and not designed to
2593 be parsed.");
2594
2595   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2596    [],
2597    "display the disk geometry from the partition table",
2598    "\
2599 This displays the disk geometry of C<device> read from the
2600 partition table.  Especially in the case where the underlying
2601 block device has been resized, this can be different from the
2602 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2603
2604 The result is in human-readable format, and not designed to
2605 be parsed.");
2606
2607   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2608    [],
2609    "activate or deactivate all volume groups",
2610    "\
2611 This command activates or (if C<activate> is false) deactivates
2612 all logical volumes in all volume groups.
2613 If activated, then they are made known to the
2614 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2615 then those devices disappear.
2616
2617 This command is the same as running C<vgchange -a y|n>");
2618
2619   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2620    [],
2621    "activate or deactivate some volume groups",
2622    "\
2623 This command activates or (if C<activate> is false) deactivates
2624 all logical volumes in the listed volume groups C<volgroups>.
2625 If activated, then they are made known to the
2626 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2627 then those devices disappear.
2628
2629 This command is the same as running C<vgchange -a y|n volgroups...>
2630
2631 Note that if C<volgroups> is an empty list then B<all> volume groups
2632 are activated or deactivated.");
2633
2634   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2635    [InitNone, Always, TestOutput (
2636       [["part_disk"; "/dev/sda"; "mbr"];
2637        ["pvcreate"; "/dev/sda1"];
2638        ["vgcreate"; "VG"; "/dev/sda1"];
2639        ["lvcreate"; "LV"; "VG"; "10"];
2640        ["mkfs"; "ext2"; "/dev/VG/LV"];
2641        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2642        ["write"; "/new"; "test content"];
2643        ["umount"; "/"];
2644        ["lvresize"; "/dev/VG/LV"; "20"];
2645        ["e2fsck_f"; "/dev/VG/LV"];
2646        ["resize2fs"; "/dev/VG/LV"];
2647        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2648        ["cat"; "/new"]], "test content");
2649     InitNone, Always, TestRun (
2650       (* Make an LV smaller to test RHBZ#587484. *)
2651       [["part_disk"; "/dev/sda"; "mbr"];
2652        ["pvcreate"; "/dev/sda1"];
2653        ["vgcreate"; "VG"; "/dev/sda1"];
2654        ["lvcreate"; "LV"; "VG"; "20"];
2655        ["lvresize"; "/dev/VG/LV"; "10"]])],
2656    "resize an LVM logical volume",
2657    "\
2658 This resizes (expands or shrinks) an existing LVM logical
2659 volume to C<mbytes>.  When reducing, data in the reduced part
2660 is lost.");
2661
2662   ("resize2fs", (RErr, [Device "device"]), 106, [],
2663    [], (* lvresize tests this *)
2664    "resize an ext2, ext3 or ext4 filesystem",
2665    "\
2666 This resizes an ext2, ext3 or ext4 filesystem to match the size of
2667 the underlying device.
2668
2669 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2670 on the C<device> before calling this command.  For unknown reasons
2671 C<resize2fs> sometimes gives an error about this and sometimes not.
2672 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2673 calling this function.");
2674
2675   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2676    [InitBasicFS, Always, TestOutputList (
2677       [["find"; "/"]], ["lost+found"]);
2678     InitBasicFS, Always, TestOutputList (
2679       [["touch"; "/a"];
2680        ["mkdir"; "/b"];
2681        ["touch"; "/b/c"];
2682        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2683     InitBasicFS, Always, TestOutputList (
2684       [["mkdir_p"; "/a/b/c"];
2685        ["touch"; "/a/b/c/d"];
2686        ["find"; "/a/b/"]], ["c"; "c/d"])],
2687    "find all files and directories",
2688    "\
2689 This command lists out all files and directories, recursively,
2690 starting at C<directory>.  It is essentially equivalent to
2691 running the shell command C<find directory -print> but some
2692 post-processing happens on the output, described below.
2693
2694 This returns a list of strings I<without any prefix>.  Thus
2695 if the directory structure was:
2696
2697  /tmp/a
2698  /tmp/b
2699  /tmp/c/d
2700
2701 then the returned list from C<guestfs_find> C</tmp> would be
2702 4 elements:
2703
2704  a
2705  b
2706  c
2707  c/d
2708
2709 If C<directory> is not a directory, then this command returns
2710 an error.
2711
2712 The returned list is sorted.
2713
2714 See also C<guestfs_find0>.");
2715
2716   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2717    [], (* lvresize tests this *)
2718    "check an ext2/ext3 filesystem",
2719    "\
2720 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2721 filesystem checker on C<device>, noninteractively (C<-p>),
2722 even if the filesystem appears to be clean (C<-f>).
2723
2724 This command is only needed because of C<guestfs_resize2fs>
2725 (q.v.).  Normally you should use C<guestfs_fsck>.");
2726
2727   ("sleep", (RErr, [Int "secs"]), 109, [],
2728    [InitNone, Always, TestRun (
2729       [["sleep"; "1"]])],
2730    "sleep for some seconds",
2731    "\
2732 Sleep for C<secs> seconds.");
2733
2734   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2735    [InitNone, Always, TestOutputInt (
2736       [["part_disk"; "/dev/sda"; "mbr"];
2737        ["mkfs"; "ntfs"; "/dev/sda1"];
2738        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2739     InitNone, Always, TestOutputInt (
2740       [["part_disk"; "/dev/sda"; "mbr"];
2741        ["mkfs"; "ext2"; "/dev/sda1"];
2742        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2743    "probe NTFS volume",
2744    "\
2745 This command runs the L<ntfs-3g.probe(8)> command which probes
2746 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2747 be mounted read-write, and some cannot be mounted at all).
2748
2749 C<rw> is a boolean flag.  Set it to true if you want to test
2750 if the volume can be mounted read-write.  Set it to false if
2751 you want to test if the volume can be mounted read-only.
2752
2753 The return value is an integer which C<0> if the operation
2754 would succeed, or some non-zero value documented in the
2755 L<ntfs-3g.probe(8)> manual page.");
2756
2757   ("sh", (RString "output", [String "command"]), 111, [],
2758    [], (* XXX needs tests *)
2759    "run a command via the shell",
2760    "\
2761 This call runs a command from the guest filesystem via the
2762 guest's C</bin/sh>.
2763
2764 This is like C<guestfs_command>, but passes the command to:
2765
2766  /bin/sh -c \"command\"
2767
2768 Depending on the guest's shell, this usually results in
2769 wildcards being expanded, shell expressions being interpolated
2770 and so on.
2771
2772 All the provisos about C<guestfs_command> apply to this call.");
2773
2774   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2775    [], (* XXX needs tests *)
2776    "run a command via the shell returning lines",
2777    "\
2778 This is the same as C<guestfs_sh>, but splits the result
2779 into a list of lines.
2780
2781 See also: C<guestfs_command_lines>");
2782
2783   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2784    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2785     * code in stubs.c, since all valid glob patterns must start with "/".
2786     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2787     *)
2788    [InitBasicFS, Always, TestOutputList (
2789       [["mkdir_p"; "/a/b/c"];
2790        ["touch"; "/a/b/c/d"];
2791        ["touch"; "/a/b/c/e"];
2792        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2793     InitBasicFS, Always, TestOutputList (
2794       [["mkdir_p"; "/a/b/c"];
2795        ["touch"; "/a/b/c/d"];
2796        ["touch"; "/a/b/c/e"];
2797        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2798     InitBasicFS, Always, TestOutputList (
2799       [["mkdir_p"; "/a/b/c"];
2800        ["touch"; "/a/b/c/d"];
2801        ["touch"; "/a/b/c/e"];
2802        ["glob_expand"; "/a/*/x/*"]], [])],
2803    "expand a wildcard path",
2804    "\
2805 This command searches for all the pathnames matching
2806 C<pattern> according to the wildcard expansion rules
2807 used by the shell.
2808
2809 If no paths match, then this returns an empty list
2810 (note: not an error).
2811
2812 It is just a wrapper around the C L<glob(3)> function
2813 with flags C<GLOB_MARK|GLOB_BRACE>.
2814 See that manual page for more details.");
2815
2816   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2817    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2818       [["scrub_device"; "/dev/sdc"]])],
2819    "scrub (securely wipe) a device",
2820    "\
2821 This command writes patterns over C<device> to make data retrieval
2822 more difficult.
2823
2824 It is an interface to the L<scrub(1)> program.  See that
2825 manual page for more details.");
2826
2827   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2828    [InitBasicFS, Always, TestRun (
2829       [["write"; "/file"; "content"];
2830        ["scrub_file"; "/file"]])],
2831    "scrub (securely wipe) a file",
2832    "\
2833 This command writes patterns over a file to make data retrieval
2834 more difficult.
2835
2836 The file is I<removed> after scrubbing.
2837
2838 It is an interface to the L<scrub(1)> program.  See that
2839 manual page for more details.");
2840
2841   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2842    [], (* XXX needs testing *)
2843    "scrub (securely wipe) free space",
2844    "\
2845 This command creates the directory C<dir> and then fills it
2846 with files until the filesystem is full, and scrubs the files
2847 as for C<guestfs_scrub_file>, and deletes them.
2848 The intention is to scrub any free space on the partition
2849 containing C<dir>.
2850
2851 It is an interface to the L<scrub(1)> program.  See that
2852 manual page for more details.");
2853
2854   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2855    [InitBasicFS, Always, TestRun (
2856       [["mkdir"; "/tmp"];
2857        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2858    "create a temporary directory",
2859    "\
2860 This command creates a temporary directory.  The
2861 C<template> parameter should be a full pathname for the
2862 temporary directory name with the final six characters being
2863 \"XXXXXX\".
2864
2865 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2866 the second one being suitable for Windows filesystems.
2867
2868 The name of the temporary directory that was created
2869 is returned.
2870
2871 The temporary directory is created with mode 0700
2872 and is owned by root.
2873
2874 The caller is responsible for deleting the temporary
2875 directory and its contents after use.
2876
2877 See also: L<mkdtemp(3)>");
2878
2879   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2880    [InitISOFS, Always, TestOutputInt (
2881       [["wc_l"; "/10klines"]], 10000);
2882     (* Test for RHBZ#579608, absolute symbolic links. *)
2883     InitISOFS, Always, TestOutputInt (
2884       [["wc_l"; "/abssymlink"]], 10000)],
2885    "count lines in a file",
2886    "\
2887 This command counts the lines in a file, using the
2888 C<wc -l> external command.");
2889
2890   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2891    [InitISOFS, Always, TestOutputInt (
2892       [["wc_w"; "/10klines"]], 10000)],
2893    "count words in a file",
2894    "\
2895 This command counts the words in a file, using the
2896 C<wc -w> external command.");
2897
2898   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2899    [InitISOFS, Always, TestOutputInt (
2900       [["wc_c"; "/100kallspaces"]], 102400)],
2901    "count characters in a file",
2902    "\
2903 This command counts the characters in a file, using the
2904 C<wc -c> external command.");
2905
2906   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2907    [InitISOFS, Always, TestOutputList (
2908       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2909     (* Test for RHBZ#579608, absolute symbolic links. *)
2910     InitISOFS, Always, TestOutputList (
2911       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2912    "return first 10 lines of a file",
2913    "\
2914 This command returns up to the first 10 lines of a file as
2915 a list of strings.");
2916
2917   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2918    [InitISOFS, Always, TestOutputList (
2919       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2920     InitISOFS, Always, TestOutputList (
2921       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2922     InitISOFS, Always, TestOutputList (
2923       [["head_n"; "0"; "/10klines"]], [])],
2924    "return first N lines of a file",
2925    "\
2926 If the parameter C<nrlines> is a positive number, this returns the first
2927 C<nrlines> lines of the file C<path>.
2928
2929 If the parameter C<nrlines> is a negative number, this returns lines
2930 from the file C<path>, excluding the last C<nrlines> lines.
2931
2932 If the parameter C<nrlines> is zero, this returns an empty list.");
2933
2934   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2935    [InitISOFS, Always, TestOutputList (
2936       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2937    "return last 10 lines of a file",
2938    "\
2939 This command returns up to the last 10 lines of a file as
2940 a list of strings.");
2941
2942   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2943    [InitISOFS, Always, TestOutputList (
2944       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2945     InitISOFS, Always, TestOutputList (
2946       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2947     InitISOFS, Always, TestOutputList (
2948       [["tail_n"; "0"; "/10klines"]], [])],
2949    "return last N lines of a file",
2950    "\
2951 If the parameter C<nrlines> is a positive number, this returns the last
2952 C<nrlines> lines of the file C<path>.
2953
2954 If the parameter C<nrlines> is a negative number, this returns lines
2955 from the file C<path>, starting with the C<-nrlines>th line.
2956
2957 If the parameter C<nrlines> is zero, this returns an empty list.");
2958
2959   ("df", (RString "output", []), 125, [],
2960    [], (* XXX Tricky to test because it depends on the exact format
2961         * of the 'df' command and other imponderables.
2962         *)
2963    "report file system disk space usage",
2964    "\
2965 This command runs the C<df> command to report disk space used.
2966
2967 This command is mostly useful for interactive sessions.  It
2968 is I<not> intended that you try to parse the output string.
2969 Use C<statvfs> from programs.");
2970
2971   ("df_h", (RString "output", []), 126, [],
2972    [], (* XXX Tricky to test because it depends on the exact format
2973         * of the 'df' command and other imponderables.
2974         *)
2975    "report file system disk space usage (human readable)",
2976    "\
2977 This command runs the C<df -h> command to report disk space used
2978 in human-readable format.
2979
2980 This command is mostly useful for interactive sessions.  It
2981 is I<not> intended that you try to parse the output string.
2982 Use C<statvfs> from programs.");
2983
2984   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2985    [InitISOFS, Always, TestOutputInt (
2986       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2987    "estimate file space usage",
2988    "\
2989 This command runs the C<du -s> command to estimate file space
2990 usage for C<path>.
2991
2992 C<path> can be a file or a directory.  If C<path> is a directory
2993 then the estimate includes the contents of the directory and all
2994 subdirectories (recursively).
2995
2996 The result is the estimated size in I<kilobytes>
2997 (ie. units of 1024 bytes).");
2998
2999   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
3000    [InitISOFS, Always, TestOutputList (
3001       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
3002    "list files in an initrd",
3003    "\
3004 This command lists out files contained in an initrd.
3005
3006 The files are listed without any initial C</> character.  The
3007 files are listed in the order they appear (not necessarily
3008 alphabetical).  Directory names are listed as separate items.
3009
3010 Old Linux kernels (2.4 and earlier) used a compressed ext2
3011 filesystem as initrd.  We I<only> support the newer initramfs
3012 format (compressed cpio files).");
3013
3014   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3015    [],
3016    "mount a file using the loop device",
3017    "\
3018 This command lets you mount C<file> (a filesystem image
3019 in a file) on a mount point.  It is entirely equivalent to
3020 the command C<mount -o loop file mountpoint>.");
3021
3022   ("mkswap", (RErr, [Device "device"]), 130, [],
3023    [InitEmpty, Always, TestRun (
3024       [["part_disk"; "/dev/sda"; "mbr"];
3025        ["mkswap"; "/dev/sda1"]])],
3026    "create a swap partition",
3027    "\
3028 Create a swap partition on C<device>.");
3029
3030   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3031    [InitEmpty, Always, TestRun (
3032       [["part_disk"; "/dev/sda"; "mbr"];
3033        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3034    "create a swap partition with a label",
3035    "\
3036 Create a swap partition on C<device> with label C<label>.
3037
3038 Note that you cannot attach a swap label to a block device
3039 (eg. C</dev/sda>), just to a partition.  This appears to be
3040 a limitation of the kernel or swap tools.");
3041
3042   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3043    (let uuid = uuidgen () in
3044     [InitEmpty, Always, TestRun (
3045        [["part_disk"; "/dev/sda"; "mbr"];
3046         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3047    "create a swap partition with an explicit UUID",
3048    "\
3049 Create a swap partition on C<device> with UUID C<uuid>.");
3050
3051   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3052    [InitBasicFS, Always, TestOutputStruct (
3053       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3054        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3055        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3056     InitBasicFS, Always, TestOutputStruct (
3057       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3058        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3059    "make block, character or FIFO devices",
3060    "\
3061 This call creates block or character special devices, or
3062 named pipes (FIFOs).
3063
3064 The C<mode> parameter should be the mode, using the standard
3065 constants.  C<devmajor> and C<devminor> are the
3066 device major and minor numbers, only used when creating block
3067 and character special devices.
3068
3069 Note that, just like L<mknod(2)>, the mode must be bitwise
3070 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3071 just creates a regular file).  These constants are
3072 available in the standard Linux header files, or you can use
3073 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3074 which are wrappers around this command which bitwise OR
3075 in the appropriate constant for you.
3076
3077 The mode actually set is affected by the umask.");
3078
3079   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3080    [InitBasicFS, Always, TestOutputStruct (
3081       [["mkfifo"; "0o777"; "/node"];
3082        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3083    "make FIFO (named pipe)",
3084    "\
3085 This call creates a FIFO (named pipe) called C<path> with
3086 mode C<mode>.  It is just a convenient wrapper around
3087 C<guestfs_mknod>.
3088
3089 The mode actually set is affected by the umask.");
3090
3091   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3092    [InitBasicFS, Always, TestOutputStruct (
3093       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3094        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3095    "make block device node",
3096    "\
3097 This call creates a block device node called C<path> with
3098 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3099 It is just a convenient wrapper around C<guestfs_mknod>.
3100
3101 The mode actually set is affected by the umask.");
3102
3103   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3104    [InitBasicFS, Always, TestOutputStruct (
3105       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3106        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3107    "make char device node",
3108    "\
3109 This call creates a char device node called C<path> with
3110 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3111 It is just a convenient wrapper around C<guestfs_mknod>.
3112
3113 The mode actually set is affected by the umask.");
3114
3115   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3116    [InitEmpty, Always, TestOutputInt (
3117       [["umask"; "0o22"]], 0o22)],
3118    "set file mode creation mask (umask)",
3119    "\
3120 This function sets the mask used for creating new files and
3121 device nodes to C<mask & 0777>.
3122
3123 Typical umask values would be C<022> which creates new files
3124 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3125 C<002> which creates new files with permissions like
3126 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3127
3128 The default umask is C<022>.  This is important because it
3129 means that directories and device nodes will be created with
3130 C<0644> or C<0755> mode even if you specify C<0777>.
3131
3132 See also C<guestfs_get_umask>,
3133 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3134
3135 This call returns the previous umask.");
3136
3137   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3138    [],
3139    "read directories entries",
3140    "\
3141 This returns the list of directory entries in directory C<dir>.
3142
3143 All entries in the directory are returned, including C<.> and
3144 C<..>.  The entries are I<not> sorted, but returned in the same
3145 order as the underlying filesystem.
3146
3147 Also this call returns basic file type information about each
3148 file.  The C<ftyp> field will contain one of the following characters:
3149
3150 =over 4
3151
3152 =item 'b'
3153
3154 Block special
3155
3156 =item 'c'
3157
3158 Char special
3159
3160 =item 'd'
3161
3162 Directory
3163
3164 =item 'f'
3165
3166 FIFO (named pipe)
3167
3168 =item 'l'
3169
3170 Symbolic link
3171
3172 =item 'r'
3173
3174 Regular file
3175
3176 =item 's'
3177
3178 Socket
3179
3180 =item 'u'
3181
3182 Unknown file type
3183
3184 =item '?'
3185
3186 The L<readdir(3)> call returned a C<d_type> field with an
3187 unexpected value
3188
3189 =back
3190
3191 This function is primarily intended for use by programs.  To
3192 get a simple list of names, use C<guestfs_ls>.  To get a printable
3193 directory for human consumption, use C<guestfs_ll>.");
3194
3195   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3196    [],
3197    "create partitions on a block device",
3198    "\
3199 This is a simplified interface to the C<guestfs_sfdisk>
3200 command, where partition sizes are specified in megabytes
3201 only (rounded to the nearest cylinder) and you don't need
3202 to specify the cyls, heads and sectors parameters which
3203 were rarely if ever used anyway.
3204
3205 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3206 and C<guestfs_part_disk>");
3207
3208   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3209    [],
3210    "determine file type inside a compressed file",
3211    "\
3212 This command runs C<file> after first decompressing C<path>
3213 using C<method>.
3214
3215 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3216
3217 Since 1.0.63, use C<guestfs_file> instead which can now
3218 process compressed files.");
3219
3220   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3221    [],
3222    "list extended attributes of a file or directory",
3223    "\
3224 This call lists the extended attributes of the file or directory
3225 C<path>.
3226
3227 At the system call level, this is a combination of the
3228 L<listxattr(2)> and L<getxattr(2)> calls.
3229
3230 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3231
3232   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3233    [],
3234    "list extended attributes of a file or directory",
3235    "\
3236 This is the same as C<guestfs_getxattrs>, but if C<path>
3237 is a symbolic link, then it returns the extended attributes
3238 of the link itself.");
3239
3240   ("setxattr", (RErr, [String "xattr";
3241                        String "val"; Int "vallen"; (* will be BufferIn *)
3242                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3243    [],
3244    "set extended attribute of a file or directory",
3245    "\
3246 This call sets the extended attribute named C<xattr>
3247 of the file C<path> to the value C<val> (of length C<vallen>).
3248 The value is arbitrary 8 bit data.
3249
3250 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3251
3252   ("lsetxattr", (RErr, [String "xattr";
3253                         String "val"; Int "vallen"; (* will be BufferIn *)
3254                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3255    [],
3256    "set extended attribute of a file or directory",
3257    "\
3258 This is the same as C<guestfs_setxattr>, but if C<path>
3259 is a symbolic link, then it sets an extended attribute
3260 of the link itself.");
3261
3262   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3263    [],
3264    "remove extended attribute of a file or directory",
3265    "\
3266 This call removes the extended attribute named C<xattr>
3267 of the file C<path>.
3268
3269 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3270
3271   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3272    [],
3273    "remove extended attribute of a file or directory",
3274    "\
3275 This is the same as C<guestfs_removexattr>, but if C<path>
3276 is a symbolic link, then it removes an extended attribute
3277 of the link itself.");
3278
3279   ("mountpoints", (RHashtable "mps", []), 147, [],
3280    [],
3281    "show mountpoints",
3282    "\
3283 This call is similar to C<guestfs_mounts>.  That call returns
3284 a list of devices.  This one returns a hash table (map) of
3285 device name to directory where the device is mounted.");
3286
3287   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3288    (* This is a special case: while you would expect a parameter
3289     * of type "Pathname", that doesn't work, because it implies
3290     * NEED_ROOT in the generated calling code in stubs.c, and
3291     * this function cannot use NEED_ROOT.
3292     *)
3293    [],
3294    "create a mountpoint",
3295    "\
3296 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3297 specialized calls that can be used to create extra mountpoints
3298 before mounting the first filesystem.
3299
3300 These calls are I<only> necessary in some very limited circumstances,
3301 mainly the case where you want to mount a mix of unrelated and/or
3302 read-only filesystems together.
3303
3304 For example, live CDs often contain a \"Russian doll\" nest of
3305 filesystems, an ISO outer layer, with a squashfs image inside, with
3306 an ext2/3 image inside that.  You can unpack this as follows
3307 in guestfish:
3308
3309  add-ro Fedora-11-i686-Live.iso
3310  run
3311  mkmountpoint /cd
3312  mkmountpoint /squash
3313  mkmountpoint /ext3
3314  mount /dev/sda /cd
3315  mount-loop /cd/LiveOS/squashfs.img /squash
3316  mount-loop /squash/LiveOS/ext3fs.img /ext3
3317
3318 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3319
3320   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3321    [],
3322    "remove a mountpoint",
3323    "\
3324 This calls removes a mountpoint that was previously created
3325 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3326 for full details.");
3327
3328   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3329    [InitISOFS, Always, TestOutputBuffer (
3330       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3331     (* Test various near large, large and too large files (RHBZ#589039). *)
3332     InitBasicFS, Always, TestLastFail (
3333       [["touch"; "/a"];
3334        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3335        ["read_file"; "/a"]]);
3336     InitBasicFS, Always, TestLastFail (
3337       [["touch"; "/a"];
3338        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3339        ["read_file"; "/a"]]);
3340     InitBasicFS, Always, TestLastFail (
3341       [["touch"; "/a"];
3342        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3343        ["read_file"; "/a"]])],
3344    "read a file",
3345    "\
3346 This calls returns the contents of the file C<path> as a
3347 buffer.
3348
3349 Unlike C<guestfs_cat>, this function can correctly
3350 handle files that contain embedded ASCII NUL characters.
3351 However unlike C<guestfs_download>, this function is limited
3352 in the total size of file that can be handled.");
3353
3354   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3355    [InitISOFS, Always, TestOutputList (
3356       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3357     InitISOFS, Always, TestOutputList (
3358       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3359     (* Test for RHBZ#579608, absolute symbolic links. *)
3360     InitISOFS, Always, TestOutputList (
3361       [["grep"; "nomatch"; "/abssymlink"]], [])],
3362    "return lines matching a pattern",
3363    "\
3364 This calls the external C<grep> program and returns the
3365 matching lines.");
3366
3367   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3368    [InitISOFS, Always, TestOutputList (
3369       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3370    "return lines matching a pattern",
3371    "\
3372 This calls the external C<egrep> program and returns the
3373 matching lines.");
3374
3375   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3376    [InitISOFS, Always, TestOutputList (
3377       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3378    "return lines matching a pattern",
3379    "\
3380 This calls the external C<fgrep> program and returns the
3381 matching lines.");
3382
3383   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3384    [InitISOFS, Always, TestOutputList (
3385       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3386    "return lines matching a pattern",
3387    "\
3388 This calls the external C<grep -i> program and returns the
3389 matching lines.");
3390
3391   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3392    [InitISOFS, Always, TestOutputList (
3393       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3394    "return lines matching a pattern",
3395    "\
3396 This calls the external C<egrep -i> program and returns the
3397 matching lines.");
3398
3399   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3400    [InitISOFS, Always, TestOutputList (
3401       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3402    "return lines matching a pattern",
3403    "\
3404 This calls the external C<fgrep -i> program and returns the
3405 matching lines.");
3406
3407   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3408    [InitISOFS, Always, TestOutputList (
3409       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3410    "return lines matching a pattern",
3411    "\
3412 This calls the external C<zgrep> program and returns the
3413 matching lines.");
3414
3415   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3416    [InitISOFS, Always, TestOutputList (
3417       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3418    "return lines matching a pattern",
3419    "\
3420 This calls the external C<zegrep> program and returns the
3421 matching lines.");
3422
3423   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3424    [InitISOFS, Always, TestOutputList (
3425       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3426    "return lines matching a pattern",
3427    "\
3428 This calls the external C<zfgrep> program and returns the
3429 matching lines.");
3430
3431   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3432    [InitISOFS, Always, TestOutputList (
3433       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3434    "return lines matching a pattern",
3435    "\
3436 This calls the external C<zgrep -i> program and returns the
3437 matching lines.");
3438
3439   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3440    [InitISOFS, Always, TestOutputList (
3441       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3442    "return lines matching a pattern",
3443    "\
3444 This calls the external C<zegrep -i> program and returns the
3445 matching lines.");
3446
3447   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3448    [InitISOFS, Always, TestOutputList (
3449       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3450    "return lines matching a pattern",
3451    "\
3452 This calls the external C<zfgrep -i> program and returns the
3453 matching lines.");
3454
3455   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3456    [InitISOFS, Always, TestOutput (
3457       [["realpath"; "/../directory"]], "/directory")],
3458    "canonicalized absolute pathname",
3459    "\
3460 Return the canonicalized absolute pathname of C<path>.  The
3461 returned path has no C<.>, C<..> or symbolic link path elements.");
3462
3463   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3464    [InitBasicFS, Always, TestOutputStruct (
3465       [["touch"; "/a"];
3466        ["ln"; "/a"; "/b"];
3467        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3468    "create a hard link",
3469    "\
3470 This command creates a hard link using the C<ln> command.");
3471
3472   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3473    [InitBasicFS, Always, TestOutputStruct (
3474       [["touch"; "/a"];
3475        ["touch"; "/b"];
3476        ["ln_f"; "/a"; "/b"];
3477        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3478    "create a hard link",
3479    "\
3480 This command creates a hard link using the C<ln -f> command.
3481 The C<-f> option removes the link (C<linkname>) if it exists already.");
3482
3483   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3484    [InitBasicFS, Always, TestOutputStruct (
3485       [["touch"; "/a"];
3486        ["ln_s"; "a"; "/b"];
3487        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3488    "create a symbolic link",
3489    "\
3490 This command creates a symbolic link using the C<ln -s> command.");
3491
3492   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3493    [InitBasicFS, Always, TestOutput (
3494       [["mkdir_p"; "/a/b"];
3495        ["touch"; "/a/b/c"];
3496        ["ln_sf"; "../d"; "/a/b/c"];
3497        ["readlink"; "/a/b/c"]], "../d")],
3498    "create a symbolic link",
3499    "\
3500 This command creates a symbolic link using the C<ln -sf> command,
3501 The C<-f> option removes the link (C<linkname>) if it exists already.");
3502
3503   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3504    [] (* XXX tested above *),
3505    "read the target of a symbolic link",
3506    "\
3507 This command reads the target of a symbolic link.");
3508
3509   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3510    [InitBasicFS, Always, TestOutputStruct (
3511       [["fallocate"; "/a"; "1000000"];
3512        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3513    "preallocate a file in the guest filesystem",
3514    "\
3515 This command preallocates a file (containing zero bytes) named
3516 C<path> of size C<len> bytes.  If the file exists already, it
3517 is overwritten.
3518
3519 Do not confuse this with the guestfish-specific
3520 C<alloc> command which allocates a file in the host and
3521 attaches it as a device.");
3522
3523   ("swapon_device", (RErr, [Device "device"]), 170, [],
3524    [InitPartition, Always, TestRun (
3525       [["mkswap"; "/dev/sda1"];
3526        ["swapon_device"; "/dev/sda1"];
3527        ["swapoff_device"; "/dev/sda1"]])],
3528    "enable swap on device",
3529    "\
3530 This command enables the libguestfs appliance to use the
3531 swap device or partition named C<device>.  The increased
3532 memory is made available for all commands, for example
3533 those run using C<guestfs_command> or C<guestfs_sh>.
3534
3535 Note that you should not swap to existing guest swap
3536 partitions unless you know what you are doing.  They may
3537 contain hibernation information, or other information that
3538 the guest doesn't want you to trash.  You also risk leaking
3539 information about the host to the guest this way.  Instead,
3540 attach a new host device to the guest and swap on that.");
3541
3542   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3543    [], (* XXX tested by swapon_device *)
3544    "disable swap on device",
3545    "\
3546 This command disables the libguestfs appliance swap
3547 device or partition named C<device>.
3548 See C<guestfs_swapon_device>.");
3549
3550   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3551    [InitBasicFS, Always, TestRun (
3552       [["fallocate"; "/swap"; "8388608"];
3553        ["mkswap_file"; "/swap"];
3554        ["swapon_file"; "/swap"];
3555        ["swapoff_file"; "/swap"]])],
3556    "enable swap on file",
3557    "\
3558 This command enables swap to a file.
3559 See C<guestfs_swapon_device> for other notes.");
3560
3561   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3562    [], (* XXX tested by swapon_file *)
3563    "disable swap on file",
3564    "\
3565 This command disables the libguestfs appliance swap on file.");
3566
3567   ("swapon_label", (RErr, [String "label"]), 174, [],
3568    [InitEmpty, Always, TestRun (
3569       [["part_disk"; "/dev/sdb"; "mbr"];
3570        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3571        ["swapon_label"; "swapit"];
3572        ["swapoff_label"; "swapit"];
3573        ["zero"; "/dev/sdb"];
3574        ["blockdev_rereadpt"; "/dev/sdb"]])],
3575    "enable swap on labeled swap partition",
3576    "\
3577 This command enables swap to a labeled swap partition.
3578 See C<guestfs_swapon_device> for other notes.");
3579
3580   ("swapoff_label", (RErr, [String "label"]), 175, [],
3581    [], (* XXX tested by swapon_label *)
3582    "disable swap on labeled swap partition",
3583    "\
3584 This command disables the libguestfs appliance swap on
3585 labeled swap partition.");
3586
3587   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3588    (let uuid = uuidgen () in
3589     [InitEmpty, Always, TestRun (
3590        [["mkswap_U"; uuid; "/dev/sdb"];
3591         ["swapon_uuid"; uuid];
3592         ["swapoff_uuid"; uuid]])]),
3593    "enable swap on swap partition by UUID",
3594    "\
3595 This command enables swap to a swap partition with the given UUID.
3596 See C<guestfs_swapon_device> for other notes.");
3597
3598   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3599    [], (* XXX tested by swapon_uuid *)
3600    "disable swap on swap partition by UUID",
3601    "\
3602 This command disables the libguestfs appliance swap partition
3603 with the given UUID.");
3604
3605   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3606    [InitBasicFS, Always, TestRun (
3607       [["fallocate"; "/swap"; "8388608"];
3608        ["mkswap_file"; "/swap"]])],
3609    "create a swap file",
3610    "\
3611 Create a swap file.
3612
3613 This command just writes a swap file signature to an existing
3614 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3615
3616   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3617    [InitISOFS, Always, TestRun (
3618       [["inotify_init"; "0"]])],
3619    "create an inotify handle",
3620    "\
3621 This command creates a new inotify handle.
3622 The inotify subsystem can be used to notify events which happen to
3623 objects in the guest filesystem.
3624
3625 C<maxevents> is the maximum number of events which will be
3626 queued up between calls to C<guestfs_inotify_read> or
3627 C<guestfs_inotify_files>.
3628 If this is passed as C<0>, then the kernel (or previously set)
3629 default is used.  For Linux 2.6.29 the default was 16384 events.
3630 Beyond this limit, the kernel throws away events, but records
3631 the fact that it threw them away by setting a flag
3632 C<IN_Q_OVERFLOW> in the returned structure list (see
3633 C<guestfs_inotify_read>).
3634
3635 Before any events are generated, you have to add some
3636 watches to the internal watch list.  See:
3637 C<guestfs_inotify_add_watch>,
3638 C<guestfs_inotify_rm_watch> and
3639 C<guestfs_inotify_watch_all>.
3640
3641 Queued up events should be read periodically by calling
3642 C<guestfs_inotify_read>
3643 (or C<guestfs_inotify_files> which is just a helpful
3644 wrapper around C<guestfs_inotify_read>).  If you don't
3645 read the events out often enough then you risk the internal
3646 queue overflowing.
3647
3648 The handle should be closed after use by calling
3649 C<guestfs_inotify_close>.  This also removes any
3650 watches automatically.
3651
3652 See also L<inotify(7)> for an overview of the inotify interface
3653 as exposed by the Linux kernel, which is roughly what we expose
3654 via libguestfs.  Note that there is one global inotify handle
3655 per libguestfs instance.");
3656
3657   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3658    [InitBasicFS, Always, TestOutputList (
3659       [["inotify_init"; "0"];
3660        ["inotify_add_watch"; "/"; "1073741823"];
3661        ["touch"; "/a"];
3662        ["touch"; "/b"];
3663        ["inotify_files"]], ["a"; "b"])],
3664    "add an inotify watch",
3665    "\
3666 Watch C<path> for the events listed in C<mask>.
3667
3668 Note that if C<path> is a directory then events within that
3669 directory are watched, but this does I<not> happen recursively
3670 (in subdirectories).
3671
3672 Note for non-C or non-Linux callers: the inotify events are
3673 defined by the Linux kernel ABI and are listed in
3674 C</usr/include/sys/inotify.h>.");
3675
3676   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3677    [],
3678    "remove an inotify watch",
3679    "\
3680 Remove a previously defined inotify watch.
3681 See C<guestfs_inotify_add_watch>.");
3682
3683   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3684    [],
3685    "return list of inotify events",
3686    "\
3687 Return the complete queue of events that have happened
3688 since the previous read call.
3689
3690 If no events have happened, this returns an empty list.
3691
3692 I<Note>: In order to make sure that all events have been
3693 read, you must call this function repeatedly until it
3694 returns an empty list.  The reason is that the call will
3695 read events up to the maximum appliance-to-host message
3696 size and leave remaining events in the queue.");
3697
3698   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3699    [],
3700    "return list of watched files that had events",
3701    "\
3702 This function is a helpful wrapper around C<guestfs_inotify_read>
3703 which just returns a list of pathnames of objects that were
3704 touched.  The returned pathnames are sorted and deduplicated.");
3705
3706   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3707    [],
3708    "close the inotify handle",
3709    "\
3710 This closes the inotify handle which was previously
3711 opened by inotify_init.  It removes all watches, throws
3712 away any pending events, and deallocates all resources.");
3713
3714   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3715    [],
3716    "set SELinux security context",
3717    "\
3718 This sets the SELinux security context of the daemon
3719 to the string C<context>.
3720
3721 See the documentation about SELINUX in L<guestfs(3)>.");
3722
3723   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3724    [],
3725    "get SELinux security context",
3726    "\
3727 This gets the SELinux security context of the daemon.
3728
3729 See the documentation about SELINUX in L<guestfs(3)>,
3730 and C<guestfs_setcon>");
3731
3732   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3733    [InitEmpty, Always, TestOutput (
3734       [["part_disk"; "/dev/sda"; "mbr"];
3735        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3736        ["mount_options"; ""; "/dev/sda1"; "/"];
3737        ["write"; "/new"; "new file contents"];
3738        ["cat"; "/new"]], "new file contents");
3739     InitEmpty, Always, TestRun (
3740       [["part_disk"; "/dev/sda"; "mbr"];
3741        ["mkfs_b"; "vfat"; "32768"; "/dev/sda1"]]);
3742     InitEmpty, Always, TestLastFail (
3743       [["part_disk"; "/dev/sda"; "mbr"];
3744        ["mkfs_b"; "vfat"; "32769"; "/dev/sda1"]]);
3745     InitEmpty, Always, TestLastFail (
3746       [["part_disk"; "/dev/sda"; "mbr"];
3747        ["mkfs_b"; "vfat"; "33280"; "/dev/sda1"]]);
3748     InitEmpty, IfAvailable "ntfsprogs", TestRun (
3749       [["part_disk"; "/dev/sda"; "mbr"];
3750        ["mkfs_b"; "ntfs"; "32768"; "/dev/sda1"]])],
3751    "make a filesystem with block size",
3752    "\
3753 This call is similar to C<guestfs_mkfs>, but it allows you to
3754 control the block size of the resulting filesystem.  Supported
3755 block sizes depend on the filesystem type, but typically they
3756 are C<1024>, C<2048> or C<4096> only.
3757
3758 For VFAT and NTFS the C<blocksize> parameter is treated as
3759 the requested cluster size.");
3760
3761   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3762    [InitEmpty, Always, TestOutput (
3763       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3764        ["mke2journal"; "4096"; "/dev/sda1"];
3765        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3766        ["mount_options"; ""; "/dev/sda2"; "/"];
3767        ["write"; "/new"; "new file contents"];
3768        ["cat"; "/new"]], "new file contents")],
3769    "make ext2/3/4 external journal",
3770    "\
3771 This creates an ext2 external journal on C<device>.  It is equivalent
3772 to the command:
3773
3774  mke2fs -O journal_dev -b blocksize device");
3775
3776   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3777    [InitEmpty, Always, TestOutput (
3778       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3779        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3780        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3781        ["mount_options"; ""; "/dev/sda2"; "/"];
3782        ["write"; "/new"; "new file contents"];
3783        ["cat"; "/new"]], "new file contents")],
3784    "make ext2/3/4 external journal with label",
3785    "\
3786 This creates an ext2 external journal on C<device> with label C<label>.");
3787
3788   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3789    (let uuid = uuidgen () in
3790     [InitEmpty, Always, TestOutput (
3791        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3792         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3793         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3794         ["mount_options"; ""; "/dev/sda2"; "/"];
3795         ["write"; "/new"; "new file contents"];
3796         ["cat"; "/new"]], "new file contents")]),
3797    "make ext2/3/4 external journal with UUID",
3798    "\
3799 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3800
3801   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3802    [],
3803    "make ext2/3/4 filesystem with external journal",
3804    "\
3805 This creates an ext2/3/4 filesystem on C<device> with
3806 an external journal on C<journal>.  It is equivalent
3807 to the command:
3808
3809  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3810
3811 See also C<guestfs_mke2journal>.");
3812
3813   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3814    [],
3815    "make ext2/3/4 filesystem with external journal",
3816    "\
3817 This creates an ext2/3/4 filesystem on C<device> with
3818 an external journal on the journal labeled C<label>.
3819
3820 See also C<guestfs_mke2journal_L>.");
3821
3822   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3823    [],
3824    "make ext2/3/4 filesystem with external journal",
3825    "\
3826 This creates an ext2/3/4 filesystem on C<device> with
3827 an external journal on the journal with UUID C<uuid>.
3828
3829 See also C<guestfs_mke2journal_U>.");
3830
3831   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3832    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3833    "load a kernel module",
3834    "\
3835 This loads a kernel module in the appliance.
3836
3837 The kernel module must have been whitelisted when libguestfs
3838 was built (see C<appliance/kmod.whitelist.in> in the source).");
3839
3840   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3841    [InitNone, Always, TestOutput (
3842       [["echo_daemon"; "This is a test"]], "This is a test"
3843     )],
3844    "echo arguments back to the client",
3845    "\
3846 This command concatenates the list of C<words> passed with single spaces
3847 between them and returns the resulting string.
3848
3849 You can use this command to test the connection through to the daemon.
3850
3851 See also C<guestfs_ping_daemon>.");
3852
3853   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3854    [], (* There is a regression test for this. *)
3855    "find all files and directories, returning NUL-separated list",
3856    "\
3857 This command lists out all files and directories, recursively,
3858 starting at C<directory>, placing the resulting list in the
3859 external file called C<files>.
3860
3861 This command works the same way as C<guestfs_find> with the
3862 following exceptions:
3863
3864 =over 4
3865
3866 =item *
3867
3868 The resulting list is written to an external file.
3869
3870 =item *
3871
3872 Items (filenames) in the result are separated
3873 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3874
3875 =item *
3876
3877 This command is not limited in the number of names that it
3878 can return.
3879
3880 =item *
3881
3882 The result list is not sorted.
3883
3884 =back");
3885
3886   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3887    [InitISOFS, Always, TestOutput (
3888       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3889     InitISOFS, Always, TestOutput (
3890       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3891     InitISOFS, Always, TestOutput (
3892       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3893     InitISOFS, Always, TestLastFail (
3894       [["case_sensitive_path"; "/Known-1/"]]);
3895     InitBasicFS, Always, TestOutput (
3896       [["mkdir"; "/a"];
3897        ["mkdir"; "/a/bbb"];
3898        ["touch"; "/a/bbb/c"];
3899        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3900     InitBasicFS, Always, TestOutput (
3901       [["mkdir"; "/a"];
3902        ["mkdir"; "/a/bbb"];
3903        ["touch"; "/a/bbb/c"];
3904        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3905     InitBasicFS, Always, TestLastFail (
3906       [["mkdir"; "/a"];
3907        ["mkdir"; "/a/bbb"];
3908        ["touch"; "/a/bbb/c"];
3909        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3910    "return true path on case-insensitive filesystem",
3911    "\
3912 This can be used to resolve case insensitive paths on
3913 a filesystem which is case sensitive.  The use case is
3914 to resolve paths which you have read from Windows configuration
3915 files or the Windows Registry, to the true path.
3916
3917 The command handles a peculiarity of the Linux ntfs-3g
3918 filesystem driver (and probably others), which is that although
3919 the underlying filesystem is case-insensitive, the driver
3920 exports the filesystem to Linux as case-sensitive.
3921
3922 One consequence of this is that special directories such
3923 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3924 (or other things) depending on the precise details of how
3925 they were created.  In Windows itself this would not be
3926 a problem.
3927
3928 Bug or feature?  You decide:
3929 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3930
3931 This function resolves the true case of each element in the
3932 path and returns the case-sensitive path.
3933
3934 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3935 might return C<\"/WINDOWS/system32\"> (the exact return value
3936 would depend on details of how the directories were originally
3937 created under Windows).
3938
3939 I<Note>:
3940 This function does not handle drive names, backslashes etc.
3941
3942 See also C<guestfs_realpath>.");
3943
3944   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3945    [InitBasicFS, Always, TestOutput (
3946       [["vfs_type"; "/dev/sda1"]], "ext2")],
3947    "get the Linux VFS type corresponding to a mounted device",
3948    "\
3949 This command gets the filesystem type corresponding to
3950 the filesystem on C<device>.
3951
3952 For most filesystems, the result is the name of the Linux
3953 VFS module which would be used to mount this filesystem
3954 if you mounted it without specifying the filesystem type.
3955 For example a string such as C<ext3> or C<ntfs>.");
3956
3957   ("truncate", (RErr, [Pathname "path"]), 199, [],
3958    [InitBasicFS, Always, TestOutputStruct (
3959       [["write"; "/test"; "some stuff so size is not zero"];
3960        ["truncate"; "/test"];
3961        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3962    "truncate a file to zero size",
3963    "\
3964 This command truncates C<path> to a zero-length file.  The
3965 file must exist already.");
3966
3967   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3968    [InitBasicFS, Always, TestOutputStruct (
3969       [["touch"; "/test"];
3970        ["truncate_size"; "/test"; "1000"];
3971        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3972    "truncate a file to a particular size",
3973    "\
3974 This command truncates C<path> to size C<size> bytes.  The file
3975 must exist already.
3976
3977 If the current file size is less than C<size> then
3978 the file is extended to the required size with zero bytes.
3979 This creates a sparse file (ie. disk blocks are not allocated
3980 for the file until you write to it).  To create a non-sparse
3981 file of zeroes, use C<guestfs_fallocate64> instead.");
3982
3983   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3984    [InitBasicFS, Always, TestOutputStruct (
3985       [["touch"; "/test"];
3986        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3987        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3988    "set timestamp of a file with nanosecond precision",
3989    "\
3990 This command sets the timestamps of a file with nanosecond
3991 precision.
3992
3993 C<atsecs, atnsecs> are the last access time (atime) in secs and
3994 nanoseconds from the epoch.
3995
3996 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3997 secs and nanoseconds from the epoch.
3998
3999 If the C<*nsecs> field contains the special value C<-1> then
4000 the corresponding timestamp is set to the current time.  (The
4001 C<*secs> field is ignored in this case).
4002
4003 If the C<*nsecs> field contains the special value C<-2> then
4004 the corresponding timestamp is left unchanged.  (The
4005 C<*secs> field is ignored in this case).");
4006
4007   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
4008    [InitBasicFS, Always, TestOutputStruct (
4009       [["mkdir_mode"; "/test"; "0o111"];
4010        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
4011    "create a directory with a particular mode",
4012    "\
4013 This command creates a directory, setting the initial permissions
4014 of the directory to C<mode>.
4015
4016 For common Linux filesystems, the actual mode which is set will
4017 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
4018 interpret the mode in other ways.
4019
4020 See also C<guestfs_mkdir>, C<guestfs_umask>");
4021
4022   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
4023    [], (* XXX *)
4024    "change file owner and group",
4025    "\
4026 Change the file owner to C<owner> and group to C<group>.
4027 This is like C<guestfs_chown> but if C<path> is a symlink then
4028 the link itself is changed, not the target.
4029
4030 Only numeric uid and gid are supported.  If you want to use
4031 names, you will need to locate and parse the password file
4032 yourself (Augeas support makes this relatively easy).");
4033
4034   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4035    [], (* XXX *)
4036    "lstat on multiple files",
4037    "\
4038 This call allows you to perform the C<guestfs_lstat> operation
4039 on multiple files, where all files are in the directory C<path>.
4040 C<names> is the list of files from this directory.
4041
4042 On return you get a list of stat structs, with a one-to-one
4043 correspondence to the C<names> list.  If any name did not exist
4044 or could not be lstat'd, then the C<ino> field of that structure
4045 is set to C<-1>.
4046
4047 This call is intended for programs that want to efficiently
4048 list a directory contents without making many round-trips.
4049 See also C<guestfs_lxattrlist> for a similarly efficient call
4050 for getting extended attributes.  Very long directory listings
4051 might cause the protocol message size to be exceeded, causing
4052 this call to fail.  The caller must split up such requests
4053 into smaller groups of names.");
4054
4055   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4056    [], (* XXX *)
4057    "lgetxattr on multiple files",
4058    "\
4059 This call allows you to get the extended attributes
4060 of multiple files, where all files are in the directory C<path>.
4061 C<names> is the list of files from this directory.
4062
4063 On return you get a flat list of xattr structs which must be
4064 interpreted sequentially.  The first xattr struct always has a zero-length
4065 C<attrname>.  C<attrval> in this struct is zero-length
4066 to indicate there was an error doing C<lgetxattr> for this
4067 file, I<or> is a C string which is a decimal number
4068 (the number of following attributes for this file, which could
4069 be C<\"0\">).  Then after the first xattr struct are the
4070 zero or more attributes for the first named file.
4071 This repeats for the second and subsequent files.
4072
4073 This call is intended for programs that want to efficiently
4074 list a directory contents without making many round-trips.
4075 See also C<guestfs_lstatlist> for a similarly efficient call
4076 for getting standard stats.  Very long directory listings
4077 might cause the protocol message size to be exceeded, causing
4078 this call to fail.  The caller must split up such requests
4079 into smaller groups of names.");
4080
4081   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4082    [], (* XXX *)
4083    "readlink on multiple files",
4084    "\
4085 This call allows you to do a C<readlink> operation
4086 on multiple files, where all files are in the directory C<path>.
4087 C<names> is the list of files from this directory.
4088
4089 On return you get a list of strings, with a one-to-one
4090 correspondence to the C<names> list.  Each string is the
4091 value of the symbolic link.
4092
4093 If the C<readlink(2)> operation fails on any name, then
4094 the corresponding result string is the empty string C<\"\">.
4095 However the whole operation is completed even if there
4096 were C<readlink(2)> errors, and so you can call this
4097 function with names where you don't know if they are
4098 symbolic links already (albeit slightly less efficient).
4099
4100 This call is intended for programs that want to efficiently
4101 list a directory contents without making many round-trips.
4102 Very long directory listings might cause the protocol
4103 message size to be exceeded, causing
4104 this call to fail.  The caller must split up such requests
4105 into smaller groups of names.");
4106
4107   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4108    [InitISOFS, Always, TestOutputBuffer (
4109       [["pread"; "/known-4"; "1"; "3"]], "\n");
4110     InitISOFS, Always, TestOutputBuffer (
4111       [["pread"; "/empty"; "0"; "100"]], "")],
4112    "read part of a file",
4113    "\
4114 This command lets you read part of a file.  It reads C<count>
4115 bytes of the file, starting at C<offset>, from file C<path>.
4116
4117 This may read fewer bytes than requested.  For further details
4118 see the L<pread(2)> system call.
4119
4120 See also C<guestfs_pwrite>.");
4121
4122   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4123    [InitEmpty, Always, TestRun (
4124       [["part_init"; "/dev/sda"; "gpt"]])],
4125    "create an empty partition table",
4126    "\
4127 This creates an empty partition table on C<device> of one of the
4128 partition types listed below.  Usually C<parttype> should be
4129 either C<msdos> or C<gpt> (for large disks).
4130
4131 Initially there are no partitions.  Following this, you should
4132 call C<guestfs_part_add> for each partition required.
4133
4134 Possible values for C<parttype> are:
4135
4136 =over 4
4137
4138 =item B<efi> | B<gpt>
4139
4140 Intel EFI / GPT partition table.
4141
4142 This is recommended for >= 2 TB partitions that will be accessed
4143 from Linux and Intel-based Mac OS X.  It also has limited backwards
4144 compatibility with the C<mbr> format.
4145
4146 =item B<mbr> | B<msdos>
4147
4148 The standard PC \"Master Boot Record\" (MBR) format used
4149 by MS-DOS and Windows.  This partition type will B<only> work
4150 for device sizes up to 2 TB.  For large disks we recommend
4151 using C<gpt>.
4152
4153 =back
4154
4155 Other partition table types that may work but are not
4156 supported include:
4157
4158 =over 4
4159
4160 =item B<aix>
4161
4162 AIX disk labels.
4163
4164 =item B<amiga> | B<rdb>
4165
4166 Amiga \"Rigid Disk Block\" format.
4167
4168 =item B<bsd>
4169
4170 BSD disk labels.
4171
4172 =item B<dasd>
4173
4174 DASD, used on IBM mainframes.
4175
4176 =item B<dvh>
4177
4178 MIPS/SGI volumes.
4179
4180 =item B<mac>
4181
4182 Old Mac partition format.  Modern Macs use C<gpt>.
4183
4184 =item B<pc98>
4185
4186 NEC PC-98 format, common in Japan apparently.
4187
4188 =item B<sun>
4189
4190 Sun disk labels.
4191
4192 =back");
4193
4194   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4195    [InitEmpty, Always, TestRun (
4196       [["part_init"; "/dev/sda"; "mbr"];
4197        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4198     InitEmpty, Always, TestRun (
4199       [["part_init"; "/dev/sda"; "gpt"];
4200        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4201        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4202     InitEmpty, Always, TestRun (
4203       [["part_init"; "/dev/sda"; "mbr"];
4204        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4205        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4206        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4207        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4208    "add a partition to the device",
4209    "\
4210 This command adds a partition to C<device>.  If there is no partition
4211 table on the device, call C<guestfs_part_init> first.
4212
4213 The C<prlogex> parameter is the type of partition.  Normally you
4214 should pass C<p> or C<primary> here, but MBR partition tables also
4215 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4216 types.
4217
4218 C<startsect> and C<endsect> are the start and end of the partition
4219 in I<sectors>.  C<endsect> may be negative, which means it counts
4220 backwards from the end of the disk (C<-1> is the last sector).
4221
4222 Creating a partition which covers the whole disk is not so easy.
4223 Use C<guestfs_part_disk> to do that.");
4224
4225   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4226    [InitEmpty, Always, TestRun (
4227       [["part_disk"; "/dev/sda"; "mbr"]]);
4228     InitEmpty, Always, TestRun (
4229       [["part_disk"; "/dev/sda"; "gpt"]])],
4230    "partition whole disk with a single primary partition",
4231    "\
4232 This command is simply a combination of C<guestfs_part_init>
4233 followed by C<guestfs_part_add> to create a single primary partition
4234 covering the whole disk.
4235
4236 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4237 but other possible values are described in C<guestfs_part_init>.");
4238
4239   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4240    [InitEmpty, Always, TestRun (
4241       [["part_disk"; "/dev/sda"; "mbr"];
4242        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4243    "make a partition bootable",
4244    "\
4245 This sets the bootable flag on partition numbered C<partnum> on
4246 device C<device>.  Note that partitions are numbered from 1.
4247
4248 The bootable flag is used by some operating systems (notably
4249 Windows) to determine which partition to boot from.  It is by
4250 no means universally recognized.");
4251
4252   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4253    [InitEmpty, Always, TestRun (
4254       [["part_disk"; "/dev/sda"; "gpt"];
4255        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4256    "set partition name",
4257    "\
4258 This sets the partition name on partition numbered C<partnum> on
4259 device C<device>.  Note that partitions are numbered from 1.
4260
4261 The partition name can only be set on certain types of partition
4262 table.  This works on C<gpt> but not on C<mbr> partitions.");
4263
4264   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4265    [], (* XXX Add a regression test for this. *)
4266    "list partitions on a device",
4267    "\
4268 This command parses the partition table on C<device> and
4269 returns the list of partitions found.
4270
4271 The fields in the returned structure are:
4272
4273 =over 4
4274
4275 =item B<part_num>
4276
4277 Partition number, counting from 1.
4278
4279 =item B<part_start>
4280
4281 Start of the partition I<in bytes>.  To get sectors you have to
4282 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4283
4284 =item B<part_end>
4285
4286 End of the partition in bytes.
4287
4288 =item B<part_size>
4289
4290 Size of the partition in bytes.
4291
4292 =back");
4293
4294   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4295    [InitEmpty, Always, TestOutput (
4296       [["part_disk"; "/dev/sda"; "gpt"];
4297        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4298    "get the partition table type",
4299    "\
4300 This command examines the partition table on C<device> and
4301 returns the partition table type (format) being used.
4302
4303 Common return values include: C<msdos> (a DOS/Windows style MBR
4304 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4305 values are possible, although unusual.  See C<guestfs_part_init>
4306 for a full list.");
4307
4308   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4309    [InitBasicFS, Always, TestOutputBuffer (
4310       [["fill"; "0x63"; "10"; "/test"];
4311        ["read_file"; "/test"]], "cccccccccc")],
4312    "fill a file with octets",
4313    "\
4314 This command creates a new file called C<path>.  The initial
4315 content of the file is C<len> octets of C<c>, where C<c>
4316 must be a number in the range C<[0..255]>.
4317
4318 To fill a file with zero bytes (sparsely), it is
4319 much more efficient to use C<guestfs_truncate_size>.
4320 To create a file with a pattern of repeating bytes
4321 use C<guestfs_fill_pattern>.");
4322
4323   ("available", (RErr, [StringList "groups"]), 216, [],
4324    [InitNone, Always, TestRun [["available"; ""]]],
4325    "test availability of some parts of the API",
4326    "\
4327 This command is used to check the availability of some
4328 groups of functionality in the appliance, which not all builds of
4329 the libguestfs appliance will be able to provide.
4330
4331 The libguestfs groups, and the functions that those
4332 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4333 You can also fetch this list at runtime by calling
4334 C<guestfs_available_all_groups>.
4335
4336 The argument C<groups> is a list of group names, eg:
4337 C<[\"inotify\", \"augeas\"]> would check for the availability of
4338 the Linux inotify functions and Augeas (configuration file
4339 editing) functions.
4340
4341 The command returns no error if I<all> requested groups are available.
4342
4343 It fails with an error if one or more of the requested
4344 groups is unavailable in the appliance.
4345
4346 If an unknown group name is included in the
4347 list of groups then an error is always returned.
4348
4349 I<Notes:>
4350
4351 =over 4
4352
4353 =item *
4354
4355 You must call C<guestfs_launch> before calling this function.
4356
4357 The reason is because we don't know what groups are
4358 supported by the appliance/daemon until it is running and can
4359 be queried.
4360
4361 =item *
4362
4363 If a group of functions is available, this does not necessarily
4364 mean that they will work.  You still have to check for errors
4365 when calling individual API functions even if they are
4366 available.
4367
4368 =item *
4369
4370 It is usually the job of distro packagers to build
4371 complete functionality into the libguestfs appliance.
4372 Upstream libguestfs, if built from source with all
4373 requirements satisfied, will support everything.
4374
4375 =item *
4376
4377 This call was added in version C<1.0.80>.  In previous
4378 versions of libguestfs all you could do would be to speculatively
4379 execute a command to find out if the daemon implemented it.
4380 See also C<guestfs_version>.
4381
4382 =back");
4383
4384   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4385    [InitBasicFS, Always, TestOutputBuffer (
4386       [["write"; "/src"; "hello, world"];
4387        ["dd"; "/src"; "/dest"];
4388        ["read_file"; "/dest"]], "hello, world")],
4389    "copy from source to destination using dd",
4390    "\
4391 This command copies from one source device or file C<src>
4392 to another destination device or file C<dest>.  Normally you
4393 would use this to copy to or from a device or partition, for
4394 example to duplicate a filesystem.
4395
4396 If the destination is a device, it must be as large or larger
4397 than the source file or device, otherwise the copy will fail.
4398 This command cannot do partial copies (see C<guestfs_copy_size>).");
4399
4400   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4401    [InitBasicFS, Always, TestOutputInt (
4402       [["write"; "/file"; "hello, world"];
4403        ["filesize"; "/file"]], 12)],
4404    "return the size of the file in bytes",
4405    "\
4406 This command returns the size of C<file> in bytes.
4407
4408 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4409 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4410 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4411
4412   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4413    [InitBasicFSonLVM, Always, TestOutputList (
4414       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4415        ["lvs"]], ["/dev/VG/LV2"])],
4416    "rename an LVM logical volume",
4417    "\
4418 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4419
4420   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4421    [InitBasicFSonLVM, Always, TestOutputList (
4422       [["umount"; "/"];
4423        ["vg_activate"; "false"; "VG"];
4424        ["vgrename"; "VG"; "VG2"];
4425        ["vg_activate"; "true"; "VG2"];
4426        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4427        ["vgs"]], ["VG2"])],
4428    "rename an LVM volume group",
4429    "\
4430 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4431
4432   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4433    [InitISOFS, Always, TestOutputBuffer (
4434       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4435    "list the contents of a single file in an initrd",
4436    "\
4437 This command unpacks the file C<filename> from the initrd file
4438 called C<initrdpath>.  The filename must be given I<without> the
4439 initial C</> character.
4440
4441 For example, in guestfish you could use the following command
4442 to examine the boot script (usually called C</init>)
4443 contained in a Linux initrd or initramfs image:
4444
4445  initrd-cat /boot/initrd-<version>.img init
4446
4447 See also C<guestfs_initrd_list>.");
4448
4449   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4450    [],
4451    "get the UUID of a physical volume",
4452    "\
4453 This command returns the UUID of the LVM PV C<device>.");
4454
4455   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4456    [],
4457    "get the UUID of a volume group",
4458    "\
4459 This command returns the UUID of the LVM VG named C<vgname>.");
4460
4461   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4462    [],
4463    "get the UUID of a logical volume",
4464    "\
4465 This command returns the UUID of the LVM LV C<device>.");
4466
4467   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4468    [],
4469    "get the PV UUIDs containing the volume group",
4470    "\
4471 Given a VG called C<vgname>, this returns the UUIDs of all
4472 the physical volumes that this volume group resides on.
4473
4474 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4475 calls to associate physical volumes and volume groups.
4476
4477 See also C<guestfs_vglvuuids>.");
4478
4479   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4480    [],
4481    "get the LV UUIDs of all LVs in the volume group",
4482    "\
4483 Given a VG called C<vgname>, this returns the UUIDs of all
4484 the logical volumes created in this volume group.
4485
4486 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4487 calls to associate logical volumes and volume groups.
4488
4489 See also C<guestfs_vgpvuuids>.");
4490
4491   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4492    [InitBasicFS, Always, TestOutputBuffer (
4493       [["write"; "/src"; "hello, world"];
4494        ["copy_size"; "/src"; "/dest"; "5"];
4495        ["read_file"; "/dest"]], "hello")],
4496    "copy size bytes from source to destination using dd",
4497    "\
4498 This command copies exactly C<size> bytes from one source device
4499 or file C<src> to another destination device or file C<dest>.
4500
4501 Note this will fail if the source is too short or if the destination
4502 is not large enough.");
4503
4504   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4505    [InitBasicFSonLVM, Always, TestRun (
4506       [["zero_device"; "/dev/VG/LV"]])],
4507    "write zeroes to an entire device",
4508    "\
4509 This command writes zeroes over the entire C<device>.  Compare
4510 with C<guestfs_zero> which just zeroes the first few blocks of
4511 a device.");
4512
4513   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4514    [InitBasicFS, Always, TestOutput (
4515       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4516        ["cat"; "/hello"]], "hello\n")],
4517    "unpack compressed tarball to directory",
4518    "\
4519 This command uploads and unpacks local file C<tarball> (an
4520 I<xz compressed> tar file) into C<directory>.");
4521
4522   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4523    [],
4524    "pack directory into compressed tarball",
4525    "\
4526 This command packs the contents of C<directory> and downloads
4527 it to local file C<tarball> (as an xz compressed tar archive).");
4528
4529   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4530    [],
4531    "resize an NTFS filesystem",
4532    "\
4533 This command resizes an NTFS filesystem, expanding or
4534 shrinking it to the size of the underlying device.
4535 See also L<ntfsresize(8)>.");
4536
4537   ("vgscan", (RErr, []), 232, [],
4538    [InitEmpty, Always, TestRun (
4539       [["vgscan"]])],
4540    "rescan for LVM physical volumes, volume groups and logical volumes",
4541    "\
4542 This rescans all block devices and rebuilds the list of LVM
4543 physical volumes, volume groups and logical volumes.");
4544
4545   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4546    [InitEmpty, Always, TestRun (
4547       [["part_init"; "/dev/sda"; "mbr"];
4548        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4549        ["part_del"; "/dev/sda"; "1"]])],
4550    "delete a partition",
4551    "\
4552 This command deletes the partition numbered C<partnum> on C<device>.
4553
4554 Note that in the case of MBR partitioning, deleting an
4555 extended partition also deletes any logical partitions
4556 it contains.");
4557
4558   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4559    [InitEmpty, Always, TestOutputTrue (
4560       [["part_init"; "/dev/sda"; "mbr"];
4561        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4562        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4563        ["part_get_bootable"; "/dev/sda"; "1"]])],
4564    "return true if a partition is bootable",
4565    "\
4566 This command returns true if the partition C<partnum> on
4567 C<device> has the bootable flag set.
4568
4569 See also C<guestfs_part_set_bootable>.");
4570
4571   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4572    [InitEmpty, Always, TestOutputInt (
4573       [["part_init"; "/dev/sda"; "mbr"];
4574        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4575        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4576        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4577    "get the MBR type byte (ID byte) from a partition",
4578    "\
4579 Returns the MBR type byte (also known as the ID byte) from
4580 the numbered partition C<partnum>.
4581
4582 Note that only MBR (old DOS-style) partitions have type bytes.
4583 You will get undefined results for other partition table
4584 types (see C<guestfs_part_get_parttype>).");
4585
4586   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4587    [], (* tested by part_get_mbr_id *)
4588    "set the MBR type byte (ID byte) of a partition",
4589    "\
4590 Sets the MBR type byte (also known as the ID byte) of
4591 the numbered partition C<partnum> to C<idbyte>.  Note
4592 that the type bytes quoted in most documentation are
4593 in fact hexadecimal numbers, but usually documented
4594 without any leading \"0x\" which might be confusing.
4595
4596 Note that only MBR (old DOS-style) partitions have type bytes.
4597 You will get undefined results for other partition table
4598 types (see C<guestfs_part_get_parttype>).");
4599
4600   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4601    [InitISOFS, Always, TestOutput (
4602       [["checksum_device"; "md5"; "/dev/sdd"]],
4603       (Digest.to_hex (Digest.file "images/test.iso")))],
4604    "compute MD5, SHAx or CRC checksum of the contents of a device",
4605    "\
4606 This call computes the MD5, SHAx or CRC checksum of the
4607 contents of the device named C<device>.  For the types of
4608 checksums supported see the C<guestfs_checksum> command.");
4609
4610   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4611    [InitNone, Always, TestRun (
4612       [["part_disk"; "/dev/sda"; "mbr"];
4613        ["pvcreate"; "/dev/sda1"];
4614        ["vgcreate"; "VG"; "/dev/sda1"];
4615        ["lvcreate"; "LV"; "VG"; "10"];
4616        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4617    "expand an LV to fill free space",
4618    "\
4619 This expands an existing logical volume C<lv> so that it fills
4620 C<pc>% of the remaining free space in the volume group.  Commonly
4621 you would call this with pc = 100 which expands the logical volume
4622 as much as possible, using all remaining free space in the volume
4623 group.");
4624
4625   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4626    [], (* XXX Augeas code needs tests. *)
4627    "clear Augeas path",
4628    "\
4629 Set the value associated with C<path> to C<NULL>.  This
4630 is the same as the L<augtool(1)> C<clear> command.");
4631
4632   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4633    [InitEmpty, Always, TestOutputInt (
4634       [["get_umask"]], 0o22)],
4635    "get the current umask",
4636    "\
4637 Return the current umask.  By default the umask is C<022>
4638 unless it has been set by calling C<guestfs_umask>.");
4639
4640   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4641    [],
4642    "upload a file to the appliance (internal use only)",
4643    "\
4644 The C<guestfs_debug_upload> command uploads a file to
4645 the libguestfs appliance.
4646
4647 There is no comprehensive help for this command.  You have
4648 to look at the file C<daemon/debug.c> in the libguestfs source
4649 to find out what it is for.");
4650
4651   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4652    [InitBasicFS, Always, TestOutput (
4653       [["base64_in"; "../images/hello.b64"; "/hello"];
4654        ["cat"; "/hello"]], "hello\n")],
4655    "upload base64-encoded data to file",
4656    "\
4657 This command uploads base64-encoded data from C<base64file>
4658 to C<filename>.");
4659
4660   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4661    [],
4662    "download file and encode as base64",
4663    "\
4664 This command downloads the contents of C<filename>, writing
4665 it out to local file C<base64file> encoded as base64.");
4666
4667   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4668    [],
4669    "compute MD5, SHAx or CRC checksum of files in a directory",
4670    "\
4671 This command computes the checksums of all regular files in
4672 C<directory> and then emits a list of those checksums to
4673 the local output file C<sumsfile>.
4674
4675 This can be used for verifying the integrity of a virtual
4676 machine.  However to be properly secure you should pay
4677 attention to the output of the checksum command (it uses
4678 the ones from GNU coreutils).  In particular when the
4679 filename is not printable, coreutils uses a special
4680 backslash syntax.  For more information, see the GNU
4681 coreutils info file.");
4682
4683   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4684    [InitBasicFS, Always, TestOutputBuffer (
4685       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4686        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4687    "fill a file with a repeating pattern of bytes",
4688    "\
4689 This function is like C<guestfs_fill> except that it creates
4690 a new file of length C<len> containing the repeating pattern
4691 of bytes in C<pattern>.  The pattern is truncated if necessary
4692 to ensure the length of the file is exactly C<len> bytes.");
4693
4694   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4695    [InitBasicFS, Always, TestOutput (
4696       [["write"; "/new"; "new file contents"];
4697        ["cat"; "/new"]], "new file contents");
4698     InitBasicFS, Always, TestOutput (
4699       [["write"; "/new"; "\nnew file contents\n"];
4700        ["cat"; "/new"]], "\nnew file contents\n");
4701     InitBasicFS, Always, TestOutput (
4702       [["write"; "/new"; "\n\n"];
4703        ["cat"; "/new"]], "\n\n");
4704     InitBasicFS, Always, TestOutput (
4705       [["write"; "/new"; ""];
4706        ["cat"; "/new"]], "");
4707     InitBasicFS, Always, TestOutput (
4708       [["write"; "/new"; "\n\n\n"];
4709        ["cat"; "/new"]], "\n\n\n");
4710     InitBasicFS, Always, TestOutput (
4711       [["write"; "/new"; "\n"];
4712        ["cat"; "/new"]], "\n")],
4713    "create a new file",
4714    "\
4715 This call creates a file called C<path>.  The content of the
4716 file is the string C<content> (which can contain any 8 bit data).");
4717
4718   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4719    [InitBasicFS, Always, TestOutput (
4720       [["write"; "/new"; "new file contents"];
4721        ["pwrite"; "/new"; "data"; "4"];
4722        ["cat"; "/new"]], "new data contents");
4723     InitBasicFS, Always, TestOutput (
4724       [["write"; "/new"; "new file contents"];
4725        ["pwrite"; "/new"; "is extended"; "9"];
4726        ["cat"; "/new"]], "new file is extended");
4727     InitBasicFS, Always, TestOutput (
4728       [["write"; "/new"; "new file contents"];
4729        ["pwrite"; "/new"; ""; "4"];
4730        ["cat"; "/new"]], "new file contents")],
4731    "write to part of a file",
4732    "\
4733 This command writes to part of a file.  It writes the data
4734 buffer C<content> to the file C<path> starting at offset C<offset>.
4735
4736 This command implements the L<pwrite(2)> system call, and like
4737 that system call it may not write the full data requested.  The
4738 return value is the number of bytes that were actually written
4739 to the file.  This could even be 0, although short writes are
4740 unlikely for regular files in ordinary circumstances.
4741
4742 See also C<guestfs_pread>.");
4743
4744   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4745    [],
4746    "resize an ext2, ext3 or ext4 filesystem (with size)",
4747    "\
4748 This command is the same as C<guestfs_resize2fs> except that it
4749 allows you to specify the new size (in bytes) explicitly.");
4750
4751   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4752    [],
4753    "resize an LVM physical volume (with size)",
4754    "\
4755 This command is the same as C<guestfs_pvresize> except that it
4756 allows you to specify the new size (in bytes) explicitly.");
4757
4758   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4759    [],
4760    "resize an NTFS filesystem (with size)",
4761    "\
4762 This command is the same as C<guestfs_ntfsresize> except that it
4763 allows you to specify the new size (in bytes) explicitly.");
4764
4765   ("available_all_groups", (RStringList "groups", []), 251, [],
4766    [InitNone, Always, TestRun [["available_all_groups"]]],
4767    "return a list of all optional groups",
4768    "\
4769 This command returns a list of all optional groups that this
4770 daemon knows about.  Note this returns both supported and unsupported
4771 groups.  To find out which ones the daemon can actually support
4772 you have to call C<guestfs_available> on each member of the
4773 returned list.
4774
4775 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4776
4777   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4778    [InitBasicFS, Always, TestOutputStruct (
4779       [["fallocate64"; "/a"; "1000000"];
4780        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4781    "preallocate a file in the guest filesystem",
4782    "\
4783 This command preallocates a file (containing zero bytes) named
4784 C<path> of size C<len> bytes.  If the file exists already, it
4785 is overwritten.
4786
4787 Note that this call allocates disk blocks for the file.
4788 To create a sparse file use C<guestfs_truncate_size> instead.
4789
4790 The deprecated call C<guestfs_fallocate> does the same,
4791 but owing to an oversight it only allowed 30 bit lengths
4792 to be specified, effectively limiting the maximum size
4793 of files created through that call to 1GB.
4794
4795 Do not confuse this with the guestfish-specific
4796 C<alloc> and C<sparse> commands which create
4797 a file in the host and attach it as a device.");
4798
4799   ("vfs_label", (RString "label", [Device "device"]), 253, [],
4800    [InitBasicFS, Always, TestOutput (
4801        [["set_e2label"; "/dev/sda1"; "LTEST"];
4802         ["vfs_label"; "/dev/sda1"]], "LTEST")],
4803    "get the filesystem label",
4804    "\
4805 This returns the filesystem label of the filesystem on
4806 C<device>.
4807
4808 If the filesystem is unlabeled, this returns the empty string.");
4809
4810   ("vfs_uuid", (RString "uuid", [Device "device"]), 254, [],
4811    (let uuid = uuidgen () in
4812     [InitBasicFS, Always, TestOutput (
4813        [["set_e2uuid"; "/dev/sda1"; uuid];
4814         ["vfs_uuid"; "/dev/sda1"]], uuid)]),
4815    "get the filesystem UUID",
4816    "\
4817 This returns the filesystem UUID of the filesystem on
4818 C<device>.
4819
4820 If the filesystem does not have a UUID, this returns the empty string.");
4821
4822 ]
4823
4824 let all_functions = non_daemon_functions @ daemon_functions
4825
4826 (* In some places we want the functions to be displayed sorted
4827  * alphabetically, so this is useful:
4828  *)
4829 let all_functions_sorted =
4830   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4831                compare n1 n2) all_functions
4832
4833 (* This is used to generate the src/MAX_PROC_NR file which
4834  * contains the maximum procedure number, a surrogate for the
4835  * ABI version number.  See src/Makefile.am for the details.
4836  *)
4837 let max_proc_nr =
4838   let proc_nrs = List.map (
4839     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4840   ) daemon_functions in
4841   List.fold_left max 0 proc_nrs
4842
4843 (* Field types for structures. *)
4844 type field =
4845   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4846   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4847   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4848   | FUInt32
4849   | FInt32
4850   | FUInt64
4851   | FInt64
4852   | FBytes                      (* Any int measure that counts bytes. *)
4853   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4854   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4855
4856 (* Because we generate extra parsing code for LVM command line tools,
4857  * we have to pull out the LVM columns separately here.
4858  *)
4859 let lvm_pv_cols = [
4860   "pv_name", FString;
4861   "pv_uuid", FUUID;
4862   "pv_fmt", FString;
4863   "pv_size", FBytes;
4864   "dev_size", FBytes;
4865   "pv_free", FBytes;
4866   "pv_used", FBytes;
4867   "pv_attr", FString (* XXX *);
4868   "pv_pe_count", FInt64;
4869   "pv_pe_alloc_count", FInt64;
4870   "pv_tags", FString;
4871   "pe_start", FBytes;
4872   "pv_mda_count", FInt64;
4873   "pv_mda_free", FBytes;
4874   (* Not in Fedora 10:
4875      "pv_mda_size", FBytes;
4876   *)
4877 ]
4878 let lvm_vg_cols = [
4879   "vg_name", FString;
4880   "vg_uuid", FUUID;
4881   "vg_fmt", FString;
4882   "vg_attr", FString (* XXX *);
4883   "vg_size", FBytes;
4884   "vg_free", FBytes;
4885   "vg_sysid", FString;
4886   "vg_extent_size", FBytes;
4887   "vg_extent_count", FInt64;
4888   "vg_free_count", FInt64;
4889   "max_lv", FInt64;
4890   "max_pv", FInt64;
4891   "pv_count", FInt64;
4892   "lv_count", FInt64;
4893   "snap_count", FInt64;
4894   "vg_seqno", FInt64;
4895   "vg_tags", FString;
4896   "vg_mda_count", FInt64;
4897   "vg_mda_free", FBytes;
4898   (* Not in Fedora 10:
4899      "vg_mda_size", FBytes;
4900   *)
4901 ]
4902 let lvm_lv_cols = [
4903   "lv_name", FString;
4904   "lv_uuid", FUUID;
4905   "lv_attr", FString (* XXX *);
4906   "lv_major", FInt64;
4907   "lv_minor", FInt64;
4908   "lv_kernel_major", FInt64;
4909   "lv_kernel_minor", FInt64;
4910   "lv_size", FBytes;
4911   "seg_count", FInt64;
4912   "origin", FString;
4913   "snap_percent", FOptPercent;
4914   "copy_percent", FOptPercent;
4915   "move_pv", FString;
4916   "lv_tags", FString;
4917   "mirror_log", FString;
4918   "modules", FString;
4919 ]
4920
4921 (* Names and fields in all structures (in RStruct and RStructList)
4922  * that we support.
4923  *)
4924 let structs = [
4925   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4926    * not use this struct in any new code.
4927    *)
4928   "int_bool", [
4929     "i", FInt32;                (* for historical compatibility *)
4930     "b", FInt32;                (* for historical compatibility *)
4931   ];
4932
4933   (* LVM PVs, VGs, LVs. *)
4934   "lvm_pv", lvm_pv_cols;
4935   "lvm_vg", lvm_vg_cols;
4936   "lvm_lv", lvm_lv_cols;
4937
4938   (* Column names and types from stat structures.
4939    * NB. Can't use things like 'st_atime' because glibc header files
4940    * define some of these as macros.  Ugh.
4941    *)
4942   "stat", [
4943     "dev", FInt64;
4944     "ino", FInt64;
4945     "mode", FInt64;
4946     "nlink", FInt64;
4947     "uid", FInt64;
4948     "gid", FInt64;
4949     "rdev", FInt64;
4950     "size", FInt64;
4951     "blksize", FInt64;
4952     "blocks", FInt64;
4953     "atime", FInt64;
4954     "mtime", FInt64;
4955     "ctime", FInt64;
4956   ];
4957   "statvfs", [
4958     "bsize", FInt64;
4959     "frsize", FInt64;
4960     "blocks", FInt64;
4961     "bfree", FInt64;
4962     "bavail", FInt64;
4963     "files", FInt64;
4964     "ffree", FInt64;
4965     "favail", FInt64;
4966     "fsid", FInt64;
4967     "flag", FInt64;
4968     "namemax", FInt64;
4969   ];
4970
4971   (* Column names in dirent structure. *)
4972   "dirent", [
4973     "ino", FInt64;
4974     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4975     "ftyp", FChar;
4976     "name", FString;
4977   ];
4978
4979   (* Version numbers. *)
4980   "version", [
4981     "major", FInt64;
4982     "minor", FInt64;
4983     "release", FInt64;
4984     "extra", FString;
4985   ];
4986
4987   (* Extended attribute. *)
4988   "xattr", [
4989     "attrname", FString;
4990     "attrval", FBuffer;
4991   ];
4992
4993   (* Inotify events. *)
4994   "inotify_event", [
4995     "in_wd", FInt64;
4996     "in_mask", FUInt32;
4997     "in_cookie", FUInt32;
4998     "in_name", FString;
4999   ];
5000
5001   (* Partition table entry. *)
5002   "partition", [
5003     "part_num", FInt32;
5004     "part_start", FBytes;
5005     "part_end", FBytes;
5006     "part_size", FBytes;
5007   ];
5008 ] (* end of structs *)
5009
5010 (* Ugh, Java has to be different ..
5011  * These names are also used by the Haskell bindings.
5012  *)
5013 let java_structs = [
5014   "int_bool", "IntBool";
5015   "lvm_pv", "PV";
5016   "lvm_vg", "VG";
5017   "lvm_lv", "LV";
5018   "stat", "Stat";
5019   "statvfs", "StatVFS";
5020   "dirent", "Dirent";
5021   "version", "Version";
5022   "xattr", "XAttr";
5023   "inotify_event", "INotifyEvent";
5024   "partition", "Partition";
5025 ]
5026
5027 (* What structs are actually returned. *)
5028 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
5029
5030 (* Returns a list of RStruct/RStructList structs that are returned
5031  * by any function.  Each element of returned list is a pair:
5032  *
5033  * (structname, RStructOnly)
5034  *    == there exists function which returns RStruct (_, structname)
5035  * (structname, RStructListOnly)
5036  *    == there exists function which returns RStructList (_, structname)
5037  * (structname, RStructAndList)
5038  *    == there are functions returning both RStruct (_, structname)
5039  *                                      and RStructList (_, structname)
5040  *)
5041 let rstructs_used_by functions =
5042   (* ||| is a "logical OR" for rstructs_used_t *)
5043   let (|||) a b =
5044     match a, b with
5045     | RStructAndList, _
5046     | _, RStructAndList -> RStructAndList
5047     | RStructOnly, RStructListOnly
5048     | RStructListOnly, RStructOnly -> RStructAndList
5049     | RStructOnly, RStructOnly -> RStructOnly
5050     | RStructListOnly, RStructListOnly -> RStructListOnly
5051   in
5052
5053   let h = Hashtbl.create 13 in
5054
5055   (* if elem->oldv exists, update entry using ||| operator,
5056    * else just add elem->newv to the hash
5057    *)
5058   let update elem newv =
5059     try  let oldv = Hashtbl.find h elem in
5060          Hashtbl.replace h elem (newv ||| oldv)
5061     with Not_found -> Hashtbl.add h elem newv
5062   in
5063
5064   List.iter (
5065     fun (_, style, _, _, _, _, _) ->
5066       match fst style with
5067       | RStruct (_, structname) -> update structname RStructOnly
5068       | RStructList (_, structname) -> update structname RStructListOnly
5069       | _ -> ()
5070   ) functions;
5071
5072   (* return key->values as a list of (key,value) *)
5073   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5074
5075 (* Used for testing language bindings. *)
5076 type callt =
5077   | CallString of string
5078   | CallOptString of string option
5079   | CallStringList of string list
5080   | CallInt of int
5081   | CallInt64 of int64
5082   | CallBool of bool
5083   | CallBuffer of string
5084
5085 (* Used to memoize the result of pod2text. *)
5086 let pod2text_memo_filename = "src/.pod2text.data"
5087 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5088   try
5089     let chan = open_in pod2text_memo_filename in
5090     let v = input_value chan in
5091     close_in chan;
5092     v
5093   with
5094     _ -> Hashtbl.create 13
5095 let pod2text_memo_updated () =
5096   let chan = open_out pod2text_memo_filename in
5097   output_value chan pod2text_memo;
5098   close_out chan
5099
5100 (* Useful functions.
5101  * Note we don't want to use any external OCaml libraries which
5102  * makes this a bit harder than it should be.
5103  *)
5104 module StringMap = Map.Make (String)
5105
5106 let failwithf fs = ksprintf failwith fs
5107
5108 let unique = let i = ref 0 in fun () -> incr i; !i
5109
5110 let replace_char s c1 c2 =
5111   let s2 = String.copy s in
5112   let r = ref false in
5113   for i = 0 to String.length s2 - 1 do
5114     if String.unsafe_get s2 i = c1 then (
5115       String.unsafe_set s2 i c2;
5116       r := true
5117     )
5118   done;
5119   if not !r then s else s2
5120
5121 let isspace c =
5122   c = ' '
5123   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5124
5125 let triml ?(test = isspace) str =
5126   let i = ref 0 in
5127   let n = ref (String.length str) in
5128   while !n > 0 && test str.[!i]; do
5129     decr n;
5130     incr i
5131   done;
5132   if !i = 0 then str
5133   else String.sub str !i !n
5134
5135 let trimr ?(test = isspace) str =
5136   let n = ref (String.length str) in
5137   while !n > 0 && test str.[!n-1]; do
5138     decr n
5139   done;
5140   if !n = String.length str then str
5141   else String.sub str 0 !n
5142
5143 let trim ?(test = isspace) str =
5144   trimr ~test (triml ~test str)
5145
5146 let rec find s sub =
5147   let len = String.length s in
5148   let sublen = String.length sub in
5149   let rec loop i =
5150     if i <= len-sublen then (
5151       let rec loop2 j =
5152         if j < sublen then (
5153           if s.[i+j] = sub.[j] then loop2 (j+1)
5154           else -1
5155         ) else
5156           i (* found *)
5157       in
5158       let r = loop2 0 in
5159       if r = -1 then loop (i+1) else r
5160     ) else
5161       -1 (* not found *)
5162   in
5163   loop 0
5164
5165 let rec replace_str s s1 s2 =
5166   let len = String.length s in
5167   let sublen = String.length s1 in
5168   let i = find s s1 in
5169   if i = -1 then s
5170   else (
5171     let s' = String.sub s 0 i in
5172     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5173     s' ^ s2 ^ replace_str s'' s1 s2
5174   )
5175
5176 let rec string_split sep str =
5177   let len = String.length str in
5178   let seplen = String.length sep in
5179   let i = find str sep in
5180   if i = -1 then [str]
5181   else (
5182     let s' = String.sub str 0 i in
5183     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5184     s' :: string_split sep s''
5185   )
5186
5187 let files_equal n1 n2 =
5188   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5189   match Sys.command cmd with
5190   | 0 -> true
5191   | 1 -> false
5192   | i -> failwithf "%s: failed with error code %d" cmd i
5193
5194 let rec filter_map f = function
5195   | [] -> []
5196   | x :: xs ->
5197       match f x with
5198       | Some y -> y :: filter_map f xs
5199       | None -> filter_map f xs
5200
5201 let rec find_map f = function
5202   | [] -> raise Not_found
5203   | x :: xs ->
5204       match f x with
5205       | Some y -> y
5206       | None -> find_map f xs
5207
5208 let iteri f xs =
5209   let rec loop i = function
5210     | [] -> ()
5211     | x :: xs -> f i x; loop (i+1) xs
5212   in
5213   loop 0 xs
5214
5215 let mapi f xs =
5216   let rec loop i = function
5217     | [] -> []
5218     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5219   in
5220   loop 0 xs
5221
5222 let count_chars c str =
5223   let count = ref 0 in
5224   for i = 0 to String.length str - 1 do
5225     if c = String.unsafe_get str i then incr count
5226   done;
5227   !count
5228
5229 let explode str =
5230   let r = ref [] in
5231   for i = 0 to String.length str - 1 do
5232     let c = String.unsafe_get str i in
5233     r := c :: !r;
5234   done;
5235   List.rev !r
5236
5237 let map_chars f str =
5238   List.map f (explode str)
5239
5240 let name_of_argt = function
5241   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5242   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5243   | FileIn n | FileOut n | BufferIn n -> n
5244
5245 let java_name_of_struct typ =
5246   try List.assoc typ java_structs
5247   with Not_found ->
5248     failwithf
5249       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5250
5251 let cols_of_struct typ =
5252   try List.assoc typ structs
5253   with Not_found ->
5254     failwithf "cols_of_struct: unknown struct %s" typ
5255
5256 let seq_of_test = function
5257   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5258   | TestOutputListOfDevices (s, _)
5259   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5260   | TestOutputTrue s | TestOutputFalse s
5261   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5262   | TestOutputStruct (s, _)
5263   | TestLastFail s -> s
5264
5265 (* Handling for function flags. *)
5266 let protocol_limit_warning =
5267   "Because of the message protocol, there is a transfer limit
5268 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5269
5270 let danger_will_robinson =
5271   "B<This command is dangerous.  Without careful use you
5272 can easily destroy all your data>."
5273
5274 let deprecation_notice flags =
5275   try
5276     let alt =
5277       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5278     let txt =
5279       sprintf "This function is deprecated.
5280 In new code, use the C<%s> call instead.
5281
5282 Deprecated functions will not be removed from the API, but the
5283 fact that they are deprecated indicates that there are problems
5284 with correct use of these functions." alt in
5285     Some txt
5286   with
5287     Not_found -> None
5288
5289 (* Create list of optional groups. *)
5290 let optgroups =
5291   let h = Hashtbl.create 13 in
5292   List.iter (
5293     fun (name, _, _, flags, _, _, _) ->
5294       List.iter (
5295         function
5296         | Optional group ->
5297             let names = try Hashtbl.find h group with Not_found -> [] in
5298             Hashtbl.replace h group (name :: names)
5299         | _ -> ()
5300       ) flags
5301   ) daemon_functions;
5302   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5303   let groups =
5304     List.map (
5305       fun group -> group, List.sort compare (Hashtbl.find h group)
5306     ) groups in
5307   List.sort (fun x y -> compare (fst x) (fst y)) groups
5308
5309 (* Check function names etc. for consistency. *)
5310 let check_functions () =
5311   let contains_uppercase str =
5312     let len = String.length str in
5313     let rec loop i =
5314       if i >= len then false
5315       else (
5316         let c = str.[i] in
5317         if c >= 'A' && c <= 'Z' then true
5318         else loop (i+1)
5319       )
5320     in
5321     loop 0
5322   in
5323
5324   (* Check function names. *)
5325   List.iter (
5326     fun (name, _, _, _, _, _, _) ->
5327       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5328         failwithf "function name %s does not need 'guestfs' prefix" name;
5329       if name = "" then
5330         failwithf "function name is empty";
5331       if name.[0] < 'a' || name.[0] > 'z' then
5332         failwithf "function name %s must start with lowercase a-z" name;
5333       if String.contains name '-' then
5334         failwithf "function name %s should not contain '-', use '_' instead."
5335           name
5336   ) all_functions;
5337
5338   (* Check function parameter/return names. *)
5339   List.iter (
5340     fun (name, style, _, _, _, _, _) ->
5341       let check_arg_ret_name n =
5342         if contains_uppercase n then
5343           failwithf "%s param/ret %s should not contain uppercase chars"
5344             name n;
5345         if String.contains n '-' || String.contains n '_' then
5346           failwithf "%s param/ret %s should not contain '-' or '_'"
5347             name n;
5348         if n = "value" then
5349           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;
5350         if n = "int" || n = "char" || n = "short" || n = "long" then
5351           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5352         if n = "i" || n = "n" then
5353           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5354         if n = "argv" || n = "args" then
5355           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5356
5357         (* List Haskell, OCaml and C keywords here.
5358          * http://www.haskell.org/haskellwiki/Keywords
5359          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5360          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5361          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5362          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5363          * Omitting _-containing words, since they're handled above.
5364          * Omitting the OCaml reserved word, "val", is ok,
5365          * and saves us from renaming several parameters.
5366          *)
5367         let reserved = [
5368           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5369           "char"; "class"; "const"; "constraint"; "continue"; "data";
5370           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5371           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5372           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5373           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5374           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5375           "interface";
5376           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5377           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5378           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5379           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5380           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5381           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5382           "volatile"; "when"; "where"; "while";
5383           ] in
5384         if List.mem n reserved then
5385           failwithf "%s has param/ret using reserved word %s" name n;
5386       in
5387
5388       (match fst style with
5389        | RErr -> ()
5390        | RInt n | RInt64 n | RBool n
5391        | RConstString n | RConstOptString n | RString n
5392        | RStringList n | RStruct (n, _) | RStructList (n, _)
5393        | RHashtable n | RBufferOut n ->
5394            check_arg_ret_name n
5395       );
5396       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5397   ) all_functions;
5398
5399   (* Check short descriptions. *)
5400   List.iter (
5401     fun (name, _, _, _, _, shortdesc, _) ->
5402       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5403         failwithf "short description of %s should begin with lowercase." name;
5404       let c = shortdesc.[String.length shortdesc-1] in
5405       if c = '\n' || c = '.' then
5406         failwithf "short description of %s should not end with . or \\n." name
5407   ) all_functions;
5408
5409   (* Check long descriptions. *)
5410   List.iter (
5411     fun (name, _, _, _, _, _, longdesc) ->
5412       if longdesc.[String.length longdesc-1] = '\n' then
5413         failwithf "long description of %s should not end with \\n." name
5414   ) all_functions;
5415
5416   (* Check proc_nrs. *)
5417   List.iter (
5418     fun (name, _, proc_nr, _, _, _, _) ->
5419       if proc_nr <= 0 then
5420         failwithf "daemon function %s should have proc_nr > 0" name
5421   ) daemon_functions;
5422
5423   List.iter (
5424     fun (name, _, proc_nr, _, _, _, _) ->
5425       if proc_nr <> -1 then
5426         failwithf "non-daemon function %s should have proc_nr -1" name
5427   ) non_daemon_functions;
5428
5429   let proc_nrs =
5430     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5431       daemon_functions in
5432   let proc_nrs =
5433     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5434   let rec loop = function
5435     | [] -> ()
5436     | [_] -> ()
5437     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5438         loop rest
5439     | (name1,nr1) :: (name2,nr2) :: _ ->
5440         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5441           name1 name2 nr1 nr2
5442   in
5443   loop proc_nrs;
5444
5445   (* Check tests. *)
5446   List.iter (
5447     function
5448       (* Ignore functions that have no tests.  We generate a
5449        * warning when the user does 'make check' instead.
5450        *)
5451     | name, _, _, _, [], _, _ -> ()
5452     | name, _, _, _, tests, _, _ ->
5453         let funcs =
5454           List.map (
5455             fun (_, _, test) ->
5456               match seq_of_test test with
5457               | [] ->
5458                   failwithf "%s has a test containing an empty sequence" name
5459               | cmds -> List.map List.hd cmds
5460           ) tests in
5461         let funcs = List.flatten funcs in
5462
5463         let tested = List.mem name funcs in
5464
5465         if not tested then
5466           failwithf "function %s has tests but does not test itself" name
5467   ) all_functions
5468
5469 (* 'pr' prints to the current output file. *)
5470 let chan = ref Pervasives.stdout
5471 let lines = ref 0
5472 let pr fs =
5473   ksprintf
5474     (fun str ->
5475        let i = count_chars '\n' str in
5476        lines := !lines + i;
5477        output_string !chan str
5478     ) fs
5479
5480 let copyright_years =
5481   let this_year = 1900 + (localtime (time ())).tm_year in
5482   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5483
5484 (* Generate a header block in a number of standard styles. *)
5485 type comment_style =
5486     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5487 type license = GPLv2plus | LGPLv2plus
5488
5489 let generate_header ?(extra_inputs = []) comment license =
5490   let inputs = "src/generator.ml" :: extra_inputs in
5491   let c = match comment with
5492     | CStyle ->         pr "/* "; " *"
5493     | CPlusPlusStyle -> pr "// "; "//"
5494     | HashStyle ->      pr "# ";  "#"
5495     | OCamlStyle ->     pr "(* "; " *"
5496     | HaskellStyle ->   pr "{- "; "  " in
5497   pr "libguestfs generated file\n";
5498   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5499   List.iter (pr "%s   %s\n" c) inputs;
5500   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5501   pr "%s\n" c;
5502   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5503   pr "%s\n" c;
5504   (match license with
5505    | GPLv2plus ->
5506        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5507        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5508        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5509        pr "%s (at your option) any later version.\n" c;
5510        pr "%s\n" c;
5511        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5512        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5513        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5514        pr "%s GNU General Public License for more details.\n" c;
5515        pr "%s\n" c;
5516        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5517        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5518        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5519
5520    | LGPLv2plus ->
5521        pr "%s This library is free software; you can redistribute it and/or\n" c;
5522        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5523        pr "%s License as published by the Free Software Foundation; either\n" c;
5524        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5525        pr "%s\n" c;
5526        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5527        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5528        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5529        pr "%s Lesser General Public License for more details.\n" c;
5530        pr "%s\n" c;
5531        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5532        pr "%s License along with this library; if not, write to the Free Software\n" c;
5533        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5534   );
5535   (match comment with
5536    | CStyle -> pr " */\n"
5537    | CPlusPlusStyle
5538    | HashStyle -> ()
5539    | OCamlStyle -> pr " *)\n"
5540    | HaskellStyle -> pr "-}\n"
5541   );
5542   pr "\n"
5543
5544 (* Start of main code generation functions below this line. *)
5545
5546 (* Generate the pod documentation for the C API. *)
5547 let rec generate_actions_pod () =
5548   List.iter (
5549     fun (shortname, style, _, flags, _, _, longdesc) ->
5550       if not (List.mem NotInDocs flags) then (
5551         let name = "guestfs_" ^ shortname in
5552         pr "=head2 %s\n\n" name;
5553         pr " ";
5554         generate_prototype ~extern:false ~handle:"g" name style;
5555         pr "\n\n";
5556         pr "%s\n\n" longdesc;
5557         (match fst style with
5558          | RErr ->
5559              pr "This function returns 0 on success or -1 on error.\n\n"
5560          | RInt _ ->
5561              pr "On error this function returns -1.\n\n"
5562          | RInt64 _ ->
5563              pr "On error this function returns -1.\n\n"
5564          | RBool _ ->
5565              pr "This function returns a C truth value on success or -1 on error.\n\n"
5566          | RConstString _ ->
5567              pr "This function returns a string, or NULL on error.
5568 The string is owned by the guest handle and must I<not> be freed.\n\n"
5569          | RConstOptString _ ->
5570              pr "This function returns a string which may be NULL.
5571 There is way to return an error from this function.
5572 The string is owned by the guest handle and must I<not> be freed.\n\n"
5573          | RString _ ->
5574              pr "This function returns a string, or NULL on error.
5575 I<The caller must free the returned string after use>.\n\n"
5576          | RStringList _ ->
5577              pr "This function returns a NULL-terminated array of strings
5578 (like L<environ(3)>), or NULL if there was an error.
5579 I<The caller must free the strings and the array after use>.\n\n"
5580          | RStruct (_, typ) ->
5581              pr "This function returns a C<struct guestfs_%s *>,
5582 or NULL if there was an error.
5583 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5584          | RStructList (_, typ) ->
5585              pr "This function returns a C<struct guestfs_%s_list *>
5586 (see E<lt>guestfs-structs.hE<gt>),
5587 or NULL if there was an error.
5588 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5589          | RHashtable _ ->
5590              pr "This function returns a NULL-terminated array of
5591 strings, or NULL if there was an error.
5592 The array of strings will always have length C<2n+1>, where
5593 C<n> keys and values alternate, followed by the trailing NULL entry.
5594 I<The caller must free the strings and the array after use>.\n\n"
5595          | RBufferOut _ ->
5596              pr "This function returns a buffer, or NULL on error.
5597 The size of the returned buffer is written to C<*size_r>.
5598 I<The caller must free the returned buffer after use>.\n\n"
5599         );
5600         if List.mem ProtocolLimitWarning flags then
5601           pr "%s\n\n" protocol_limit_warning;
5602         if List.mem DangerWillRobinson flags then
5603           pr "%s\n\n" danger_will_robinson;
5604         match deprecation_notice flags with
5605         | None -> ()
5606         | Some txt -> pr "%s\n\n" txt
5607       )
5608   ) all_functions_sorted
5609
5610 and generate_structs_pod () =
5611   (* Structs documentation. *)
5612   List.iter (
5613     fun (typ, cols) ->
5614       pr "=head2 guestfs_%s\n" typ;
5615       pr "\n";
5616       pr " struct guestfs_%s {\n" typ;
5617       List.iter (
5618         function
5619         | name, FChar -> pr "   char %s;\n" name
5620         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5621         | name, FInt32 -> pr "   int32_t %s;\n" name
5622         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5623         | name, FInt64 -> pr "   int64_t %s;\n" name
5624         | name, FString -> pr "   char *%s;\n" name
5625         | name, FBuffer ->
5626             pr "   /* The next two fields describe a byte array. */\n";
5627             pr "   uint32_t %s_len;\n" name;
5628             pr "   char *%s;\n" name
5629         | name, FUUID ->
5630             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5631             pr "   char %s[32];\n" name
5632         | name, FOptPercent ->
5633             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5634             pr "   float %s;\n" name
5635       ) cols;
5636       pr " };\n";
5637       pr " \n";
5638       pr " struct guestfs_%s_list {\n" typ;
5639       pr "   uint32_t len; /* Number of elements in list. */\n";
5640       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5641       pr " };\n";
5642       pr " \n";
5643       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5644       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5645         typ typ;
5646       pr "\n"
5647   ) structs
5648
5649 and generate_availability_pod () =
5650   (* Availability documentation. *)
5651   pr "=over 4\n";
5652   pr "\n";
5653   List.iter (
5654     fun (group, functions) ->
5655       pr "=item B<%s>\n" group;
5656       pr "\n";
5657       pr "The following functions:\n";
5658       List.iter (pr "L</guestfs_%s>\n") functions;
5659       pr "\n"
5660   ) optgroups;
5661   pr "=back\n";
5662   pr "\n"
5663
5664 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5665  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5666  *
5667  * We have to use an underscore instead of a dash because otherwise
5668  * rpcgen generates incorrect code.
5669  *
5670  * This header is NOT exported to clients, but see also generate_structs_h.
5671  *)
5672 and generate_xdr () =
5673   generate_header CStyle LGPLv2plus;
5674
5675   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5676   pr "typedef string str<>;\n";
5677   pr "\n";
5678
5679   (* Internal structures. *)
5680   List.iter (
5681     function
5682     | typ, cols ->
5683         pr "struct guestfs_int_%s {\n" typ;
5684         List.iter (function
5685                    | name, FChar -> pr "  char %s;\n" name
5686                    | name, FString -> pr "  string %s<>;\n" name
5687                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5688                    | name, FUUID -> pr "  opaque %s[32];\n" name
5689                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5690                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5691                    | name, FOptPercent -> pr "  float %s;\n" name
5692                   ) cols;
5693         pr "};\n";
5694         pr "\n";
5695         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5696         pr "\n";
5697   ) structs;
5698
5699   List.iter (
5700     fun (shortname, style, _, _, _, _, _) ->
5701       let name = "guestfs_" ^ shortname in
5702
5703       (match snd style with
5704        | [] -> ()
5705        | args ->
5706            pr "struct %s_args {\n" name;
5707            List.iter (
5708              function
5709              | Pathname n | Device n | Dev_or_Path n | String n ->
5710                  pr "  string %s<>;\n" n
5711              | OptString n -> pr "  str *%s;\n" n
5712              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5713              | Bool n -> pr "  bool %s;\n" n
5714              | Int n -> pr "  int %s;\n" n
5715              | Int64 n -> pr "  hyper %s;\n" n
5716              | BufferIn n ->
5717                  pr "  opaque %s<>;\n" n
5718              | FileIn _ | FileOut _ -> ()
5719            ) args;
5720            pr "};\n\n"
5721       );
5722       (match fst style with
5723        | RErr -> ()
5724        | RInt n ->
5725            pr "struct %s_ret {\n" name;
5726            pr "  int %s;\n" n;
5727            pr "};\n\n"
5728        | RInt64 n ->
5729            pr "struct %s_ret {\n" name;
5730            pr "  hyper %s;\n" n;
5731            pr "};\n\n"
5732        | RBool n ->
5733            pr "struct %s_ret {\n" name;
5734            pr "  bool %s;\n" n;
5735            pr "};\n\n"
5736        | RConstString _ | RConstOptString _ ->
5737            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5738        | RString n ->
5739            pr "struct %s_ret {\n" name;
5740            pr "  string %s<>;\n" n;
5741            pr "};\n\n"
5742        | RStringList n ->
5743            pr "struct %s_ret {\n" name;
5744            pr "  str %s<>;\n" n;
5745            pr "};\n\n"
5746        | RStruct (n, typ) ->
5747            pr "struct %s_ret {\n" name;
5748            pr "  guestfs_int_%s %s;\n" typ n;
5749            pr "};\n\n"
5750        | RStructList (n, typ) ->
5751            pr "struct %s_ret {\n" name;
5752            pr "  guestfs_int_%s_list %s;\n" typ n;
5753            pr "};\n\n"
5754        | RHashtable n ->
5755            pr "struct %s_ret {\n" name;
5756            pr "  str %s<>;\n" n;
5757            pr "};\n\n"
5758        | RBufferOut n ->
5759            pr "struct %s_ret {\n" name;
5760            pr "  opaque %s<>;\n" n;
5761            pr "};\n\n"
5762       );
5763   ) daemon_functions;
5764
5765   (* Table of procedure numbers. *)
5766   pr "enum guestfs_procedure {\n";
5767   List.iter (
5768     fun (shortname, _, proc_nr, _, _, _, _) ->
5769       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5770   ) daemon_functions;
5771   pr "  GUESTFS_PROC_NR_PROCS\n";
5772   pr "};\n";
5773   pr "\n";
5774
5775   (* Having to choose a maximum message size is annoying for several
5776    * reasons (it limits what we can do in the API), but it (a) makes
5777    * the protocol a lot simpler, and (b) provides a bound on the size
5778    * of the daemon which operates in limited memory space.
5779    *)
5780   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5781   pr "\n";
5782
5783   (* Message header, etc. *)
5784   pr "\
5785 /* The communication protocol is now documented in the guestfs(3)
5786  * manpage.
5787  */
5788
5789 const GUESTFS_PROGRAM = 0x2000F5F5;
5790 const GUESTFS_PROTOCOL_VERSION = 1;
5791
5792 /* These constants must be larger than any possible message length. */
5793 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5794 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5795
5796 enum guestfs_message_direction {
5797   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5798   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5799 };
5800
5801 enum guestfs_message_status {
5802   GUESTFS_STATUS_OK = 0,
5803   GUESTFS_STATUS_ERROR = 1
5804 };
5805
5806 const GUESTFS_ERROR_LEN = 256;
5807
5808 struct guestfs_message_error {
5809   string error_message<GUESTFS_ERROR_LEN>;
5810 };
5811
5812 struct guestfs_message_header {
5813   unsigned prog;                     /* GUESTFS_PROGRAM */
5814   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5815   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5816   guestfs_message_direction direction;
5817   unsigned serial;                   /* message serial number */
5818   guestfs_message_status status;
5819 };
5820
5821 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5822
5823 struct guestfs_chunk {
5824   int cancel;                        /* if non-zero, transfer is cancelled */
5825   /* data size is 0 bytes if the transfer has finished successfully */
5826   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5827 };
5828 "
5829
5830 (* Generate the guestfs-structs.h file. *)
5831 and generate_structs_h () =
5832   generate_header CStyle LGPLv2plus;
5833
5834   (* This is a public exported header file containing various
5835    * structures.  The structures are carefully written to have
5836    * exactly the same in-memory format as the XDR structures that
5837    * we use on the wire to the daemon.  The reason for creating
5838    * copies of these structures here is just so we don't have to
5839    * export the whole of guestfs_protocol.h (which includes much
5840    * unrelated and XDR-dependent stuff that we don't want to be
5841    * public, or required by clients).
5842    *
5843    * To reiterate, we will pass these structures to and from the
5844    * client with a simple assignment or memcpy, so the format
5845    * must be identical to what rpcgen / the RFC defines.
5846    *)
5847
5848   (* Public structures. *)
5849   List.iter (
5850     fun (typ, cols) ->
5851       pr "struct guestfs_%s {\n" typ;
5852       List.iter (
5853         function
5854         | name, FChar -> pr "  char %s;\n" name
5855         | name, FString -> pr "  char *%s;\n" name
5856         | name, FBuffer ->
5857             pr "  uint32_t %s_len;\n" name;
5858             pr "  char *%s;\n" name
5859         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5860         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5861         | name, FInt32 -> pr "  int32_t %s;\n" name
5862         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5863         | name, FInt64 -> pr "  int64_t %s;\n" name
5864         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5865       ) cols;
5866       pr "};\n";
5867       pr "\n";
5868       pr "struct guestfs_%s_list {\n" typ;
5869       pr "  uint32_t len;\n";
5870       pr "  struct guestfs_%s *val;\n" typ;
5871       pr "};\n";
5872       pr "\n";
5873       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5874       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5875       pr "\n"
5876   ) structs
5877
5878 (* Generate the guestfs-actions.h file. *)
5879 and generate_actions_h () =
5880   generate_header CStyle LGPLv2plus;
5881   List.iter (
5882     fun (shortname, style, _, _, _, _, _) ->
5883       let name = "guestfs_" ^ shortname in
5884       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5885         name style
5886   ) all_functions
5887
5888 (* Generate the guestfs-internal-actions.h file. *)
5889 and generate_internal_actions_h () =
5890   generate_header CStyle LGPLv2plus;
5891   List.iter (
5892     fun (shortname, style, _, _, _, _, _) ->
5893       let name = "guestfs__" ^ shortname in
5894       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5895         name style
5896   ) non_daemon_functions
5897
5898 (* Generate the client-side dispatch stubs. *)
5899 and generate_client_actions () =
5900   generate_header CStyle LGPLv2plus;
5901
5902   pr "\
5903 #include <stdio.h>
5904 #include <stdlib.h>
5905 #include <stdint.h>
5906 #include <string.h>
5907 #include <inttypes.h>
5908
5909 #include \"guestfs.h\"
5910 #include \"guestfs-internal.h\"
5911 #include \"guestfs-internal-actions.h\"
5912 #include \"guestfs_protocol.h\"
5913
5914 #define error guestfs_error
5915 //#define perrorf guestfs_perrorf
5916 #define safe_malloc guestfs_safe_malloc
5917 #define safe_realloc guestfs_safe_realloc
5918 //#define safe_strdup guestfs_safe_strdup
5919 #define safe_memdup guestfs_safe_memdup
5920
5921 /* Check the return message from a call for validity. */
5922 static int
5923 check_reply_header (guestfs_h *g,
5924                     const struct guestfs_message_header *hdr,
5925                     unsigned int proc_nr, unsigned int serial)
5926 {
5927   if (hdr->prog != GUESTFS_PROGRAM) {
5928     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5929     return -1;
5930   }
5931   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5932     error (g, \"wrong protocol version (%%d/%%d)\",
5933            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5934     return -1;
5935   }
5936   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5937     error (g, \"unexpected message direction (%%d/%%d)\",
5938            hdr->direction, GUESTFS_DIRECTION_REPLY);
5939     return -1;
5940   }
5941   if (hdr->proc != proc_nr) {
5942     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5943     return -1;
5944   }
5945   if (hdr->serial != serial) {
5946     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5947     return -1;
5948   }
5949
5950   return 0;
5951 }
5952
5953 /* Check we are in the right state to run a high-level action. */
5954 static int
5955 check_state (guestfs_h *g, const char *caller)
5956 {
5957   if (!guestfs__is_ready (g)) {
5958     if (guestfs__is_config (g) || guestfs__is_launching (g))
5959       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5960         caller);
5961     else
5962       error (g, \"%%s called from the wrong state, %%d != READY\",
5963         caller, guestfs__get_state (g));
5964     return -1;
5965   }
5966   return 0;
5967 }
5968
5969 ";
5970
5971   let error_code_of = function
5972     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5973     | RConstString _ | RConstOptString _
5974     | RString _ | RStringList _
5975     | RStruct _ | RStructList _
5976     | RHashtable _ | RBufferOut _ -> "NULL"
5977   in
5978
5979   (* Generate code to check String-like parameters are not passed in
5980    * as NULL (returning an error if they are).
5981    *)
5982   let check_null_strings shortname style =
5983     let pr_newline = ref false in
5984     List.iter (
5985       function
5986       (* parameters which should not be NULL *)
5987       | String n
5988       | Device n
5989       | Pathname n
5990       | Dev_or_Path n
5991       | FileIn n
5992       | FileOut n
5993       | BufferIn n
5994       | StringList n
5995       | DeviceList n ->
5996           pr "  if (%s == NULL) {\n" n;
5997           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
5998           pr "           \"%s\", \"%s\");\n" shortname n;
5999           pr "    return %s;\n" (error_code_of (fst style));
6000           pr "  }\n";
6001           pr_newline := true
6002
6003       (* can be NULL *)
6004       | OptString _
6005
6006       (* not applicable *)
6007       | Bool _
6008       | Int _
6009       | Int64 _ -> ()
6010     ) (snd style);
6011
6012     if !pr_newline then pr "\n";
6013   in
6014
6015   (* Generate code to generate guestfish call traces. *)
6016   let trace_call shortname style =
6017     pr "  if (guestfs__get_trace (g)) {\n";
6018
6019     let needs_i =
6020       List.exists (function
6021                    | StringList _ | DeviceList _ -> true
6022                    | _ -> false) (snd style) in
6023     if needs_i then (
6024       pr "    int i;\n";
6025       pr "\n"
6026     );
6027
6028     pr "    printf (\"%s\");\n" shortname;
6029     List.iter (
6030       function
6031       | String n                        (* strings *)
6032       | Device n
6033       | Pathname n
6034       | Dev_or_Path n
6035       | FileIn n
6036       | FileOut n
6037       | BufferIn n ->
6038           (* guestfish doesn't support string escaping, so neither do we *)
6039           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
6040       | OptString n ->                  (* string option *)
6041           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
6042           pr "    else printf (\" null\");\n"
6043       | StringList n
6044       | DeviceList n ->                 (* string list *)
6045           pr "    putchar (' ');\n";
6046           pr "    putchar ('\"');\n";
6047           pr "    for (i = 0; %s[i]; ++i) {\n" n;
6048           pr "      if (i > 0) putchar (' ');\n";
6049           pr "      fputs (%s[i], stdout);\n" n;
6050           pr "    }\n";
6051           pr "    putchar ('\"');\n";
6052       | Bool n ->                       (* boolean *)
6053           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
6054       | Int n ->                        (* int *)
6055           pr "    printf (\" %%d\", %s);\n" n
6056       | Int64 n ->
6057           pr "    printf (\" %%\" PRIi64, %s);\n" n
6058     ) (snd style);
6059     pr "    putchar ('\\n');\n";
6060     pr "  }\n";
6061     pr "\n";
6062   in
6063
6064   (* For non-daemon functions, generate a wrapper around each function. *)
6065   List.iter (
6066     fun (shortname, style, _, _, _, _, _) ->
6067       let name = "guestfs_" ^ shortname in
6068
6069       generate_prototype ~extern:false ~semicolon:false ~newline:true
6070         ~handle:"g" name style;
6071       pr "{\n";
6072       check_null_strings shortname style;
6073       trace_call shortname style;
6074       pr "  return guestfs__%s " shortname;
6075       generate_c_call_args ~handle:"g" style;
6076       pr ";\n";
6077       pr "}\n";
6078       pr "\n"
6079   ) non_daemon_functions;
6080
6081   (* Client-side stubs for each function. *)
6082   List.iter (
6083     fun (shortname, style, _, _, _, _, _) ->
6084       let name = "guestfs_" ^ shortname in
6085       let error_code = error_code_of (fst style) in
6086
6087       (* Generate the action stub. *)
6088       generate_prototype ~extern:false ~semicolon:false ~newline:true
6089         ~handle:"g" name style;
6090
6091       pr "{\n";
6092
6093       (match snd style with
6094        | [] -> ()
6095        | _ -> pr "  struct %s_args args;\n" name
6096       );
6097
6098       pr "  guestfs_message_header hdr;\n";
6099       pr "  guestfs_message_error err;\n";
6100       let has_ret =
6101         match fst style with
6102         | RErr -> false
6103         | RConstString _ | RConstOptString _ ->
6104             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6105         | RInt _ | RInt64 _
6106         | RBool _ | RString _ | RStringList _
6107         | RStruct _ | RStructList _
6108         | RHashtable _ | RBufferOut _ ->
6109             pr "  struct %s_ret ret;\n" name;
6110             true in
6111
6112       pr "  int serial;\n";
6113       pr "  int r;\n";
6114       pr "\n";
6115       check_null_strings shortname style;
6116       trace_call shortname style;
6117       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6118         shortname error_code;
6119       pr "  guestfs___set_busy (g);\n";
6120       pr "\n";
6121
6122       (* Send the main header and arguments. *)
6123       (match snd style with
6124        | [] ->
6125            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6126              (String.uppercase shortname)
6127        | args ->
6128            List.iter (
6129              function
6130              | Pathname n | Device n | Dev_or_Path n | String n ->
6131                  pr "  args.%s = (char *) %s;\n" n n
6132              | OptString n ->
6133                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6134              | StringList n | DeviceList n ->
6135                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6136                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6137              | Bool n ->
6138                  pr "  args.%s = %s;\n" n n
6139              | Int n ->
6140                  pr "  args.%s = %s;\n" n n
6141              | Int64 n ->
6142                  pr "  args.%s = %s;\n" n n
6143              | FileIn _ | FileOut _ -> ()
6144              | BufferIn n ->
6145                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6146                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6147                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6148                    shortname;
6149                  pr "    guestfs___end_busy (g);\n";
6150                  pr "    return %s;\n" error_code;
6151                  pr "  }\n";
6152                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6153                  pr "  args.%s.%s_len = %s_size;\n" n n n
6154            ) args;
6155            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6156              (String.uppercase shortname);
6157            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6158              name;
6159       );
6160       pr "  if (serial == -1) {\n";
6161       pr "    guestfs___end_busy (g);\n";
6162       pr "    return %s;\n" error_code;
6163       pr "  }\n";
6164       pr "\n";
6165
6166       (* Send any additional files (FileIn) requested. *)
6167       let need_read_reply_label = ref false in
6168       List.iter (
6169         function
6170         | FileIn n ->
6171             pr "  r = guestfs___send_file (g, %s);\n" n;
6172             pr "  if (r == -1) {\n";
6173             pr "    guestfs___end_busy (g);\n";
6174             pr "    return %s;\n" error_code;
6175             pr "  }\n";
6176             pr "  if (r == -2) /* daemon cancelled */\n";
6177             pr "    goto read_reply;\n";
6178             need_read_reply_label := true;
6179             pr "\n";
6180         | _ -> ()
6181       ) (snd style);
6182
6183       (* Wait for the reply from the remote end. *)
6184       if !need_read_reply_label then pr " read_reply:\n";
6185       pr "  memset (&hdr, 0, sizeof hdr);\n";
6186       pr "  memset (&err, 0, sizeof err);\n";
6187       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6188       pr "\n";
6189       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6190       if not has_ret then
6191         pr "NULL, NULL"
6192       else
6193         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6194       pr ");\n";
6195
6196       pr "  if (r == -1) {\n";
6197       pr "    guestfs___end_busy (g);\n";
6198       pr "    return %s;\n" error_code;
6199       pr "  }\n";
6200       pr "\n";
6201
6202       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6203         (String.uppercase shortname);
6204       pr "    guestfs___end_busy (g);\n";
6205       pr "    return %s;\n" error_code;
6206       pr "  }\n";
6207       pr "\n";
6208
6209       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6210       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6211       pr "    free (err.error_message);\n";
6212       pr "    guestfs___end_busy (g);\n";
6213       pr "    return %s;\n" error_code;
6214       pr "  }\n";
6215       pr "\n";
6216
6217       (* Expecting to receive further files (FileOut)? *)
6218       List.iter (
6219         function
6220         | FileOut n ->
6221             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6222             pr "    guestfs___end_busy (g);\n";
6223             pr "    return %s;\n" error_code;
6224             pr "  }\n";
6225             pr "\n";
6226         | _ -> ()
6227       ) (snd style);
6228
6229       pr "  guestfs___end_busy (g);\n";
6230
6231       (match fst style with
6232        | RErr -> pr "  return 0;\n"
6233        | RInt n | RInt64 n | RBool n ->
6234            pr "  return ret.%s;\n" n
6235        | RConstString _ | RConstOptString _ ->
6236            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6237        | RString n ->
6238            pr "  return ret.%s; /* caller will free */\n" n
6239        | RStringList n | RHashtable n ->
6240            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6241            pr "  ret.%s.%s_val =\n" n n;
6242            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6243            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6244              n n;
6245            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6246            pr "  return ret.%s.%s_val;\n" n n
6247        | RStruct (n, _) ->
6248            pr "  /* caller will free this */\n";
6249            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6250        | RStructList (n, _) ->
6251            pr "  /* caller will free this */\n";
6252            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6253        | RBufferOut n ->
6254            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6255            pr "   * _val might be NULL here.  To make the API saner for\n";
6256            pr "   * callers, we turn this case into a unique pointer (using\n";
6257            pr "   * malloc(1)).\n";
6258            pr "   */\n";
6259            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6260            pr "    *size_r = ret.%s.%s_len;\n" n n;
6261            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6262            pr "  } else {\n";
6263            pr "    free (ret.%s.%s_val);\n" n n;
6264            pr "    char *p = safe_malloc (g, 1);\n";
6265            pr "    *size_r = ret.%s.%s_len;\n" n n;
6266            pr "    return p;\n";
6267            pr "  }\n";
6268       );
6269
6270       pr "}\n\n"
6271   ) daemon_functions;
6272
6273   (* Functions to free structures. *)
6274   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6275   pr " * structure format is identical to the XDR format.  See note in\n";
6276   pr " * generator.ml.\n";
6277   pr " */\n";
6278   pr "\n";
6279
6280   List.iter (
6281     fun (typ, _) ->
6282       pr "void\n";
6283       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6284       pr "{\n";
6285       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6286       pr "  free (x);\n";
6287       pr "}\n";
6288       pr "\n";
6289
6290       pr "void\n";
6291       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6292       pr "{\n";
6293       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6294       pr "  free (x);\n";
6295       pr "}\n";
6296       pr "\n";
6297
6298   ) structs;
6299
6300 (* Generate daemon/actions.h. *)
6301 and generate_daemon_actions_h () =
6302   generate_header CStyle GPLv2plus;
6303
6304   pr "#include \"../src/guestfs_protocol.h\"\n";
6305   pr "\n";
6306
6307   List.iter (
6308     fun (name, style, _, _, _, _, _) ->
6309       generate_prototype
6310         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6311         name style;
6312   ) daemon_functions
6313
6314 (* Generate the linker script which controls the visibility of
6315  * symbols in the public ABI and ensures no other symbols get
6316  * exported accidentally.
6317  *)
6318 and generate_linker_script () =
6319   generate_header HashStyle GPLv2plus;
6320
6321   let globals = [
6322     "guestfs_create";
6323     "guestfs_close";
6324     "guestfs_get_error_handler";
6325     "guestfs_get_out_of_memory_handler";
6326     "guestfs_last_error";
6327     "guestfs_set_error_handler";
6328     "guestfs_set_launch_done_callback";
6329     "guestfs_set_log_message_callback";
6330     "guestfs_set_out_of_memory_handler";
6331     "guestfs_set_subprocess_quit_callback";
6332
6333     (* Unofficial parts of the API: the bindings code use these
6334      * functions, so it is useful to export them.
6335      *)
6336     "guestfs_safe_calloc";
6337     "guestfs_safe_malloc";
6338   ] in
6339   let functions =
6340     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6341       all_functions in
6342   let structs =
6343     List.concat (
6344       List.map (fun (typ, _) ->
6345                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6346         structs
6347     ) in
6348   let globals = List.sort compare (globals @ functions @ structs) in
6349
6350   pr "{\n";
6351   pr "    global:\n";
6352   List.iter (pr "        %s;\n") globals;
6353   pr "\n";
6354
6355   pr "    local:\n";
6356   pr "        *;\n";
6357   pr "};\n"
6358
6359 (* Generate the server-side stubs. *)
6360 and generate_daemon_actions () =
6361   generate_header CStyle GPLv2plus;
6362
6363   pr "#include <config.h>\n";
6364   pr "\n";
6365   pr "#include <stdio.h>\n";
6366   pr "#include <stdlib.h>\n";
6367   pr "#include <string.h>\n";
6368   pr "#include <inttypes.h>\n";
6369   pr "#include <rpc/types.h>\n";
6370   pr "#include <rpc/xdr.h>\n";
6371   pr "\n";
6372   pr "#include \"daemon.h\"\n";
6373   pr "#include \"c-ctype.h\"\n";
6374   pr "#include \"../src/guestfs_protocol.h\"\n";
6375   pr "#include \"actions.h\"\n";
6376   pr "\n";
6377
6378   List.iter (
6379     fun (name, style, _, _, _, _, _) ->
6380       (* Generate server-side stubs. *)
6381       pr "static void %s_stub (XDR *xdr_in)\n" name;
6382       pr "{\n";
6383       let error_code =
6384         match fst style with
6385         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6386         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6387         | RBool _ -> pr "  int r;\n"; "-1"
6388         | RConstString _ | RConstOptString _ ->
6389             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6390         | RString _ -> pr "  char *r;\n"; "NULL"
6391         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6392         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6393         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6394         | RBufferOut _ ->
6395             pr "  size_t size = 1;\n";
6396             pr "  char *r;\n";
6397             "NULL" in
6398
6399       (match snd style with
6400        | [] -> ()
6401        | args ->
6402            pr "  struct guestfs_%s_args args;\n" name;
6403            List.iter (
6404              function
6405              | Device n | Dev_or_Path n
6406              | Pathname n
6407              | String n -> ()
6408              | OptString n -> pr "  char *%s;\n" n
6409              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6410              | Bool n -> pr "  int %s;\n" n
6411              | Int n -> pr "  int %s;\n" n
6412              | Int64 n -> pr "  int64_t %s;\n" n
6413              | FileIn _ | FileOut _ -> ()
6414              | BufferIn n ->
6415                  pr "  const char *%s;\n" n;
6416                  pr "  size_t %s_size;\n" n
6417            ) args
6418       );
6419       pr "\n";
6420
6421       let is_filein =
6422         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6423
6424       (match snd style with
6425        | [] -> ()
6426        | args ->
6427            pr "  memset (&args, 0, sizeof args);\n";
6428            pr "\n";
6429            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6430            if is_filein then
6431              pr "    if (cancel_receive () != -2)\n";
6432            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6433            pr "    goto done;\n";
6434            pr "  }\n";
6435            let pr_args n =
6436              pr "  char *%s = args.%s;\n" n n
6437            in
6438            let pr_list_handling_code n =
6439              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6440              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6441              pr "  if (%s == NULL) {\n" n;
6442              if is_filein then
6443                pr "    if (cancel_receive () != -2)\n";
6444              pr "      reply_with_perror (\"realloc\");\n";
6445              pr "    goto done;\n";
6446              pr "  }\n";
6447              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6448              pr "  args.%s.%s_val = %s;\n" n n n;
6449            in
6450            List.iter (
6451              function
6452              | Pathname n ->
6453                  pr_args n;
6454                  pr "  ABS_PATH (%s, %s, goto done);\n"
6455                    n (if is_filein then "cancel_receive ()" else "0");
6456              | Device n ->
6457                  pr_args n;
6458                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6459                    n (if is_filein then "cancel_receive ()" else "0");
6460              | Dev_or_Path n ->
6461                  pr_args n;
6462                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6463                    n (if is_filein then "cancel_receive ()" else "0");
6464              | String n -> pr_args n
6465              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6466              | StringList n ->
6467                  pr_list_handling_code n;
6468              | DeviceList n ->
6469                  pr_list_handling_code n;
6470                  pr "  /* Ensure that each is a device,\n";
6471                  pr "   * and perform device name translation. */\n";
6472                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6473                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6474                    (if is_filein then "cancel_receive ()" else "0");
6475                  pr "  }\n";
6476              | Bool n -> pr "  %s = args.%s;\n" n n
6477              | Int n -> pr "  %s = args.%s;\n" n n
6478              | Int64 n -> pr "  %s = args.%s;\n" n n
6479              | FileIn _ | FileOut _ -> ()
6480              | BufferIn n ->
6481                  pr "  %s = args.%s.%s_val;\n" n n n;
6482                  pr "  %s_size = args.%s.%s_len;\n" n n n
6483            ) args;
6484            pr "\n"
6485       );
6486
6487       (* this is used at least for do_equal *)
6488       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6489         (* Emit NEED_ROOT just once, even when there are two or
6490            more Pathname args *)
6491         pr "  NEED_ROOT (%s, goto done);\n"
6492           (if is_filein then "cancel_receive ()" else "0");
6493       );
6494
6495       (* Don't want to call the impl with any FileIn or FileOut
6496        * parameters, since these go "outside" the RPC protocol.
6497        *)
6498       let args' =
6499         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6500           (snd style) in
6501       pr "  r = do_%s " name;
6502       generate_c_call_args (fst style, args');
6503       pr ";\n";
6504
6505       (match fst style with
6506        | RErr | RInt _ | RInt64 _ | RBool _
6507        | RConstString _ | RConstOptString _
6508        | RString _ | RStringList _ | RHashtable _
6509        | RStruct (_, _) | RStructList (_, _) ->
6510            pr "  if (r == %s)\n" error_code;
6511            pr "    /* do_%s has already called reply_with_error */\n" name;
6512            pr "    goto done;\n";
6513            pr "\n"
6514        | RBufferOut _ ->
6515            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6516            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6517            pr "   */\n";
6518            pr "  if (size == 1 && r == %s)\n" error_code;
6519            pr "    /* do_%s has already called reply_with_error */\n" name;
6520            pr "    goto done;\n";
6521            pr "\n"
6522       );
6523
6524       (* If there are any FileOut parameters, then the impl must
6525        * send its own reply.
6526        *)
6527       let no_reply =
6528         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6529       if no_reply then
6530         pr "  /* do_%s has already sent a reply */\n" name
6531       else (
6532         match fst style with
6533         | RErr -> pr "  reply (NULL, NULL);\n"
6534         | RInt n | RInt64 n | RBool n ->
6535             pr "  struct guestfs_%s_ret ret;\n" name;
6536             pr "  ret.%s = r;\n" n;
6537             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6538               name
6539         | RConstString _ | RConstOptString _ ->
6540             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6541         | RString n ->
6542             pr "  struct guestfs_%s_ret ret;\n" name;
6543             pr "  ret.%s = r;\n" n;
6544             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6545               name;
6546             pr "  free (r);\n"
6547         | RStringList n | RHashtable n ->
6548             pr "  struct guestfs_%s_ret ret;\n" name;
6549             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6550             pr "  ret.%s.%s_val = r;\n" n n;
6551             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6552               name;
6553             pr "  free_strings (r);\n"
6554         | RStruct (n, _) ->
6555             pr "  struct guestfs_%s_ret ret;\n" name;
6556             pr "  ret.%s = *r;\n" n;
6557             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6558               name;
6559             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6560               name
6561         | RStructList (n, _) ->
6562             pr "  struct guestfs_%s_ret ret;\n" name;
6563             pr "  ret.%s = *r;\n" n;
6564             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6565               name;
6566             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6567               name
6568         | RBufferOut n ->
6569             pr "  struct guestfs_%s_ret ret;\n" name;
6570             pr "  ret.%s.%s_val = r;\n" n n;
6571             pr "  ret.%s.%s_len = size;\n" n n;
6572             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6573               name;
6574             pr "  free (r);\n"
6575       );
6576
6577       (* Free the args. *)
6578       pr "done:\n";
6579       (match snd style with
6580        | [] -> ()
6581        | _ ->
6582            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6583              name
6584       );
6585       pr "  return;\n";
6586       pr "}\n\n";
6587   ) daemon_functions;
6588
6589   (* Dispatch function. *)
6590   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6591   pr "{\n";
6592   pr "  switch (proc_nr) {\n";
6593
6594   List.iter (
6595     fun (name, style, _, _, _, _, _) ->
6596       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6597       pr "      %s_stub (xdr_in);\n" name;
6598       pr "      break;\n"
6599   ) daemon_functions;
6600
6601   pr "    default:\n";
6602   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";
6603   pr "  }\n";
6604   pr "}\n";
6605   pr "\n";
6606
6607   (* LVM columns and tokenization functions. *)
6608   (* XXX This generates crap code.  We should rethink how we
6609    * do this parsing.
6610    *)
6611   List.iter (
6612     function
6613     | typ, cols ->
6614         pr "static const char *lvm_%s_cols = \"%s\";\n"
6615           typ (String.concat "," (List.map fst cols));
6616         pr "\n";
6617
6618         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6619         pr "{\n";
6620         pr "  char *tok, *p, *next;\n";
6621         pr "  int i, j;\n";
6622         pr "\n";
6623         (*
6624           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6625           pr "\n";
6626         *)
6627         pr "  if (!str) {\n";
6628         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6629         pr "    return -1;\n";
6630         pr "  }\n";
6631         pr "  if (!*str || c_isspace (*str)) {\n";
6632         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6633         pr "    return -1;\n";
6634         pr "  }\n";
6635         pr "  tok = str;\n";
6636         List.iter (
6637           fun (name, coltype) ->
6638             pr "  if (!tok) {\n";
6639             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6640             pr "    return -1;\n";
6641             pr "  }\n";
6642             pr "  p = strchrnul (tok, ',');\n";
6643             pr "  if (*p) next = p+1; else next = NULL;\n";
6644             pr "  *p = '\\0';\n";
6645             (match coltype with
6646              | FString ->
6647                  pr "  r->%s = strdup (tok);\n" name;
6648                  pr "  if (r->%s == NULL) {\n" name;
6649                  pr "    perror (\"strdup\");\n";
6650                  pr "    return -1;\n";
6651                  pr "  }\n"
6652              | FUUID ->
6653                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6654                  pr "    if (tok[j] == '\\0') {\n";
6655                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6656                  pr "      return -1;\n";
6657                  pr "    } else if (tok[j] != '-')\n";
6658                  pr "      r->%s[i++] = tok[j];\n" name;
6659                  pr "  }\n";
6660              | FBytes ->
6661                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6662                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6663                  pr "    return -1;\n";
6664                  pr "  }\n";
6665              | FInt64 ->
6666                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6667                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6668                  pr "    return -1;\n";
6669                  pr "  }\n";
6670              | FOptPercent ->
6671                  pr "  if (tok[0] == '\\0')\n";
6672                  pr "    r->%s = -1;\n" name;
6673                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6674                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6675                  pr "    return -1;\n";
6676                  pr "  }\n";
6677              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6678                  assert false (* can never be an LVM column *)
6679             );
6680             pr "  tok = next;\n";
6681         ) cols;
6682
6683         pr "  if (tok != NULL) {\n";
6684         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6685         pr "    return -1;\n";
6686         pr "  }\n";
6687         pr "  return 0;\n";
6688         pr "}\n";
6689         pr "\n";
6690
6691         pr "guestfs_int_lvm_%s_list *\n" typ;
6692         pr "parse_command_line_%ss (void)\n" typ;
6693         pr "{\n";
6694         pr "  char *out, *err;\n";
6695         pr "  char *p, *pend;\n";
6696         pr "  int r, i;\n";
6697         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6698         pr "  void *newp;\n";
6699         pr "\n";
6700         pr "  ret = malloc (sizeof *ret);\n";
6701         pr "  if (!ret) {\n";
6702         pr "    reply_with_perror (\"malloc\");\n";
6703         pr "    return NULL;\n";
6704         pr "  }\n";
6705         pr "\n";
6706         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6707         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6708         pr "\n";
6709         pr "  r = command (&out, &err,\n";
6710         pr "           \"lvm\", \"%ss\",\n" typ;
6711         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6712         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6713         pr "  if (r == -1) {\n";
6714         pr "    reply_with_error (\"%%s\", err);\n";
6715         pr "    free (out);\n";
6716         pr "    free (err);\n";
6717         pr "    free (ret);\n";
6718         pr "    return NULL;\n";
6719         pr "  }\n";
6720         pr "\n";
6721         pr "  free (err);\n";
6722         pr "\n";
6723         pr "  /* Tokenize each line of the output. */\n";
6724         pr "  p = out;\n";
6725         pr "  i = 0;\n";
6726         pr "  while (p) {\n";
6727         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6728         pr "    if (pend) {\n";
6729         pr "      *pend = '\\0';\n";
6730         pr "      pend++;\n";
6731         pr "    }\n";
6732         pr "\n";
6733         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6734         pr "      p++;\n";
6735         pr "\n";
6736         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6737         pr "      p = pend;\n";
6738         pr "      continue;\n";
6739         pr "    }\n";
6740         pr "\n";
6741         pr "    /* Allocate some space to store this next entry. */\n";
6742         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6743         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6744         pr "    if (newp == NULL) {\n";
6745         pr "      reply_with_perror (\"realloc\");\n";
6746         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6747         pr "      free (ret);\n";
6748         pr "      free (out);\n";
6749         pr "      return NULL;\n";
6750         pr "    }\n";
6751         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6752         pr "\n";
6753         pr "    /* Tokenize the next entry. */\n";
6754         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6755         pr "    if (r == -1) {\n";
6756         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6757         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6758         pr "      free (ret);\n";
6759         pr "      free (out);\n";
6760         pr "      return NULL;\n";
6761         pr "    }\n";
6762         pr "\n";
6763         pr "    ++i;\n";
6764         pr "    p = pend;\n";
6765         pr "  }\n";
6766         pr "\n";
6767         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6768         pr "\n";
6769         pr "  free (out);\n";
6770         pr "  return ret;\n";
6771         pr "}\n"
6772
6773   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6774
6775 (* Generate a list of function names, for debugging in the daemon.. *)
6776 and generate_daemon_names () =
6777   generate_header CStyle GPLv2plus;
6778
6779   pr "#include <config.h>\n";
6780   pr "\n";
6781   pr "#include \"daemon.h\"\n";
6782   pr "\n";
6783
6784   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6785   pr "const char *function_names[] = {\n";
6786   List.iter (
6787     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6788   ) daemon_functions;
6789   pr "};\n";
6790
6791 (* Generate the optional groups for the daemon to implement
6792  * guestfs_available.
6793  *)
6794 and generate_daemon_optgroups_c () =
6795   generate_header CStyle GPLv2plus;
6796
6797   pr "#include <config.h>\n";
6798   pr "\n";
6799   pr "#include \"daemon.h\"\n";
6800   pr "#include \"optgroups.h\"\n";
6801   pr "\n";
6802
6803   pr "struct optgroup optgroups[] = {\n";
6804   List.iter (
6805     fun (group, _) ->
6806       pr "  { \"%s\", optgroup_%s_available },\n" group group
6807   ) optgroups;
6808   pr "  { NULL, NULL }\n";
6809   pr "};\n"
6810
6811 and generate_daemon_optgroups_h () =
6812   generate_header CStyle GPLv2plus;
6813
6814   List.iter (
6815     fun (group, _) ->
6816       pr "extern int optgroup_%s_available (void);\n" group
6817   ) optgroups
6818
6819 (* Generate the tests. *)
6820 and generate_tests () =
6821   generate_header CStyle GPLv2plus;
6822
6823   pr "\
6824 #include <stdio.h>
6825 #include <stdlib.h>
6826 #include <string.h>
6827 #include <unistd.h>
6828 #include <sys/types.h>
6829 #include <fcntl.h>
6830
6831 #include \"guestfs.h\"
6832 #include \"guestfs-internal.h\"
6833
6834 static guestfs_h *g;
6835 static int suppress_error = 0;
6836
6837 static void print_error (guestfs_h *g, void *data, const char *msg)
6838 {
6839   if (!suppress_error)
6840     fprintf (stderr, \"%%s\\n\", msg);
6841 }
6842
6843 /* FIXME: nearly identical code appears in fish.c */
6844 static void print_strings (char *const *argv)
6845 {
6846   int argc;
6847
6848   for (argc = 0; argv[argc] != NULL; ++argc)
6849     printf (\"\\t%%s\\n\", argv[argc]);
6850 }
6851
6852 /*
6853 static void print_table (char const *const *argv)
6854 {
6855   int i;
6856
6857   for (i = 0; argv[i] != NULL; i += 2)
6858     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6859 }
6860 */
6861
6862 static int
6863 is_available (const char *group)
6864 {
6865   const char *groups[] = { group, NULL };
6866   int r;
6867
6868   suppress_error = 1;
6869   r = guestfs_available (g, (char **) groups);
6870   suppress_error = 0;
6871
6872   return r == 0;
6873 }
6874
6875 ";
6876
6877   (* Generate a list of commands which are not tested anywhere. *)
6878   pr "static void no_test_warnings (void)\n";
6879   pr "{\n";
6880
6881   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6882   List.iter (
6883     fun (_, _, _, _, tests, _, _) ->
6884       let tests = filter_map (
6885         function
6886         | (_, (Always|If _|Unless _|IfAvailable _), test) -> Some test
6887         | (_, Disabled, _) -> None
6888       ) tests in
6889       let seq = List.concat (List.map seq_of_test tests) in
6890       let cmds_tested = List.map List.hd seq in
6891       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6892   ) all_functions;
6893
6894   List.iter (
6895     fun (name, _, _, _, _, _, _) ->
6896       if not (Hashtbl.mem hash name) then
6897         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6898   ) all_functions;
6899
6900   pr "}\n";
6901   pr "\n";
6902
6903   (* Generate the actual tests.  Note that we generate the tests
6904    * in reverse order, deliberately, so that (in general) the
6905    * newest tests run first.  This makes it quicker and easier to
6906    * debug them.
6907    *)
6908   let test_names =
6909     List.map (
6910       fun (name, _, _, flags, tests, _, _) ->
6911         mapi (generate_one_test name flags) tests
6912     ) (List.rev all_functions) in
6913   let test_names = List.concat test_names in
6914   let nr_tests = List.length test_names in
6915
6916   pr "\
6917 int main (int argc, char *argv[])
6918 {
6919   char c = 0;
6920   unsigned long int n_failed = 0;
6921   const char *filename;
6922   int fd;
6923   int nr_tests, test_num = 0;
6924
6925   setbuf (stdout, NULL);
6926
6927   no_test_warnings ();
6928
6929   g = guestfs_create ();
6930   if (g == NULL) {
6931     printf (\"guestfs_create FAILED\\n\");
6932     exit (EXIT_FAILURE);
6933   }
6934
6935   guestfs_set_error_handler (g, print_error, NULL);
6936
6937   guestfs_set_path (g, \"../appliance\");
6938
6939   filename = \"test1.img\";
6940   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6941   if (fd == -1) {
6942     perror (filename);
6943     exit (EXIT_FAILURE);
6944   }
6945   if (lseek (fd, %d, SEEK_SET) == -1) {
6946     perror (\"lseek\");
6947     close (fd);
6948     unlink (filename);
6949     exit (EXIT_FAILURE);
6950   }
6951   if (write (fd, &c, 1) == -1) {
6952     perror (\"write\");
6953     close (fd);
6954     unlink (filename);
6955     exit (EXIT_FAILURE);
6956   }
6957   if (close (fd) == -1) {
6958     perror (filename);
6959     unlink (filename);
6960     exit (EXIT_FAILURE);
6961   }
6962   if (guestfs_add_drive (g, filename) == -1) {
6963     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6964     exit (EXIT_FAILURE);
6965   }
6966
6967   filename = \"test2.img\";
6968   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6969   if (fd == -1) {
6970     perror (filename);
6971     exit (EXIT_FAILURE);
6972   }
6973   if (lseek (fd, %d, SEEK_SET) == -1) {
6974     perror (\"lseek\");
6975     close (fd);
6976     unlink (filename);
6977     exit (EXIT_FAILURE);
6978   }
6979   if (write (fd, &c, 1) == -1) {
6980     perror (\"write\");
6981     close (fd);
6982     unlink (filename);
6983     exit (EXIT_FAILURE);
6984   }
6985   if (close (fd) == -1) {
6986     perror (filename);
6987     unlink (filename);
6988     exit (EXIT_FAILURE);
6989   }
6990   if (guestfs_add_drive (g, filename) == -1) {
6991     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6992     exit (EXIT_FAILURE);
6993   }
6994
6995   filename = \"test3.img\";
6996   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6997   if (fd == -1) {
6998     perror (filename);
6999     exit (EXIT_FAILURE);
7000   }
7001   if (lseek (fd, %d, SEEK_SET) == -1) {
7002     perror (\"lseek\");
7003     close (fd);
7004     unlink (filename);
7005     exit (EXIT_FAILURE);
7006   }
7007   if (write (fd, &c, 1) == -1) {
7008     perror (\"write\");
7009     close (fd);
7010     unlink (filename);
7011     exit (EXIT_FAILURE);
7012   }
7013   if (close (fd) == -1) {
7014     perror (filename);
7015     unlink (filename);
7016     exit (EXIT_FAILURE);
7017   }
7018   if (guestfs_add_drive (g, filename) == -1) {
7019     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7020     exit (EXIT_FAILURE);
7021   }
7022
7023   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
7024     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
7025     exit (EXIT_FAILURE);
7026   }
7027
7028   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
7029   alarm (600);
7030
7031   if (guestfs_launch (g) == -1) {
7032     printf (\"guestfs_launch FAILED\\n\");
7033     exit (EXIT_FAILURE);
7034   }
7035
7036   /* Cancel previous alarm. */
7037   alarm (0);
7038
7039   nr_tests = %d;
7040
7041 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
7042
7043   iteri (
7044     fun i test_name ->
7045       pr "  test_num++;\n";
7046       pr "  if (guestfs_get_verbose (g))\n";
7047       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
7048       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
7049       pr "  if (%s () == -1) {\n" test_name;
7050       pr "    printf (\"%s FAILED\\n\");\n" test_name;
7051       pr "    n_failed++;\n";
7052       pr "  }\n";
7053   ) test_names;
7054   pr "\n";
7055
7056   pr "  guestfs_close (g);\n";
7057   pr "  unlink (\"test1.img\");\n";
7058   pr "  unlink (\"test2.img\");\n";
7059   pr "  unlink (\"test3.img\");\n";
7060   pr "\n";
7061
7062   pr "  if (n_failed > 0) {\n";
7063   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7064   pr "    exit (EXIT_FAILURE);\n";
7065   pr "  }\n";
7066   pr "\n";
7067
7068   pr "  exit (EXIT_SUCCESS);\n";
7069   pr "}\n"
7070
7071 and generate_one_test name flags i (init, prereq, test) =
7072   let test_name = sprintf "test_%s_%d" name i in
7073
7074   pr "\
7075 static int %s_skip (void)
7076 {
7077   const char *str;
7078
7079   str = getenv (\"TEST_ONLY\");
7080   if (str)
7081     return strstr (str, \"%s\") == NULL;
7082   str = getenv (\"SKIP_%s\");
7083   if (str && STREQ (str, \"1\")) return 1;
7084   str = getenv (\"SKIP_TEST_%s\");
7085   if (str && STREQ (str, \"1\")) return 1;
7086   return 0;
7087 }
7088
7089 " test_name name (String.uppercase test_name) (String.uppercase name);
7090
7091   (match prereq with
7092    | Disabled | Always | IfAvailable _ -> ()
7093    | If code | Unless code ->
7094        pr "static int %s_prereq (void)\n" test_name;
7095        pr "{\n";
7096        pr "  %s\n" code;
7097        pr "}\n";
7098        pr "\n";
7099   );
7100
7101   pr "\
7102 static int %s (void)
7103 {
7104   if (%s_skip ()) {
7105     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7106     return 0;
7107   }
7108
7109 " test_name test_name test_name;
7110
7111   (* Optional functions should only be tested if the relevant
7112    * support is available in the daemon.
7113    *)
7114   List.iter (
7115     function
7116     | Optional group ->
7117         pr "  if (!is_available (\"%s\")) {\n" group;
7118         pr "    printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", \"%s\");\n" test_name group;
7119         pr "    return 0;\n";
7120         pr "  }\n";
7121     | _ -> ()
7122   ) flags;
7123
7124   (match prereq with
7125    | Disabled ->
7126        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7127    | If _ ->
7128        pr "  if (! %s_prereq ()) {\n" test_name;
7129        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7130        pr "    return 0;\n";
7131        pr "  }\n";
7132        pr "\n";
7133        generate_one_test_body name i test_name init test;
7134    | Unless _ ->
7135        pr "  if (%s_prereq ()) {\n" test_name;
7136        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7137        pr "    return 0;\n";
7138        pr "  }\n";
7139        pr "\n";
7140        generate_one_test_body name i test_name init test;
7141    | IfAvailable group ->
7142        pr "  if (!is_available (\"%s\")) {\n" group;
7143        pr "    printf (\"        %%s skipped (reason: %%s not available)\\n\", \"%s\", \"%s\");\n" test_name group;
7144        pr "    return 0;\n";
7145        pr "  }\n";
7146        pr "\n";
7147        generate_one_test_body name i test_name init test;
7148    | Always ->
7149        generate_one_test_body name i test_name init test
7150   );
7151
7152   pr "  return 0;\n";
7153   pr "}\n";
7154   pr "\n";
7155   test_name
7156
7157 and generate_one_test_body name i test_name init test =
7158   (match init with
7159    | InitNone (* XXX at some point, InitNone and InitEmpty became
7160                * folded together as the same thing.  Really we should
7161                * make InitNone do nothing at all, but the tests may
7162                * need to be checked to make sure this is OK.
7163                *)
7164    | InitEmpty ->
7165        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7166        List.iter (generate_test_command_call test_name)
7167          [["blockdev_setrw"; "/dev/sda"];
7168           ["umount_all"];
7169           ["lvm_remove_all"]]
7170    | InitPartition ->
7171        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7172        List.iter (generate_test_command_call test_name)
7173          [["blockdev_setrw"; "/dev/sda"];
7174           ["umount_all"];
7175           ["lvm_remove_all"];
7176           ["part_disk"; "/dev/sda"; "mbr"]]
7177    | InitBasicFS ->
7178        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7179        List.iter (generate_test_command_call test_name)
7180          [["blockdev_setrw"; "/dev/sda"];
7181           ["umount_all"];
7182           ["lvm_remove_all"];
7183           ["part_disk"; "/dev/sda"; "mbr"];
7184           ["mkfs"; "ext2"; "/dev/sda1"];
7185           ["mount_options"; ""; "/dev/sda1"; "/"]]
7186    | InitBasicFSonLVM ->
7187        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7188          test_name;
7189        List.iter (generate_test_command_call test_name)
7190          [["blockdev_setrw"; "/dev/sda"];
7191           ["umount_all"];
7192           ["lvm_remove_all"];
7193           ["part_disk"; "/dev/sda"; "mbr"];
7194           ["pvcreate"; "/dev/sda1"];
7195           ["vgcreate"; "VG"; "/dev/sda1"];
7196           ["lvcreate"; "LV"; "VG"; "8"];
7197           ["mkfs"; "ext2"; "/dev/VG/LV"];
7198           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7199    | InitISOFS ->
7200        pr "  /* InitISOFS for %s */\n" test_name;
7201        List.iter (generate_test_command_call test_name)
7202          [["blockdev_setrw"; "/dev/sda"];
7203           ["umount_all"];
7204           ["lvm_remove_all"];
7205           ["mount_ro"; "/dev/sdd"; "/"]]
7206   );
7207
7208   let get_seq_last = function
7209     | [] ->
7210         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7211           test_name
7212     | seq ->
7213         let seq = List.rev seq in
7214         List.rev (List.tl seq), List.hd seq
7215   in
7216
7217   match test with
7218   | TestRun seq ->
7219       pr "  /* TestRun for %s (%d) */\n" name i;
7220       List.iter (generate_test_command_call test_name) seq
7221   | TestOutput (seq, expected) ->
7222       pr "  /* TestOutput for %s (%d) */\n" name i;
7223       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7224       let seq, last = get_seq_last seq in
7225       let test () =
7226         pr "    if (STRNEQ (r, expected)) {\n";
7227         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7228         pr "      return -1;\n";
7229         pr "    }\n"
7230       in
7231       List.iter (generate_test_command_call test_name) seq;
7232       generate_test_command_call ~test test_name last
7233   | TestOutputList (seq, expected) ->
7234       pr "  /* TestOutputList for %s (%d) */\n" name i;
7235       let seq, last = get_seq_last seq in
7236       let test () =
7237         iteri (
7238           fun i str ->
7239             pr "    if (!r[%d]) {\n" i;
7240             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7241             pr "      print_strings (r);\n";
7242             pr "      return -1;\n";
7243             pr "    }\n";
7244             pr "    {\n";
7245             pr "      const char *expected = \"%s\";\n" (c_quote str);
7246             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7247             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7248             pr "        return -1;\n";
7249             pr "      }\n";
7250             pr "    }\n"
7251         ) expected;
7252         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7253         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7254           test_name;
7255         pr "      print_strings (r);\n";
7256         pr "      return -1;\n";
7257         pr "    }\n"
7258       in
7259       List.iter (generate_test_command_call test_name) seq;
7260       generate_test_command_call ~test test_name last
7261   | TestOutputListOfDevices (seq, expected) ->
7262       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7263       let seq, last = get_seq_last seq in
7264       let test () =
7265         iteri (
7266           fun i str ->
7267             pr "    if (!r[%d]) {\n" i;
7268             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7269             pr "      print_strings (r);\n";
7270             pr "      return -1;\n";
7271             pr "    }\n";
7272             pr "    {\n";
7273             pr "      const char *expected = \"%s\";\n" (c_quote str);
7274             pr "      r[%d][5] = 's';\n" i;
7275             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7276             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7277             pr "        return -1;\n";
7278             pr "      }\n";
7279             pr "    }\n"
7280         ) expected;
7281         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7282         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7283           test_name;
7284         pr "      print_strings (r);\n";
7285         pr "      return -1;\n";
7286         pr "    }\n"
7287       in
7288       List.iter (generate_test_command_call test_name) seq;
7289       generate_test_command_call ~test test_name last
7290   | TestOutputInt (seq, expected) ->
7291       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7292       let seq, last = get_seq_last seq in
7293       let test () =
7294         pr "    if (r != %d) {\n" expected;
7295         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7296           test_name expected;
7297         pr "               (int) r);\n";
7298         pr "      return -1;\n";
7299         pr "    }\n"
7300       in
7301       List.iter (generate_test_command_call test_name) seq;
7302       generate_test_command_call ~test test_name last
7303   | TestOutputIntOp (seq, op, expected) ->
7304       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7305       let seq, last = get_seq_last seq in
7306       let test () =
7307         pr "    if (! (r %s %d)) {\n" op expected;
7308         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7309           test_name op expected;
7310         pr "               (int) r);\n";
7311         pr "      return -1;\n";
7312         pr "    }\n"
7313       in
7314       List.iter (generate_test_command_call test_name) seq;
7315       generate_test_command_call ~test test_name last
7316   | TestOutputTrue seq ->
7317       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7318       let seq, last = get_seq_last seq in
7319       let test () =
7320         pr "    if (!r) {\n";
7321         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7322           test_name;
7323         pr "      return -1;\n";
7324         pr "    }\n"
7325       in
7326       List.iter (generate_test_command_call test_name) seq;
7327       generate_test_command_call ~test test_name last
7328   | TestOutputFalse seq ->
7329       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7330       let seq, last = get_seq_last seq in
7331       let test () =
7332         pr "    if (r) {\n";
7333         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7334           test_name;
7335         pr "      return -1;\n";
7336         pr "    }\n"
7337       in
7338       List.iter (generate_test_command_call test_name) seq;
7339       generate_test_command_call ~test test_name last
7340   | TestOutputLength (seq, expected) ->
7341       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7342       let seq, last = get_seq_last seq in
7343       let test () =
7344         pr "    int j;\n";
7345         pr "    for (j = 0; j < %d; ++j)\n" expected;
7346         pr "      if (r[j] == NULL) {\n";
7347         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7348           test_name;
7349         pr "        print_strings (r);\n";
7350         pr "        return -1;\n";
7351         pr "      }\n";
7352         pr "    if (r[j] != NULL) {\n";
7353         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7354           test_name;
7355         pr "      print_strings (r);\n";
7356         pr "      return -1;\n";
7357         pr "    }\n"
7358       in
7359       List.iter (generate_test_command_call test_name) seq;
7360       generate_test_command_call ~test test_name last
7361   | TestOutputBuffer (seq, expected) ->
7362       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7363       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7364       let seq, last = get_seq_last seq in
7365       let len = String.length expected in
7366       let test () =
7367         pr "    if (size != %d) {\n" len;
7368         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7369         pr "      return -1;\n";
7370         pr "    }\n";
7371         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7372         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7373         pr "      return -1;\n";
7374         pr "    }\n"
7375       in
7376       List.iter (generate_test_command_call test_name) seq;
7377       generate_test_command_call ~test test_name last
7378   | TestOutputStruct (seq, checks) ->
7379       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7380       let seq, last = get_seq_last seq in
7381       let test () =
7382         List.iter (
7383           function
7384           | CompareWithInt (field, expected) ->
7385               pr "    if (r->%s != %d) {\n" field expected;
7386               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7387                 test_name field expected;
7388               pr "               (int) r->%s);\n" field;
7389               pr "      return -1;\n";
7390               pr "    }\n"
7391           | CompareWithIntOp (field, op, expected) ->
7392               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7393               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7394                 test_name field op expected;
7395               pr "               (int) r->%s);\n" field;
7396               pr "      return -1;\n";
7397               pr "    }\n"
7398           | CompareWithString (field, expected) ->
7399               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7400               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7401                 test_name field expected;
7402               pr "               r->%s);\n" field;
7403               pr "      return -1;\n";
7404               pr "    }\n"
7405           | CompareFieldsIntEq (field1, field2) ->
7406               pr "    if (r->%s != r->%s) {\n" field1 field2;
7407               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7408                 test_name field1 field2;
7409               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7410               pr "      return -1;\n";
7411               pr "    }\n"
7412           | CompareFieldsStrEq (field1, field2) ->
7413               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7414               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7415                 test_name field1 field2;
7416               pr "               r->%s, r->%s);\n" field1 field2;
7417               pr "      return -1;\n";
7418               pr "    }\n"
7419         ) checks
7420       in
7421       List.iter (generate_test_command_call test_name) seq;
7422       generate_test_command_call ~test test_name last
7423   | TestLastFail seq ->
7424       pr "  /* TestLastFail for %s (%d) */\n" name i;
7425       let seq, last = get_seq_last seq in
7426       List.iter (generate_test_command_call test_name) seq;
7427       generate_test_command_call test_name ~expect_error:true last
7428
7429 (* Generate the code to run a command, leaving the result in 'r'.
7430  * If you expect to get an error then you should set expect_error:true.
7431  *)
7432 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7433   match cmd with
7434   | [] -> assert false
7435   | name :: args ->
7436       (* Look up the command to find out what args/ret it has. *)
7437       let style =
7438         try
7439           let _, style, _, _, _, _, _ =
7440             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7441           style
7442         with Not_found ->
7443           failwithf "%s: in test, command %s was not found" test_name name in
7444
7445       if List.length (snd style) <> List.length args then
7446         failwithf "%s: in test, wrong number of args given to %s"
7447           test_name name;
7448
7449       pr "  {\n";
7450
7451       List.iter (
7452         function
7453         | OptString n, "NULL" -> ()
7454         | Pathname n, arg
7455         | Device n, arg
7456         | Dev_or_Path n, arg
7457         | String n, arg
7458         | OptString n, arg ->
7459             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7460         | BufferIn n, arg ->
7461             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7462             pr "    size_t %s_size = %d;\n" n (String.length arg)
7463         | Int _, _
7464         | Int64 _, _
7465         | Bool _, _
7466         | FileIn _, _ | FileOut _, _ -> ()
7467         | StringList n, "" | DeviceList n, "" ->
7468             pr "    const char *const %s[1] = { NULL };\n" n
7469         | StringList n, arg | DeviceList n, arg ->
7470             let strs = string_split " " arg in
7471             iteri (
7472               fun i str ->
7473                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7474             ) strs;
7475             pr "    const char *const %s[] = {\n" n;
7476             iteri (
7477               fun i _ -> pr "      %s_%d,\n" n i
7478             ) strs;
7479             pr "      NULL\n";
7480             pr "    };\n";
7481       ) (List.combine (snd style) args);
7482
7483       let error_code =
7484         match fst style with
7485         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7486         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7487         | RConstString _ | RConstOptString _ ->
7488             pr "    const char *r;\n"; "NULL"
7489         | RString _ -> pr "    char *r;\n"; "NULL"
7490         | RStringList _ | RHashtable _ ->
7491             pr "    char **r;\n";
7492             pr "    int i;\n";
7493             "NULL"
7494         | RStruct (_, typ) ->
7495             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7496         | RStructList (_, typ) ->
7497             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7498         | RBufferOut _ ->
7499             pr "    char *r;\n";
7500             pr "    size_t size;\n";
7501             "NULL" in
7502
7503       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7504       pr "    r = guestfs_%s (g" name;
7505
7506       (* Generate the parameters. *)
7507       List.iter (
7508         function
7509         | OptString _, "NULL" -> pr ", NULL"
7510         | Pathname n, _
7511         | Device n, _ | Dev_or_Path n, _
7512         | String n, _
7513         | OptString n, _ ->
7514             pr ", %s" n
7515         | BufferIn n, _ ->
7516             pr ", %s, %s_size" n n
7517         | FileIn _, arg | FileOut _, arg ->
7518             pr ", \"%s\"" (c_quote arg)
7519         | StringList n, _ | DeviceList n, _ ->
7520             pr ", (char **) %s" n
7521         | Int _, arg ->
7522             let i =
7523               try int_of_string arg
7524               with Failure "int_of_string" ->
7525                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7526             pr ", %d" i
7527         | Int64 _, arg ->
7528             let i =
7529               try Int64.of_string arg
7530               with Failure "int_of_string" ->
7531                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7532             pr ", %Ld" i
7533         | Bool _, arg ->
7534             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7535       ) (List.combine (snd style) args);
7536
7537       (match fst style with
7538        | RBufferOut _ -> pr ", &size"
7539        | _ -> ()
7540       );
7541
7542       pr ");\n";
7543
7544       if not expect_error then
7545         pr "    if (r == %s)\n" error_code
7546       else
7547         pr "    if (r != %s)\n" error_code;
7548       pr "      return -1;\n";
7549
7550       (* Insert the test code. *)
7551       (match test with
7552        | None -> ()
7553        | Some f -> f ()
7554       );
7555
7556       (match fst style with
7557        | RErr | RInt _ | RInt64 _ | RBool _
7558        | RConstString _ | RConstOptString _ -> ()
7559        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7560        | RStringList _ | RHashtable _ ->
7561            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7562            pr "      free (r[i]);\n";
7563            pr "    free (r);\n"
7564        | RStruct (_, typ) ->
7565            pr "    guestfs_free_%s (r);\n" typ
7566        | RStructList (_, typ) ->
7567            pr "    guestfs_free_%s_list (r);\n" typ
7568       );
7569
7570       pr "  }\n"
7571
7572 and c_quote str =
7573   let str = replace_str str "\r" "\\r" in
7574   let str = replace_str str "\n" "\\n" in
7575   let str = replace_str str "\t" "\\t" in
7576   let str = replace_str str "\000" "\\0" in
7577   str
7578
7579 (* Generate a lot of different functions for guestfish. *)
7580 and generate_fish_cmds () =
7581   generate_header CStyle GPLv2plus;
7582
7583   let all_functions =
7584     List.filter (
7585       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7586     ) all_functions in
7587   let all_functions_sorted =
7588     List.filter (
7589       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7590     ) all_functions_sorted in
7591
7592   pr "#include <config.h>\n";
7593   pr "\n";
7594   pr "#include <stdio.h>\n";
7595   pr "#include <stdlib.h>\n";
7596   pr "#include <string.h>\n";
7597   pr "#include <inttypes.h>\n";
7598   pr "\n";
7599   pr "#include <guestfs.h>\n";
7600   pr "#include \"c-ctype.h\"\n";
7601   pr "#include \"full-write.h\"\n";
7602   pr "#include \"xstrtol.h\"\n";
7603   pr "#include \"fish.h\"\n";
7604   pr "\n";
7605   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7606   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7607   pr "\n";
7608
7609   (* list_commands function, which implements guestfish -h *)
7610   pr "void list_commands (void)\n";
7611   pr "{\n";
7612   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7613   pr "  list_builtin_commands ();\n";
7614   List.iter (
7615     fun (name, _, _, flags, _, shortdesc, _) ->
7616       let name = replace_char name '_' '-' in
7617       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7618         name shortdesc
7619   ) all_functions_sorted;
7620   pr "  printf (\"    %%s\\n\",";
7621   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7622   pr "}\n";
7623   pr "\n";
7624
7625   (* display_command function, which implements guestfish -h cmd *)
7626   pr "int display_command (const char *cmd)\n";
7627   pr "{\n";
7628   List.iter (
7629     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7630       let name2 = replace_char name '_' '-' in
7631       let alias =
7632         try find_map (function FishAlias n -> Some n | _ -> None) flags
7633         with Not_found -> name in
7634       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7635       let synopsis =
7636         match snd style with
7637         | [] -> name2
7638         | args ->
7639             sprintf "%s %s"
7640               name2 (String.concat " " (List.map name_of_argt args)) in
7641
7642       let warnings =
7643         if List.mem ProtocolLimitWarning flags then
7644           ("\n\n" ^ protocol_limit_warning)
7645         else "" in
7646
7647       (* For DangerWillRobinson commands, we should probably have
7648        * guestfish prompt before allowing you to use them (especially
7649        * in interactive mode). XXX
7650        *)
7651       let warnings =
7652         warnings ^
7653           if List.mem DangerWillRobinson flags then
7654             ("\n\n" ^ danger_will_robinson)
7655           else "" in
7656
7657       let warnings =
7658         warnings ^
7659           match deprecation_notice flags with
7660           | None -> ""
7661           | Some txt -> "\n\n" ^ txt in
7662
7663       let describe_alias =
7664         if name <> alias then
7665           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7666         else "" in
7667
7668       pr "  if (";
7669       pr "STRCASEEQ (cmd, \"%s\")" name;
7670       if name <> name2 then
7671         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7672       if name <> alias then
7673         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7674       pr ") {\n";
7675       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7676         name2 shortdesc
7677         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7678          "=head1 DESCRIPTION\n\n" ^
7679          longdesc ^ warnings ^ describe_alias);
7680       pr "    return 0;\n";
7681       pr "  }\n";
7682       pr "  else\n"
7683   ) all_functions;
7684   pr "    return display_builtin_command (cmd);\n";
7685   pr "}\n";
7686   pr "\n";
7687
7688   let emit_print_list_function typ =
7689     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7690       typ typ typ;
7691     pr "{\n";
7692     pr "  unsigned int i;\n";
7693     pr "\n";
7694     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7695     pr "    printf (\"[%%d] = {\\n\", i);\n";
7696     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7697     pr "    printf (\"}\\n\");\n";
7698     pr "  }\n";
7699     pr "}\n";
7700     pr "\n";
7701   in
7702
7703   (* print_* functions *)
7704   List.iter (
7705     fun (typ, cols) ->
7706       let needs_i =
7707         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7708
7709       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7710       pr "{\n";
7711       if needs_i then (
7712         pr "  unsigned int i;\n";
7713         pr "\n"
7714       );
7715       List.iter (
7716         function
7717         | name, FString ->
7718             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7719         | name, FUUID ->
7720             pr "  printf (\"%%s%s: \", indent);\n" name;
7721             pr "  for (i = 0; i < 32; ++i)\n";
7722             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7723             pr "  printf (\"\\n\");\n"
7724         | name, FBuffer ->
7725             pr "  printf (\"%%s%s: \", indent);\n" name;
7726             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7727             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7728             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7729             pr "    else\n";
7730             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7731             pr "  printf (\"\\n\");\n"
7732         | name, (FUInt64|FBytes) ->
7733             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7734               name typ name
7735         | name, FInt64 ->
7736             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7737               name typ name
7738         | name, FUInt32 ->
7739             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7740               name typ name
7741         | name, FInt32 ->
7742             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7743               name typ name
7744         | name, FChar ->
7745             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7746               name typ name
7747         | name, FOptPercent ->
7748             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7749               typ name name typ name;
7750             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7751       ) cols;
7752       pr "}\n";
7753       pr "\n";
7754   ) structs;
7755
7756   (* Emit a print_TYPE_list function definition only if that function is used. *)
7757   List.iter (
7758     function
7759     | typ, (RStructListOnly | RStructAndList) ->
7760         (* generate the function for typ *)
7761         emit_print_list_function typ
7762     | typ, _ -> () (* empty *)
7763   ) (rstructs_used_by all_functions);
7764
7765   (* Emit a print_TYPE function definition only if that function is used. *)
7766   List.iter (
7767     function
7768     | typ, (RStructOnly | RStructAndList) ->
7769         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7770         pr "{\n";
7771         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7772         pr "}\n";
7773         pr "\n";
7774     | typ, _ -> () (* empty *)
7775   ) (rstructs_used_by all_functions);
7776
7777   (* run_<action> actions *)
7778   List.iter (
7779     fun (name, style, _, flags, _, _, _) ->
7780       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7781       pr "{\n";
7782       (match fst style with
7783        | RErr
7784        | RInt _
7785        | RBool _ -> pr "  int r;\n"
7786        | RInt64 _ -> pr "  int64_t r;\n"
7787        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7788        | RString _ -> pr "  char *r;\n"
7789        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7790        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7791        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7792        | RBufferOut _ ->
7793            pr "  char *r;\n";
7794            pr "  size_t size;\n";
7795       );
7796       List.iter (
7797         function
7798         | Device n
7799         | String n
7800         | OptString n -> pr "  const char *%s;\n" n
7801         | Pathname n
7802         | Dev_or_Path n
7803         | FileIn n
7804         | FileOut n -> pr "  char *%s;\n" n
7805         | BufferIn n ->
7806             pr "  const char *%s;\n" n;
7807             pr "  size_t %s_size;\n" n
7808         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7809         | Bool n -> pr "  int %s;\n" n
7810         | Int n -> pr "  int %s;\n" n
7811         | Int64 n -> pr "  int64_t %s;\n" n
7812       ) (snd style);
7813
7814       (* Check and convert parameters. *)
7815       let argc_expected = List.length (snd style) in
7816       pr "  if (argc != %d) {\n" argc_expected;
7817       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7818         argc_expected;
7819       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7820       pr "    return -1;\n";
7821       pr "  }\n";
7822
7823       let parse_integer fn fntyp rtyp range name i =
7824         pr "  {\n";
7825         pr "    strtol_error xerr;\n";
7826         pr "    %s r;\n" fntyp;
7827         pr "\n";
7828         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7829         pr "    if (xerr != LONGINT_OK) {\n";
7830         pr "      fprintf (stderr,\n";
7831         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7832         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7833         pr "      return -1;\n";
7834         pr "    }\n";
7835         (match range with
7836          | None -> ()
7837          | Some (min, max, comment) ->
7838              pr "    /* %s */\n" comment;
7839              pr "    if (r < %s || r > %s) {\n" min max;
7840              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7841                name;
7842              pr "      return -1;\n";
7843              pr "    }\n";
7844              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7845         );
7846         pr "    %s = r;\n" name;
7847         pr "  }\n";
7848       in
7849
7850       iteri (
7851         fun i ->
7852           function
7853           | Device name
7854           | String name ->
7855               pr "  %s = argv[%d];\n" name i
7856           | Pathname name
7857           | Dev_or_Path name ->
7858               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7859               pr "  if (%s == NULL) return -1;\n" name
7860           | OptString name ->
7861               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7862                 name i i
7863           | BufferIn name ->
7864               pr "  %s = argv[%d];\n" name i;
7865               pr "  %s_size = strlen (argv[%d]);\n" name i
7866           | FileIn name ->
7867               pr "  %s = file_in (argv[%d]);\n" name i;
7868               pr "  if (%s == NULL) return -1;\n" name
7869           | FileOut name ->
7870               pr "  %s = file_out (argv[%d]);\n" name i;
7871               pr "  if (%s == NULL) return -1;\n" name
7872           | StringList name | DeviceList name ->
7873               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7874               pr "  if (%s == NULL) return -1;\n" name;
7875           | Bool name ->
7876               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7877           | Int name ->
7878               let range =
7879                 let min = "(-(2LL<<30))"
7880                 and max = "((2LL<<30)-1)"
7881                 and comment =
7882                   "The Int type in the generator is a signed 31 bit int." in
7883                 Some (min, max, comment) in
7884               parse_integer "xstrtoll" "long long" "int" range name i
7885           | Int64 name ->
7886               parse_integer "xstrtoll" "long long" "int64_t" None name i
7887       ) (snd style);
7888
7889       (* Call C API function. *)
7890       pr "  r = guestfs_%s " name;
7891       generate_c_call_args ~handle:"g" style;
7892       pr ";\n";
7893
7894       List.iter (
7895         function
7896         | Device name | String name
7897         | OptString name | Bool name
7898         | Int name | Int64 name
7899         | BufferIn name -> ()
7900         | Pathname name | Dev_or_Path name | FileOut name ->
7901             pr "  free (%s);\n" name
7902         | FileIn name ->
7903             pr "  free_file_in (%s);\n" name
7904         | StringList name | DeviceList name ->
7905             pr "  free_strings (%s);\n" name
7906       ) (snd style);
7907
7908       (* Any output flags? *)
7909       let fish_output =
7910         let flags = filter_map (
7911           function FishOutput flag -> Some flag | _ -> None
7912         ) flags in
7913         match flags with
7914         | [] -> None
7915         | [f] -> Some f
7916         | _ ->
7917             failwithf "%s: more than one FishOutput flag is not allowed" name in
7918
7919       (* Check return value for errors and display command results. *)
7920       (match fst style with
7921        | RErr -> pr "  return r;\n"
7922        | RInt _ ->
7923            pr "  if (r == -1) return -1;\n";
7924            (match fish_output with
7925             | None ->
7926                 pr "  printf (\"%%d\\n\", r);\n";
7927             | Some FishOutputOctal ->
7928                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7929             | Some FishOutputHexadecimal ->
7930                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7931            pr "  return 0;\n"
7932        | RInt64 _ ->
7933            pr "  if (r == -1) return -1;\n";
7934            (match fish_output with
7935             | None ->
7936                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7937             | Some FishOutputOctal ->
7938                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7939             | Some FishOutputHexadecimal ->
7940                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7941            pr "  return 0;\n"
7942        | RBool _ ->
7943            pr "  if (r == -1) return -1;\n";
7944            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7945            pr "  return 0;\n"
7946        | RConstString _ ->
7947            pr "  if (r == NULL) return -1;\n";
7948            pr "  printf (\"%%s\\n\", r);\n";
7949            pr "  return 0;\n"
7950        | RConstOptString _ ->
7951            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7952            pr "  return 0;\n"
7953        | RString _ ->
7954            pr "  if (r == NULL) return -1;\n";
7955            pr "  printf (\"%%s\\n\", r);\n";
7956            pr "  free (r);\n";
7957            pr "  return 0;\n"
7958        | RStringList _ ->
7959            pr "  if (r == NULL) return -1;\n";
7960            pr "  print_strings (r);\n";
7961            pr "  free_strings (r);\n";
7962            pr "  return 0;\n"
7963        | RStruct (_, typ) ->
7964            pr "  if (r == NULL) return -1;\n";
7965            pr "  print_%s (r);\n" typ;
7966            pr "  guestfs_free_%s (r);\n" typ;
7967            pr "  return 0;\n"
7968        | RStructList (_, typ) ->
7969            pr "  if (r == NULL) return -1;\n";
7970            pr "  print_%s_list (r);\n" typ;
7971            pr "  guestfs_free_%s_list (r);\n" typ;
7972            pr "  return 0;\n"
7973        | RHashtable _ ->
7974            pr "  if (r == NULL) return -1;\n";
7975            pr "  print_table (r);\n";
7976            pr "  free_strings (r);\n";
7977            pr "  return 0;\n"
7978        | RBufferOut _ ->
7979            pr "  if (r == NULL) return -1;\n";
7980            pr "  if (full_write (1, r, size) != size) {\n";
7981            pr "    perror (\"write\");\n";
7982            pr "    free (r);\n";
7983            pr "    return -1;\n";
7984            pr "  }\n";
7985            pr "  free (r);\n";
7986            pr "  return 0;\n"
7987       );
7988       pr "}\n";
7989       pr "\n"
7990   ) all_functions;
7991
7992   (* run_action function *)
7993   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7994   pr "{\n";
7995   List.iter (
7996     fun (name, _, _, flags, _, _, _) ->
7997       let name2 = replace_char name '_' '-' in
7998       let alias =
7999         try find_map (function FishAlias n -> Some n | _ -> None) flags
8000         with Not_found -> name in
8001       pr "  if (";
8002       pr "STRCASEEQ (cmd, \"%s\")" name;
8003       if name <> name2 then
8004         pr " || STRCASEEQ (cmd, \"%s\")" name2;
8005       if name <> alias then
8006         pr " || STRCASEEQ (cmd, \"%s\")" alias;
8007       pr ")\n";
8008       pr "    return run_%s (cmd, argc, argv);\n" name;
8009       pr "  else\n";
8010   ) all_functions;
8011   pr "    {\n";
8012   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
8013   pr "      if (command_num == 1)\n";
8014   pr "        extended_help_message ();\n";
8015   pr "      return -1;\n";
8016   pr "    }\n";
8017   pr "  return 0;\n";
8018   pr "}\n";
8019   pr "\n"
8020
8021 (* Readline completion for guestfish. *)
8022 and generate_fish_completion () =
8023   generate_header CStyle GPLv2plus;
8024
8025   let all_functions =
8026     List.filter (
8027       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
8028     ) all_functions in
8029
8030   pr "\
8031 #include <config.h>
8032
8033 #include <stdio.h>
8034 #include <stdlib.h>
8035 #include <string.h>
8036
8037 #ifdef HAVE_LIBREADLINE
8038 #include <readline/readline.h>
8039 #endif
8040
8041 #include \"fish.h\"
8042
8043 #ifdef HAVE_LIBREADLINE
8044
8045 static const char *const commands[] = {
8046   BUILTIN_COMMANDS_FOR_COMPLETION,
8047 ";
8048
8049   (* Get the commands, including the aliases.  They don't need to be
8050    * sorted - the generator() function just does a dumb linear search.
8051    *)
8052   let commands =
8053     List.map (
8054       fun (name, _, _, flags, _, _, _) ->
8055         let name2 = replace_char name '_' '-' in
8056         let alias =
8057           try find_map (function FishAlias n -> Some n | _ -> None) flags
8058           with Not_found -> name in
8059
8060         if name <> alias then [name2; alias] else [name2]
8061     ) all_functions in
8062   let commands = List.flatten commands in
8063
8064   List.iter (pr "  \"%s\",\n") commands;
8065
8066   pr "  NULL
8067 };
8068
8069 static char *
8070 generator (const char *text, int state)
8071 {
8072   static int index, len;
8073   const char *name;
8074
8075   if (!state) {
8076     index = 0;
8077     len = strlen (text);
8078   }
8079
8080   rl_attempted_completion_over = 1;
8081
8082   while ((name = commands[index]) != NULL) {
8083     index++;
8084     if (STRCASEEQLEN (name, text, len))
8085       return strdup (name);
8086   }
8087
8088   return NULL;
8089 }
8090
8091 #endif /* HAVE_LIBREADLINE */
8092
8093 #ifdef HAVE_RL_COMPLETION_MATCHES
8094 #define RL_COMPLETION_MATCHES rl_completion_matches
8095 #else
8096 #ifdef HAVE_COMPLETION_MATCHES
8097 #define RL_COMPLETION_MATCHES completion_matches
8098 #endif
8099 #endif /* else just fail if we don't have either symbol */
8100
8101 char **
8102 do_completion (const char *text, int start, int end)
8103 {
8104   char **matches = NULL;
8105
8106 #ifdef HAVE_LIBREADLINE
8107   rl_completion_append_character = ' ';
8108
8109   if (start == 0)
8110     matches = RL_COMPLETION_MATCHES (text, generator);
8111   else if (complete_dest_paths)
8112     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8113 #endif
8114
8115   return matches;
8116 }
8117 ";
8118
8119 (* Generate the POD documentation for guestfish. *)
8120 and generate_fish_actions_pod () =
8121   let all_functions_sorted =
8122     List.filter (
8123       fun (_, _, _, flags, _, _, _) ->
8124         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8125     ) all_functions_sorted in
8126
8127   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8128
8129   List.iter (
8130     fun (name, style, _, flags, _, _, longdesc) ->
8131       let longdesc =
8132         Str.global_substitute rex (
8133           fun s ->
8134             let sub =
8135               try Str.matched_group 1 s
8136               with Not_found ->
8137                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8138             "C<" ^ replace_char sub '_' '-' ^ ">"
8139         ) longdesc in
8140       let name = replace_char name '_' '-' in
8141       let alias =
8142         try find_map (function FishAlias n -> Some n | _ -> None) flags
8143         with Not_found -> name in
8144
8145       pr "=head2 %s" name;
8146       if name <> alias then
8147         pr " | %s" alias;
8148       pr "\n";
8149       pr "\n";
8150       pr " %s" name;
8151       List.iter (
8152         function
8153         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8154         | OptString n -> pr " %s" n
8155         | StringList n | DeviceList n -> pr " '%s ...'" n
8156         | Bool _ -> pr " true|false"
8157         | Int n -> pr " %s" n
8158         | Int64 n -> pr " %s" n
8159         | FileIn n | FileOut n -> pr " (%s|-)" n
8160         | BufferIn n -> pr " %s" n
8161       ) (snd style);
8162       pr "\n";
8163       pr "\n";
8164       pr "%s\n\n" longdesc;
8165
8166       if List.exists (function FileIn _ | FileOut _ -> true
8167                       | _ -> false) (snd style) then
8168         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8169
8170       if List.mem ProtocolLimitWarning flags then
8171         pr "%s\n\n" protocol_limit_warning;
8172
8173       if List.mem DangerWillRobinson flags then
8174         pr "%s\n\n" danger_will_robinson;
8175
8176       match deprecation_notice flags with
8177       | None -> ()
8178       | Some txt -> pr "%s\n\n" txt
8179   ) all_functions_sorted
8180
8181 (* Generate a C function prototype. *)
8182 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8183     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8184     ?(prefix = "")
8185     ?handle name style =
8186   if extern then pr "extern ";
8187   if static then pr "static ";
8188   (match fst style with
8189    | RErr -> pr "int "
8190    | RInt _ -> pr "int "
8191    | RInt64 _ -> pr "int64_t "
8192    | RBool _ -> pr "int "
8193    | RConstString _ | RConstOptString _ -> pr "const char *"
8194    | RString _ | RBufferOut _ -> pr "char *"
8195    | RStringList _ | RHashtable _ -> pr "char **"
8196    | RStruct (_, typ) ->
8197        if not in_daemon then pr "struct guestfs_%s *" typ
8198        else pr "guestfs_int_%s *" typ
8199    | RStructList (_, typ) ->
8200        if not in_daemon then pr "struct guestfs_%s_list *" typ
8201        else pr "guestfs_int_%s_list *" typ
8202   );
8203   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8204   pr "%s%s (" prefix name;
8205   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8206     pr "void"
8207   else (
8208     let comma = ref false in
8209     (match handle with
8210      | None -> ()
8211      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8212     );
8213     let next () =
8214       if !comma then (
8215         if single_line then pr ", " else pr ",\n\t\t"
8216       );
8217       comma := true
8218     in
8219     List.iter (
8220       function
8221       | Pathname n
8222       | Device n | Dev_or_Path n
8223       | String n
8224       | OptString n ->
8225           next ();
8226           pr "const char *%s" n
8227       | StringList n | DeviceList n ->
8228           next ();
8229           pr "char *const *%s" n
8230       | Bool n -> next (); pr "int %s" n
8231       | Int n -> next (); pr "int %s" n
8232       | Int64 n -> next (); pr "int64_t %s" n
8233       | FileIn n
8234       | FileOut n ->
8235           if not in_daemon then (next (); pr "const char *%s" n)
8236       | BufferIn n ->
8237           next ();
8238           pr "const char *%s" n;
8239           next ();
8240           pr "size_t %s_size" n
8241     ) (snd style);
8242     if is_RBufferOut then (next (); pr "size_t *size_r");
8243   );
8244   pr ")";
8245   if semicolon then pr ";";
8246   if newline then pr "\n"
8247
8248 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8249 and generate_c_call_args ?handle ?(decl = false) style =
8250   pr "(";
8251   let comma = ref false in
8252   let next () =
8253     if !comma then pr ", ";
8254     comma := true
8255   in
8256   (match handle with
8257    | None -> ()
8258    | Some handle -> pr "%s" handle; comma := true
8259   );
8260   List.iter (
8261     function
8262     | BufferIn n ->
8263         next ();
8264         pr "%s, %s_size" n n
8265     | arg ->
8266         next ();
8267         pr "%s" (name_of_argt arg)
8268   ) (snd style);
8269   (* For RBufferOut calls, add implicit &size parameter. *)
8270   if not decl then (
8271     match fst style with
8272     | RBufferOut _ ->
8273         next ();
8274         pr "&size"
8275     | _ -> ()
8276   );
8277   pr ")"
8278
8279 (* Generate the OCaml bindings interface. *)
8280 and generate_ocaml_mli () =
8281   generate_header OCamlStyle LGPLv2plus;
8282
8283   pr "\
8284 (** For API documentation you should refer to the C API
8285     in the guestfs(3) manual page.  The OCaml API uses almost
8286     exactly the same calls. *)
8287
8288 type t
8289 (** A [guestfs_h] handle. *)
8290
8291 exception Error of string
8292 (** This exception is raised when there is an error. *)
8293
8294 exception Handle_closed of string
8295 (** This exception is raised if you use a {!Guestfs.t} handle
8296     after calling {!close} on it.  The string is the name of
8297     the function. *)
8298
8299 val create : unit -> t
8300 (** Create a {!Guestfs.t} handle. *)
8301
8302 val close : t -> unit
8303 (** Close the {!Guestfs.t} handle and free up all resources used
8304     by it immediately.
8305
8306     Handles are closed by the garbage collector when they become
8307     unreferenced, but callers can call this in order to provide
8308     predictable cleanup. *)
8309
8310 ";
8311   generate_ocaml_structure_decls ();
8312
8313   (* The actions. *)
8314   List.iter (
8315     fun (name, style, _, _, _, shortdesc, _) ->
8316       generate_ocaml_prototype name style;
8317       pr "(** %s *)\n" shortdesc;
8318       pr "\n"
8319   ) all_functions_sorted
8320
8321 (* Generate the OCaml bindings implementation. *)
8322 and generate_ocaml_ml () =
8323   generate_header OCamlStyle LGPLv2plus;
8324
8325   pr "\
8326 type t
8327
8328 exception Error of string
8329 exception Handle_closed of string
8330
8331 external create : unit -> t = \"ocaml_guestfs_create\"
8332 external close : t -> unit = \"ocaml_guestfs_close\"
8333
8334 (* Give the exceptions names, so they can be raised from the C code. *)
8335 let () =
8336   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8337   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8338
8339 ";
8340
8341   generate_ocaml_structure_decls ();
8342
8343   (* The actions. *)
8344   List.iter (
8345     fun (name, style, _, _, _, shortdesc, _) ->
8346       generate_ocaml_prototype ~is_external:true name style;
8347   ) all_functions_sorted
8348
8349 (* Generate the OCaml bindings C implementation. *)
8350 and generate_ocaml_c () =
8351   generate_header CStyle LGPLv2plus;
8352
8353   pr "\
8354 #include <stdio.h>
8355 #include <stdlib.h>
8356 #include <string.h>
8357
8358 #include <caml/config.h>
8359 #include <caml/alloc.h>
8360 #include <caml/callback.h>
8361 #include <caml/fail.h>
8362 #include <caml/memory.h>
8363 #include <caml/mlvalues.h>
8364 #include <caml/signals.h>
8365
8366 #include <guestfs.h>
8367
8368 #include \"guestfs_c.h\"
8369
8370 /* Copy a hashtable of string pairs into an assoc-list.  We return
8371  * the list in reverse order, but hashtables aren't supposed to be
8372  * ordered anyway.
8373  */
8374 static CAMLprim value
8375 copy_table (char * const * argv)
8376 {
8377   CAMLparam0 ();
8378   CAMLlocal5 (rv, pairv, kv, vv, cons);
8379   int i;
8380
8381   rv = Val_int (0);
8382   for (i = 0; argv[i] != NULL; i += 2) {
8383     kv = caml_copy_string (argv[i]);
8384     vv = caml_copy_string (argv[i+1]);
8385     pairv = caml_alloc (2, 0);
8386     Store_field (pairv, 0, kv);
8387     Store_field (pairv, 1, vv);
8388     cons = caml_alloc (2, 0);
8389     Store_field (cons, 1, rv);
8390     rv = cons;
8391     Store_field (cons, 0, pairv);
8392   }
8393
8394   CAMLreturn (rv);
8395 }
8396
8397 ";
8398
8399   (* Struct copy functions. *)
8400
8401   let emit_ocaml_copy_list_function typ =
8402     pr "static CAMLprim value\n";
8403     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8404     pr "{\n";
8405     pr "  CAMLparam0 ();\n";
8406     pr "  CAMLlocal2 (rv, v);\n";
8407     pr "  unsigned int i;\n";
8408     pr "\n";
8409     pr "  if (%ss->len == 0)\n" typ;
8410     pr "    CAMLreturn (Atom (0));\n";
8411     pr "  else {\n";
8412     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8413     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8414     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8415     pr "      caml_modify (&Field (rv, i), v);\n";
8416     pr "    }\n";
8417     pr "    CAMLreturn (rv);\n";
8418     pr "  }\n";
8419     pr "}\n";
8420     pr "\n";
8421   in
8422
8423   List.iter (
8424     fun (typ, cols) ->
8425       let has_optpercent_col =
8426         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8427
8428       pr "static CAMLprim value\n";
8429       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8430       pr "{\n";
8431       pr "  CAMLparam0 ();\n";
8432       if has_optpercent_col then
8433         pr "  CAMLlocal3 (rv, v, v2);\n"
8434       else
8435         pr "  CAMLlocal2 (rv, v);\n";
8436       pr "\n";
8437       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8438       iteri (
8439         fun i col ->
8440           (match col with
8441            | name, FString ->
8442                pr "  v = caml_copy_string (%s->%s);\n" typ name
8443            | name, FBuffer ->
8444                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8445                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8446                  typ name typ name
8447            | name, FUUID ->
8448                pr "  v = caml_alloc_string (32);\n";
8449                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8450            | name, (FBytes|FInt64|FUInt64) ->
8451                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8452            | name, (FInt32|FUInt32) ->
8453                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8454            | name, FOptPercent ->
8455                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8456                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8457                pr "    v = caml_alloc (1, 0);\n";
8458                pr "    Store_field (v, 0, v2);\n";
8459                pr "  } else /* None */\n";
8460                pr "    v = Val_int (0);\n";
8461            | name, FChar ->
8462                pr "  v = Val_int (%s->%s);\n" typ name
8463           );
8464           pr "  Store_field (rv, %d, v);\n" i
8465       ) cols;
8466       pr "  CAMLreturn (rv);\n";
8467       pr "}\n";
8468       pr "\n";
8469   ) structs;
8470
8471   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8472   List.iter (
8473     function
8474     | typ, (RStructListOnly | RStructAndList) ->
8475         (* generate the function for typ *)
8476         emit_ocaml_copy_list_function typ
8477     | typ, _ -> () (* empty *)
8478   ) (rstructs_used_by all_functions);
8479
8480   (* The wrappers. *)
8481   List.iter (
8482     fun (name, style, _, _, _, _, _) ->
8483       pr "/* Automatically generated wrapper for function\n";
8484       pr " * ";
8485       generate_ocaml_prototype name style;
8486       pr " */\n";
8487       pr "\n";
8488
8489       let params =
8490         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8491
8492       let needs_extra_vs =
8493         match fst style with RConstOptString _ -> true | _ -> false in
8494
8495       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8496       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8497       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8498       pr "\n";
8499
8500       pr "CAMLprim value\n";
8501       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8502       List.iter (pr ", value %s") (List.tl params);
8503       pr ")\n";
8504       pr "{\n";
8505
8506       (match params with
8507        | [p1; p2; p3; p4; p5] ->
8508            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8509        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8510            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8511            pr "  CAMLxparam%d (%s);\n"
8512              (List.length rest) (String.concat ", " rest)
8513        | ps ->
8514            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8515       );
8516       if not needs_extra_vs then
8517         pr "  CAMLlocal1 (rv);\n"
8518       else
8519         pr "  CAMLlocal3 (rv, v, v2);\n";
8520       pr "\n";
8521
8522       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8523       pr "  if (g == NULL)\n";
8524       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8525       pr "\n";
8526
8527       List.iter (
8528         function
8529         | Pathname n
8530         | Device n | Dev_or_Path n
8531         | String n
8532         | FileIn n
8533         | FileOut n ->
8534             pr "  const char *%s = String_val (%sv);\n" n n
8535         | OptString n ->
8536             pr "  const char *%s =\n" n;
8537             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8538               n n
8539         | BufferIn n ->
8540             pr "  const char *%s = String_val (%sv);\n" n n;
8541             pr "  size_t %s_size = caml_string_length (%sv);\n" n n
8542         | StringList n | DeviceList n ->
8543             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8544         | Bool n ->
8545             pr "  int %s = Bool_val (%sv);\n" n n
8546         | Int n ->
8547             pr "  int %s = Int_val (%sv);\n" n n
8548         | Int64 n ->
8549             pr "  int64_t %s = Int64_val (%sv);\n" n n
8550       ) (snd style);
8551       let error_code =
8552         match fst style with
8553         | RErr -> pr "  int r;\n"; "-1"
8554         | RInt _ -> pr "  int r;\n"; "-1"
8555         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8556         | RBool _ -> pr "  int r;\n"; "-1"
8557         | RConstString _ | RConstOptString _ ->
8558             pr "  const char *r;\n"; "NULL"
8559         | RString _ -> pr "  char *r;\n"; "NULL"
8560         | RStringList _ ->
8561             pr "  int i;\n";
8562             pr "  char **r;\n";
8563             "NULL"
8564         | RStruct (_, typ) ->
8565             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8566         | RStructList (_, typ) ->
8567             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8568         | RHashtable _ ->
8569             pr "  int i;\n";
8570             pr "  char **r;\n";
8571             "NULL"
8572         | RBufferOut _ ->
8573             pr "  char *r;\n";
8574             pr "  size_t size;\n";
8575             "NULL" in
8576       pr "\n";
8577
8578       pr "  caml_enter_blocking_section ();\n";
8579       pr "  r = guestfs_%s " name;
8580       generate_c_call_args ~handle:"g" style;
8581       pr ";\n";
8582       pr "  caml_leave_blocking_section ();\n";
8583
8584       List.iter (
8585         function
8586         | StringList n | DeviceList n ->
8587             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8588         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8589         | Bool _ | Int _ | Int64 _
8590         | FileIn _ | FileOut _ | BufferIn _ -> ()
8591       ) (snd style);
8592
8593       pr "  if (r == %s)\n" error_code;
8594       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8595       pr "\n";
8596
8597       (match fst style with
8598        | RErr -> pr "  rv = Val_unit;\n"
8599        | RInt _ -> pr "  rv = Val_int (r);\n"
8600        | RInt64 _ ->
8601            pr "  rv = caml_copy_int64 (r);\n"
8602        | RBool _ -> pr "  rv = Val_bool (r);\n"
8603        | RConstString _ ->
8604            pr "  rv = caml_copy_string (r);\n"
8605        | RConstOptString _ ->
8606            pr "  if (r) { /* Some string */\n";
8607            pr "    v = caml_alloc (1, 0);\n";
8608            pr "    v2 = caml_copy_string (r);\n";
8609            pr "    Store_field (v, 0, v2);\n";
8610            pr "  } else /* None */\n";
8611            pr "    v = Val_int (0);\n";
8612        | RString _ ->
8613            pr "  rv = caml_copy_string (r);\n";
8614            pr "  free (r);\n"
8615        | RStringList _ ->
8616            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8617            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8618            pr "  free (r);\n"
8619        | RStruct (_, typ) ->
8620            pr "  rv = copy_%s (r);\n" typ;
8621            pr "  guestfs_free_%s (r);\n" typ;
8622        | RStructList (_, typ) ->
8623            pr "  rv = copy_%s_list (r);\n" typ;
8624            pr "  guestfs_free_%s_list (r);\n" typ;
8625        | RHashtable _ ->
8626            pr "  rv = copy_table (r);\n";
8627            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8628            pr "  free (r);\n";
8629        | RBufferOut _ ->
8630            pr "  rv = caml_alloc_string (size);\n";
8631            pr "  memcpy (String_val (rv), r, size);\n";
8632       );
8633
8634       pr "  CAMLreturn (rv);\n";
8635       pr "}\n";
8636       pr "\n";
8637
8638       if List.length params > 5 then (
8639         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8640         pr "CAMLprim value ";
8641         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8642         pr "CAMLprim value\n";
8643         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8644         pr "{\n";
8645         pr "  return ocaml_guestfs_%s (argv[0]" name;
8646         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8647         pr ");\n";
8648         pr "}\n";
8649         pr "\n"
8650       )
8651   ) all_functions_sorted
8652
8653 and generate_ocaml_structure_decls () =
8654   List.iter (
8655     fun (typ, cols) ->
8656       pr "type %s = {\n" typ;
8657       List.iter (
8658         function
8659         | name, FString -> pr "  %s : string;\n" name
8660         | name, FBuffer -> pr "  %s : string;\n" name
8661         | name, FUUID -> pr "  %s : string;\n" name
8662         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8663         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8664         | name, FChar -> pr "  %s : char;\n" name
8665         | name, FOptPercent -> pr "  %s : float option;\n" name
8666       ) cols;
8667       pr "}\n";
8668       pr "\n"
8669   ) structs
8670
8671 and generate_ocaml_prototype ?(is_external = false) name style =
8672   if is_external then pr "external " else pr "val ";
8673   pr "%s : t -> " name;
8674   List.iter (
8675     function
8676     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8677     | BufferIn _ -> pr "string -> "
8678     | OptString _ -> pr "string option -> "
8679     | StringList _ | DeviceList _ -> pr "string array -> "
8680     | Bool _ -> pr "bool -> "
8681     | Int _ -> pr "int -> "
8682     | Int64 _ -> pr "int64 -> "
8683   ) (snd style);
8684   (match fst style with
8685    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8686    | RInt _ -> pr "int"
8687    | RInt64 _ -> pr "int64"
8688    | RBool _ -> pr "bool"
8689    | RConstString _ -> pr "string"
8690    | RConstOptString _ -> pr "string option"
8691    | RString _ | RBufferOut _ -> pr "string"
8692    | RStringList _ -> pr "string array"
8693    | RStruct (_, typ) -> pr "%s" typ
8694    | RStructList (_, typ) -> pr "%s array" typ
8695    | RHashtable _ -> pr "(string * string) list"
8696   );
8697   if is_external then (
8698     pr " = ";
8699     if List.length (snd style) + 1 > 5 then
8700       pr "\"ocaml_guestfs_%s_byte\" " name;
8701     pr "\"ocaml_guestfs_%s\"" name
8702   );
8703   pr "\n"
8704
8705 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8706 and generate_perl_xs () =
8707   generate_header CStyle LGPLv2plus;
8708
8709   pr "\
8710 #include \"EXTERN.h\"
8711 #include \"perl.h\"
8712 #include \"XSUB.h\"
8713
8714 #include <guestfs.h>
8715
8716 #ifndef PRId64
8717 #define PRId64 \"lld\"
8718 #endif
8719
8720 static SV *
8721 my_newSVll(long long val) {
8722 #ifdef USE_64_BIT_ALL
8723   return newSViv(val);
8724 #else
8725   char buf[100];
8726   int len;
8727   len = snprintf(buf, 100, \"%%\" PRId64, val);
8728   return newSVpv(buf, len);
8729 #endif
8730 }
8731
8732 #ifndef PRIu64
8733 #define PRIu64 \"llu\"
8734 #endif
8735
8736 static SV *
8737 my_newSVull(unsigned long long val) {
8738 #ifdef USE_64_BIT_ALL
8739   return newSVuv(val);
8740 #else
8741   char buf[100];
8742   int len;
8743   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8744   return newSVpv(buf, len);
8745 #endif
8746 }
8747
8748 /* http://www.perlmonks.org/?node_id=680842 */
8749 static char **
8750 XS_unpack_charPtrPtr (SV *arg) {
8751   char **ret;
8752   AV *av;
8753   I32 i;
8754
8755   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8756     croak (\"array reference expected\");
8757
8758   av = (AV *)SvRV (arg);
8759   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8760   if (!ret)
8761     croak (\"malloc failed\");
8762
8763   for (i = 0; i <= av_len (av); i++) {
8764     SV **elem = av_fetch (av, i, 0);
8765
8766     if (!elem || !*elem)
8767       croak (\"missing element in list\");
8768
8769     ret[i] = SvPV_nolen (*elem);
8770   }
8771
8772   ret[i] = NULL;
8773
8774   return ret;
8775 }
8776
8777 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8778
8779 PROTOTYPES: ENABLE
8780
8781 guestfs_h *
8782 _create ()
8783    CODE:
8784       RETVAL = guestfs_create ();
8785       if (!RETVAL)
8786         croak (\"could not create guestfs handle\");
8787       guestfs_set_error_handler (RETVAL, NULL, NULL);
8788  OUTPUT:
8789       RETVAL
8790
8791 void
8792 DESTROY (g)
8793       guestfs_h *g;
8794  PPCODE:
8795       guestfs_close (g);
8796
8797 ";
8798
8799   List.iter (
8800     fun (name, style, _, _, _, _, _) ->
8801       (match fst style with
8802        | RErr -> pr "void\n"
8803        | RInt _ -> pr "SV *\n"
8804        | RInt64 _ -> pr "SV *\n"
8805        | RBool _ -> pr "SV *\n"
8806        | RConstString _ -> pr "SV *\n"
8807        | RConstOptString _ -> pr "SV *\n"
8808        | RString _ -> pr "SV *\n"
8809        | RBufferOut _ -> pr "SV *\n"
8810        | RStringList _
8811        | RStruct _ | RStructList _
8812        | RHashtable _ ->
8813            pr "void\n" (* all lists returned implictly on the stack *)
8814       );
8815       (* Call and arguments. *)
8816       pr "%s (g" name;
8817       List.iter (
8818         fun arg -> pr ", %s" (name_of_argt arg)
8819       ) (snd style);
8820       pr ")\n";
8821       pr "      guestfs_h *g;\n";
8822       iteri (
8823         fun i ->
8824           function
8825           | Pathname n | Device n | Dev_or_Path n | String n
8826           | FileIn n | FileOut n ->
8827               pr "      char *%s;\n" n
8828           | BufferIn n ->
8829               pr "      char *%s;\n" n;
8830               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8831           | OptString n ->
8832               (* http://www.perlmonks.org/?node_id=554277
8833                * Note that the implicit handle argument means we have
8834                * to add 1 to the ST(x) operator.
8835                *)
8836               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8837           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8838           | Bool n -> pr "      int %s;\n" n
8839           | Int n -> pr "      int %s;\n" n
8840           | Int64 n -> pr "      int64_t %s;\n" n
8841       ) (snd style);
8842
8843       let do_cleanups () =
8844         List.iter (
8845           function
8846           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8847           | Bool _ | Int _ | Int64 _
8848           | FileIn _ | FileOut _
8849           | BufferIn _ -> ()
8850           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8851         ) (snd style)
8852       in
8853
8854       (* Code. *)
8855       (match fst style with
8856        | RErr ->
8857            pr "PREINIT:\n";
8858            pr "      int r;\n";
8859            pr " PPCODE:\n";
8860            pr "      r = guestfs_%s " name;
8861            generate_c_call_args ~handle:"g" style;
8862            pr ";\n";
8863            do_cleanups ();
8864            pr "      if (r == -1)\n";
8865            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8866        | RInt n
8867        | RBool n ->
8868            pr "PREINIT:\n";
8869            pr "      int %s;\n" n;
8870            pr "   CODE:\n";
8871            pr "      %s = guestfs_%s " n name;
8872            generate_c_call_args ~handle:"g" style;
8873            pr ";\n";
8874            do_cleanups ();
8875            pr "      if (%s == -1)\n" n;
8876            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8877            pr "      RETVAL = newSViv (%s);\n" n;
8878            pr " OUTPUT:\n";
8879            pr "      RETVAL\n"
8880        | RInt64 n ->
8881            pr "PREINIT:\n";
8882            pr "      int64_t %s;\n" n;
8883            pr "   CODE:\n";
8884            pr "      %s = guestfs_%s " n name;
8885            generate_c_call_args ~handle:"g" style;
8886            pr ";\n";
8887            do_cleanups ();
8888            pr "      if (%s == -1)\n" n;
8889            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8890            pr "      RETVAL = my_newSVll (%s);\n" n;
8891            pr " OUTPUT:\n";
8892            pr "      RETVAL\n"
8893        | RConstString n ->
8894            pr "PREINIT:\n";
8895            pr "      const char *%s;\n" n;
8896            pr "   CODE:\n";
8897            pr "      %s = guestfs_%s " n name;
8898            generate_c_call_args ~handle:"g" style;
8899            pr ";\n";
8900            do_cleanups ();
8901            pr "      if (%s == NULL)\n" n;
8902            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8903            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8904            pr " OUTPUT:\n";
8905            pr "      RETVAL\n"
8906        | RConstOptString n ->
8907            pr "PREINIT:\n";
8908            pr "      const char *%s;\n" n;
8909            pr "   CODE:\n";
8910            pr "      %s = guestfs_%s " n name;
8911            generate_c_call_args ~handle:"g" style;
8912            pr ";\n";
8913            do_cleanups ();
8914            pr "      if (%s == NULL)\n" n;
8915            pr "        RETVAL = &PL_sv_undef;\n";
8916            pr "      else\n";
8917            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8918            pr " OUTPUT:\n";
8919            pr "      RETVAL\n"
8920        | RString n ->
8921            pr "PREINIT:\n";
8922            pr "      char *%s;\n" n;
8923            pr "   CODE:\n";
8924            pr "      %s = guestfs_%s " n name;
8925            generate_c_call_args ~handle:"g" style;
8926            pr ";\n";
8927            do_cleanups ();
8928            pr "      if (%s == NULL)\n" n;
8929            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8930            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8931            pr "      free (%s);\n" n;
8932            pr " OUTPUT:\n";
8933            pr "      RETVAL\n"
8934        | RStringList n | RHashtable n ->
8935            pr "PREINIT:\n";
8936            pr "      char **%s;\n" n;
8937            pr "      int i, n;\n";
8938            pr " PPCODE:\n";
8939            pr "      %s = guestfs_%s " n name;
8940            generate_c_call_args ~handle:"g" style;
8941            pr ";\n";
8942            do_cleanups ();
8943            pr "      if (%s == NULL)\n" n;
8944            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8945            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8946            pr "      EXTEND (SP, n);\n";
8947            pr "      for (i = 0; i < n; ++i) {\n";
8948            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8949            pr "        free (%s[i]);\n" n;
8950            pr "      }\n";
8951            pr "      free (%s);\n" n;
8952        | RStruct (n, typ) ->
8953            let cols = cols_of_struct typ in
8954            generate_perl_struct_code typ cols name style n do_cleanups
8955        | RStructList (n, typ) ->
8956            let cols = cols_of_struct typ in
8957            generate_perl_struct_list_code typ cols name style n do_cleanups
8958        | RBufferOut n ->
8959            pr "PREINIT:\n";
8960            pr "      char *%s;\n" n;
8961            pr "      size_t size;\n";
8962            pr "   CODE:\n";
8963            pr "      %s = guestfs_%s " n name;
8964            generate_c_call_args ~handle:"g" style;
8965            pr ";\n";
8966            do_cleanups ();
8967            pr "      if (%s == NULL)\n" n;
8968            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8969            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8970            pr "      free (%s);\n" n;
8971            pr " OUTPUT:\n";
8972            pr "      RETVAL\n"
8973       );
8974
8975       pr "\n"
8976   ) all_functions
8977
8978 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8979   pr "PREINIT:\n";
8980   pr "      struct guestfs_%s_list *%s;\n" typ n;
8981   pr "      int i;\n";
8982   pr "      HV *hv;\n";
8983   pr " PPCODE:\n";
8984   pr "      %s = guestfs_%s " n name;
8985   generate_c_call_args ~handle:"g" style;
8986   pr ";\n";
8987   do_cleanups ();
8988   pr "      if (%s == NULL)\n" n;
8989   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8990   pr "      EXTEND (SP, %s->len);\n" n;
8991   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8992   pr "        hv = newHV ();\n";
8993   List.iter (
8994     function
8995     | name, FString ->
8996         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8997           name (String.length name) n name
8998     | name, FUUID ->
8999         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
9000           name (String.length name) n name
9001     | name, FBuffer ->
9002         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
9003           name (String.length name) n name n name
9004     | name, (FBytes|FUInt64) ->
9005         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
9006           name (String.length name) n name
9007     | name, FInt64 ->
9008         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
9009           name (String.length name) n name
9010     | name, (FInt32|FUInt32) ->
9011         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9012           name (String.length name) n name
9013     | name, FChar ->
9014         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
9015           name (String.length name) n name
9016     | name, FOptPercent ->
9017         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9018           name (String.length name) n name
9019   ) cols;
9020   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
9021   pr "      }\n";
9022   pr "      guestfs_free_%s_list (%s);\n" typ n
9023
9024 and generate_perl_struct_code typ cols name style n do_cleanups =
9025   pr "PREINIT:\n";
9026   pr "      struct guestfs_%s *%s;\n" typ n;
9027   pr " PPCODE:\n";
9028   pr "      %s = guestfs_%s " n name;
9029   generate_c_call_args ~handle:"g" style;
9030   pr ";\n";
9031   do_cleanups ();
9032   pr "      if (%s == NULL)\n" n;
9033   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9034   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
9035   List.iter (
9036     fun ((name, _) as col) ->
9037       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
9038
9039       match col with
9040       | name, FString ->
9041           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
9042             n name
9043       | name, FBuffer ->
9044           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
9045             n name n name
9046       | name, FUUID ->
9047           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
9048             n name
9049       | name, (FBytes|FUInt64) ->
9050           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
9051             n name
9052       | name, FInt64 ->
9053           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
9054             n name
9055       | name, (FInt32|FUInt32) ->
9056           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9057             n name
9058       | name, FChar ->
9059           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9060             n name
9061       | name, FOptPercent ->
9062           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9063             n name
9064   ) cols;
9065   pr "      free (%s);\n" n
9066
9067 (* Generate Sys/Guestfs.pm. *)
9068 and generate_perl_pm () =
9069   generate_header HashStyle LGPLv2plus;
9070
9071   pr "\
9072 =pod
9073
9074 =head1 NAME
9075
9076 Sys::Guestfs - Perl bindings for libguestfs
9077
9078 =head1 SYNOPSIS
9079
9080  use Sys::Guestfs;
9081
9082  my $h = Sys::Guestfs->new ();
9083  $h->add_drive ('guest.img');
9084  $h->launch ();
9085  $h->mount ('/dev/sda1', '/');
9086  $h->touch ('/hello');
9087  $h->sync ();
9088
9089 =head1 DESCRIPTION
9090
9091 The C<Sys::Guestfs> module provides a Perl XS binding to the
9092 libguestfs API for examining and modifying virtual machine
9093 disk images.
9094
9095 Amongst the things this is good for: making batch configuration
9096 changes to guests, getting disk used/free statistics (see also:
9097 virt-df), migrating between virtualization systems (see also:
9098 virt-p2v), performing partial backups, performing partial guest
9099 clones, cloning guests and changing registry/UUID/hostname info, and
9100 much else besides.
9101
9102 Libguestfs uses Linux kernel and qemu code, and can access any type of
9103 guest filesystem that Linux and qemu can, including but not limited
9104 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9105 schemes, qcow, qcow2, vmdk.
9106
9107 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9108 LVs, what filesystem is in each LV, etc.).  It can also run commands
9109 in the context of the guest.  Also you can access filesystems over
9110 FUSE.
9111
9112 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9113 functions for using libguestfs from Perl, including integration
9114 with libvirt.
9115
9116 =head1 ERRORS
9117
9118 All errors turn into calls to C<croak> (see L<Carp(3)>).
9119
9120 =head1 METHODS
9121
9122 =over 4
9123
9124 =cut
9125
9126 package Sys::Guestfs;
9127
9128 use strict;
9129 use warnings;
9130
9131 # This version number changes whenever a new function
9132 # is added to the libguestfs API.  It is not directly
9133 # related to the libguestfs version number.
9134 use vars qw($VERSION);
9135 $VERSION = '0.%d';
9136
9137 require XSLoader;
9138 XSLoader::load ('Sys::Guestfs');
9139
9140 =item $h = Sys::Guestfs->new ();
9141
9142 Create a new guestfs handle.
9143
9144 =cut
9145
9146 sub new {
9147   my $proto = shift;
9148   my $class = ref ($proto) || $proto;
9149
9150   my $self = Sys::Guestfs::_create ();
9151   bless $self, $class;
9152   return $self;
9153 }
9154
9155 " max_proc_nr;
9156
9157   (* Actions.  We only need to print documentation for these as
9158    * they are pulled in from the XS code automatically.
9159    *)
9160   List.iter (
9161     fun (name, style, _, flags, _, _, longdesc) ->
9162       if not (List.mem NotInDocs flags) then (
9163         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9164         pr "=item ";
9165         generate_perl_prototype name style;
9166         pr "\n\n";
9167         pr "%s\n\n" longdesc;
9168         if List.mem ProtocolLimitWarning flags then
9169           pr "%s\n\n" protocol_limit_warning;
9170         if List.mem DangerWillRobinson flags then
9171           pr "%s\n\n" danger_will_robinson;
9172         match deprecation_notice flags with
9173         | None -> ()
9174         | Some txt -> pr "%s\n\n" txt
9175       )
9176   ) all_functions_sorted;
9177
9178   (* End of file. *)
9179   pr "\
9180 =cut
9181
9182 1;
9183
9184 =back
9185
9186 =head1 COPYRIGHT
9187
9188 Copyright (C) %s Red Hat Inc.
9189
9190 =head1 LICENSE
9191
9192 Please see the file COPYING.LIB for the full license.
9193
9194 =head1 SEE ALSO
9195
9196 L<guestfs(3)>,
9197 L<guestfish(1)>,
9198 L<http://libguestfs.org>,
9199 L<Sys::Guestfs::Lib(3)>.
9200
9201 =cut
9202 " copyright_years
9203
9204 and generate_perl_prototype name style =
9205   (match fst style with
9206    | RErr -> ()
9207    | RBool n
9208    | RInt n
9209    | RInt64 n
9210    | RConstString n
9211    | RConstOptString n
9212    | RString n
9213    | RBufferOut n -> pr "$%s = " n
9214    | RStruct (n,_)
9215    | RHashtable n -> pr "%%%s = " n
9216    | RStringList n
9217    | RStructList (n,_) -> pr "@%s = " n
9218   );
9219   pr "$h->%s (" name;
9220   let comma = ref false in
9221   List.iter (
9222     fun arg ->
9223       if !comma then pr ", ";
9224       comma := true;
9225       match arg with
9226       | Pathname n | Device n | Dev_or_Path n | String n
9227       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9228       | BufferIn n ->
9229           pr "$%s" n
9230       | StringList n | DeviceList n ->
9231           pr "\\@%s" n
9232   ) (snd style);
9233   pr ");"
9234
9235 (* Generate Python C module. *)
9236 and generate_python_c () =
9237   generate_header CStyle LGPLv2plus;
9238
9239   pr "\
9240 #define PY_SSIZE_T_CLEAN 1
9241 #include <Python.h>
9242
9243 #if PY_VERSION_HEX < 0x02050000
9244 typedef int Py_ssize_t;
9245 #define PY_SSIZE_T_MAX INT_MAX
9246 #define PY_SSIZE_T_MIN INT_MIN
9247 #endif
9248
9249 #include <stdio.h>
9250 #include <stdlib.h>
9251 #include <assert.h>
9252
9253 #include \"guestfs.h\"
9254
9255 typedef struct {
9256   PyObject_HEAD
9257   guestfs_h *g;
9258 } Pyguestfs_Object;
9259
9260 static guestfs_h *
9261 get_handle (PyObject *obj)
9262 {
9263   assert (obj);
9264   assert (obj != Py_None);
9265   return ((Pyguestfs_Object *) obj)->g;
9266 }
9267
9268 static PyObject *
9269 put_handle (guestfs_h *g)
9270 {
9271   assert (g);
9272   return
9273     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9274 }
9275
9276 /* This list should be freed (but not the strings) after use. */
9277 static char **
9278 get_string_list (PyObject *obj)
9279 {
9280   int i, len;
9281   char **r;
9282
9283   assert (obj);
9284
9285   if (!PyList_Check (obj)) {
9286     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9287     return NULL;
9288   }
9289
9290   len = PyList_Size (obj);
9291   r = malloc (sizeof (char *) * (len+1));
9292   if (r == NULL) {
9293     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9294     return NULL;
9295   }
9296
9297   for (i = 0; i < len; ++i)
9298     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9299   r[len] = NULL;
9300
9301   return r;
9302 }
9303
9304 static PyObject *
9305 put_string_list (char * const * const argv)
9306 {
9307   PyObject *list;
9308   int argc, i;
9309
9310   for (argc = 0; argv[argc] != NULL; ++argc)
9311     ;
9312
9313   list = PyList_New (argc);
9314   for (i = 0; i < argc; ++i)
9315     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9316
9317   return list;
9318 }
9319
9320 static PyObject *
9321 put_table (char * const * const argv)
9322 {
9323   PyObject *list, *item;
9324   int argc, i;
9325
9326   for (argc = 0; argv[argc] != NULL; ++argc)
9327     ;
9328
9329   list = PyList_New (argc >> 1);
9330   for (i = 0; i < argc; i += 2) {
9331     item = PyTuple_New (2);
9332     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9333     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9334     PyList_SetItem (list, i >> 1, item);
9335   }
9336
9337   return list;
9338 }
9339
9340 static void
9341 free_strings (char **argv)
9342 {
9343   int argc;
9344
9345   for (argc = 0; argv[argc] != NULL; ++argc)
9346     free (argv[argc]);
9347   free (argv);
9348 }
9349
9350 static PyObject *
9351 py_guestfs_create (PyObject *self, PyObject *args)
9352 {
9353   guestfs_h *g;
9354
9355   g = guestfs_create ();
9356   if (g == NULL) {
9357     PyErr_SetString (PyExc_RuntimeError,
9358                      \"guestfs.create: failed to allocate handle\");
9359     return NULL;
9360   }
9361   guestfs_set_error_handler (g, NULL, NULL);
9362   return put_handle (g);
9363 }
9364
9365 static PyObject *
9366 py_guestfs_close (PyObject *self, PyObject *args)
9367 {
9368   PyObject *py_g;
9369   guestfs_h *g;
9370
9371   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9372     return NULL;
9373   g = get_handle (py_g);
9374
9375   guestfs_close (g);
9376
9377   Py_INCREF (Py_None);
9378   return Py_None;
9379 }
9380
9381 ";
9382
9383   let emit_put_list_function typ =
9384     pr "static PyObject *\n";
9385     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9386     pr "{\n";
9387     pr "  PyObject *list;\n";
9388     pr "  int i;\n";
9389     pr "\n";
9390     pr "  list = PyList_New (%ss->len);\n" typ;
9391     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9392     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9393     pr "  return list;\n";
9394     pr "};\n";
9395     pr "\n"
9396   in
9397
9398   (* Structures, turned into Python dictionaries. *)
9399   List.iter (
9400     fun (typ, cols) ->
9401       pr "static PyObject *\n";
9402       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9403       pr "{\n";
9404       pr "  PyObject *dict;\n";
9405       pr "\n";
9406       pr "  dict = PyDict_New ();\n";
9407       List.iter (
9408         function
9409         | name, FString ->
9410             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9411             pr "                        PyString_FromString (%s->%s));\n"
9412               typ name
9413         | name, FBuffer ->
9414             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9415             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9416               typ name typ name
9417         | name, FUUID ->
9418             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9419             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9420               typ name
9421         | name, (FBytes|FUInt64) ->
9422             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9423             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9424               typ name
9425         | name, FInt64 ->
9426             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9427             pr "                        PyLong_FromLongLong (%s->%s));\n"
9428               typ name
9429         | name, FUInt32 ->
9430             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9431             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9432               typ name
9433         | name, FInt32 ->
9434             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9435             pr "                        PyLong_FromLong (%s->%s));\n"
9436               typ name
9437         | name, FOptPercent ->
9438             pr "  if (%s->%s >= 0)\n" typ name;
9439             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9440             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9441               typ name;
9442             pr "  else {\n";
9443             pr "    Py_INCREF (Py_None);\n";
9444             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9445             pr "  }\n"
9446         | name, FChar ->
9447             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9448             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9449       ) cols;
9450       pr "  return dict;\n";
9451       pr "};\n";
9452       pr "\n";
9453
9454   ) structs;
9455
9456   (* Emit a put_TYPE_list function definition only if that function is used. *)
9457   List.iter (
9458     function
9459     | typ, (RStructListOnly | RStructAndList) ->
9460         (* generate the function for typ *)
9461         emit_put_list_function typ
9462     | typ, _ -> () (* empty *)
9463   ) (rstructs_used_by all_functions);
9464
9465   (* Python wrapper functions. *)
9466   List.iter (
9467     fun (name, style, _, _, _, _, _) ->
9468       pr "static PyObject *\n";
9469       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9470       pr "{\n";
9471
9472       pr "  PyObject *py_g;\n";
9473       pr "  guestfs_h *g;\n";
9474       pr "  PyObject *py_r;\n";
9475
9476       let error_code =
9477         match fst style with
9478         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9479         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9480         | RConstString _ | RConstOptString _ ->
9481             pr "  const char *r;\n"; "NULL"
9482         | RString _ -> pr "  char *r;\n"; "NULL"
9483         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9484         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9485         | RStructList (_, typ) ->
9486             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9487         | RBufferOut _ ->
9488             pr "  char *r;\n";
9489             pr "  size_t size;\n";
9490             "NULL" in
9491
9492       List.iter (
9493         function
9494         | Pathname n | Device n | Dev_or_Path n | String n
9495         | FileIn n | FileOut n ->
9496             pr "  const char *%s;\n" n
9497         | OptString n -> pr "  const char *%s;\n" n
9498         | BufferIn n ->
9499             pr "  const char *%s;\n" n;
9500             pr "  Py_ssize_t %s_size;\n" n
9501         | StringList n | DeviceList n ->
9502             pr "  PyObject *py_%s;\n" n;
9503             pr "  char **%s;\n" n
9504         | Bool n -> pr "  int %s;\n" n
9505         | Int n -> pr "  int %s;\n" n
9506         | Int64 n -> pr "  long long %s;\n" n
9507       ) (snd style);
9508
9509       pr "\n";
9510
9511       (* Convert the parameters. *)
9512       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9513       List.iter (
9514         function
9515         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9516         | OptString _ -> pr "z"
9517         | StringList _ | DeviceList _ -> pr "O"
9518         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9519         | Int _ -> pr "i"
9520         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9521                              * emulate C's int/long/long long in Python?
9522                              *)
9523         | BufferIn _ -> pr "s#"
9524       ) (snd style);
9525       pr ":guestfs_%s\",\n" name;
9526       pr "                         &py_g";
9527       List.iter (
9528         function
9529         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9530         | OptString n -> pr ", &%s" n
9531         | StringList n | DeviceList n -> pr ", &py_%s" n
9532         | Bool n -> pr ", &%s" n
9533         | Int n -> pr ", &%s" n
9534         | Int64 n -> pr ", &%s" n
9535         | BufferIn n -> pr ", &%s, &%s_size" n n
9536       ) (snd style);
9537
9538       pr "))\n";
9539       pr "    return NULL;\n";
9540
9541       pr "  g = get_handle (py_g);\n";
9542       List.iter (
9543         function
9544         | Pathname _ | Device _ | Dev_or_Path _ | String _
9545         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9546         | BufferIn _ -> ()
9547         | StringList n | DeviceList n ->
9548             pr "  %s = get_string_list (py_%s);\n" n n;
9549             pr "  if (!%s) return NULL;\n" n
9550       ) (snd style);
9551
9552       pr "\n";
9553
9554       pr "  r = guestfs_%s " name;
9555       generate_c_call_args ~handle:"g" style;
9556       pr ";\n";
9557
9558       List.iter (
9559         function
9560         | Pathname _ | Device _ | Dev_or_Path _ | String _
9561         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9562         | BufferIn _ -> ()
9563         | StringList n | DeviceList n ->
9564             pr "  free (%s);\n" n
9565       ) (snd style);
9566
9567       pr "  if (r == %s) {\n" error_code;
9568       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9569       pr "    return NULL;\n";
9570       pr "  }\n";
9571       pr "\n";
9572
9573       (match fst style with
9574        | RErr ->
9575            pr "  Py_INCREF (Py_None);\n";
9576            pr "  py_r = Py_None;\n"
9577        | RInt _
9578        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9579        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9580        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9581        | RConstOptString _ ->
9582            pr "  if (r)\n";
9583            pr "    py_r = PyString_FromString (r);\n";
9584            pr "  else {\n";
9585            pr "    Py_INCREF (Py_None);\n";
9586            pr "    py_r = Py_None;\n";
9587            pr "  }\n"
9588        | RString _ ->
9589            pr "  py_r = PyString_FromString (r);\n";
9590            pr "  free (r);\n"
9591        | RStringList _ ->
9592            pr "  py_r = put_string_list (r);\n";
9593            pr "  free_strings (r);\n"
9594        | RStruct (_, typ) ->
9595            pr "  py_r = put_%s (r);\n" typ;
9596            pr "  guestfs_free_%s (r);\n" typ
9597        | RStructList (_, typ) ->
9598            pr "  py_r = put_%s_list (r);\n" typ;
9599            pr "  guestfs_free_%s_list (r);\n" typ
9600        | RHashtable n ->
9601            pr "  py_r = put_table (r);\n";
9602            pr "  free_strings (r);\n"
9603        | RBufferOut _ ->
9604            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9605            pr "  free (r);\n"
9606       );
9607
9608       pr "  return py_r;\n";
9609       pr "}\n";
9610       pr "\n"
9611   ) all_functions;
9612
9613   (* Table of functions. *)
9614   pr "static PyMethodDef methods[] = {\n";
9615   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9616   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9617   List.iter (
9618     fun (name, _, _, _, _, _, _) ->
9619       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9620         name name
9621   ) all_functions;
9622   pr "  { NULL, NULL, 0, NULL }\n";
9623   pr "};\n";
9624   pr "\n";
9625
9626   (* Init function. *)
9627   pr "\
9628 void
9629 initlibguestfsmod (void)
9630 {
9631   static int initialized = 0;
9632
9633   if (initialized) return;
9634   Py_InitModule ((char *) \"libguestfsmod\", methods);
9635   initialized = 1;
9636 }
9637 "
9638
9639 (* Generate Python module. *)
9640 and generate_python_py () =
9641   generate_header HashStyle LGPLv2plus;
9642
9643   pr "\
9644 u\"\"\"Python bindings for libguestfs
9645
9646 import guestfs
9647 g = guestfs.GuestFS ()
9648 g.add_drive (\"guest.img\")
9649 g.launch ()
9650 parts = g.list_partitions ()
9651
9652 The guestfs module provides a Python binding to the libguestfs API
9653 for examining and modifying virtual machine disk images.
9654
9655 Amongst the things this is good for: making batch configuration
9656 changes to guests, getting disk used/free statistics (see also:
9657 virt-df), migrating between virtualization systems (see also:
9658 virt-p2v), performing partial backups, performing partial guest
9659 clones, cloning guests and changing registry/UUID/hostname info, and
9660 much else besides.
9661
9662 Libguestfs uses Linux kernel and qemu code, and can access any type of
9663 guest filesystem that Linux and qemu can, including but not limited
9664 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9665 schemes, qcow, qcow2, vmdk.
9666
9667 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9668 LVs, what filesystem is in each LV, etc.).  It can also run commands
9669 in the context of the guest.  Also you can access filesystems over
9670 FUSE.
9671
9672 Errors which happen while using the API are turned into Python
9673 RuntimeError exceptions.
9674
9675 To create a guestfs handle you usually have to perform the following
9676 sequence of calls:
9677
9678 # Create the handle, call add_drive at least once, and possibly
9679 # several times if the guest has multiple block devices:
9680 g = guestfs.GuestFS ()
9681 g.add_drive (\"guest.img\")
9682
9683 # Launch the qemu subprocess and wait for it to become ready:
9684 g.launch ()
9685
9686 # Now you can issue commands, for example:
9687 logvols = g.lvs ()
9688
9689 \"\"\"
9690
9691 import libguestfsmod
9692
9693 class GuestFS:
9694     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9695
9696     def __init__ (self):
9697         \"\"\"Create a new libguestfs handle.\"\"\"
9698         self._o = libguestfsmod.create ()
9699
9700     def __del__ (self):
9701         libguestfsmod.close (self._o)
9702
9703 ";
9704
9705   List.iter (
9706     fun (name, style, _, flags, _, _, longdesc) ->
9707       pr "    def %s " name;
9708       generate_py_call_args ~handle:"self" (snd style);
9709       pr ":\n";
9710
9711       if not (List.mem NotInDocs flags) then (
9712         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9713         let doc =
9714           match fst style with
9715           | RErr | RInt _ | RInt64 _ | RBool _
9716           | RConstOptString _ | RConstString _
9717           | RString _ | RBufferOut _ -> doc
9718           | RStringList _ ->
9719               doc ^ "\n\nThis function returns a list of strings."
9720           | RStruct (_, typ) ->
9721               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9722           | RStructList (_, typ) ->
9723               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9724           | RHashtable _ ->
9725               doc ^ "\n\nThis function returns a dictionary." in
9726         let doc =
9727           if List.mem ProtocolLimitWarning flags then
9728             doc ^ "\n\n" ^ protocol_limit_warning
9729           else doc in
9730         let doc =
9731           if List.mem DangerWillRobinson flags then
9732             doc ^ "\n\n" ^ danger_will_robinson
9733           else doc in
9734         let doc =
9735           match deprecation_notice flags with
9736           | None -> doc
9737           | Some txt -> doc ^ "\n\n" ^ txt in
9738         let doc = pod2text ~width:60 name doc in
9739         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9740         let doc = String.concat "\n        " doc in
9741         pr "        u\"\"\"%s\"\"\"\n" doc;
9742       );
9743       pr "        return libguestfsmod.%s " name;
9744       generate_py_call_args ~handle:"self._o" (snd style);
9745       pr "\n";
9746       pr "\n";
9747   ) all_functions
9748
9749 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9750 and generate_py_call_args ~handle args =
9751   pr "(%s" handle;
9752   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9753   pr ")"
9754
9755 (* Useful if you need the longdesc POD text as plain text.  Returns a
9756  * list of lines.
9757  *
9758  * Because this is very slow (the slowest part of autogeneration),
9759  * we memoize the results.
9760  *)
9761 and pod2text ~width name longdesc =
9762   let key = width, name, longdesc in
9763   try Hashtbl.find pod2text_memo key
9764   with Not_found ->
9765     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9766     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9767     close_out chan;
9768     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9769     let chan = open_process_in cmd in
9770     let lines = ref [] in
9771     let rec loop i =
9772       let line = input_line chan in
9773       if i = 1 then             (* discard the first line of output *)
9774         loop (i+1)
9775       else (
9776         let line = triml line in
9777         lines := line :: !lines;
9778         loop (i+1)
9779       ) in
9780     let lines = try loop 1 with End_of_file -> List.rev !lines in
9781     unlink filename;
9782     (match close_process_in chan with
9783      | WEXITED 0 -> ()
9784      | WEXITED i ->
9785          failwithf "pod2text: process exited with non-zero status (%d)" i
9786      | WSIGNALED i | WSTOPPED i ->
9787          failwithf "pod2text: process signalled or stopped by signal %d" i
9788     );
9789     Hashtbl.add pod2text_memo key lines;
9790     pod2text_memo_updated ();
9791     lines
9792
9793 (* Generate ruby bindings. *)
9794 and generate_ruby_c () =
9795   generate_header CStyle LGPLv2plus;
9796
9797   pr "\
9798 #include <stdio.h>
9799 #include <stdlib.h>
9800
9801 #include <ruby.h>
9802
9803 #include \"guestfs.h\"
9804
9805 #include \"extconf.h\"
9806
9807 /* For Ruby < 1.9 */
9808 #ifndef RARRAY_LEN
9809 #define RARRAY_LEN(r) (RARRAY((r))->len)
9810 #endif
9811
9812 static VALUE m_guestfs;                 /* guestfs module */
9813 static VALUE c_guestfs;                 /* guestfs_h handle */
9814 static VALUE e_Error;                   /* used for all errors */
9815
9816 static void ruby_guestfs_free (void *p)
9817 {
9818   if (!p) return;
9819   guestfs_close ((guestfs_h *) p);
9820 }
9821
9822 static VALUE ruby_guestfs_create (VALUE m)
9823 {
9824   guestfs_h *g;
9825
9826   g = guestfs_create ();
9827   if (!g)
9828     rb_raise (e_Error, \"failed to create guestfs handle\");
9829
9830   /* Don't print error messages to stderr by default. */
9831   guestfs_set_error_handler (g, NULL, NULL);
9832
9833   /* Wrap it, and make sure the close function is called when the
9834    * handle goes away.
9835    */
9836   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9837 }
9838
9839 static VALUE ruby_guestfs_close (VALUE gv)
9840 {
9841   guestfs_h *g;
9842   Data_Get_Struct (gv, guestfs_h, g);
9843
9844   ruby_guestfs_free (g);
9845   DATA_PTR (gv) = NULL;
9846
9847   return Qnil;
9848 }
9849
9850 ";
9851
9852   List.iter (
9853     fun (name, style, _, _, _, _, _) ->
9854       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9855       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9856       pr ")\n";
9857       pr "{\n";
9858       pr "  guestfs_h *g;\n";
9859       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9860       pr "  if (!g)\n";
9861       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9862         name;
9863       pr "\n";
9864
9865       List.iter (
9866         function
9867         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9868             pr "  Check_Type (%sv, T_STRING);\n" n;
9869             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9870             pr "  if (!%s)\n" n;
9871             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9872             pr "              \"%s\", \"%s\");\n" n name
9873         | BufferIn n ->
9874             pr "  Check_Type (%sv, T_STRING);\n" n;
9875             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9876             pr "  if (!%s)\n" n;
9877             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9878             pr "              \"%s\", \"%s\");\n" n name;
9879             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9880         | OptString n ->
9881             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9882         | StringList n | DeviceList n ->
9883             pr "  char **%s;\n" n;
9884             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9885             pr "  {\n";
9886             pr "    int i, len;\n";
9887             pr "    len = RARRAY_LEN (%sv);\n" n;
9888             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9889               n;
9890             pr "    for (i = 0; i < len; ++i) {\n";
9891             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9892             pr "      %s[i] = StringValueCStr (v);\n" n;
9893             pr "    }\n";
9894             pr "    %s[len] = NULL;\n" n;
9895             pr "  }\n";
9896         | Bool n ->
9897             pr "  int %s = RTEST (%sv);\n" n n
9898         | Int n ->
9899             pr "  int %s = NUM2INT (%sv);\n" n n
9900         | Int64 n ->
9901             pr "  long long %s = NUM2LL (%sv);\n" n n
9902       ) (snd style);
9903       pr "\n";
9904
9905       let error_code =
9906         match fst style with
9907         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9908         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9909         | RConstString _ | RConstOptString _ ->
9910             pr "  const char *r;\n"; "NULL"
9911         | RString _ -> pr "  char *r;\n"; "NULL"
9912         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9913         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9914         | RStructList (_, typ) ->
9915             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9916         | RBufferOut _ ->
9917             pr "  char *r;\n";
9918             pr "  size_t size;\n";
9919             "NULL" in
9920       pr "\n";
9921
9922       pr "  r = guestfs_%s " name;
9923       generate_c_call_args ~handle:"g" style;
9924       pr ";\n";
9925
9926       List.iter (
9927         function
9928         | Pathname _ | Device _ | Dev_or_Path _ | String _
9929         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9930         | BufferIn _ -> ()
9931         | StringList n | DeviceList n ->
9932             pr "  free (%s);\n" n
9933       ) (snd style);
9934
9935       pr "  if (r == %s)\n" error_code;
9936       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9937       pr "\n";
9938
9939       (match fst style with
9940        | RErr ->
9941            pr "  return Qnil;\n"
9942        | RInt _ | RBool _ ->
9943            pr "  return INT2NUM (r);\n"
9944        | RInt64 _ ->
9945            pr "  return ULL2NUM (r);\n"
9946        | RConstString _ ->
9947            pr "  return rb_str_new2 (r);\n";
9948        | RConstOptString _ ->
9949            pr "  if (r)\n";
9950            pr "    return rb_str_new2 (r);\n";
9951            pr "  else\n";
9952            pr "    return Qnil;\n";
9953        | RString _ ->
9954            pr "  VALUE rv = rb_str_new2 (r);\n";
9955            pr "  free (r);\n";
9956            pr "  return rv;\n";
9957        | RStringList _ ->
9958            pr "  int i, len = 0;\n";
9959            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9960            pr "  VALUE rv = rb_ary_new2 (len);\n";
9961            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9962            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9963            pr "    free (r[i]);\n";
9964            pr "  }\n";
9965            pr "  free (r);\n";
9966            pr "  return rv;\n"
9967        | RStruct (_, typ) ->
9968            let cols = cols_of_struct typ in
9969            generate_ruby_struct_code typ cols
9970        | RStructList (_, typ) ->
9971            let cols = cols_of_struct typ in
9972            generate_ruby_struct_list_code typ cols
9973        | RHashtable _ ->
9974            pr "  VALUE rv = rb_hash_new ();\n";
9975            pr "  int i;\n";
9976            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9977            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9978            pr "    free (r[i]);\n";
9979            pr "    free (r[i+1]);\n";
9980            pr "  }\n";
9981            pr "  free (r);\n";
9982            pr "  return rv;\n"
9983        | RBufferOut _ ->
9984            pr "  VALUE rv = rb_str_new (r, size);\n";
9985            pr "  free (r);\n";
9986            pr "  return rv;\n";
9987       );
9988
9989       pr "}\n";
9990       pr "\n"
9991   ) all_functions;
9992
9993   pr "\
9994 /* Initialize the module. */
9995 void Init__guestfs ()
9996 {
9997   m_guestfs = rb_define_module (\"Guestfs\");
9998   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9999   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
10000
10001   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
10002   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
10003
10004 ";
10005   (* Define the rest of the methods. *)
10006   List.iter (
10007     fun (name, style, _, _, _, _, _) ->
10008       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
10009       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
10010   ) all_functions;
10011
10012   pr "}\n"
10013
10014 (* Ruby code to return a struct. *)
10015 and generate_ruby_struct_code typ cols =
10016   pr "  VALUE rv = rb_hash_new ();\n";
10017   List.iter (
10018     function
10019     | name, FString ->
10020         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
10021     | name, FBuffer ->
10022         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
10023     | name, FUUID ->
10024         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
10025     | name, (FBytes|FUInt64) ->
10026         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10027     | name, FInt64 ->
10028         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
10029     | name, FUInt32 ->
10030         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
10031     | name, FInt32 ->
10032         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
10033     | name, FOptPercent ->
10034         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
10035     | name, FChar -> (* XXX wrong? *)
10036         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10037   ) cols;
10038   pr "  guestfs_free_%s (r);\n" typ;
10039   pr "  return rv;\n"
10040
10041 (* Ruby code to return a struct list. *)
10042 and generate_ruby_struct_list_code typ cols =
10043   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
10044   pr "  int i;\n";
10045   pr "  for (i = 0; i < r->len; ++i) {\n";
10046   pr "    VALUE hv = rb_hash_new ();\n";
10047   List.iter (
10048     function
10049     | name, FString ->
10050         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
10051     | name, FBuffer ->
10052         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
10053     | name, FUUID ->
10054         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
10055     | name, (FBytes|FUInt64) ->
10056         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10057     | name, FInt64 ->
10058         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10059     | name, FUInt32 ->
10060         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10061     | name, FInt32 ->
10062         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10063     | name, FOptPercent ->
10064         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10065     | name, FChar -> (* XXX wrong? *)
10066         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10067   ) cols;
10068   pr "    rb_ary_push (rv, hv);\n";
10069   pr "  }\n";
10070   pr "  guestfs_free_%s_list (r);\n" typ;
10071   pr "  return rv;\n"
10072
10073 (* Generate Java bindings GuestFS.java file. *)
10074 and generate_java_java () =
10075   generate_header CStyle LGPLv2plus;
10076
10077   pr "\
10078 package com.redhat.et.libguestfs;
10079
10080 import java.util.HashMap;
10081 import com.redhat.et.libguestfs.LibGuestFSException;
10082 import com.redhat.et.libguestfs.PV;
10083 import com.redhat.et.libguestfs.VG;
10084 import com.redhat.et.libguestfs.LV;
10085 import com.redhat.et.libguestfs.Stat;
10086 import com.redhat.et.libguestfs.StatVFS;
10087 import com.redhat.et.libguestfs.IntBool;
10088 import com.redhat.et.libguestfs.Dirent;
10089
10090 /**
10091  * The GuestFS object is a libguestfs handle.
10092  *
10093  * @author rjones
10094  */
10095 public class GuestFS {
10096   // Load the native code.
10097   static {
10098     System.loadLibrary (\"guestfs_jni\");
10099   }
10100
10101   /**
10102    * The native guestfs_h pointer.
10103    */
10104   long g;
10105
10106   /**
10107    * Create a libguestfs handle.
10108    *
10109    * @throws LibGuestFSException
10110    */
10111   public GuestFS () throws LibGuestFSException
10112   {
10113     g = _create ();
10114   }
10115   private native long _create () throws LibGuestFSException;
10116
10117   /**
10118    * Close a libguestfs handle.
10119    *
10120    * You can also leave handles to be collected by the garbage
10121    * collector, but this method ensures that the resources used
10122    * by the handle are freed up immediately.  If you call any
10123    * other methods after closing the handle, you will get an
10124    * exception.
10125    *
10126    * @throws LibGuestFSException
10127    */
10128   public void close () throws LibGuestFSException
10129   {
10130     if (g != 0)
10131       _close (g);
10132     g = 0;
10133   }
10134   private native void _close (long g) throws LibGuestFSException;
10135
10136   public void finalize () throws LibGuestFSException
10137   {
10138     close ();
10139   }
10140
10141 ";
10142
10143   List.iter (
10144     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10145       if not (List.mem NotInDocs flags); then (
10146         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10147         let doc =
10148           if List.mem ProtocolLimitWarning flags then
10149             doc ^ "\n\n" ^ protocol_limit_warning
10150           else doc in
10151         let doc =
10152           if List.mem DangerWillRobinson flags then
10153             doc ^ "\n\n" ^ danger_will_robinson
10154           else doc in
10155         let doc =
10156           match deprecation_notice flags with
10157           | None -> doc
10158           | Some txt -> doc ^ "\n\n" ^ txt in
10159         let doc = pod2text ~width:60 name doc in
10160         let doc = List.map (            (* RHBZ#501883 *)
10161           function
10162           | "" -> "<p>"
10163           | nonempty -> nonempty
10164         ) doc in
10165         let doc = String.concat "\n   * " doc in
10166
10167         pr "  /**\n";
10168         pr "   * %s\n" shortdesc;
10169         pr "   * <p>\n";
10170         pr "   * %s\n" doc;
10171         pr "   * @throws LibGuestFSException\n";
10172         pr "   */\n";
10173         pr "  ";
10174       );
10175       generate_java_prototype ~public:true ~semicolon:false name style;
10176       pr "\n";
10177       pr "  {\n";
10178       pr "    if (g == 0)\n";
10179       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10180         name;
10181       pr "    ";
10182       if fst style <> RErr then pr "return ";
10183       pr "_%s " name;
10184       generate_java_call_args ~handle:"g" (snd style);
10185       pr ";\n";
10186       pr "  }\n";
10187       pr "  ";
10188       generate_java_prototype ~privat:true ~native:true name style;
10189       pr "\n";
10190       pr "\n";
10191   ) all_functions;
10192
10193   pr "}\n"
10194
10195 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10196 and generate_java_call_args ~handle args =
10197   pr "(%s" handle;
10198   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10199   pr ")"
10200
10201 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10202     ?(semicolon=true) name style =
10203   if privat then pr "private ";
10204   if public then pr "public ";
10205   if native then pr "native ";
10206
10207   (* return type *)
10208   (match fst style with
10209    | RErr -> pr "void ";
10210    | RInt _ -> pr "int ";
10211    | RInt64 _ -> pr "long ";
10212    | RBool _ -> pr "boolean ";
10213    | RConstString _ | RConstOptString _ | RString _
10214    | RBufferOut _ -> pr "String ";
10215    | RStringList _ -> pr "String[] ";
10216    | RStruct (_, typ) ->
10217        let name = java_name_of_struct typ in
10218        pr "%s " name;
10219    | RStructList (_, typ) ->
10220        let name = java_name_of_struct typ in
10221        pr "%s[] " name;
10222    | RHashtable _ -> pr "HashMap<String,String> ";
10223   );
10224
10225   if native then pr "_%s " name else pr "%s " name;
10226   pr "(";
10227   let needs_comma = ref false in
10228   if native then (
10229     pr "long g";
10230     needs_comma := true
10231   );
10232
10233   (* args *)
10234   List.iter (
10235     fun arg ->
10236       if !needs_comma then pr ", ";
10237       needs_comma := true;
10238
10239       match arg with
10240       | Pathname n
10241       | Device n | Dev_or_Path n
10242       | String n
10243       | OptString n
10244       | FileIn n
10245       | FileOut n ->
10246           pr "String %s" n
10247       | BufferIn n ->
10248           pr "byte[] %s" n
10249       | StringList n | DeviceList n ->
10250           pr "String[] %s" n
10251       | Bool n ->
10252           pr "boolean %s" n
10253       | Int n ->
10254           pr "int %s" n
10255       | Int64 n ->
10256           pr "long %s" n
10257   ) (snd style);
10258
10259   pr ")\n";
10260   pr "    throws LibGuestFSException";
10261   if semicolon then pr ";"
10262
10263 and generate_java_struct jtyp cols () =
10264   generate_header CStyle LGPLv2plus;
10265
10266   pr "\
10267 package com.redhat.et.libguestfs;
10268
10269 /**
10270  * Libguestfs %s structure.
10271  *
10272  * @author rjones
10273  * @see GuestFS
10274  */
10275 public class %s {
10276 " jtyp jtyp;
10277
10278   List.iter (
10279     function
10280     | name, FString
10281     | name, FUUID
10282     | name, FBuffer -> pr "  public String %s;\n" name
10283     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10284     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10285     | name, FChar -> pr "  public char %s;\n" name
10286     | name, FOptPercent ->
10287         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10288         pr "  public float %s;\n" name
10289   ) cols;
10290
10291   pr "}\n"
10292
10293 and generate_java_c () =
10294   generate_header CStyle LGPLv2plus;
10295
10296   pr "\
10297 #include <stdio.h>
10298 #include <stdlib.h>
10299 #include <string.h>
10300
10301 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10302 #include \"guestfs.h\"
10303
10304 /* Note that this function returns.  The exception is not thrown
10305  * until after the wrapper function returns.
10306  */
10307 static void
10308 throw_exception (JNIEnv *env, const char *msg)
10309 {
10310   jclass cl;
10311   cl = (*env)->FindClass (env,
10312                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10313   (*env)->ThrowNew (env, cl, msg);
10314 }
10315
10316 JNIEXPORT jlong JNICALL
10317 Java_com_redhat_et_libguestfs_GuestFS__1create
10318   (JNIEnv *env, jobject obj)
10319 {
10320   guestfs_h *g;
10321
10322   g = guestfs_create ();
10323   if (g == NULL) {
10324     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10325     return 0;
10326   }
10327   guestfs_set_error_handler (g, NULL, NULL);
10328   return (jlong) (long) g;
10329 }
10330
10331 JNIEXPORT void JNICALL
10332 Java_com_redhat_et_libguestfs_GuestFS__1close
10333   (JNIEnv *env, jobject obj, jlong jg)
10334 {
10335   guestfs_h *g = (guestfs_h *) (long) jg;
10336   guestfs_close (g);
10337 }
10338
10339 ";
10340
10341   List.iter (
10342     fun (name, style, _, _, _, _, _) ->
10343       pr "JNIEXPORT ";
10344       (match fst style with
10345        | RErr -> pr "void ";
10346        | RInt _ -> pr "jint ";
10347        | RInt64 _ -> pr "jlong ";
10348        | RBool _ -> pr "jboolean ";
10349        | RConstString _ | RConstOptString _ | RString _
10350        | RBufferOut _ -> pr "jstring ";
10351        | RStruct _ | RHashtable _ ->
10352            pr "jobject ";
10353        | RStringList _ | RStructList _ ->
10354            pr "jobjectArray ";
10355       );
10356       pr "JNICALL\n";
10357       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10358       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10359       pr "\n";
10360       pr "  (JNIEnv *env, jobject obj, jlong jg";
10361       List.iter (
10362         function
10363         | Pathname n
10364         | Device n | Dev_or_Path n
10365         | String n
10366         | OptString n
10367         | FileIn n
10368         | FileOut n ->
10369             pr ", jstring j%s" n
10370         | BufferIn n ->
10371             pr ", jbyteArray j%s" n
10372         | StringList n | DeviceList n ->
10373             pr ", jobjectArray j%s" n
10374         | Bool n ->
10375             pr ", jboolean j%s" n
10376         | Int n ->
10377             pr ", jint j%s" n
10378         | Int64 n ->
10379             pr ", jlong j%s" n
10380       ) (snd style);
10381       pr ")\n";
10382       pr "{\n";
10383       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10384       let error_code, no_ret =
10385         match fst style with
10386         | RErr -> pr "  int r;\n"; "-1", ""
10387         | RBool _
10388         | RInt _ -> pr "  int r;\n"; "-1", "0"
10389         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10390         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10391         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10392         | RString _ ->
10393             pr "  jstring jr;\n";
10394             pr "  char *r;\n"; "NULL", "NULL"
10395         | RStringList _ ->
10396             pr "  jobjectArray jr;\n";
10397             pr "  int r_len;\n";
10398             pr "  jclass cl;\n";
10399             pr "  jstring jstr;\n";
10400             pr "  char **r;\n"; "NULL", "NULL"
10401         | RStruct (_, typ) ->
10402             pr "  jobject jr;\n";
10403             pr "  jclass cl;\n";
10404             pr "  jfieldID fl;\n";
10405             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10406         | RStructList (_, typ) ->
10407             pr "  jobjectArray jr;\n";
10408             pr "  jclass cl;\n";
10409             pr "  jfieldID fl;\n";
10410             pr "  jobject jfl;\n";
10411             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10412         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10413         | RBufferOut _ ->
10414             pr "  jstring jr;\n";
10415             pr "  char *r;\n";
10416             pr "  size_t size;\n";
10417             "NULL", "NULL" in
10418       List.iter (
10419         function
10420         | Pathname n
10421         | Device n | Dev_or_Path n
10422         | String n
10423         | OptString n
10424         | FileIn n
10425         | FileOut n ->
10426             pr "  const char *%s;\n" n
10427         | BufferIn n ->
10428             pr "  jbyte *%s;\n" n;
10429             pr "  size_t %s_size;\n" n
10430         | StringList n | DeviceList n ->
10431             pr "  int %s_len;\n" n;
10432             pr "  const char **%s;\n" n
10433         | Bool n
10434         | Int n ->
10435             pr "  int %s;\n" n
10436         | Int64 n ->
10437             pr "  int64_t %s;\n" n
10438       ) (snd style);
10439
10440       let needs_i =
10441         (match fst style with
10442          | RStringList _ | RStructList _ -> true
10443          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10444          | RConstOptString _
10445          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10446           List.exists (function
10447                        | StringList _ -> true
10448                        | DeviceList _ -> true
10449                        | _ -> false) (snd style) in
10450       if needs_i then
10451         pr "  int i;\n";
10452
10453       pr "\n";
10454
10455       (* Get the parameters. *)
10456       List.iter (
10457         function
10458         | Pathname n
10459         | Device n | Dev_or_Path n
10460         | String n
10461         | FileIn n
10462         | FileOut n ->
10463             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10464         | OptString n ->
10465             (* This is completely undocumented, but Java null becomes
10466              * a NULL parameter.
10467              *)
10468             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10469         | BufferIn n ->
10470             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10471             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10472         | StringList n | DeviceList n ->
10473             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10474             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10475             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10476             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10477               n;
10478             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10479             pr "  }\n";
10480             pr "  %s[%s_len] = NULL;\n" n n;
10481         | Bool n
10482         | Int n
10483         | Int64 n ->
10484             pr "  %s = j%s;\n" n n
10485       ) (snd style);
10486
10487       (* Make the call. *)
10488       pr "  r = guestfs_%s " name;
10489       generate_c_call_args ~handle:"g" style;
10490       pr ";\n";
10491
10492       (* Release the parameters. *)
10493       List.iter (
10494         function
10495         | Pathname n
10496         | Device n | Dev_or_Path n
10497         | String n
10498         | FileIn n
10499         | FileOut n ->
10500             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10501         | OptString n ->
10502             pr "  if (j%s)\n" n;
10503             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10504         | BufferIn n ->
10505             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10506         | StringList n | DeviceList n ->
10507             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10508             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10509               n;
10510             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10511             pr "  }\n";
10512             pr "  free (%s);\n" n
10513         | Bool n
10514         | Int n
10515         | Int64 n -> ()
10516       ) (snd style);
10517
10518       (* Check for errors. *)
10519       pr "  if (r == %s) {\n" error_code;
10520       pr "    throw_exception (env, guestfs_last_error (g));\n";
10521       pr "    return %s;\n" no_ret;
10522       pr "  }\n";
10523
10524       (* Return value. *)
10525       (match fst style with
10526        | RErr -> ()
10527        | RInt _ -> pr "  return (jint) r;\n"
10528        | RBool _ -> pr "  return (jboolean) r;\n"
10529        | RInt64 _ -> pr "  return (jlong) r;\n"
10530        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10531        | RConstOptString _ ->
10532            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10533        | RString _ ->
10534            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10535            pr "  free (r);\n";
10536            pr "  return jr;\n"
10537        | RStringList _ ->
10538            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10539            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10540            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10541            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10542            pr "  for (i = 0; i < r_len; ++i) {\n";
10543            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10544            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10545            pr "    free (r[i]);\n";
10546            pr "  }\n";
10547            pr "  free (r);\n";
10548            pr "  return jr;\n"
10549        | RStruct (_, typ) ->
10550            let jtyp = java_name_of_struct typ in
10551            let cols = cols_of_struct typ in
10552            generate_java_struct_return typ jtyp cols
10553        | RStructList (_, typ) ->
10554            let jtyp = java_name_of_struct typ in
10555            let cols = cols_of_struct typ in
10556            generate_java_struct_list_return typ jtyp cols
10557        | RHashtable _ ->
10558            (* XXX *)
10559            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10560            pr "  return NULL;\n"
10561        | RBufferOut _ ->
10562            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10563            pr "  free (r);\n";
10564            pr "  return jr;\n"
10565       );
10566
10567       pr "}\n";
10568       pr "\n"
10569   ) all_functions
10570
10571 and generate_java_struct_return typ jtyp cols =
10572   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10573   pr "  jr = (*env)->AllocObject (env, cl);\n";
10574   List.iter (
10575     function
10576     | name, FString ->
10577         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10578         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10579     | name, FUUID ->
10580         pr "  {\n";
10581         pr "    char s[33];\n";
10582         pr "    memcpy (s, r->%s, 32);\n" name;
10583         pr "    s[32] = 0;\n";
10584         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10585         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10586         pr "  }\n";
10587     | name, FBuffer ->
10588         pr "  {\n";
10589         pr "    int len = r->%s_len;\n" name;
10590         pr "    char s[len+1];\n";
10591         pr "    memcpy (s, r->%s, len);\n" name;
10592         pr "    s[len] = 0;\n";
10593         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10594         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10595         pr "  }\n";
10596     | name, (FBytes|FUInt64|FInt64) ->
10597         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10598         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10599     | name, (FUInt32|FInt32) ->
10600         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10601         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10602     | name, FOptPercent ->
10603         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10604         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10605     | name, FChar ->
10606         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10607         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10608   ) cols;
10609   pr "  free (r);\n";
10610   pr "  return jr;\n"
10611
10612 and generate_java_struct_list_return typ jtyp cols =
10613   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10614   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10615   pr "  for (i = 0; i < r->len; ++i) {\n";
10616   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10617   List.iter (
10618     function
10619     | name, FString ->
10620         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10621         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10622     | name, FUUID ->
10623         pr "    {\n";
10624         pr "      char s[33];\n";
10625         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10626         pr "      s[32] = 0;\n";
10627         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10628         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10629         pr "    }\n";
10630     | name, FBuffer ->
10631         pr "    {\n";
10632         pr "      int len = r->val[i].%s_len;\n" name;
10633         pr "      char s[len+1];\n";
10634         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10635         pr "      s[len] = 0;\n";
10636         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10637         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10638         pr "    }\n";
10639     | name, (FBytes|FUInt64|FInt64) ->
10640         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10641         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10642     | name, (FUInt32|FInt32) ->
10643         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10644         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10645     | name, FOptPercent ->
10646         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10647         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10648     | name, FChar ->
10649         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10650         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10651   ) cols;
10652   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10653   pr "  }\n";
10654   pr "  guestfs_free_%s_list (r);\n" typ;
10655   pr "  return jr;\n"
10656
10657 and generate_java_makefile_inc () =
10658   generate_header HashStyle GPLv2plus;
10659
10660   pr "java_built_sources = \\\n";
10661   List.iter (
10662     fun (typ, jtyp) ->
10663         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10664   ) java_structs;
10665   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10666
10667 and generate_haskell_hs () =
10668   generate_header HaskellStyle LGPLv2plus;
10669
10670   (* XXX We only know how to generate partial FFI for Haskell
10671    * at the moment.  Please help out!
10672    *)
10673   let can_generate style =
10674     match style with
10675     | RErr, _
10676     | RInt _, _
10677     | RInt64 _, _ -> true
10678     | RBool _, _
10679     | RConstString _, _
10680     | RConstOptString _, _
10681     | RString _, _
10682     | RStringList _, _
10683     | RStruct _, _
10684     | RStructList _, _
10685     | RHashtable _, _
10686     | RBufferOut _, _ -> false in
10687
10688   pr "\
10689 {-# INCLUDE <guestfs.h> #-}
10690 {-# LANGUAGE ForeignFunctionInterface #-}
10691
10692 module Guestfs (
10693   create";
10694
10695   (* List out the names of the actions we want to export. *)
10696   List.iter (
10697     fun (name, style, _, _, _, _, _) ->
10698       if can_generate style then pr ",\n  %s" name
10699   ) all_functions;
10700
10701   pr "
10702   ) where
10703
10704 -- Unfortunately some symbols duplicate ones already present
10705 -- in Prelude.  We don't know which, so we hard-code a list
10706 -- here.
10707 import Prelude hiding (truncate)
10708
10709 import Foreign
10710 import Foreign.C
10711 import Foreign.C.Types
10712 import IO
10713 import Control.Exception
10714 import Data.Typeable
10715
10716 data GuestfsS = GuestfsS            -- represents the opaque C struct
10717 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10718 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10719
10720 -- XXX define properly later XXX
10721 data PV = PV
10722 data VG = VG
10723 data LV = LV
10724 data IntBool = IntBool
10725 data Stat = Stat
10726 data StatVFS = StatVFS
10727 data Hashtable = Hashtable
10728
10729 foreign import ccall unsafe \"guestfs_create\" c_create
10730   :: IO GuestfsP
10731 foreign import ccall unsafe \"&guestfs_close\" c_close
10732   :: FunPtr (GuestfsP -> IO ())
10733 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10734   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10735
10736 create :: IO GuestfsH
10737 create = do
10738   p <- c_create
10739   c_set_error_handler p nullPtr nullPtr
10740   h <- newForeignPtr c_close p
10741   return h
10742
10743 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10744   :: GuestfsP -> IO CString
10745
10746 -- last_error :: GuestfsH -> IO (Maybe String)
10747 -- last_error h = do
10748 --   str <- withForeignPtr h (\\p -> c_last_error p)
10749 --   maybePeek peekCString str
10750
10751 last_error :: GuestfsH -> IO (String)
10752 last_error h = do
10753   str <- withForeignPtr h (\\p -> c_last_error p)
10754   if (str == nullPtr)
10755     then return \"no error\"
10756     else peekCString str
10757
10758 ";
10759
10760   (* Generate wrappers for each foreign function. *)
10761   List.iter (
10762     fun (name, style, _, _, _, _, _) ->
10763       if can_generate style then (
10764         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10765         pr "  :: ";
10766         generate_haskell_prototype ~handle:"GuestfsP" style;
10767         pr "\n";
10768         pr "\n";
10769         pr "%s :: " name;
10770         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10771         pr "\n";
10772         pr "%s %s = do\n" name
10773           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10774         pr "  r <- ";
10775         (* Convert pointer arguments using with* functions. *)
10776         List.iter (
10777           function
10778           | FileIn n
10779           | FileOut n
10780           | Pathname n | Device n | Dev_or_Path n | String n ->
10781               pr "withCString %s $ \\%s -> " n n
10782           | BufferIn n ->
10783               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10784           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10785           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10786           | Bool _ | Int _ | Int64 _ -> ()
10787         ) (snd style);
10788         (* Convert integer arguments. *)
10789         let args =
10790           List.map (
10791             function
10792             | Bool n -> sprintf "(fromBool %s)" n
10793             | Int n -> sprintf "(fromIntegral %s)" n
10794             | Int64 n -> sprintf "(fromIntegral %s)" n
10795             | FileIn n | FileOut n
10796             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10797             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10798           ) (snd style) in
10799         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10800           (String.concat " " ("p" :: args));
10801         (match fst style with
10802          | RErr | RInt _ | RInt64 _ | RBool _ ->
10803              pr "  if (r == -1)\n";
10804              pr "    then do\n";
10805              pr "      err <- last_error h\n";
10806              pr "      fail err\n";
10807          | RConstString _ | RConstOptString _ | RString _
10808          | RStringList _ | RStruct _
10809          | RStructList _ | RHashtable _ | RBufferOut _ ->
10810              pr "  if (r == nullPtr)\n";
10811              pr "    then do\n";
10812              pr "      err <- last_error h\n";
10813              pr "      fail err\n";
10814         );
10815         (match fst style with
10816          | RErr ->
10817              pr "    else return ()\n"
10818          | RInt _ ->
10819              pr "    else return (fromIntegral r)\n"
10820          | RInt64 _ ->
10821              pr "    else return (fromIntegral r)\n"
10822          | RBool _ ->
10823              pr "    else return (toBool r)\n"
10824          | RConstString _
10825          | RConstOptString _
10826          | RString _
10827          | RStringList _
10828          | RStruct _
10829          | RStructList _
10830          | RHashtable _
10831          | RBufferOut _ ->
10832              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10833         );
10834         pr "\n";
10835       )
10836   ) all_functions
10837
10838 and generate_haskell_prototype ~handle ?(hs = false) style =
10839   pr "%s -> " handle;
10840   let string = if hs then "String" else "CString" in
10841   let int = if hs then "Int" else "CInt" in
10842   let bool = if hs then "Bool" else "CInt" in
10843   let int64 = if hs then "Integer" else "Int64" in
10844   List.iter (
10845     fun arg ->
10846       (match arg with
10847        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10848        | BufferIn _ ->
10849            if hs then pr "String"
10850            else pr "CString -> CInt"
10851        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10852        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10853        | Bool _ -> pr "%s" bool
10854        | Int _ -> pr "%s" int
10855        | Int64 _ -> pr "%s" int
10856        | FileIn _ -> pr "%s" string
10857        | FileOut _ -> pr "%s" string
10858       );
10859       pr " -> ";
10860   ) (snd style);
10861   pr "IO (";
10862   (match fst style with
10863    | RErr -> if not hs then pr "CInt"
10864    | RInt _ -> pr "%s" int
10865    | RInt64 _ -> pr "%s" int64
10866    | RBool _ -> pr "%s" bool
10867    | RConstString _ -> pr "%s" string
10868    | RConstOptString _ -> pr "Maybe %s" string
10869    | RString _ -> pr "%s" string
10870    | RStringList _ -> pr "[%s]" string
10871    | RStruct (_, typ) ->
10872        let name = java_name_of_struct typ in
10873        pr "%s" name
10874    | RStructList (_, typ) ->
10875        let name = java_name_of_struct typ in
10876        pr "[%s]" name
10877    | RHashtable _ -> pr "Hashtable"
10878    | RBufferOut _ -> pr "%s" string
10879   );
10880   pr ")"
10881
10882 and generate_csharp () =
10883   generate_header CPlusPlusStyle LGPLv2plus;
10884
10885   (* XXX Make this configurable by the C# assembly users. *)
10886   let library = "libguestfs.so.0" in
10887
10888   pr "\
10889 // These C# bindings are highly experimental at present.
10890 //
10891 // Firstly they only work on Linux (ie. Mono).  In order to get them
10892 // to work on Windows (ie. .Net) you would need to port the library
10893 // itself to Windows first.
10894 //
10895 // The second issue is that some calls are known to be incorrect and
10896 // can cause Mono to segfault.  Particularly: calls which pass or
10897 // return string[], or return any structure value.  This is because
10898 // we haven't worked out the correct way to do this from C#.
10899 //
10900 // The third issue is that when compiling you get a lot of warnings.
10901 // We are not sure whether the warnings are important or not.
10902 //
10903 // Fourthly we do not routinely build or test these bindings as part
10904 // of the make && make check cycle, which means that regressions might
10905 // go unnoticed.
10906 //
10907 // Suggestions and patches are welcome.
10908
10909 // To compile:
10910 //
10911 // gmcs Libguestfs.cs
10912 // mono Libguestfs.exe
10913 //
10914 // (You'll probably want to add a Test class / static main function
10915 // otherwise this won't do anything useful).
10916
10917 using System;
10918 using System.IO;
10919 using System.Runtime.InteropServices;
10920 using System.Runtime.Serialization;
10921 using System.Collections;
10922
10923 namespace Guestfs
10924 {
10925   class Error : System.ApplicationException
10926   {
10927     public Error (string message) : base (message) {}
10928     protected Error (SerializationInfo info, StreamingContext context) {}
10929   }
10930
10931   class Guestfs
10932   {
10933     IntPtr _handle;
10934
10935     [DllImport (\"%s\")]
10936     static extern IntPtr guestfs_create ();
10937
10938     public Guestfs ()
10939     {
10940       _handle = guestfs_create ();
10941       if (_handle == IntPtr.Zero)
10942         throw new Error (\"could not create guestfs handle\");
10943     }
10944
10945     [DllImport (\"%s\")]
10946     static extern void guestfs_close (IntPtr h);
10947
10948     ~Guestfs ()
10949     {
10950       guestfs_close (_handle);
10951     }
10952
10953     [DllImport (\"%s\")]
10954     static extern string guestfs_last_error (IntPtr h);
10955
10956 " library library library;
10957
10958   (* Generate C# structure bindings.  We prefix struct names with
10959    * underscore because C# cannot have conflicting struct names and
10960    * method names (eg. "class stat" and "stat").
10961    *)
10962   List.iter (
10963     fun (typ, cols) ->
10964       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10965       pr "    public class _%s {\n" typ;
10966       List.iter (
10967         function
10968         | name, FChar -> pr "      char %s;\n" name
10969         | name, FString -> pr "      string %s;\n" name
10970         | name, FBuffer ->
10971             pr "      uint %s_len;\n" name;
10972             pr "      string %s;\n" name
10973         | name, FUUID ->
10974             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10975             pr "      string %s;\n" name
10976         | name, FUInt32 -> pr "      uint %s;\n" name
10977         | name, FInt32 -> pr "      int %s;\n" name
10978         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10979         | name, FInt64 -> pr "      long %s;\n" name
10980         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10981       ) cols;
10982       pr "    }\n";
10983       pr "\n"
10984   ) structs;
10985
10986   (* Generate C# function bindings. *)
10987   List.iter (
10988     fun (name, style, _, _, _, shortdesc, _) ->
10989       let rec csharp_return_type () =
10990         match fst style with
10991         | RErr -> "void"
10992         | RBool n -> "bool"
10993         | RInt n -> "int"
10994         | RInt64 n -> "long"
10995         | RConstString n
10996         | RConstOptString n
10997         | RString n
10998         | RBufferOut n -> "string"
10999         | RStruct (_,n) -> "_" ^ n
11000         | RHashtable n -> "Hashtable"
11001         | RStringList n -> "string[]"
11002         | RStructList (_,n) -> sprintf "_%s[]" n
11003
11004       and c_return_type () =
11005         match fst style with
11006         | RErr
11007         | RBool _
11008         | RInt _ -> "int"
11009         | RInt64 _ -> "long"
11010         | RConstString _
11011         | RConstOptString _
11012         | RString _
11013         | RBufferOut _ -> "string"
11014         | RStruct (_,n) -> "_" ^ n
11015         | RHashtable _
11016         | RStringList _ -> "string[]"
11017         | RStructList (_,n) -> sprintf "_%s[]" n
11018
11019       and c_error_comparison () =
11020         match fst style with
11021         | RErr
11022         | RBool _
11023         | RInt _
11024         | RInt64 _ -> "== -1"
11025         | RConstString _
11026         | RConstOptString _
11027         | RString _
11028         | RBufferOut _
11029         | RStruct (_,_)
11030         | RHashtable _
11031         | RStringList _
11032         | RStructList (_,_) -> "== null"
11033
11034       and generate_extern_prototype () =
11035         pr "    static extern %s guestfs_%s (IntPtr h"
11036           (c_return_type ()) name;
11037         List.iter (
11038           function
11039           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11040           | FileIn n | FileOut n
11041           | BufferIn n ->
11042               pr ", [In] string %s" n
11043           | StringList n | DeviceList n ->
11044               pr ", [In] string[] %s" n
11045           | Bool n ->
11046               pr ", bool %s" n
11047           | Int n ->
11048               pr ", int %s" n
11049           | Int64 n ->
11050               pr ", long %s" n
11051         ) (snd style);
11052         pr ");\n"
11053
11054       and generate_public_prototype () =
11055         pr "    public %s %s (" (csharp_return_type ()) name;
11056         let comma = ref false in
11057         let next () =
11058           if !comma then pr ", ";
11059           comma := true
11060         in
11061         List.iter (
11062           function
11063           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11064           | FileIn n | FileOut n
11065           | BufferIn n ->
11066               next (); pr "string %s" n
11067           | StringList n | DeviceList n ->
11068               next (); pr "string[] %s" n
11069           | Bool n ->
11070               next (); pr "bool %s" n
11071           | Int n ->
11072               next (); pr "int %s" n
11073           | Int64 n ->
11074               next (); pr "long %s" n
11075         ) (snd style);
11076         pr ")\n"
11077
11078       and generate_call () =
11079         pr "guestfs_%s (_handle" name;
11080         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11081         pr ");\n";
11082       in
11083
11084       pr "    [DllImport (\"%s\")]\n" library;
11085       generate_extern_prototype ();
11086       pr "\n";
11087       pr "    /// <summary>\n";
11088       pr "    /// %s\n" shortdesc;
11089       pr "    /// </summary>\n";
11090       generate_public_prototype ();
11091       pr "    {\n";
11092       pr "      %s r;\n" (c_return_type ());
11093       pr "      r = ";
11094       generate_call ();
11095       pr "      if (r %s)\n" (c_error_comparison ());
11096       pr "        throw new Error (guestfs_last_error (_handle));\n";
11097       (match fst style with
11098        | RErr -> ()
11099        | RBool _ ->
11100            pr "      return r != 0 ? true : false;\n"
11101        | RHashtable _ ->
11102            pr "      Hashtable rr = new Hashtable ();\n";
11103            pr "      for (int i = 0; i < r.Length; i += 2)\n";
11104            pr "        rr.Add (r[i], r[i+1]);\n";
11105            pr "      return rr;\n"
11106        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11107        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11108        | RStructList _ ->
11109            pr "      return r;\n"
11110       );
11111       pr "    }\n";
11112       pr "\n";
11113   ) all_functions_sorted;
11114
11115   pr "  }
11116 }
11117 "
11118
11119 and generate_bindtests () =
11120   generate_header CStyle LGPLv2plus;
11121
11122   pr "\
11123 #include <stdio.h>
11124 #include <stdlib.h>
11125 #include <inttypes.h>
11126 #include <string.h>
11127
11128 #include \"guestfs.h\"
11129 #include \"guestfs-internal.h\"
11130 #include \"guestfs-internal-actions.h\"
11131 #include \"guestfs_protocol.h\"
11132
11133 #define error guestfs_error
11134 #define safe_calloc guestfs_safe_calloc
11135 #define safe_malloc guestfs_safe_malloc
11136
11137 static void
11138 print_strings (char *const *argv)
11139 {
11140   int argc;
11141
11142   printf (\"[\");
11143   for (argc = 0; argv[argc] != NULL; ++argc) {
11144     if (argc > 0) printf (\", \");
11145     printf (\"\\\"%%s\\\"\", argv[argc]);
11146   }
11147   printf (\"]\\n\");
11148 }
11149
11150 /* The test0 function prints its parameters to stdout. */
11151 ";
11152
11153   let test0, tests =
11154     match test_functions with
11155     | [] -> assert false
11156     | test0 :: tests -> test0, tests in
11157
11158   let () =
11159     let (name, style, _, _, _, _, _) = test0 in
11160     generate_prototype ~extern:false ~semicolon:false ~newline:true
11161       ~handle:"g" ~prefix:"guestfs__" name style;
11162     pr "{\n";
11163     List.iter (
11164       function
11165       | Pathname n
11166       | Device n | Dev_or_Path n
11167       | String n
11168       | FileIn n
11169       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11170       | BufferIn n ->
11171           pr "  {\n";
11172           pr "    size_t i;\n";
11173           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11174           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11175           pr "    printf (\"\\n\");\n";
11176           pr "  }\n";
11177       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11178       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11179       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11180       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11181       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11182     ) (snd style);
11183     pr "  /* Java changes stdout line buffering so we need this: */\n";
11184     pr "  fflush (stdout);\n";
11185     pr "  return 0;\n";
11186     pr "}\n";
11187     pr "\n" in
11188
11189   List.iter (
11190     fun (name, style, _, _, _, _, _) ->
11191       if String.sub name (String.length name - 3) 3 <> "err" then (
11192         pr "/* Test normal return. */\n";
11193         generate_prototype ~extern:false ~semicolon:false ~newline:true
11194           ~handle:"g" ~prefix:"guestfs__" name style;
11195         pr "{\n";
11196         (match fst style with
11197          | RErr ->
11198              pr "  return 0;\n"
11199          | RInt _ ->
11200              pr "  int r;\n";
11201              pr "  sscanf (val, \"%%d\", &r);\n";
11202              pr "  return r;\n"
11203          | RInt64 _ ->
11204              pr "  int64_t r;\n";
11205              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11206              pr "  return r;\n"
11207          | RBool _ ->
11208              pr "  return STREQ (val, \"true\");\n"
11209          | RConstString _
11210          | RConstOptString _ ->
11211              (* Can't return the input string here.  Return a static
11212               * string so we ensure we get a segfault if the caller
11213               * tries to free it.
11214               *)
11215              pr "  return \"static string\";\n"
11216          | RString _ ->
11217              pr "  return strdup (val);\n"
11218          | RStringList _ ->
11219              pr "  char **strs;\n";
11220              pr "  int n, i;\n";
11221              pr "  sscanf (val, \"%%d\", &n);\n";
11222              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11223              pr "  for (i = 0; i < n; ++i) {\n";
11224              pr "    strs[i] = safe_malloc (g, 16);\n";
11225              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11226              pr "  }\n";
11227              pr "  strs[n] = NULL;\n";
11228              pr "  return strs;\n"
11229          | RStruct (_, typ) ->
11230              pr "  struct guestfs_%s *r;\n" typ;
11231              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11232              pr "  return r;\n"
11233          | RStructList (_, typ) ->
11234              pr "  struct guestfs_%s_list *r;\n" typ;
11235              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11236              pr "  sscanf (val, \"%%d\", &r->len);\n";
11237              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11238              pr "  return r;\n"
11239          | RHashtable _ ->
11240              pr "  char **strs;\n";
11241              pr "  int n, i;\n";
11242              pr "  sscanf (val, \"%%d\", &n);\n";
11243              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11244              pr "  for (i = 0; i < n; ++i) {\n";
11245              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11246              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11247              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11248              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11249              pr "  }\n";
11250              pr "  strs[n*2] = NULL;\n";
11251              pr "  return strs;\n"
11252          | RBufferOut _ ->
11253              pr "  return strdup (val);\n"
11254         );
11255         pr "}\n";
11256         pr "\n"
11257       ) else (
11258         pr "/* Test error return. */\n";
11259         generate_prototype ~extern:false ~semicolon:false ~newline:true
11260           ~handle:"g" ~prefix:"guestfs__" name style;
11261         pr "{\n";
11262         pr "  error (g, \"error\");\n";
11263         (match fst style with
11264          | RErr | RInt _ | RInt64 _ | RBool _ ->
11265              pr "  return -1;\n"
11266          | RConstString _ | RConstOptString _
11267          | RString _ | RStringList _ | RStruct _
11268          | RStructList _
11269          | RHashtable _
11270          | RBufferOut _ ->
11271              pr "  return NULL;\n"
11272         );
11273         pr "}\n";
11274         pr "\n"
11275       )
11276   ) tests
11277
11278 and generate_ocaml_bindtests () =
11279   generate_header OCamlStyle GPLv2plus;
11280
11281   pr "\
11282 let () =
11283   let g = Guestfs.create () in
11284 ";
11285
11286   let mkargs args =
11287     String.concat " " (
11288       List.map (
11289         function
11290         | CallString s -> "\"" ^ s ^ "\""
11291         | CallOptString None -> "None"
11292         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11293         | CallStringList xs ->
11294             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11295         | CallInt i when i >= 0 -> string_of_int i
11296         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11297         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11298         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11299         | CallBool b -> string_of_bool b
11300         | CallBuffer s -> sprintf "%S" s
11301       ) args
11302     )
11303   in
11304
11305   generate_lang_bindtests (
11306     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11307   );
11308
11309   pr "print_endline \"EOF\"\n"
11310
11311 and generate_perl_bindtests () =
11312   pr "#!/usr/bin/perl -w\n";
11313   generate_header HashStyle GPLv2plus;
11314
11315   pr "\
11316 use strict;
11317
11318 use Sys::Guestfs;
11319
11320 my $g = Sys::Guestfs->new ();
11321 ";
11322
11323   let mkargs args =
11324     String.concat ", " (
11325       List.map (
11326         function
11327         | CallString s -> "\"" ^ s ^ "\""
11328         | CallOptString None -> "undef"
11329         | CallOptString (Some s) -> sprintf "\"%s\"" s
11330         | CallStringList xs ->
11331             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11332         | CallInt i -> string_of_int i
11333         | CallInt64 i -> Int64.to_string i
11334         | CallBool b -> if b then "1" else "0"
11335         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11336       ) args
11337     )
11338   in
11339
11340   generate_lang_bindtests (
11341     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11342   );
11343
11344   pr "print \"EOF\\n\"\n"
11345
11346 and generate_python_bindtests () =
11347   generate_header HashStyle GPLv2plus;
11348
11349   pr "\
11350 import guestfs
11351
11352 g = guestfs.GuestFS ()
11353 ";
11354
11355   let mkargs args =
11356     String.concat ", " (
11357       List.map (
11358         function
11359         | CallString s -> "\"" ^ s ^ "\""
11360         | CallOptString None -> "None"
11361         | CallOptString (Some s) -> sprintf "\"%s\"" s
11362         | CallStringList xs ->
11363             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11364         | CallInt i -> string_of_int i
11365         | CallInt64 i -> Int64.to_string i
11366         | CallBool b -> if b then "1" else "0"
11367         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11368       ) args
11369     )
11370   in
11371
11372   generate_lang_bindtests (
11373     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11374   );
11375
11376   pr "print \"EOF\"\n"
11377
11378 and generate_ruby_bindtests () =
11379   generate_header HashStyle GPLv2plus;
11380
11381   pr "\
11382 require 'guestfs'
11383
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 -> "nil"
11393         | CallOptString (Some s) -> sprintf "\"%s\"" s
11394         | CallStringList xs ->
11395             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11396         | CallInt i -> string_of_int i
11397         | CallInt64 i -> Int64.to_string i
11398         | CallBool b -> string_of_bool b
11399         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11400       ) args
11401     )
11402   in
11403
11404   generate_lang_bindtests (
11405     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11406   );
11407
11408   pr "print \"EOF\\n\"\n"
11409
11410 and generate_java_bindtests () =
11411   generate_header CStyle GPLv2plus;
11412
11413   pr "\
11414 import com.redhat.et.libguestfs.*;
11415
11416 public class Bindtests {
11417     public static void main (String[] argv)
11418     {
11419         try {
11420             GuestFS g = new GuestFS ();
11421 ";
11422
11423   let mkargs args =
11424     String.concat ", " (
11425       List.map (
11426         function
11427         | CallString s -> "\"" ^ s ^ "\""
11428         | CallOptString None -> "null"
11429         | CallOptString (Some s) -> sprintf "\"%s\"" s
11430         | CallStringList xs ->
11431             "new String[]{" ^
11432               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11433         | CallInt i -> string_of_int i
11434         | CallInt64 i -> Int64.to_string i
11435         | CallBool b -> string_of_bool b
11436         | CallBuffer s ->
11437             "new byte[] { " ^ String.concat "," (
11438               map_chars (fun c -> string_of_int (Char.code c)) s
11439             ) ^ " }"
11440       ) args
11441     )
11442   in
11443
11444   generate_lang_bindtests (
11445     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11446   );
11447
11448   pr "
11449             System.out.println (\"EOF\");
11450         }
11451         catch (Exception exn) {
11452             System.err.println (exn);
11453             System.exit (1);
11454         }
11455     }
11456 }
11457 "
11458
11459 and generate_haskell_bindtests () =
11460   generate_header HaskellStyle GPLv2plus;
11461
11462   pr "\
11463 module Bindtests where
11464 import qualified Guestfs
11465
11466 main = do
11467   g <- Guestfs.create
11468 ";
11469
11470   let mkargs args =
11471     String.concat " " (
11472       List.map (
11473         function
11474         | CallString s -> "\"" ^ s ^ "\""
11475         | CallOptString None -> "Nothing"
11476         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11477         | CallStringList xs ->
11478             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11479         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11480         | CallInt i -> string_of_int i
11481         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11482         | CallInt64 i -> Int64.to_string i
11483         | CallBool true -> "True"
11484         | CallBool false -> "False"
11485         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11486       ) args
11487     )
11488   in
11489
11490   generate_lang_bindtests (
11491     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11492   );
11493
11494   pr "  putStrLn \"EOF\"\n"
11495
11496 (* Language-independent bindings tests - we do it this way to
11497  * ensure there is parity in testing bindings across all languages.
11498  *)
11499 and generate_lang_bindtests call =
11500   call "test0" [CallString "abc"; CallOptString (Some "def");
11501                 CallStringList []; CallBool false;
11502                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11503                 CallBuffer "abc\000abc"];
11504   call "test0" [CallString "abc"; CallOptString None;
11505                 CallStringList []; CallBool false;
11506                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11507                 CallBuffer "abc\000abc"];
11508   call "test0" [CallString ""; CallOptString (Some "def");
11509                 CallStringList []; CallBool false;
11510                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11511                 CallBuffer "abc\000abc"];
11512   call "test0" [CallString ""; CallOptString (Some "");
11513                 CallStringList []; CallBool false;
11514                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11515                 CallBuffer "abc\000abc"];
11516   call "test0" [CallString "abc"; CallOptString (Some "def");
11517                 CallStringList ["1"]; CallBool false;
11518                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11519                 CallBuffer "abc\000abc"];
11520   call "test0" [CallString "abc"; CallOptString (Some "def");
11521                 CallStringList ["1"; "2"]; CallBool false;
11522                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11523                 CallBuffer "abc\000abc"];
11524   call "test0" [CallString "abc"; CallOptString (Some "def");
11525                 CallStringList ["1"]; CallBool true;
11526                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11527                 CallBuffer "abc\000abc"];
11528   call "test0" [CallString "abc"; CallOptString (Some "def");
11529                 CallStringList ["1"]; CallBool false;
11530                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11531                 CallBuffer "abc\000abc"];
11532   call "test0" [CallString "abc"; CallOptString (Some "def");
11533                 CallStringList ["1"]; CallBool false;
11534                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11535                 CallBuffer "abc\000abc"];
11536   call "test0" [CallString "abc"; CallOptString (Some "def");
11537                 CallStringList ["1"]; CallBool false;
11538                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11539                 CallBuffer "abc\000abc"];
11540   call "test0" [CallString "abc"; CallOptString (Some "def");
11541                 CallStringList ["1"]; CallBool false;
11542                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11543                 CallBuffer "abc\000abc"];
11544   call "test0" [CallString "abc"; CallOptString (Some "def");
11545                 CallStringList ["1"]; CallBool false;
11546                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11547                 CallBuffer "abc\000abc"];
11548   call "test0" [CallString "abc"; CallOptString (Some "def");
11549                 CallStringList ["1"]; CallBool false;
11550                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11551                 CallBuffer "abc\000abc"]
11552
11553 (* XXX Add here tests of the return and error functions. *)
11554
11555 (* Code to generator bindings for virt-inspector.  Currently only
11556  * implemented for OCaml code (for virt-p2v 2.0).
11557  *)
11558 let rng_input = "inspector/virt-inspector.rng"
11559
11560 (* Read the input file and parse it into internal structures.  This is
11561  * by no means a complete RELAX NG parser, but is just enough to be
11562  * able to parse the specific input file.
11563  *)
11564 type rng =
11565   | Element of string * rng list        (* <element name=name/> *)
11566   | Attribute of string * rng list        (* <attribute name=name/> *)
11567   | Interleave of rng list                (* <interleave/> *)
11568   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11569   | OneOrMore of rng                        (* <oneOrMore/> *)
11570   | Optional of rng                        (* <optional/> *)
11571   | Choice of string list                (* <choice><value/>*</choice> *)
11572   | Value of string                        (* <value>str</value> *)
11573   | Text                                (* <text/> *)
11574
11575 let rec string_of_rng = function
11576   | Element (name, xs) ->
11577       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11578   | Attribute (name, xs) ->
11579       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11580   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11581   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11582   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11583   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11584   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11585   | Value value -> "Value \"" ^ value ^ "\""
11586   | Text -> "Text"
11587
11588 and string_of_rng_list xs =
11589   String.concat ", " (List.map string_of_rng xs)
11590
11591 let rec parse_rng ?defines context = function
11592   | [] -> []
11593   | Xml.Element ("element", ["name", name], children) :: rest ->
11594       Element (name, parse_rng ?defines context children)
11595       :: parse_rng ?defines context rest
11596   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11597       Attribute (name, parse_rng ?defines context children)
11598       :: parse_rng ?defines context rest
11599   | Xml.Element ("interleave", [], children) :: rest ->
11600       Interleave (parse_rng ?defines context children)
11601       :: parse_rng ?defines context rest
11602   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11603       let rng = parse_rng ?defines context [child] in
11604       (match rng with
11605        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11606        | _ ->
11607            failwithf "%s: <zeroOrMore> contains more than one child element"
11608              context
11609       )
11610   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11611       let rng = parse_rng ?defines context [child] in
11612       (match rng with
11613        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11614        | _ ->
11615            failwithf "%s: <oneOrMore> contains more than one child element"
11616              context
11617       )
11618   | Xml.Element ("optional", [], [child]) :: rest ->
11619       let rng = parse_rng ?defines context [child] in
11620       (match rng with
11621        | [child] -> Optional child :: parse_rng ?defines context rest
11622        | _ ->
11623            failwithf "%s: <optional> contains more than one child element"
11624              context
11625       )
11626   | Xml.Element ("choice", [], children) :: rest ->
11627       let values = List.map (
11628         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11629         | _ ->
11630             failwithf "%s: can't handle anything except <value> in <choice>"
11631               context
11632       ) children in
11633       Choice values
11634       :: parse_rng ?defines context rest
11635   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11636       Value value :: parse_rng ?defines context rest
11637   | Xml.Element ("text", [], []) :: rest ->
11638       Text :: parse_rng ?defines context rest
11639   | Xml.Element ("ref", ["name", name], []) :: rest ->
11640       (* Look up the reference.  Because of limitations in this parser,
11641        * we can't handle arbitrarily nested <ref> yet.  You can only
11642        * use <ref> from inside <start>.
11643        *)
11644       (match defines with
11645        | None ->
11646            failwithf "%s: contains <ref>, but no refs are defined yet" context
11647        | Some map ->
11648            let rng = StringMap.find name map in
11649            rng @ parse_rng ?defines context rest
11650       )
11651   | x :: _ ->
11652       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11653
11654 let grammar =
11655   let xml = Xml.parse_file rng_input in
11656   match xml with
11657   | Xml.Element ("grammar", _,
11658                  Xml.Element ("start", _, gram) :: defines) ->
11659       (* The <define/> elements are referenced in the <start> section,
11660        * so build a map of those first.
11661        *)
11662       let defines = List.fold_left (
11663         fun map ->
11664           function Xml.Element ("define", ["name", name], defn) ->
11665             StringMap.add name defn map
11666           | _ ->
11667               failwithf "%s: expected <define name=name/>" rng_input
11668       ) StringMap.empty defines in
11669       let defines = StringMap.mapi parse_rng defines in
11670
11671       (* Parse the <start> clause, passing the defines. *)
11672       parse_rng ~defines "<start>" gram
11673   | _ ->
11674       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11675         rng_input
11676
11677 let name_of_field = function
11678   | Element (name, _) | Attribute (name, _)
11679   | ZeroOrMore (Element (name, _))
11680   | OneOrMore (Element (name, _))
11681   | Optional (Element (name, _)) -> name
11682   | Optional (Attribute (name, _)) -> name
11683   | Text -> (* an unnamed field in an element *)
11684       "data"
11685   | rng ->
11686       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11687
11688 (* At the moment this function only generates OCaml types.  However we
11689  * should parameterize it later so it can generate types/structs in a
11690  * variety of languages.
11691  *)
11692 let generate_types xs =
11693   (* A simple type is one that can be printed out directly, eg.
11694    * "string option".  A complex type is one which has a name and has
11695    * to be defined via another toplevel definition, eg. a struct.
11696    *
11697    * generate_type generates code for either simple or complex types.
11698    * In the simple case, it returns the string ("string option").  In
11699    * the complex case, it returns the name ("mountpoint").  In the
11700    * complex case it has to print out the definition before returning,
11701    * so it should only be called when we are at the beginning of a
11702    * new line (BOL context).
11703    *)
11704   let rec generate_type = function
11705     | Text ->                                (* string *)
11706         "string", true
11707     | Choice values ->                        (* [`val1|`val2|...] *)
11708         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11709     | ZeroOrMore rng ->                        (* <rng> list *)
11710         let t, is_simple = generate_type rng in
11711         t ^ " list (* 0 or more *)", is_simple
11712     | OneOrMore rng ->                        (* <rng> list *)
11713         let t, is_simple = generate_type rng in
11714         t ^ " list (* 1 or more *)", is_simple
11715                                         (* virt-inspector hack: bool *)
11716     | Optional (Attribute (name, [Value "1"])) ->
11717         "bool", true
11718     | Optional rng ->                        (* <rng> list *)
11719         let t, is_simple = generate_type rng in
11720         t ^ " option", is_simple
11721                                         (* type name = { fields ... } *)
11722     | Element (name, fields) when is_attrs_interleave fields ->
11723         generate_type_struct name (get_attrs_interleave fields)
11724     | Element (name, [field])                (* type name = field *)
11725     | Attribute (name, [field]) ->
11726         let t, is_simple = generate_type field in
11727         if is_simple then (t, true)
11728         else (
11729           pr "type %s = %s\n" name t;
11730           name, false
11731         )
11732     | Element (name, fields) ->              (* type name = { fields ... } *)
11733         generate_type_struct name fields
11734     | rng ->
11735         failwithf "generate_type failed at: %s" (string_of_rng rng)
11736
11737   and is_attrs_interleave = function
11738     | [Interleave _] -> true
11739     | Attribute _ :: fields -> is_attrs_interleave fields
11740     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11741     | _ -> false
11742
11743   and get_attrs_interleave = function
11744     | [Interleave fields] -> fields
11745     | ((Attribute _) as field) :: fields
11746     | ((Optional (Attribute _)) as field) :: fields ->
11747         field :: get_attrs_interleave fields
11748     | _ -> assert false
11749
11750   and generate_types xs =
11751     List.iter (fun x -> ignore (generate_type x)) xs
11752
11753   and generate_type_struct name fields =
11754     (* Calculate the types of the fields first.  We have to do this
11755      * before printing anything so we are still in BOL context.
11756      *)
11757     let types = List.map fst (List.map generate_type fields) in
11758
11759     (* Special case of a struct containing just a string and another
11760      * field.  Turn it into an assoc list.
11761      *)
11762     match types with
11763     | ["string"; other] ->
11764         let fname1, fname2 =
11765           match fields with
11766           | [f1; f2] -> name_of_field f1, name_of_field f2
11767           | _ -> assert false in
11768         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11769         name, false
11770
11771     | types ->
11772         pr "type %s = {\n" name;
11773         List.iter (
11774           fun (field, ftype) ->
11775             let fname = name_of_field field in
11776             pr "  %s_%s : %s;\n" name fname ftype
11777         ) (List.combine fields types);
11778         pr "}\n";
11779         (* Return the name of this type, and
11780          * false because it's not a simple type.
11781          *)
11782         name, false
11783   in
11784
11785   generate_types xs
11786
11787 let generate_parsers xs =
11788   (* As for generate_type above, generate_parser makes a parser for
11789    * some type, and returns the name of the parser it has generated.
11790    * Because it (may) need to print something, it should always be
11791    * called in BOL context.
11792    *)
11793   let rec generate_parser = function
11794     | Text ->                                (* string *)
11795         "string_child_or_empty"
11796     | Choice values ->                        (* [`val1|`val2|...] *)
11797         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11798           (String.concat "|"
11799              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11800     | ZeroOrMore rng ->                        (* <rng> list *)
11801         let pa = generate_parser rng in
11802         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11803     | OneOrMore rng ->                        (* <rng> list *)
11804         let pa = generate_parser rng in
11805         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11806                                         (* virt-inspector hack: bool *)
11807     | Optional (Attribute (name, [Value "1"])) ->
11808         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11809     | Optional rng ->                        (* <rng> list *)
11810         let pa = generate_parser rng in
11811         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11812                                         (* type name = { fields ... } *)
11813     | Element (name, fields) when is_attrs_interleave fields ->
11814         generate_parser_struct name (get_attrs_interleave fields)
11815     | Element (name, [field]) ->        (* type name = field *)
11816         let pa = generate_parser field in
11817         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11818         pr "let %s =\n" parser_name;
11819         pr "  %s\n" pa;
11820         pr "let parse_%s = %s\n" name parser_name;
11821         parser_name
11822     | Attribute (name, [field]) ->
11823         let pa = generate_parser field in
11824         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11825         pr "let %s =\n" parser_name;
11826         pr "  %s\n" pa;
11827         pr "let parse_%s = %s\n" name parser_name;
11828         parser_name
11829     | Element (name, fields) ->              (* type name = { fields ... } *)
11830         generate_parser_struct name ([], fields)
11831     | rng ->
11832         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11833
11834   and is_attrs_interleave = function
11835     | [Interleave _] -> true
11836     | Attribute _ :: fields -> is_attrs_interleave fields
11837     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11838     | _ -> false
11839
11840   and get_attrs_interleave = function
11841     | [Interleave fields] -> [], fields
11842     | ((Attribute _) as field) :: fields
11843     | ((Optional (Attribute _)) as field) :: fields ->
11844         let attrs, interleaves = get_attrs_interleave fields in
11845         (field :: attrs), interleaves
11846     | _ -> assert false
11847
11848   and generate_parsers xs =
11849     List.iter (fun x -> ignore (generate_parser x)) xs
11850
11851   and generate_parser_struct name (attrs, interleaves) =
11852     (* Generate parsers for the fields first.  We have to do this
11853      * before printing anything so we are still in BOL context.
11854      *)
11855     let fields = attrs @ interleaves in
11856     let pas = List.map generate_parser fields in
11857
11858     (* Generate an intermediate tuple from all the fields first.
11859      * If the type is just a string + another field, then we will
11860      * return this directly, otherwise it is turned into a record.
11861      *
11862      * RELAX NG note: This code treats <interleave> and plain lists of
11863      * fields the same.  In other words, it doesn't bother enforcing
11864      * any ordering of fields in the XML.
11865      *)
11866     pr "let parse_%s x =\n" name;
11867     pr "  let t = (\n    ";
11868     let comma = ref false in
11869     List.iter (
11870       fun x ->
11871         if !comma then pr ",\n    ";
11872         comma := true;
11873         match x with
11874         | Optional (Attribute (fname, [field])), pa ->
11875             pr "%s x" pa
11876         | Optional (Element (fname, [field])), pa ->
11877             pr "%s (optional_child %S x)" pa fname
11878         | Attribute (fname, [Text]), _ ->
11879             pr "attribute %S x" fname
11880         | (ZeroOrMore _ | OneOrMore _), pa ->
11881             pr "%s x" pa
11882         | Text, pa ->
11883             pr "%s x" pa
11884         | (field, pa) ->
11885             let fname = name_of_field field in
11886             pr "%s (child %S x)" pa fname
11887     ) (List.combine fields pas);
11888     pr "\n  ) in\n";
11889
11890     (match fields with
11891      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11892          pr "  t\n"
11893
11894      | _ ->
11895          pr "  (Obj.magic t : %s)\n" name
11896 (*
11897          List.iter (
11898            function
11899            | (Optional (Attribute (fname, [field])), pa) ->
11900                pr "  %s_%s =\n" name fname;
11901                pr "    %s x;\n" pa
11902            | (Optional (Element (fname, [field])), pa) ->
11903                pr "  %s_%s =\n" name fname;
11904                pr "    (let x = optional_child %S x in\n" fname;
11905                pr "     %s x);\n" pa
11906            | (field, pa) ->
11907                let fname = name_of_field field in
11908                pr "  %s_%s =\n" name fname;
11909                pr "    (let x = child %S x in\n" fname;
11910                pr "     %s x);\n" pa
11911          ) (List.combine fields pas);
11912          pr "}\n"
11913 *)
11914     );
11915     sprintf "parse_%s" name
11916   in
11917
11918   generate_parsers xs
11919
11920 (* Generate ocaml/guestfs_inspector.mli. *)
11921 let generate_ocaml_inspector_mli () =
11922   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11923
11924   pr "\
11925 (** This is an OCaml language binding to the external [virt-inspector]
11926     program.
11927
11928     For more information, please read the man page [virt-inspector(1)].
11929 *)
11930
11931 ";
11932
11933   generate_types grammar;
11934   pr "(** The nested information returned from the {!inspect} function. *)\n";
11935   pr "\n";
11936
11937   pr "\
11938 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11939 (** To inspect a libvirt domain called [name], pass a singleton
11940     list: [inspect [name]].  When using libvirt only, you may
11941     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11942
11943     To inspect a disk image or images, pass a list of the filenames
11944     of the disk images: [inspect filenames]
11945
11946     This function inspects the given guest or disk images and
11947     returns a list of operating system(s) found and a large amount
11948     of information about them.  In the vast majority of cases,
11949     a virtual machine only contains a single operating system.
11950
11951     If the optional [~xml] parameter is given, then this function
11952     skips running the external virt-inspector program and just
11953     parses the given XML directly (which is expected to be XML
11954     produced from a previous run of virt-inspector).  The list of
11955     names and connect URI are ignored in this case.
11956
11957     This function can throw a wide variety of exceptions, for example
11958     if the external virt-inspector program cannot be found, or if
11959     it doesn't generate valid XML.
11960 *)
11961 "
11962
11963 (* Generate ocaml/guestfs_inspector.ml. *)
11964 let generate_ocaml_inspector_ml () =
11965   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11966
11967   pr "open Unix\n";
11968   pr "\n";
11969
11970   generate_types grammar;
11971   pr "\n";
11972
11973   pr "\
11974 (* Misc functions which are used by the parser code below. *)
11975 let first_child = function
11976   | Xml.Element (_, _, c::_) -> c
11977   | Xml.Element (name, _, []) ->
11978       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11979   | Xml.PCData str ->
11980       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11981
11982 let string_child_or_empty = function
11983   | Xml.Element (_, _, [Xml.PCData s]) -> s
11984   | Xml.Element (_, _, []) -> \"\"
11985   | Xml.Element (x, _, _) ->
11986       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11987                 x ^ \" instead\")
11988   | Xml.PCData str ->
11989       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11990
11991 let optional_child name xml =
11992   let children = Xml.children xml in
11993   try
11994     Some (List.find (function
11995                      | Xml.Element (n, _, _) when n = name -> true
11996                      | _ -> false) children)
11997   with
11998     Not_found -> None
11999
12000 let child name xml =
12001   match optional_child name xml with
12002   | Some c -> c
12003   | None ->
12004       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
12005
12006 let attribute name xml =
12007   try Xml.attrib xml name
12008   with Xml.No_attribute _ ->
12009     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
12010
12011 ";
12012
12013   generate_parsers grammar;
12014   pr "\n";
12015
12016   pr "\
12017 (* Run external virt-inspector, then use parser to parse the XML. *)
12018 let inspect ?connect ?xml names =
12019   let xml =
12020     match xml with
12021     | None ->
12022         if names = [] then invalid_arg \"inspect: no names given\";
12023         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
12024           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
12025           names in
12026         let cmd = List.map Filename.quote cmd in
12027         let cmd = String.concat \" \" cmd in
12028         let chan = open_process_in cmd in
12029         let xml = Xml.parse_in chan in
12030         (match close_process_in chan with
12031          | WEXITED 0 -> ()
12032          | WEXITED _ -> failwith \"external virt-inspector command failed\"
12033          | WSIGNALED i | WSTOPPED i ->
12034              failwith (\"external virt-inspector command died or stopped on sig \" ^
12035                        string_of_int i)
12036         );
12037         xml
12038     | Some doc ->
12039         Xml.parse_string doc in
12040   parse_operatingsystems xml
12041 "
12042
12043 and generate_max_proc_nr () =
12044   pr "%d\n" max_proc_nr
12045
12046 let output_to filename k =
12047   let filename_new = filename ^ ".new" in
12048   chan := open_out filename_new;
12049   k ();
12050   close_out !chan;
12051   chan := Pervasives.stdout;
12052
12053   (* Is the new file different from the current file? *)
12054   if Sys.file_exists filename && files_equal filename filename_new then
12055     unlink filename_new                 (* same, so skip it *)
12056   else (
12057     (* different, overwrite old one *)
12058     (try chmod filename 0o644 with Unix_error _ -> ());
12059     rename filename_new filename;
12060     chmod filename 0o444;
12061     printf "written %s\n%!" filename;
12062   )
12063
12064 let perror msg = function
12065   | Unix_error (err, _, _) ->
12066       eprintf "%s: %s\n" msg (error_message err)
12067   | exn ->
12068       eprintf "%s: %s\n" msg (Printexc.to_string exn)
12069
12070 (* Main program. *)
12071 let () =
12072   let lock_fd =
12073     try openfile "HACKING" [O_RDWR] 0
12074     with
12075     | Unix_error (ENOENT, _, _) ->
12076         eprintf "\
12077 You are probably running this from the wrong directory.
12078 Run it from the top source directory using the command
12079   src/generator.ml
12080 ";
12081         exit 1
12082     | exn ->
12083         perror "open: HACKING" exn;
12084         exit 1 in
12085
12086   (* Acquire a lock so parallel builds won't try to run the generator
12087    * twice at the same time.  Subsequent builds will wait for the first
12088    * one to finish.  Note the lock is released implicitly when the
12089    * program exits.
12090    *)
12091   (try lockf lock_fd F_LOCK 1
12092    with exn ->
12093      perror "lock: HACKING" exn;
12094      exit 1);
12095
12096   check_functions ();
12097
12098   output_to "src/guestfs_protocol.x" generate_xdr;
12099   output_to "src/guestfs-structs.h" generate_structs_h;
12100   output_to "src/guestfs-actions.h" generate_actions_h;
12101   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12102   output_to "src/guestfs-actions.c" generate_client_actions;
12103   output_to "src/guestfs-bindtests.c" generate_bindtests;
12104   output_to "src/guestfs-structs.pod" generate_structs_pod;
12105   output_to "src/guestfs-actions.pod" generate_actions_pod;
12106   output_to "src/guestfs-availability.pod" generate_availability_pod;
12107   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12108   output_to "src/libguestfs.syms" generate_linker_script;
12109   output_to "daemon/actions.h" generate_daemon_actions_h;
12110   output_to "daemon/stubs.c" generate_daemon_actions;
12111   output_to "daemon/names.c" generate_daemon_names;
12112   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12113   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12114   output_to "capitests/tests.c" generate_tests;
12115   output_to "fish/cmds.c" generate_fish_cmds;
12116   output_to "fish/completion.c" generate_fish_completion;
12117   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12118   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12119   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12120   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12121   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12122   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12123   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12124   output_to "perl/Guestfs.xs" generate_perl_xs;
12125   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12126   output_to "perl/bindtests.pl" generate_perl_bindtests;
12127   output_to "python/guestfs-py.c" generate_python_c;
12128   output_to "python/guestfs.py" generate_python_py;
12129   output_to "python/bindtests.py" generate_python_bindtests;
12130   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12131   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12132   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12133
12134   List.iter (
12135     fun (typ, jtyp) ->
12136       let cols = cols_of_struct typ in
12137       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12138       output_to filename (generate_java_struct jtyp cols);
12139   ) java_structs;
12140
12141   output_to "java/Makefile.inc" generate_java_makefile_inc;
12142   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12143   output_to "java/Bindtests.java" generate_java_bindtests;
12144   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12145   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12146   output_to "csharp/Libguestfs.cs" generate_csharp;
12147
12148   (* Always generate this file last, and unconditionally.  It's used
12149    * by the Makefile to know when we must re-run the generator.
12150    *)
12151   let chan = open_out "src/stamp-generator" in
12152   fprintf chan "1\n";
12153   close_out chan;
12154
12155   printf "generated %d lines of code\n" !lines