New partition APIs: part_del, part_get_bootable, part_get/set_mbr_id
[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 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | NotInFish             (* do not export via guestfish *)
186   | NotInDocs             (* do not add this function to documentation *)
187   | DeprecatedBy of string (* function is deprecated, use .. instead *)
188   | Optional of string    (* function is part of an optional group *)
189
190 (* You can supply zero or as many tests as you want per API call.
191  *
192  * Note that the test environment has 3 block devices, of size 500MB,
193  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194  * a fourth ISO block device with some known files on it (/dev/sdd).
195  *
196  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197  * Number of cylinders was 63 for IDE emulated disks with precisely
198  * the same size.  How exactly this is calculated is a mystery.
199  *
200  * The ISO block device (/dev/sdd) comes from images/test.iso.
201  *
202  * To be able to run the tests in a reasonable amount of time,
203  * the virtual machine and block devices are reused between tests.
204  * So don't try testing kill_subprocess :-x
205  *
206  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
207  *
208  * Don't assume anything about the previous contents of the block
209  * devices.  Use 'Init*' to create some initial scenarios.
210  *
211  * You can add a prerequisite clause to any individual test.  This
212  * is a run-time check, which, if it fails, causes the test to be
213  * skipped.  Useful if testing a command which might not work on
214  * all variations of libguestfs builds.  A test that has prerequisite
215  * of 'Always' is run unconditionally.
216  *
217  * In addition, packagers can skip individual tests by setting the
218  * environment variables:     eg:
219  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
220  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
221  *)
222 type tests = (test_init * test_prereq * test) list
223 and test =
224     (* Run the command sequence and just expect nothing to fail. *)
225   | TestRun of seq
226
227     (* Run the command sequence and expect the output of the final
228      * command to be the string.
229      *)
230   | TestOutput of seq * string
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the list of strings.
234      *)
235   | TestOutputList of seq * string list
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of block devices (could be either
239      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240      * character of each string).
241      *)
242   | TestOutputListOfDevices of seq * string list
243
244     (* Run the command sequence and expect the output of the final
245      * command to be the integer.
246      *)
247   | TestOutputInt of seq * int
248
249     (* Run the command sequence and expect the output of the final
250      * command to be <op> <int>, eg. ">=", "1".
251      *)
252   | TestOutputIntOp of seq * string * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be a true value (!= 0 or != NULL).
256      *)
257   | TestOutputTrue of seq
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a false value (== 0 or == NULL, but not an error).
261      *)
262   | TestOutputFalse of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a list of the given length (but don't care about
266      * content).
267      *)
268   | TestOutputLength of seq * int
269
270     (* Run the command sequence and expect the output of the final
271      * command to be a buffer (RBufferOut), ie. string + size.
272      *)
273   | TestOutputBuffer of seq * string
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a structure.
277      *)
278   | TestOutputStruct of seq * test_field_compare list
279
280     (* Run the command sequence and expect the final command (only)
281      * to fail.
282      *)
283   | TestLastFail of seq
284
285 and test_field_compare =
286   | CompareWithInt of string * int
287   | CompareWithIntOp of string * string * int
288   | CompareWithString of string * string
289   | CompareFieldsIntEq of string * string
290   | CompareFieldsStrEq of string * string
291
292 (* Test prerequisites. *)
293 and test_prereq =
294     (* Test always runs. *)
295   | Always
296
297     (* Test is currently disabled - eg. it fails, or it tests some
298      * unimplemented feature.
299      *)
300   | Disabled
301
302     (* 'string' is some C code (a function body) that should return
303      * true or false.  The test will run if the code returns true.
304      *)
305   | If of string
306
307     (* As for 'If' but the test runs _unless_ the code returns true. *)
308   | Unless of string
309
310 (* Some initial scenarios for testing. *)
311 and test_init =
312     (* Do nothing, block devices could contain random stuff including
313      * LVM PVs, and some filesystems might be mounted.  This is usually
314      * a bad idea.
315      *)
316   | InitNone
317
318     (* Block devices are empty and no filesystems are mounted. *)
319   | InitEmpty
320
321     (* /dev/sda contains a single partition /dev/sda1, with random
322      * content.  /dev/sdb and /dev/sdc may have random content.
323      * No LVM.
324      *)
325   | InitPartition
326
327     (* /dev/sda contains a single partition /dev/sda1, which is formatted
328      * as ext2, empty [except for lost+found] and mounted on /.
329      * /dev/sdb and /dev/sdc may have random content.
330      * No LVM.
331      *)
332   | InitBasicFS
333
334     (* /dev/sda:
335      *   /dev/sda1 (is a PV):
336      *     /dev/VG/LV (size 8MB):
337      *       formatted as ext2, empty [except for lost+found], mounted on /
338      * /dev/sdb and /dev/sdc may have random content.
339      *)
340   | InitBasicFSonLVM
341
342     (* /dev/sdd (the ISO, see images/ directory in source)
343      * is mounted on /
344      *)
345   | InitISOFS
346
347 (* Sequence of commands for testing. *)
348 and seq = cmd list
349 and cmd = string list
350
351 (* Note about long descriptions: When referring to another
352  * action, use the format C<guestfs_other> (ie. the full name of
353  * the C function).  This will be replaced as appropriate in other
354  * language bindings.
355  *
356  * Apart from that, long descriptions are just perldoc paragraphs.
357  *)
358
359 (* Generate a random UUID (used in tests). *)
360 let uuidgen () =
361   let chan = open_process_in "uuidgen" in
362   let uuid = input_line chan in
363   (match close_process_in chan with
364    | WEXITED 0 -> ()
365    | WEXITED _ ->
366        failwith "uuidgen: process exited with non-zero status"
367    | WSIGNALED _ | WSTOPPED _ ->
368        failwith "uuidgen: process signalled or stopped by signal"
369   );
370   uuid
371
372 (* These test functions are used in the language binding tests. *)
373
374 let test_all_args = [
375   String "str";
376   OptString "optstr";
377   StringList "strlist";
378   Bool "b";
379   Int "integer";
380   Int64 "integer64";
381   FileIn "filein";
382   FileOut "fileout";
383 ]
384
385 let test_all_rets = [
386   (* except for RErr, which is tested thoroughly elsewhere *)
387   "test0rint",         RInt "valout";
388   "test0rint64",       RInt64 "valout";
389   "test0rbool",        RBool "valout";
390   "test0rconststring", RConstString "valout";
391   "test0rconstoptstring", RConstOptString "valout";
392   "test0rstring",      RString "valout";
393   "test0rstringlist",  RStringList "valout";
394   "test0rstruct",      RStruct ("valout", "lvm_pv");
395   "test0rstructlist",  RStructList ("valout", "lvm_pv");
396   "test0rhashtable",   RHashtable "valout";
397 ]
398
399 let test_functions = [
400   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
401    [],
402    "internal test function - do not use",
403    "\
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 parameter type correctly.
407
408 It echos the contents of each parameter to stdout.
409
410 You probably don't want to call this function.");
411 ] @ List.flatten (
412   List.map (
413     fun (name, ret) ->
414       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
415         [],
416         "internal test function - do not use",
417         "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
421
422 It converts string C<val> to the return type.
423
424 You probably don't want to call this function.");
425        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
426         [],
427         "internal test function - do not use",
428         "\
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
432
433 This function always returns an error.
434
435 You probably don't want to call this function.")]
436   ) test_all_rets
437 )
438
439 (* non_daemon_functions are any functions which don't get processed
440  * in the daemon, eg. functions for setting and getting local
441  * configuration values.
442  *)
443
444 let non_daemon_functions = test_functions @ [
445   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
446    [],
447    "launch the qemu subprocess",
448    "\
449 Internally libguestfs is implemented by running a virtual machine
450 using L<qemu(1)>.
451
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
454
455   ("wait_ready", (RErr, []), -1, [NotInFish],
456    [],
457    "wait until the qemu subprocess launches (no op)",
458    "\
459 This function is a no op.
460
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete.  However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
465
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
469
470   ("kill_subprocess", (RErr, []), -1, [],
471    [],
472    "kill the qemu subprocess",
473    "\
474 This kills the qemu subprocess.  You should never need to call this.");
475
476   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
477    [],
478    "add an image to examine or modify",
479    "\
480 This function adds a virtual machine disk image C<filename> to the
481 guest.  The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
483 so on.
484
485 You don't necessarily need to be root when using libguestfs.  However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
489 image).
490
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
493
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
496
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>.  In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
501
502 Note that this call checks for the existence of C<filename>.  This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
505 the general C<guestfs_config> call instead.");
506
507   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
508    [],
509    "add a CD-ROM disk image to examine",
510    "\
511 This function adds a virtual CD-ROM disk image to the guest.
512
513 This is equivalent to the qemu parameter C<-cdrom filename>.
514
515 Notes:
516
517 =over 4
518
519 =item *
520
521 This call checks for the existence of C<filename>.  This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
524 the general C<guestfs_config> call instead.
525
526 =item *
527
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
531
532 =back");
533
534   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
535    [],
536    "add a drive in snapshot mode (read-only)",
537    "\
538 This adds a drive in snapshot mode, making it effectively
539 read-only.
540
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed.  We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
546
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
549
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>.  In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
554
555 C<readonly=on> is only added where qemu supports this option.
556
557 Note that this call checks for the existence of C<filename>.  This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
560 the general C<guestfs_config> call instead.");
561
562   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
563    [],
564    "add qemu parameters",
565    "\
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>.  Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
570
571 The first character of C<param> string must be a C<-> (dash).
572
573 C<value> can be NULL.");
574
575   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
576    [],
577    "set the qemu binary",
578    "\
579 Set the qemu binary that we will use.
580
581 The default is chosen when the library was compiled by the
582 configure script.
583
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
586
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
588
589 Note that you should call this function as early as possible
590 after creating the handle.  This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results.  Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
596
597   ("get_qemu", (RConstString "qemu", []), -1, [],
598    [InitNone, Always, TestRun (
599       [["get_qemu"]])],
600    "get the qemu binary",
601    "\
602 Return the current qemu binary.
603
604 This is always non-NULL.  If it wasn't set already, then this will
605 return the default qemu binary name.");
606
607   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
608    [],
609    "set the search path",
610    "\
611 Set the path that libguestfs searches for kernel and initrd.img.
612
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
615
616 Setting C<path> to C<NULL> restores the default path.");
617
618   ("get_path", (RConstString "path", []), -1, [],
619    [InitNone, Always, TestRun (
620       [["get_path"]])],
621    "get the search path",
622    "\
623 Return the current search path.
624
625 This is always non-NULL.  If it wasn't set already, then this will
626 return the default path.");
627
628   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
629    [],
630    "add options to kernel command line",
631    "\
632 This function is used to add additional options to the
633 guest kernel command line.
634
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
637
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
640
641   ("get_append", (RConstOptString "append", []), -1, [],
642    (* This cannot be tested with the current framework.  The
643     * function can return NULL in normal operations, which the
644     * test framework interprets as an error.
645     *)
646    [],
647    "get the additional kernel options",
648    "\
649 Return the additional kernel options which are added to the
650 guest kernel command line.
651
652 If C<NULL> then no options are added.");
653
654   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
655    [],
656    "set autosync mode",
657    "\
658 If C<autosync> is true, this enables autosync.  Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
662
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
665
666   ("get_autosync", (RBool "autosync", []), -1, [],
667    [InitNone, Always, TestRun (
668       [["get_autosync"]])],
669    "get autosync mode",
670    "\
671 Get the autosync flag.");
672
673   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
674    [],
675    "set verbose mode",
676    "\
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
678
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
681
682   ("get_verbose", (RBool "verbose", []), -1, [],
683    [],
684    "get verbose mode",
685    "\
686 This returns the verbose messages flag.");
687
688   ("is_ready", (RBool "ready", []), -1, [],
689    [InitNone, Always, TestOutputTrue (
690       [["is_ready"]])],
691    "is ready to accept commands",
692    "\
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
695
696 For more information on states, see L<guestfs(3)>.");
697
698   ("is_config", (RBool "config", []), -1, [],
699    [InitNone, Always, TestOutputFalse (
700       [["is_config"]])],
701    "is in configuration state",
702    "\
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
705
706 For more information on states, see L<guestfs(3)>.");
707
708   ("is_launching", (RBool "launching", []), -1, [],
709    [InitNone, Always, TestOutputFalse (
710       [["is_launching"]])],
711    "is launching subprocess",
712    "\
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
715
716 For more information on states, see L<guestfs(3)>.");
717
718   ("is_busy", (RBool "busy", []), -1, [],
719    [InitNone, Always, TestOutputFalse (
720       [["is_busy"]])],
721    "is busy processing a command",
722    "\
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
725
726 For more information on states, see L<guestfs(3)>.");
727
728   ("get_state", (RInt "state", []), -1, [],
729    [],
730    "get the current state",
731    "\
732 This returns the current state as an opaque integer.  This is
733 only useful for printing debug and internal error messages.
734
735 For more information on states, see L<guestfs(3)>.");
736
737   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738    [InitNone, Always, TestOutputInt (
739       [["set_memsize"; "500"];
740        ["get_memsize"]], 500)],
741    "set memory allocated to the qemu subprocess",
742    "\
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess.  This only has any effect if called before
745 C<guestfs_launch>.
746
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
749 created.
750
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
753
754   ("get_memsize", (RInt "memsize", []), -1, [],
755    [InitNone, Always, TestOutputIntOp (
756       [["get_memsize"]], ">=", 256)],
757    "get memory allocated to the qemu subprocess",
758    "\
759 This gets the memory size in megabytes allocated to the
760 qemu subprocess.
761
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
765
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
768
769   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770    [InitNone, Always, TestOutputIntOp (
771       [["get_pid"]], ">=", 1)],
772    "get PID of qemu subprocess",
773    "\
774 Return the process ID of the qemu subprocess.  If there is no
775 qemu subprocess, then this will return an error.
776
777 This is an internal call used for debugging and testing.");
778
779   ("version", (RStruct ("version", "version"), []), -1, [],
780    [InitNone, Always, TestOutputStruct (
781       [["version"]], [CompareWithInt ("major", 1)])],
782    "get the library version number",
783    "\
784 Return the libguestfs version number that the program is linked
785 against.
786
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against.  You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
791
792 This call was added in version C<1.0.58>.  In previous
793 versions of libguestfs there was no way to get the version
794 number.  From C code you can use ELF weak linking tricks to find out if
795 this symbol exists (if it doesn't, then it's an earlier version).
796
797 The call returns a structure with four elements.  The first
798 three (C<major>, C<minor> and C<release>) are numbers and
799 correspond to the usual version triplet.  The fourth element
800 (C<extra>) is a string and is normally empty, but may be
801 used for distro-specific information.
802
803 To construct the original version string:
804 C<$major.$minor.$release$extra>
805
806 I<Note:> Don't use this call to test for availability
807 of features.  Distro backports makes this unreliable.  Use
808 C<guestfs_available> instead.");
809
810   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
811    [InitNone, Always, TestOutputTrue (
812       [["set_selinux"; "true"];
813        ["get_selinux"]])],
814    "set SELinux enabled or disabled at appliance boot",
815    "\
816 This sets the selinux flag that is passed to the appliance
817 at boot time.  The default is C<selinux=0> (disabled).
818
819 Note that if SELinux is enabled, it is always in
820 Permissive mode (C<enforcing=0>).
821
822 For more information on the architecture of libguestfs,
823 see L<guestfs(3)>.");
824
825   ("get_selinux", (RBool "selinux", []), -1, [],
826    [],
827    "get SELinux enabled flag",
828    "\
829 This returns the current setting of the selinux flag which
830 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
831
832 For more information on the architecture of libguestfs,
833 see L<guestfs(3)>.");
834
835   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
836    [InitNone, Always, TestOutputFalse (
837       [["set_trace"; "false"];
838        ["get_trace"]])],
839    "enable or disable command traces",
840    "\
841 If the command trace flag is set to 1, then commands are
842 printed on stdout before they are executed in a format
843 which is very similar to the one used by guestfish.  In
844 other words, you can run a program with this enabled, and
845 you will get out a script which you can feed to guestfish
846 to perform the same set of actions.
847
848 If you want to trace C API calls into libguestfs (and
849 other libraries) then possibly a better way is to use
850 the external ltrace(1) command.
851
852 Command traces are disabled unless the environment variable
853 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
854
855   ("get_trace", (RBool "trace", []), -1, [],
856    [],
857    "get command trace enabled flag",
858    "\
859 Return the command trace flag.");
860
861   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
862    [InitNone, Always, TestOutputFalse (
863       [["set_direct"; "false"];
864        ["get_direct"]])],
865    "enable or disable direct appliance mode",
866    "\
867 If the direct appliance mode flag is enabled, then stdin and
868 stdout are passed directly through to the appliance once it
869 is launched.
870
871 One consequence of this is that log messages aren't caught
872 by the library and handled by C<guestfs_set_log_message_callback>,
873 but go straight to stdout.
874
875 You probably don't want to use this unless you know what you
876 are doing.
877
878 The default is disabled.");
879
880   ("get_direct", (RBool "direct", []), -1, [],
881    [],
882    "get direct appliance mode flag",
883    "\
884 Return the direct appliance mode flag.");
885
886   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
887    [InitNone, Always, TestOutputTrue (
888       [["set_recovery_proc"; "true"];
889        ["get_recovery_proc"]])],
890    "enable or disable the recovery process",
891    "\
892 If this is called with the parameter C<false> then
893 C<guestfs_launch> does not create a recovery process.  The
894 purpose of the recovery process is to stop runaway qemu
895 processes in the case where the main program aborts abruptly.
896
897 This only has any effect if called before C<guestfs_launch>,
898 and the default is true.
899
900 About the only time when you would want to disable this is
901 if the main process will fork itself into the background
902 (\"daemonize\" itself).  In this case the recovery process
903 thinks that the main program has disappeared and so kills
904 qemu, which is not very helpful.");
905
906   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
907    [],
908    "get recovery process enabled flag",
909    "\
910 Return the recovery process enabled flag.");
911
912   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
913    [],
914    "add a drive specifying the QEMU block emulation to use",
915    "\
916 This is the same as C<guestfs_add_drive> but it allows you
917 to specify the QEMU interface emulation to use at run time.");
918
919   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
920    [],
921    "add a drive read-only specifying the QEMU block emulation to use",
922    "\
923 This is the same as C<guestfs_add_drive_ro> but it allows you
924 to specify the QEMU interface emulation to use at run time.");
925
926 ]
927
928 (* daemon_functions are any functions which cause some action
929  * to take place in the daemon.
930  *)
931
932 let daemon_functions = [
933   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
934    [InitEmpty, Always, TestOutput (
935       [["part_disk"; "/dev/sda"; "mbr"];
936        ["mkfs"; "ext2"; "/dev/sda1"];
937        ["mount"; "/dev/sda1"; "/"];
938        ["write_file"; "/new"; "new file contents"; "0"];
939        ["cat"; "/new"]], "new file contents")],
940    "mount a guest disk at a position in the filesystem",
941    "\
942 Mount a guest disk at a position in the filesystem.  Block devices
943 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
944 the guest.  If those block devices contain partitions, they will have
945 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
946 names can be used.
947
948 The rules are the same as for L<mount(2)>:  A filesystem must
949 first be mounted on C</> before others can be mounted.  Other
950 filesystems can only be mounted on directories which already
951 exist.
952
953 The mounted filesystem is writable, if we have sufficient permissions
954 on the underlying device.
955
956 The filesystem options C<sync> and C<noatime> are set with this
957 call, in order to improve reliability.");
958
959   ("sync", (RErr, []), 2, [],
960    [ InitEmpty, Always, TestRun [["sync"]]],
961    "sync disks, writes are flushed through to the disk image",
962    "\
963 This syncs the disk, so that any writes are flushed through to the
964 underlying disk image.
965
966 You should always call this if you have modified a disk image, before
967 closing the handle.");
968
969   ("touch", (RErr, [Pathname "path"]), 3, [],
970    [InitBasicFS, Always, TestOutputTrue (
971       [["touch"; "/new"];
972        ["exists"; "/new"]])],
973    "update file timestamps or create a new file",
974    "\
975 Touch acts like the L<touch(1)> command.  It can be used to
976 update the timestamps on a file, or, if the file does not exist,
977 to create a new zero-length file.");
978
979   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
980    [InitISOFS, Always, TestOutput (
981       [["cat"; "/known-2"]], "abcdef\n")],
982    "list the contents of a file",
983    "\
984 Return the contents of the file named C<path>.
985
986 Note that this function cannot correctly handle binary files
987 (specifically, files containing C<\\0> character which is treated
988 as end of string).  For those you need to use the C<guestfs_read_file>
989 or C<guestfs_download> functions which have a more complex interface.");
990
991   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
992    [], (* XXX Tricky to test because it depends on the exact format
993         * of the 'ls -l' command, which changes between F10 and F11.
994         *)
995    "list the files in a directory (long format)",
996    "\
997 List the files in C<directory> (relative to the root directory,
998 there is no cwd) in the format of 'ls -la'.
999
1000 This command is mostly useful for interactive sessions.  It
1001 is I<not> intended that you try to parse the output string.");
1002
1003   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1004    [InitBasicFS, Always, TestOutputList (
1005       [["touch"; "/new"];
1006        ["touch"; "/newer"];
1007        ["touch"; "/newest"];
1008        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1009    "list the files in a directory",
1010    "\
1011 List the files in C<directory> (relative to the root directory,
1012 there is no cwd).  The '.' and '..' entries are not returned, but
1013 hidden files are shown.
1014
1015 This command is mostly useful for interactive sessions.  Programs
1016 should probably use C<guestfs_readdir> instead.");
1017
1018   ("list_devices", (RStringList "devices", []), 7, [],
1019    [InitEmpty, Always, TestOutputListOfDevices (
1020       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1021    "list the block devices",
1022    "\
1023 List all the block devices.
1024
1025 The full block device names are returned, eg. C</dev/sda>");
1026
1027   ("list_partitions", (RStringList "partitions", []), 8, [],
1028    [InitBasicFS, Always, TestOutputListOfDevices (
1029       [["list_partitions"]], ["/dev/sda1"]);
1030     InitEmpty, Always, TestOutputListOfDevices (
1031       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1032        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1033    "list the partitions",
1034    "\
1035 List all the partitions detected on all block devices.
1036
1037 The full partition device names are returned, eg. C</dev/sda1>
1038
1039 This does not return logical volumes.  For that you will need to
1040 call C<guestfs_lvs>.");
1041
1042   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1043    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1044       [["pvs"]], ["/dev/sda1"]);
1045     InitEmpty, Always, TestOutputListOfDevices (
1046       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047        ["pvcreate"; "/dev/sda1"];
1048        ["pvcreate"; "/dev/sda2"];
1049        ["pvcreate"; "/dev/sda3"];
1050        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1051    "list the LVM physical volumes (PVs)",
1052    "\
1053 List all the physical volumes detected.  This is the equivalent
1054 of the L<pvs(8)> command.
1055
1056 This returns a list of just the device names that contain
1057 PVs (eg. C</dev/sda2>).
1058
1059 See also C<guestfs_pvs_full>.");
1060
1061   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1062    [InitBasicFSonLVM, Always, TestOutputList (
1063       [["vgs"]], ["VG"]);
1064     InitEmpty, Always, TestOutputList (
1065       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066        ["pvcreate"; "/dev/sda1"];
1067        ["pvcreate"; "/dev/sda2"];
1068        ["pvcreate"; "/dev/sda3"];
1069        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1070        ["vgcreate"; "VG2"; "/dev/sda3"];
1071        ["vgs"]], ["VG1"; "VG2"])],
1072    "list the LVM volume groups (VGs)",
1073    "\
1074 List all the volumes groups detected.  This is the equivalent
1075 of the L<vgs(8)> command.
1076
1077 This returns a list of just the volume group names that were
1078 detected (eg. C<VolGroup00>).
1079
1080 See also C<guestfs_vgs_full>.");
1081
1082   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1083    [InitBasicFSonLVM, Always, TestOutputList (
1084       [["lvs"]], ["/dev/VG/LV"]);
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        ["lvcreate"; "LV1"; "VG1"; "50"];
1093        ["lvcreate"; "LV2"; "VG1"; "50"];
1094        ["lvcreate"; "LV3"; "VG2"; "50"];
1095        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1096    "list the LVM logical volumes (LVs)",
1097    "\
1098 List all the logical volumes detected.  This is the equivalent
1099 of the L<lvs(8)> command.
1100
1101 This returns a list of the logical volume device names
1102 (eg. C</dev/VolGroup00/LogVol00>).
1103
1104 See also C<guestfs_lvs_full>.");
1105
1106   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1107    [], (* XXX how to test? *)
1108    "list the LVM physical volumes (PVs)",
1109    "\
1110 List all the physical volumes detected.  This is the equivalent
1111 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1112
1113   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1114    [], (* XXX how to test? *)
1115    "list the LVM volume groups (VGs)",
1116    "\
1117 List all the volumes groups detected.  This is the equivalent
1118 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1119
1120   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1121    [], (* XXX how to test? *)
1122    "list the LVM logical volumes (LVs)",
1123    "\
1124 List all the logical volumes detected.  This is the equivalent
1125 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1126
1127   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1128    [InitISOFS, Always, TestOutputList (
1129       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1130     InitISOFS, Always, TestOutputList (
1131       [["read_lines"; "/empty"]], [])],
1132    "read file as lines",
1133    "\
1134 Return the contents of the file named C<path>.
1135
1136 The file contents are returned as a list of lines.  Trailing
1137 C<LF> and C<CRLF> character sequences are I<not> returned.
1138
1139 Note that this function cannot correctly handle binary files
1140 (specifically, files containing C<\\0> character which is treated
1141 as end of line).  For those you need to use the C<guestfs_read_file>
1142 function which has a more complex interface.");
1143
1144   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1145    [], (* XXX Augeas code needs tests. *)
1146    "create a new Augeas handle",
1147    "\
1148 Create a new Augeas handle for editing configuration files.
1149 If there was any previous Augeas handle associated with this
1150 guestfs session, then it is closed.
1151
1152 You must call this before using any other C<guestfs_aug_*>
1153 commands.
1154
1155 C<root> is the filesystem root.  C<root> must not be NULL,
1156 use C</> instead.
1157
1158 The flags are the same as the flags defined in
1159 E<lt>augeas.hE<gt>, the logical I<or> of the following
1160 integers:
1161
1162 =over 4
1163
1164 =item C<AUG_SAVE_BACKUP> = 1
1165
1166 Keep the original file with a C<.augsave> extension.
1167
1168 =item C<AUG_SAVE_NEWFILE> = 2
1169
1170 Save changes into a file with extension C<.augnew>, and
1171 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1172
1173 =item C<AUG_TYPE_CHECK> = 4
1174
1175 Typecheck lenses (can be expensive).
1176
1177 =item C<AUG_NO_STDINC> = 8
1178
1179 Do not use standard load path for modules.
1180
1181 =item C<AUG_SAVE_NOOP> = 16
1182
1183 Make save a no-op, just record what would have been changed.
1184
1185 =item C<AUG_NO_LOAD> = 32
1186
1187 Do not load the tree in C<guestfs_aug_init>.
1188
1189 =back
1190
1191 To close the handle, you can call C<guestfs_aug_close>.
1192
1193 To find out more about Augeas, see L<http://augeas.net/>.");
1194
1195   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1196    [], (* XXX Augeas code needs tests. *)
1197    "close the current Augeas handle",
1198    "\
1199 Close the current Augeas handle and free up any resources
1200 used by it.  After calling this, you have to call
1201 C<guestfs_aug_init> again before you can use any other
1202 Augeas functions.");
1203
1204   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1205    [], (* XXX Augeas code needs tests. *)
1206    "define an Augeas variable",
1207    "\
1208 Defines an Augeas variable C<name> whose value is the result
1209 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1210 undefined.
1211
1212 On success this returns the number of nodes in C<expr>, or
1213 C<0> if C<expr> evaluates to something which is not a nodeset.");
1214
1215   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas node",
1218    "\
1219 Defines a variable C<name> whose value is the result of
1220 evaluating C<expr>.
1221
1222 If C<expr> evaluates to an empty nodeset, a node is created,
1223 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1224 C<name> will be the nodeset containing that single node.
1225
1226 On success this returns a pair containing the
1227 number of nodes in the nodeset, and a boolean flag
1228 if a node was created.");
1229
1230   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1231    [], (* XXX Augeas code needs tests. *)
1232    "look up the value of an Augeas path",
1233    "\
1234 Look up the value associated with C<path>.  If C<path>
1235 matches exactly one node, the C<value> is returned.");
1236
1237   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1238    [], (* XXX Augeas code needs tests. *)
1239    "set Augeas path to value",
1240    "\
1241 Set the value associated with C<path> to C<value>.");
1242
1243   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1244    [], (* XXX Augeas code needs tests. *)
1245    "insert a sibling Augeas node",
1246    "\
1247 Create a new sibling C<label> for C<path>, inserting it into
1248 the tree before or after C<path> (depending on the boolean
1249 flag C<before>).
1250
1251 C<path> must match exactly one existing node in the tree, and
1252 C<label> must be a label, ie. not contain C</>, C<*> or end
1253 with a bracketed index C<[N]>.");
1254
1255   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1256    [], (* XXX Augeas code needs tests. *)
1257    "remove an Augeas path",
1258    "\
1259 Remove C<path> and all of its children.
1260
1261 On success this returns the number of entries which were removed.");
1262
1263   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "move Augeas node",
1266    "\
1267 Move the node C<src> to C<dest>.  C<src> must match exactly
1268 one node.  C<dest> is overwritten if it exists.");
1269
1270   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1271    [], (* XXX Augeas code needs tests. *)
1272    "return Augeas nodes which match augpath",
1273    "\
1274 Returns a list of paths which match the path expression C<path>.
1275 The returned paths are sufficiently qualified so that they match
1276 exactly one node in the current tree.");
1277
1278   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "write all pending Augeas changes to disk",
1281    "\
1282 This writes all pending changes to disk.
1283
1284 The flags which were passed to C<guestfs_aug_init> affect exactly
1285 how files are saved.");
1286
1287   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "load files into the tree",
1290    "\
1291 Load files into the tree.
1292
1293 See C<aug_load> in the Augeas documentation for the full gory
1294 details.");
1295
1296   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1297    [], (* XXX Augeas code needs tests. *)
1298    "list Augeas nodes under augpath",
1299    "\
1300 This is just a shortcut for listing C<guestfs_aug_match>
1301 C<path/*> and sorting the resulting nodes into alphabetical order.");
1302
1303   ("rm", (RErr, [Pathname "path"]), 29, [],
1304    [InitBasicFS, Always, TestRun
1305       [["touch"; "/new"];
1306        ["rm"; "/new"]];
1307     InitBasicFS, Always, TestLastFail
1308       [["rm"; "/new"]];
1309     InitBasicFS, Always, TestLastFail
1310       [["mkdir"; "/new"];
1311        ["rm"; "/new"]]],
1312    "remove a file",
1313    "\
1314 Remove the single file C<path>.");
1315
1316   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1317    [InitBasicFS, Always, TestRun
1318       [["mkdir"; "/new"];
1319        ["rmdir"; "/new"]];
1320     InitBasicFS, Always, TestLastFail
1321       [["rmdir"; "/new"]];
1322     InitBasicFS, Always, TestLastFail
1323       [["touch"; "/new"];
1324        ["rmdir"; "/new"]]],
1325    "remove a directory",
1326    "\
1327 Remove the single directory C<path>.");
1328
1329   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1330    [InitBasicFS, Always, TestOutputFalse
1331       [["mkdir"; "/new"];
1332        ["mkdir"; "/new/foo"];
1333        ["touch"; "/new/foo/bar"];
1334        ["rm_rf"; "/new"];
1335        ["exists"; "/new"]]],
1336    "remove a file or directory recursively",
1337    "\
1338 Remove the file or directory C<path>, recursively removing the
1339 contents if its a directory.  This is like the C<rm -rf> shell
1340 command.");
1341
1342   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1343    [InitBasicFS, Always, TestOutputTrue
1344       [["mkdir"; "/new"];
1345        ["is_dir"; "/new"]];
1346     InitBasicFS, Always, TestLastFail
1347       [["mkdir"; "/new/foo/bar"]]],
1348    "create a directory",
1349    "\
1350 Create a directory named C<path>.");
1351
1352   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir_p"; "/new/foo/bar"];
1355        ["is_dir"; "/new/foo/bar"]];
1356     InitBasicFS, Always, TestOutputTrue
1357       [["mkdir_p"; "/new/foo/bar"];
1358        ["is_dir"; "/new/foo"]];
1359     InitBasicFS, Always, TestOutputTrue
1360       [["mkdir_p"; "/new/foo/bar"];
1361        ["is_dir"; "/new"]];
1362     (* Regression tests for RHBZ#503133: *)
1363     InitBasicFS, Always, TestRun
1364       [["mkdir"; "/new"];
1365        ["mkdir_p"; "/new"]];
1366     InitBasicFS, Always, TestLastFail
1367       [["touch"; "/new"];
1368        ["mkdir_p"; "/new"]]],
1369    "create a directory and parents",
1370    "\
1371 Create a directory named C<path>, creating any parent directories
1372 as necessary.  This is like the C<mkdir -p> shell command.");
1373
1374   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1375    [], (* XXX Need stat command to test *)
1376    "change file mode",
1377    "\
1378 Change the mode (permissions) of C<path> to C<mode>.  Only
1379 numeric modes are supported.
1380
1381 I<Note>: When using this command from guestfish, C<mode>
1382 by default would be decimal, unless you prefix it with
1383 C<0> to get octal, ie. use C<0700> not C<700>.");
1384
1385   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1386    [], (* XXX Need stat command to test *)
1387    "change file owner and group",
1388    "\
1389 Change the file owner to C<owner> and group to C<group>.
1390
1391 Only numeric uid and gid are supported.  If you want to use
1392 names, you will need to locate and parse the password file
1393 yourself (Augeas support makes this relatively easy).");
1394
1395   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1396    [InitISOFS, Always, TestOutputTrue (
1397       [["exists"; "/empty"]]);
1398     InitISOFS, Always, TestOutputTrue (
1399       [["exists"; "/directory"]])],
1400    "test if file or directory exists",
1401    "\
1402 This returns C<true> if and only if there is a file, directory
1403 (or anything) with the given C<path> name.
1404
1405 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1406
1407   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1408    [InitISOFS, Always, TestOutputTrue (
1409       [["is_file"; "/known-1"]]);
1410     InitISOFS, Always, TestOutputFalse (
1411       [["is_file"; "/directory"]])],
1412    "test if file exists",
1413    "\
1414 This returns C<true> if and only if there is a file
1415 with the given C<path> name.  Note that it returns false for
1416 other objects like directories.
1417
1418 See also C<guestfs_stat>.");
1419
1420   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1421    [InitISOFS, Always, TestOutputFalse (
1422       [["is_dir"; "/known-3"]]);
1423     InitISOFS, Always, TestOutputTrue (
1424       [["is_dir"; "/directory"]])],
1425    "test if file exists",
1426    "\
1427 This returns C<true> if and only if there is a directory
1428 with the given C<path> name.  Note that it returns false for
1429 other objects like files.
1430
1431 See also C<guestfs_stat>.");
1432
1433   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1434    [InitEmpty, Always, TestOutputListOfDevices (
1435       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1436        ["pvcreate"; "/dev/sda1"];
1437        ["pvcreate"; "/dev/sda2"];
1438        ["pvcreate"; "/dev/sda3"];
1439        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1440    "create an LVM physical volume",
1441    "\
1442 This creates an LVM physical volume on the named C<device>,
1443 where C<device> should usually be a partition name such
1444 as C</dev/sda1>.");
1445
1446   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1447    [InitEmpty, Always, TestOutputList (
1448       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1449        ["pvcreate"; "/dev/sda1"];
1450        ["pvcreate"; "/dev/sda2"];
1451        ["pvcreate"; "/dev/sda3"];
1452        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1453        ["vgcreate"; "VG2"; "/dev/sda3"];
1454        ["vgs"]], ["VG1"; "VG2"])],
1455    "create an LVM volume group",
1456    "\
1457 This creates an LVM volume group called C<volgroup>
1458 from the non-empty list of physical volumes C<physvols>.");
1459
1460   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1461    [InitEmpty, Always, TestOutputList (
1462       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1463        ["pvcreate"; "/dev/sda1"];
1464        ["pvcreate"; "/dev/sda2"];
1465        ["pvcreate"; "/dev/sda3"];
1466        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1467        ["vgcreate"; "VG2"; "/dev/sda3"];
1468        ["lvcreate"; "LV1"; "VG1"; "50"];
1469        ["lvcreate"; "LV2"; "VG1"; "50"];
1470        ["lvcreate"; "LV3"; "VG2"; "50"];
1471        ["lvcreate"; "LV4"; "VG2"; "50"];
1472        ["lvcreate"; "LV5"; "VG2"; "50"];
1473        ["lvs"]],
1474       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1475        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1476    "create an LVM volume group",
1477    "\
1478 This creates an LVM volume group called C<logvol>
1479 on the volume group C<volgroup>, with C<size> megabytes.");
1480
1481   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1482    [InitEmpty, Always, TestOutput (
1483       [["part_disk"; "/dev/sda"; "mbr"];
1484        ["mkfs"; "ext2"; "/dev/sda1"];
1485        ["mount_options"; ""; "/dev/sda1"; "/"];
1486        ["write_file"; "/new"; "new file contents"; "0"];
1487        ["cat"; "/new"]], "new file contents")],
1488    "make a filesystem",
1489    "\
1490 This creates a filesystem on C<device> (usually a partition
1491 or LVM logical volume).  The filesystem type is C<fstype>, for
1492 example C<ext3>.");
1493
1494   ("sfdisk", (RErr, [Device "device";
1495                      Int "cyls"; Int "heads"; Int "sectors";
1496                      StringList "lines"]), 43, [DangerWillRobinson],
1497    [],
1498    "create partitions on a block device",
1499    "\
1500 This is a direct interface to the L<sfdisk(8)> program for creating
1501 partitions on block devices.
1502
1503 C<device> should be a block device, for example C</dev/sda>.
1504
1505 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1506 and sectors on the device, which are passed directly to sfdisk as
1507 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1508 of these, then the corresponding parameter is omitted.  Usually for
1509 'large' disks, you can just pass C<0> for these, but for small
1510 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1511 out the right geometry and you will need to tell it.
1512
1513 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1514 information refer to the L<sfdisk(8)> manpage.
1515
1516 To create a single partition occupying the whole disk, you would
1517 pass C<lines> as a single element list, when the single element being
1518 the string C<,> (comma).
1519
1520 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1521 C<guestfs_part_init>");
1522
1523   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1524    [InitBasicFS, Always, TestOutput (
1525       [["write_file"; "/new"; "new file contents"; "0"];
1526        ["cat"; "/new"]], "new file contents");
1527     InitBasicFS, Always, TestOutput (
1528       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1529        ["cat"; "/new"]], "\nnew file contents\n");
1530     InitBasicFS, Always, TestOutput (
1531       [["write_file"; "/new"; "\n\n"; "0"];
1532        ["cat"; "/new"]], "\n\n");
1533     InitBasicFS, Always, TestOutput (
1534       [["write_file"; "/new"; ""; "0"];
1535        ["cat"; "/new"]], "");
1536     InitBasicFS, Always, TestOutput (
1537       [["write_file"; "/new"; "\n\n\n"; "0"];
1538        ["cat"; "/new"]], "\n\n\n");
1539     InitBasicFS, Always, TestOutput (
1540       [["write_file"; "/new"; "\n"; "0"];
1541        ["cat"; "/new"]], "\n")],
1542    "create a file",
1543    "\
1544 This call creates a file called C<path>.  The contents of the
1545 file is the string C<content> (which can contain any 8 bit data),
1546 with length C<size>.
1547
1548 As a special case, if C<size> is C<0>
1549 then the length is calculated using C<strlen> (so in this case
1550 the content cannot contain embedded ASCII NULs).
1551
1552 I<NB.> Owing to a bug, writing content containing ASCII NUL
1553 characters does I<not> work, even if the length is specified.
1554 We hope to resolve this bug in a future version.  In the meantime
1555 use C<guestfs_upload>.");
1556
1557   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1558    [InitEmpty, Always, TestOutputListOfDevices (
1559       [["part_disk"; "/dev/sda"; "mbr"];
1560        ["mkfs"; "ext2"; "/dev/sda1"];
1561        ["mount_options"; ""; "/dev/sda1"; "/"];
1562        ["mounts"]], ["/dev/sda1"]);
1563     InitEmpty, Always, TestOutputList (
1564       [["part_disk"; "/dev/sda"; "mbr"];
1565        ["mkfs"; "ext2"; "/dev/sda1"];
1566        ["mount_options"; ""; "/dev/sda1"; "/"];
1567        ["umount"; "/"];
1568        ["mounts"]], [])],
1569    "unmount a filesystem",
1570    "\
1571 This unmounts the given filesystem.  The filesystem may be
1572 specified either by its mountpoint (path) or the device which
1573 contains the filesystem.");
1574
1575   ("mounts", (RStringList "devices", []), 46, [],
1576    [InitBasicFS, Always, TestOutputListOfDevices (
1577       [["mounts"]], ["/dev/sda1"])],
1578    "show mounted filesystems",
1579    "\
1580 This returns the list of currently mounted filesystems.  It returns
1581 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1582
1583 Some internal mounts are not shown.
1584
1585 See also: C<guestfs_mountpoints>");
1586
1587   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1588    [InitBasicFS, Always, TestOutputList (
1589       [["umount_all"];
1590        ["mounts"]], []);
1591     (* check that umount_all can unmount nested mounts correctly: *)
1592     InitEmpty, Always, TestOutputList (
1593       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1594        ["mkfs"; "ext2"; "/dev/sda1"];
1595        ["mkfs"; "ext2"; "/dev/sda2"];
1596        ["mkfs"; "ext2"; "/dev/sda3"];
1597        ["mount_options"; ""; "/dev/sda1"; "/"];
1598        ["mkdir"; "/mp1"];
1599        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1600        ["mkdir"; "/mp1/mp2"];
1601        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1602        ["mkdir"; "/mp1/mp2/mp3"];
1603        ["umount_all"];
1604        ["mounts"]], [])],
1605    "unmount all filesystems",
1606    "\
1607 This unmounts all mounted filesystems.
1608
1609 Some internal mounts are not unmounted by this call.");
1610
1611   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1612    [],
1613    "remove all LVM LVs, VGs and PVs",
1614    "\
1615 This command removes all LVM logical volumes, volume groups
1616 and physical volumes.");
1617
1618   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1619    [InitISOFS, Always, TestOutput (
1620       [["file"; "/empty"]], "empty");
1621     InitISOFS, Always, TestOutput (
1622       [["file"; "/known-1"]], "ASCII text");
1623     InitISOFS, Always, TestLastFail (
1624       [["file"; "/notexists"]])],
1625    "determine file type",
1626    "\
1627 This call uses the standard L<file(1)> command to determine
1628 the type or contents of the file.  This also works on devices,
1629 for example to find out whether a partition contains a filesystem.
1630
1631 This call will also transparently look inside various types
1632 of compressed file.
1633
1634 The exact command which runs is C<file -zbsL path>.  Note in
1635 particular that the filename is not prepended to the output
1636 (the C<-b> option).");
1637
1638   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1639    [InitBasicFS, Always, TestOutput (
1640       [["upload"; "test-command"; "/test-command"];
1641        ["chmod"; "0o755"; "/test-command"];
1642        ["command"; "/test-command 1"]], "Result1");
1643     InitBasicFS, Always, TestOutput (
1644       [["upload"; "test-command"; "/test-command"];
1645        ["chmod"; "0o755"; "/test-command"];
1646        ["command"; "/test-command 2"]], "Result2\n");
1647     InitBasicFS, Always, TestOutput (
1648       [["upload"; "test-command"; "/test-command"];
1649        ["chmod"; "0o755"; "/test-command"];
1650        ["command"; "/test-command 3"]], "\nResult3");
1651     InitBasicFS, Always, TestOutput (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command"; "/test-command 4"]], "\nResult4\n");
1655     InitBasicFS, Always, TestOutput (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command"; "/test-command 5"]], "\nResult5\n\n");
1659     InitBasicFS, Always, TestOutput (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1663     InitBasicFS, Always, TestOutput (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command"; "/test-command 7"]], "");
1667     InitBasicFS, Always, TestOutput (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command"; "/test-command 8"]], "\n");
1671     InitBasicFS, Always, TestOutput (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command"; "/test-command 9"]], "\n\n");
1675     InitBasicFS, Always, TestOutput (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1679     InitBasicFS, Always, TestOutput (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1683     InitBasicFS, Always, TestLastFail (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command"; "/test-command"]])],
1687    "run a command from the guest filesystem",
1688    "\
1689 This call runs a command from the guest filesystem.  The
1690 filesystem must be mounted, and must contain a compatible
1691 operating system (ie. something Linux, with the same
1692 or compatible processor architecture).
1693
1694 The single parameter is an argv-style list of arguments.
1695 The first element is the name of the program to run.
1696 Subsequent elements are parameters.  The list must be
1697 non-empty (ie. must contain a program name).  Note that
1698 the command runs directly, and is I<not> invoked via
1699 the shell (see C<guestfs_sh>).
1700
1701 The return value is anything printed to I<stdout> by
1702 the command.
1703
1704 If the command returns a non-zero exit status, then
1705 this function returns an error message.  The error message
1706 string is the content of I<stderr> from the command.
1707
1708 The C<$PATH> environment variable will contain at least
1709 C</usr/bin> and C</bin>.  If you require a program from
1710 another location, you should provide the full path in the
1711 first parameter.
1712
1713 Shared libraries and data files required by the program
1714 must be available on filesystems which are mounted in the
1715 correct places.  It is the caller's responsibility to ensure
1716 all filesystems that are needed are mounted at the right
1717 locations.");
1718
1719   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1720    [InitBasicFS, Always, TestOutputList (
1721       [["upload"; "test-command"; "/test-command"];
1722        ["chmod"; "0o755"; "/test-command"];
1723        ["command_lines"; "/test-command 1"]], ["Result1"]);
1724     InitBasicFS, Always, TestOutputList (
1725       [["upload"; "test-command"; "/test-command"];
1726        ["chmod"; "0o755"; "/test-command"];
1727        ["command_lines"; "/test-command 2"]], ["Result2"]);
1728     InitBasicFS, Always, TestOutputList (
1729       [["upload"; "test-command"; "/test-command"];
1730        ["chmod"; "0o755"; "/test-command"];
1731        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1732     InitBasicFS, Always, TestOutputList (
1733       [["upload"; "test-command"; "/test-command"];
1734        ["chmod"; "0o755"; "/test-command"];
1735        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1736     InitBasicFS, Always, TestOutputList (
1737       [["upload"; "test-command"; "/test-command"];
1738        ["chmod"; "0o755"; "/test-command"];
1739        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1740     InitBasicFS, Always, TestOutputList (
1741       [["upload"; "test-command"; "/test-command"];
1742        ["chmod"; "0o755"; "/test-command"];
1743        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1744     InitBasicFS, Always, TestOutputList (
1745       [["upload"; "test-command"; "/test-command"];
1746        ["chmod"; "0o755"; "/test-command"];
1747        ["command_lines"; "/test-command 7"]], []);
1748     InitBasicFS, Always, TestOutputList (
1749       [["upload"; "test-command"; "/test-command"];
1750        ["chmod"; "0o755"; "/test-command"];
1751        ["command_lines"; "/test-command 8"]], [""]);
1752     InitBasicFS, Always, TestOutputList (
1753       [["upload"; "test-command"; "/test-command"];
1754        ["chmod"; "0o755"; "/test-command"];
1755        ["command_lines"; "/test-command 9"]], ["";""]);
1756     InitBasicFS, Always, TestOutputList (
1757       [["upload"; "test-command"; "/test-command"];
1758        ["chmod"; "0o755"; "/test-command"];
1759        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1760     InitBasicFS, Always, TestOutputList (
1761       [["upload"; "test-command"; "/test-command"];
1762        ["chmod"; "0o755"; "/test-command"];
1763        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1764    "run a command, returning lines",
1765    "\
1766 This is the same as C<guestfs_command>, but splits the
1767 result into a list of lines.
1768
1769 See also: C<guestfs_sh_lines>");
1770
1771   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1772    [InitISOFS, Always, TestOutputStruct (
1773       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1774    "get file information",
1775    "\
1776 Returns file information for the given C<path>.
1777
1778 This is the same as the C<stat(2)> system call.");
1779
1780   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1781    [InitISOFS, Always, TestOutputStruct (
1782       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1783    "get file information for a symbolic link",
1784    "\
1785 Returns file information for the given C<path>.
1786
1787 This is the same as C<guestfs_stat> except that if C<path>
1788 is a symbolic link, then the link is stat-ed, not the file it
1789 refers to.
1790
1791 This is the same as the C<lstat(2)> system call.");
1792
1793   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1794    [InitISOFS, Always, TestOutputStruct (
1795       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1796    "get file system statistics",
1797    "\
1798 Returns file system statistics for any mounted file system.
1799 C<path> should be a file or directory in the mounted file system
1800 (typically it is the mount point itself, but it doesn't need to be).
1801
1802 This is the same as the C<statvfs(2)> system call.");
1803
1804   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1805    [], (* XXX test *)
1806    "get ext2/ext3/ext4 superblock details",
1807    "\
1808 This returns the contents of the ext2, ext3 or ext4 filesystem
1809 superblock on C<device>.
1810
1811 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1812 manpage for more details.  The list of fields returned isn't
1813 clearly defined, and depends on both the version of C<tune2fs>
1814 that libguestfs was built against, and the filesystem itself.");
1815
1816   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1817    [InitEmpty, Always, TestOutputTrue (
1818       [["blockdev_setro"; "/dev/sda"];
1819        ["blockdev_getro"; "/dev/sda"]])],
1820    "set block device to read-only",
1821    "\
1822 Sets the block device named C<device> to read-only.
1823
1824 This uses the L<blockdev(8)> command.");
1825
1826   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1827    [InitEmpty, Always, TestOutputFalse (
1828       [["blockdev_setrw"; "/dev/sda"];
1829        ["blockdev_getro"; "/dev/sda"]])],
1830    "set block device to read-write",
1831    "\
1832 Sets the block device named C<device> to read-write.
1833
1834 This uses the L<blockdev(8)> command.");
1835
1836   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1837    [InitEmpty, Always, TestOutputTrue (
1838       [["blockdev_setro"; "/dev/sda"];
1839        ["blockdev_getro"; "/dev/sda"]])],
1840    "is block device set to read-only",
1841    "\
1842 Returns a boolean indicating if the block device is read-only
1843 (true if read-only, false if not).
1844
1845 This uses the L<blockdev(8)> command.");
1846
1847   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1848    [InitEmpty, Always, TestOutputInt (
1849       [["blockdev_getss"; "/dev/sda"]], 512)],
1850    "get sectorsize of block device",
1851    "\
1852 This returns the size of sectors on a block device.
1853 Usually 512, but can be larger for modern devices.
1854
1855 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1856 for that).
1857
1858 This uses the L<blockdev(8)> command.");
1859
1860   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1861    [InitEmpty, Always, TestOutputInt (
1862       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1863    "get blocksize of block device",
1864    "\
1865 This returns the block size of a device.
1866
1867 (Note this is different from both I<size in blocks> and
1868 I<filesystem block size>).
1869
1870 This uses the L<blockdev(8)> command.");
1871
1872   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1873    [], (* XXX test *)
1874    "set blocksize of block device",
1875    "\
1876 This sets 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_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1884    [InitEmpty, Always, TestOutputInt (
1885       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1886    "get total size of device in 512-byte sectors",
1887    "\
1888 This returns the size of the device in units of 512-byte sectors
1889 (even if the sectorsize isn't 512 bytes ... weird).
1890
1891 See also C<guestfs_blockdev_getss> for the real sector size of
1892 the device, and C<guestfs_blockdev_getsize64> for the more
1893 useful I<size in bytes>.
1894
1895 This uses the L<blockdev(8)> command.");
1896
1897   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1898    [InitEmpty, Always, TestOutputInt (
1899       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1900    "get total size of device in bytes",
1901    "\
1902 This returns the size of the device in bytes.
1903
1904 See also C<guestfs_blockdev_getsz>.
1905
1906 This uses the L<blockdev(8)> command.");
1907
1908   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1909    [InitEmpty, Always, TestRun
1910       [["blockdev_flushbufs"; "/dev/sda"]]],
1911    "flush device buffers",
1912    "\
1913 This tells the kernel to flush internal buffers associated
1914 with C<device>.
1915
1916 This uses the L<blockdev(8)> command.");
1917
1918   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1919    [InitEmpty, Always, TestRun
1920       [["blockdev_rereadpt"; "/dev/sda"]]],
1921    "reread partition table",
1922    "\
1923 Reread the partition table on C<device>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1928    [InitBasicFS, Always, TestOutput (
1929       (* Pick a file from cwd which isn't likely to change. *)
1930       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1931        ["checksum"; "md5"; "/COPYING.LIB"]],
1932       Digest.to_hex (Digest.file "COPYING.LIB"))],
1933    "upload a file from the local machine",
1934    "\
1935 Upload local file C<filename> to C<remotefilename> on the
1936 filesystem.
1937
1938 C<filename> can also be a named pipe.
1939
1940 See also C<guestfs_download>.");
1941
1942   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1943    [InitBasicFS, Always, TestOutput (
1944       (* Pick a file from cwd which isn't likely to change. *)
1945       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1946        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1947        ["upload"; "testdownload.tmp"; "/upload"];
1948        ["checksum"; "md5"; "/upload"]],
1949       Digest.to_hex (Digest.file "COPYING.LIB"))],
1950    "download a file to the local machine",
1951    "\
1952 Download file C<remotefilename> and save it as C<filename>
1953 on the local machine.
1954
1955 C<filename> can also be a named pipe.
1956
1957 See also C<guestfs_upload>, C<guestfs_cat>.");
1958
1959   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1960    [InitISOFS, Always, TestOutput (
1961       [["checksum"; "crc"; "/known-3"]], "2891671662");
1962     InitISOFS, Always, TestLastFail (
1963       [["checksum"; "crc"; "/notexists"]]);
1964     InitISOFS, Always, TestOutput (
1965       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1966     InitISOFS, Always, TestOutput (
1967       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1968     InitISOFS, Always, TestOutput (
1969       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1970     InitISOFS, Always, TestOutput (
1971       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1972     InitISOFS, Always, TestOutput (
1973       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1976    "compute MD5, SHAx or CRC checksum of file",
1977    "\
1978 This call computes the MD5, SHAx or CRC checksum of the
1979 file named C<path>.
1980
1981 The type of checksum to compute is given by the C<csumtype>
1982 parameter which must have one of the following values:
1983
1984 =over 4
1985
1986 =item C<crc>
1987
1988 Compute the cyclic redundancy check (CRC) specified by POSIX
1989 for the C<cksum> command.
1990
1991 =item C<md5>
1992
1993 Compute the MD5 hash (using the C<md5sum> program).
1994
1995 =item C<sha1>
1996
1997 Compute the SHA1 hash (using the C<sha1sum> program).
1998
1999 =item C<sha224>
2000
2001 Compute the SHA224 hash (using the C<sha224sum> program).
2002
2003 =item C<sha256>
2004
2005 Compute the SHA256 hash (using the C<sha256sum> program).
2006
2007 =item C<sha384>
2008
2009 Compute the SHA384 hash (using the C<sha384sum> program).
2010
2011 =item C<sha512>
2012
2013 Compute the SHA512 hash (using the C<sha512sum> program).
2014
2015 =back
2016
2017 The checksum is returned as a printable string.");
2018
2019   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2020    [InitBasicFS, Always, TestOutput (
2021       [["tar_in"; "../images/helloworld.tar"; "/"];
2022        ["cat"; "/hello"]], "hello\n")],
2023    "unpack tarfile to directory",
2024    "\
2025 This command uploads and unpacks local file C<tarfile> (an
2026 I<uncompressed> tar file) into C<directory>.
2027
2028 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2029
2030   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2031    [],
2032    "pack directory into tarfile",
2033    "\
2034 This command packs the contents of C<directory> and downloads
2035 it to local file C<tarfile>.
2036
2037 To download a compressed tarball, use C<guestfs_tgz_out>.");
2038
2039   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2040    [InitBasicFS, Always, TestOutput (
2041       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2042        ["cat"; "/hello"]], "hello\n")],
2043    "unpack compressed tarball to directory",
2044    "\
2045 This command uploads and unpacks local file C<tarball> (a
2046 I<gzip compressed> tar file) into C<directory>.
2047
2048 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2049
2050   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2051    [],
2052    "pack directory into compressed tarball",
2053    "\
2054 This command packs the contents of C<directory> and downloads
2055 it to local file C<tarball>.
2056
2057 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2058
2059   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2060    [InitBasicFS, Always, TestLastFail (
2061       [["umount"; "/"];
2062        ["mount_ro"; "/dev/sda1"; "/"];
2063        ["touch"; "/new"]]);
2064     InitBasicFS, Always, TestOutput (
2065       [["write_file"; "/new"; "data"; "0"];
2066        ["umount"; "/"];
2067        ["mount_ro"; "/dev/sda1"; "/"];
2068        ["cat"; "/new"]], "data")],
2069    "mount a guest disk, read-only",
2070    "\
2071 This is the same as the C<guestfs_mount> command, but it
2072 mounts the filesystem with the read-only (I<-o ro>) flag.");
2073
2074   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2075    [],
2076    "mount a guest disk with mount options",
2077    "\
2078 This is the same as the C<guestfs_mount> command, but it
2079 allows you to set the mount options as for the
2080 L<mount(8)> I<-o> flag.");
2081
2082   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2083    [],
2084    "mount a guest disk with mount options and vfstype",
2085    "\
2086 This is the same as the C<guestfs_mount> command, but it
2087 allows you to set both the mount options and the vfstype
2088 as for the L<mount(8)> I<-o> and I<-t> flags.");
2089
2090   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2091    [],
2092    "debugging and internals",
2093    "\
2094 The C<guestfs_debug> command exposes some internals of
2095 C<guestfsd> (the guestfs daemon) that runs inside the
2096 qemu subprocess.
2097
2098 There is no comprehensive help for this command.  You have
2099 to look at the file C<daemon/debug.c> in the libguestfs source
2100 to find out what you can do.");
2101
2102   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2103    [InitEmpty, Always, TestOutputList (
2104       [["part_disk"; "/dev/sda"; "mbr"];
2105        ["pvcreate"; "/dev/sda1"];
2106        ["vgcreate"; "VG"; "/dev/sda1"];
2107        ["lvcreate"; "LV1"; "VG"; "50"];
2108        ["lvcreate"; "LV2"; "VG"; "50"];
2109        ["lvremove"; "/dev/VG/LV1"];
2110        ["lvs"]], ["/dev/VG/LV2"]);
2111     InitEmpty, Always, TestOutputList (
2112       [["part_disk"; "/dev/sda"; "mbr"];
2113        ["pvcreate"; "/dev/sda1"];
2114        ["vgcreate"; "VG"; "/dev/sda1"];
2115        ["lvcreate"; "LV1"; "VG"; "50"];
2116        ["lvcreate"; "LV2"; "VG"; "50"];
2117        ["lvremove"; "/dev/VG"];
2118        ["lvs"]], []);
2119     InitEmpty, Always, TestOutputList (
2120       [["part_disk"; "/dev/sda"; "mbr"];
2121        ["pvcreate"; "/dev/sda1"];
2122        ["vgcreate"; "VG"; "/dev/sda1"];
2123        ["lvcreate"; "LV1"; "VG"; "50"];
2124        ["lvcreate"; "LV2"; "VG"; "50"];
2125        ["lvremove"; "/dev/VG"];
2126        ["vgs"]], ["VG"])],
2127    "remove an LVM logical volume",
2128    "\
2129 Remove an LVM logical volume C<device>, where C<device> is
2130 the path to the LV, such as C</dev/VG/LV>.
2131
2132 You can also remove all LVs in a volume group by specifying
2133 the VG name, C</dev/VG>.");
2134
2135   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2136    [InitEmpty, Always, TestOutputList (
2137       [["part_disk"; "/dev/sda"; "mbr"];
2138        ["pvcreate"; "/dev/sda1"];
2139        ["vgcreate"; "VG"; "/dev/sda1"];
2140        ["lvcreate"; "LV1"; "VG"; "50"];
2141        ["lvcreate"; "LV2"; "VG"; "50"];
2142        ["vgremove"; "VG"];
2143        ["lvs"]], []);
2144     InitEmpty, Always, TestOutputList (
2145       [["part_disk"; "/dev/sda"; "mbr"];
2146        ["pvcreate"; "/dev/sda1"];
2147        ["vgcreate"; "VG"; "/dev/sda1"];
2148        ["lvcreate"; "LV1"; "VG"; "50"];
2149        ["lvcreate"; "LV2"; "VG"; "50"];
2150        ["vgremove"; "VG"];
2151        ["vgs"]], [])],
2152    "remove an LVM volume group",
2153    "\
2154 Remove an LVM volume group C<vgname>, (for example C<VG>).
2155
2156 This also forcibly removes all logical volumes in the volume
2157 group (if any).");
2158
2159   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2160    [InitEmpty, Always, TestOutputListOfDevices (
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        ["pvremove"; "/dev/sda1"];
2168        ["lvs"]], []);
2169     InitEmpty, Always, TestOutputListOfDevices (
2170       [["part_disk"; "/dev/sda"; "mbr"];
2171        ["pvcreate"; "/dev/sda1"];
2172        ["vgcreate"; "VG"; "/dev/sda1"];
2173        ["lvcreate"; "LV1"; "VG"; "50"];
2174        ["lvcreate"; "LV2"; "VG"; "50"];
2175        ["vgremove"; "VG"];
2176        ["pvremove"; "/dev/sda1"];
2177        ["vgs"]], []);
2178     InitEmpty, Always, TestOutputListOfDevices (
2179       [["part_disk"; "/dev/sda"; "mbr"];
2180        ["pvcreate"; "/dev/sda1"];
2181        ["vgcreate"; "VG"; "/dev/sda1"];
2182        ["lvcreate"; "LV1"; "VG"; "50"];
2183        ["lvcreate"; "LV2"; "VG"; "50"];
2184        ["vgremove"; "VG"];
2185        ["pvremove"; "/dev/sda1"];
2186        ["pvs"]], [])],
2187    "remove an LVM physical volume",
2188    "\
2189 This wipes a physical volume C<device> so that LVM will no longer
2190 recognise it.
2191
2192 The implementation uses the C<pvremove> command which refuses to
2193 wipe physical volumes that contain any volume groups, so you have
2194 to remove those first.");
2195
2196   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2197    [InitBasicFS, Always, TestOutput (
2198       [["set_e2label"; "/dev/sda1"; "testlabel"];
2199        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2200    "set the ext2/3/4 filesystem label",
2201    "\
2202 This sets the ext2/3/4 filesystem label of the filesystem on
2203 C<device> to C<label>.  Filesystem labels are limited to
2204 16 characters.
2205
2206 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2207 to return the existing label on a filesystem.");
2208
2209   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2210    [],
2211    "get the ext2/3/4 filesystem label",
2212    "\
2213 This returns the ext2/3/4 filesystem label of the filesystem on
2214 C<device>.");
2215
2216   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2217    (let uuid = uuidgen () in
2218     [InitBasicFS, Always, TestOutput (
2219        [["set_e2uuid"; "/dev/sda1"; uuid];
2220         ["get_e2uuid"; "/dev/sda1"]], uuid);
2221      InitBasicFS, Always, TestOutput (
2222        [["set_e2uuid"; "/dev/sda1"; "clear"];
2223         ["get_e2uuid"; "/dev/sda1"]], "");
2224      (* We can't predict what UUIDs will be, so just check the commands run. *)
2225      InitBasicFS, Always, TestRun (
2226        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2227      InitBasicFS, Always, TestRun (
2228        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2229    "set the ext2/3/4 filesystem UUID",
2230    "\
2231 This sets the ext2/3/4 filesystem UUID of the filesystem on
2232 C<device> to C<uuid>.  The format of the UUID and alternatives
2233 such as C<clear>, C<random> and C<time> are described in the
2234 L<tune2fs(8)> manpage.
2235
2236 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2237 to return the existing UUID of a filesystem.");
2238
2239   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2240    [],
2241    "get the ext2/3/4 filesystem UUID",
2242    "\
2243 This returns the ext2/3/4 filesystem UUID of the filesystem on
2244 C<device>.");
2245
2246   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2247    [InitBasicFS, Always, TestOutputInt (
2248       [["umount"; "/dev/sda1"];
2249        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2250     InitBasicFS, Always, TestOutputInt (
2251       [["umount"; "/dev/sda1"];
2252        ["zero"; "/dev/sda1"];
2253        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2254    "run the filesystem checker",
2255    "\
2256 This runs the filesystem checker (fsck) on C<device> which
2257 should have filesystem type C<fstype>.
2258
2259 The returned integer is the status.  See L<fsck(8)> for the
2260 list of status codes from C<fsck>.
2261
2262 Notes:
2263
2264 =over 4
2265
2266 =item *
2267
2268 Multiple status codes can be summed together.
2269
2270 =item *
2271
2272 A non-zero return code can mean \"success\", for example if
2273 errors have been corrected on the filesystem.
2274
2275 =item *
2276
2277 Checking or repairing NTFS volumes is not supported
2278 (by linux-ntfs).
2279
2280 =back
2281
2282 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2283
2284   ("zero", (RErr, [Device "device"]), 85, [],
2285    [InitBasicFS, Always, TestOutput (
2286       [["umount"; "/dev/sda1"];
2287        ["zero"; "/dev/sda1"];
2288        ["file"; "/dev/sda1"]], "data")],
2289    "write zeroes to the device",
2290    "\
2291 This command writes zeroes over the first few blocks of C<device>.
2292
2293 How many blocks are zeroed isn't specified (but it's I<not> enough
2294 to securely wipe the device).  It should be sufficient to remove
2295 any partition tables, filesystem superblocks and so on.
2296
2297 See also: C<guestfs_scrub_device>.");
2298
2299   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2300    (* Test disabled because grub-install incompatible with virtio-blk driver.
2301     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2302     *)
2303    [InitBasicFS, Disabled, TestOutputTrue (
2304       [["grub_install"; "/"; "/dev/sda1"];
2305        ["is_dir"; "/boot"]])],
2306    "install GRUB",
2307    "\
2308 This command installs GRUB (the Grand Unified Bootloader) on
2309 C<device>, with the root directory being C<root>.");
2310
2311   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2312    [InitBasicFS, Always, TestOutput (
2313       [["write_file"; "/old"; "file content"; "0"];
2314        ["cp"; "/old"; "/new"];
2315        ["cat"; "/new"]], "file content");
2316     InitBasicFS, Always, TestOutputTrue (
2317       [["write_file"; "/old"; "file content"; "0"];
2318        ["cp"; "/old"; "/new"];
2319        ["is_file"; "/old"]]);
2320     InitBasicFS, Always, TestOutput (
2321       [["write_file"; "/old"; "file content"; "0"];
2322        ["mkdir"; "/dir"];
2323        ["cp"; "/old"; "/dir/new"];
2324        ["cat"; "/dir/new"]], "file content")],
2325    "copy a file",
2326    "\
2327 This copies a file from C<src> to C<dest> where C<dest> is
2328 either a destination filename or destination directory.");
2329
2330   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2331    [InitBasicFS, Always, TestOutput (
2332       [["mkdir"; "/olddir"];
2333        ["mkdir"; "/newdir"];
2334        ["write_file"; "/olddir/file"; "file content"; "0"];
2335        ["cp_a"; "/olddir"; "/newdir"];
2336        ["cat"; "/newdir/olddir/file"]], "file content")],
2337    "copy a file or directory recursively",
2338    "\
2339 This copies a file or directory from C<src> to C<dest>
2340 recursively using the C<cp -a> command.");
2341
2342   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2343    [InitBasicFS, Always, TestOutput (
2344       [["write_file"; "/old"; "file content"; "0"];
2345        ["mv"; "/old"; "/new"];
2346        ["cat"; "/new"]], "file content");
2347     InitBasicFS, Always, TestOutputFalse (
2348       [["write_file"; "/old"; "file content"; "0"];
2349        ["mv"; "/old"; "/new"];
2350        ["is_file"; "/old"]])],
2351    "move a file",
2352    "\
2353 This moves a file from C<src> to C<dest> where C<dest> is
2354 either a destination filename or destination directory.");
2355
2356   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2357    [InitEmpty, Always, TestRun (
2358       [["drop_caches"; "3"]])],
2359    "drop kernel page cache, dentries and inodes",
2360    "\
2361 This instructs the guest kernel to drop its page cache,
2362 and/or dentries and inode caches.  The parameter C<whattodrop>
2363 tells the kernel what precisely to drop, see
2364 L<http://linux-mm.org/Drop_Caches>
2365
2366 Setting C<whattodrop> to 3 should drop everything.
2367
2368 This automatically calls L<sync(2)> before the operation,
2369 so that the maximum guest memory is freed.");
2370
2371   ("dmesg", (RString "kmsgs", []), 91, [],
2372    [InitEmpty, Always, TestRun (
2373       [["dmesg"]])],
2374    "return kernel messages",
2375    "\
2376 This returns the kernel messages (C<dmesg> output) from
2377 the guest kernel.  This is sometimes useful for extended
2378 debugging of problems.
2379
2380 Another way to get the same information is to enable
2381 verbose messages with C<guestfs_set_verbose> or by setting
2382 the environment variable C<LIBGUESTFS_DEBUG=1> before
2383 running the program.");
2384
2385   ("ping_daemon", (RErr, []), 92, [],
2386    [InitEmpty, Always, TestRun (
2387       [["ping_daemon"]])],
2388    "ping the guest daemon",
2389    "\
2390 This is a test probe into the guestfs daemon running inside
2391 the qemu subprocess.  Calling this function checks that the
2392 daemon responds to the ping message, without affecting the daemon
2393 or attached block device(s) in any other way.");
2394
2395   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2396    [InitBasicFS, Always, TestOutputTrue (
2397       [["write_file"; "/file1"; "contents of a file"; "0"];
2398        ["cp"; "/file1"; "/file2"];
2399        ["equal"; "/file1"; "/file2"]]);
2400     InitBasicFS, Always, TestOutputFalse (
2401       [["write_file"; "/file1"; "contents of a file"; "0"];
2402        ["write_file"; "/file2"; "contents of another file"; "0"];
2403        ["equal"; "/file1"; "/file2"]]);
2404     InitBasicFS, Always, TestLastFail (
2405       [["equal"; "/file1"; "/file2"]])],
2406    "test if two files have equal contents",
2407    "\
2408 This compares the two files C<file1> and C<file2> and returns
2409 true if their content is exactly equal, or false otherwise.
2410
2411 The external L<cmp(1)> program is used for the comparison.");
2412
2413   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2414    [InitISOFS, Always, TestOutputList (
2415       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2416     InitISOFS, Always, TestOutputList (
2417       [["strings"; "/empty"]], [])],
2418    "print the printable strings in a file",
2419    "\
2420 This runs the L<strings(1)> command on a file and returns
2421 the list of printable strings found.");
2422
2423   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2424    [InitISOFS, Always, TestOutputList (
2425       [["strings_e"; "b"; "/known-5"]], []);
2426     InitBasicFS, Disabled, TestOutputList (
2427       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2428        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2429    "print the printable strings in a file",
2430    "\
2431 This is like the C<guestfs_strings> command, but allows you to
2432 specify the encoding.
2433
2434 See the L<strings(1)> manpage for the full list of encodings.
2435
2436 Commonly useful encodings are C<l> (lower case L) which will
2437 show strings inside Windows/x86 files.
2438
2439 The returned strings are transcoded to UTF-8.");
2440
2441   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2442    [InitISOFS, Always, TestOutput (
2443       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2444     (* Test for RHBZ#501888c2 regression which caused large hexdump
2445      * commands to segfault.
2446      *)
2447     InitISOFS, Always, TestRun (
2448       [["hexdump"; "/100krandom"]])],
2449    "dump a file in hexadecimal",
2450    "\
2451 This runs C<hexdump -C> on the given C<path>.  The result is
2452 the human-readable, canonical hex dump of the file.");
2453
2454   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2455    [InitNone, Always, TestOutput (
2456       [["part_disk"; "/dev/sda"; "mbr"];
2457        ["mkfs"; "ext3"; "/dev/sda1"];
2458        ["mount_options"; ""; "/dev/sda1"; "/"];
2459        ["write_file"; "/new"; "test file"; "0"];
2460        ["umount"; "/dev/sda1"];
2461        ["zerofree"; "/dev/sda1"];
2462        ["mount_options"; ""; "/dev/sda1"; "/"];
2463        ["cat"; "/new"]], "test file")],
2464    "zero unused inodes and disk blocks on ext2/3 filesystem",
2465    "\
2466 This runs the I<zerofree> program on C<device>.  This program
2467 claims to zero unused inodes and disk blocks on an ext2/3
2468 filesystem, thus making it possible to compress the filesystem
2469 more effectively.
2470
2471 You should B<not> run this program if the filesystem is
2472 mounted.
2473
2474 It is possible that using this program can damage the filesystem
2475 or data on the filesystem.");
2476
2477   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2478    [],
2479    "resize an LVM physical volume",
2480    "\
2481 This resizes (expands or shrinks) an existing LVM physical
2482 volume to match the new size of the underlying device.");
2483
2484   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2485                        Int "cyls"; Int "heads"; Int "sectors";
2486                        String "line"]), 99, [DangerWillRobinson],
2487    [],
2488    "modify a single partition on a block device",
2489    "\
2490 This runs L<sfdisk(8)> option to modify just the single
2491 partition C<n> (note: C<n> counts from 1).
2492
2493 For other parameters, see C<guestfs_sfdisk>.  You should usually
2494 pass C<0> for the cyls/heads/sectors parameters.
2495
2496 See also: C<guestfs_part_add>");
2497
2498   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2499    [],
2500    "display the partition table",
2501    "\
2502 This displays the partition table on C<device>, in the
2503 human-readable output of the L<sfdisk(8)> command.  It is
2504 not intended to be parsed.
2505
2506 See also: C<guestfs_part_list>");
2507
2508   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2509    [],
2510    "display the kernel geometry",
2511    "\
2512 This displays the kernel's idea of the geometry of C<device>.
2513
2514 The result is in human-readable format, and not designed to
2515 be parsed.");
2516
2517   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2518    [],
2519    "display the disk geometry from the partition table",
2520    "\
2521 This displays the disk geometry of C<device> read from the
2522 partition table.  Especially in the case where the underlying
2523 block device has been resized, this can be different from the
2524 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2525
2526 The result is in human-readable format, and not designed to
2527 be parsed.");
2528
2529   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2530    [],
2531    "activate or deactivate all volume groups",
2532    "\
2533 This command activates or (if C<activate> is false) deactivates
2534 all logical volumes in all volume groups.
2535 If activated, then they are made known to the
2536 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2537 then those devices disappear.
2538
2539 This command is the same as running C<vgchange -a y|n>");
2540
2541   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2542    [],
2543    "activate or deactivate some volume groups",
2544    "\
2545 This command activates or (if C<activate> is false) deactivates
2546 all logical volumes in the listed volume groups C<volgroups>.
2547 If activated, then they are made known to the
2548 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2549 then those devices disappear.
2550
2551 This command is the same as running C<vgchange -a y|n volgroups...>
2552
2553 Note that if C<volgroups> is an empty list then B<all> volume groups
2554 are activated or deactivated.");
2555
2556   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2557    [InitNone, Always, TestOutput (
2558       [["part_disk"; "/dev/sda"; "mbr"];
2559        ["pvcreate"; "/dev/sda1"];
2560        ["vgcreate"; "VG"; "/dev/sda1"];
2561        ["lvcreate"; "LV"; "VG"; "10"];
2562        ["mkfs"; "ext2"; "/dev/VG/LV"];
2563        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2564        ["write_file"; "/new"; "test content"; "0"];
2565        ["umount"; "/"];
2566        ["lvresize"; "/dev/VG/LV"; "20"];
2567        ["e2fsck_f"; "/dev/VG/LV"];
2568        ["resize2fs"; "/dev/VG/LV"];
2569        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2570        ["cat"; "/new"]], "test content")],
2571    "resize an LVM logical volume",
2572    "\
2573 This resizes (expands or shrinks) an existing LVM logical
2574 volume to C<mbytes>.  When reducing, data in the reduced part
2575 is lost.");
2576
2577   ("resize2fs", (RErr, [Device "device"]), 106, [],
2578    [], (* lvresize tests this *)
2579    "resize an ext2/ext3 filesystem",
2580    "\
2581 This resizes an ext2 or ext3 filesystem to match the size of
2582 the underlying device.
2583
2584 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2585 on the C<device> before calling this command.  For unknown reasons
2586 C<resize2fs> sometimes gives an error about this and sometimes not.
2587 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2588 calling this function.");
2589
2590   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2591    [InitBasicFS, Always, TestOutputList (
2592       [["find"; "/"]], ["lost+found"]);
2593     InitBasicFS, Always, TestOutputList (
2594       [["touch"; "/a"];
2595        ["mkdir"; "/b"];
2596        ["touch"; "/b/c"];
2597        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2598     InitBasicFS, Always, TestOutputList (
2599       [["mkdir_p"; "/a/b/c"];
2600        ["touch"; "/a/b/c/d"];
2601        ["find"; "/a/b/"]], ["c"; "c/d"])],
2602    "find all files and directories",
2603    "\
2604 This command lists out all files and directories, recursively,
2605 starting at C<directory>.  It is essentially equivalent to
2606 running the shell command C<find directory -print> but some
2607 post-processing happens on the output, described below.
2608
2609 This returns a list of strings I<without any prefix>.  Thus
2610 if the directory structure was:
2611
2612  /tmp/a
2613  /tmp/b
2614  /tmp/c/d
2615
2616 then the returned list from C<guestfs_find> C</tmp> would be
2617 4 elements:
2618
2619  a
2620  b
2621  c
2622  c/d
2623
2624 If C<directory> is not a directory, then this command returns
2625 an error.
2626
2627 The returned list is sorted.
2628
2629 See also C<guestfs_find0>.");
2630
2631   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2632    [], (* lvresize tests this *)
2633    "check an ext2/ext3 filesystem",
2634    "\
2635 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2636 filesystem checker on C<device>, noninteractively (C<-p>),
2637 even if the filesystem appears to be clean (C<-f>).
2638
2639 This command is only needed because of C<guestfs_resize2fs>
2640 (q.v.).  Normally you should use C<guestfs_fsck>.");
2641
2642   ("sleep", (RErr, [Int "secs"]), 109, [],
2643    [InitNone, Always, TestRun (
2644       [["sleep"; "1"]])],
2645    "sleep for some seconds",
2646    "\
2647 Sleep for C<secs> seconds.");
2648
2649   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2650    [InitNone, Always, TestOutputInt (
2651       [["part_disk"; "/dev/sda"; "mbr"];
2652        ["mkfs"; "ntfs"; "/dev/sda1"];
2653        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2654     InitNone, Always, TestOutputInt (
2655       [["part_disk"; "/dev/sda"; "mbr"];
2656        ["mkfs"; "ext2"; "/dev/sda1"];
2657        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2658    "probe NTFS volume",
2659    "\
2660 This command runs the L<ntfs-3g.probe(8)> command which probes
2661 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2662 be mounted read-write, and some cannot be mounted at all).
2663
2664 C<rw> is a boolean flag.  Set it to true if you want to test
2665 if the volume can be mounted read-write.  Set it to false if
2666 you want to test if the volume can be mounted read-only.
2667
2668 The return value is an integer which C<0> if the operation
2669 would succeed, or some non-zero value documented in the
2670 L<ntfs-3g.probe(8)> manual page.");
2671
2672   ("sh", (RString "output", [String "command"]), 111, [],
2673    [], (* XXX needs tests *)
2674    "run a command via the shell",
2675    "\
2676 This call runs a command from the guest filesystem via the
2677 guest's C</bin/sh>.
2678
2679 This is like C<guestfs_command>, but passes the command to:
2680
2681  /bin/sh -c \"command\"
2682
2683 Depending on the guest's shell, this usually results in
2684 wildcards being expanded, shell expressions being interpolated
2685 and so on.
2686
2687 All the provisos about C<guestfs_command> apply to this call.");
2688
2689   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2690    [], (* XXX needs tests *)
2691    "run a command via the shell returning lines",
2692    "\
2693 This is the same as C<guestfs_sh>, but splits the result
2694 into a list of lines.
2695
2696 See also: C<guestfs_command_lines>");
2697
2698   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2699    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2700     * code in stubs.c, since all valid glob patterns must start with "/".
2701     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2702     *)
2703    [InitBasicFS, Always, TestOutputList (
2704       [["mkdir_p"; "/a/b/c"];
2705        ["touch"; "/a/b/c/d"];
2706        ["touch"; "/a/b/c/e"];
2707        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2708     InitBasicFS, Always, TestOutputList (
2709       [["mkdir_p"; "/a/b/c"];
2710        ["touch"; "/a/b/c/d"];
2711        ["touch"; "/a/b/c/e"];
2712        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2713     InitBasicFS, Always, TestOutputList (
2714       [["mkdir_p"; "/a/b/c"];
2715        ["touch"; "/a/b/c/d"];
2716        ["touch"; "/a/b/c/e"];
2717        ["glob_expand"; "/a/*/x/*"]], [])],
2718    "expand a wildcard path",
2719    "\
2720 This command searches for all the pathnames matching
2721 C<pattern> according to the wildcard expansion rules
2722 used by the shell.
2723
2724 If no paths match, then this returns an empty list
2725 (note: not an error).
2726
2727 It is just a wrapper around the C L<glob(3)> function
2728 with flags C<GLOB_MARK|GLOB_BRACE>.
2729 See that manual page for more details.");
2730
2731   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2732    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2733       [["scrub_device"; "/dev/sdc"]])],
2734    "scrub (securely wipe) a device",
2735    "\
2736 This command writes patterns over C<device> to make data retrieval
2737 more difficult.
2738
2739 It is an interface to the L<scrub(1)> program.  See that
2740 manual page for more details.");
2741
2742   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2743    [InitBasicFS, Always, TestRun (
2744       [["write_file"; "/file"; "content"; "0"];
2745        ["scrub_file"; "/file"]])],
2746    "scrub (securely wipe) a file",
2747    "\
2748 This command writes patterns over a file to make data retrieval
2749 more difficult.
2750
2751 The file is I<removed> after scrubbing.
2752
2753 It is an interface to the L<scrub(1)> program.  See that
2754 manual page for more details.");
2755
2756   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2757    [], (* XXX needs testing *)
2758    "scrub (securely wipe) free space",
2759    "\
2760 This command creates the directory C<dir> and then fills it
2761 with files until the filesystem is full, and scrubs the files
2762 as for C<guestfs_scrub_file>, and deletes them.
2763 The intention is to scrub any free space on the partition
2764 containing C<dir>.
2765
2766 It is an interface to the L<scrub(1)> program.  See that
2767 manual page for more details.");
2768
2769   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2770    [InitBasicFS, Always, TestRun (
2771       [["mkdir"; "/tmp"];
2772        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2773    "create a temporary directory",
2774    "\
2775 This command creates a temporary directory.  The
2776 C<template> parameter should be a full pathname for the
2777 temporary directory name with the final six characters being
2778 \"XXXXXX\".
2779
2780 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2781 the second one being suitable for Windows filesystems.
2782
2783 The name of the temporary directory that was created
2784 is returned.
2785
2786 The temporary directory is created with mode 0700
2787 and is owned by root.
2788
2789 The caller is responsible for deleting the temporary
2790 directory and its contents after use.
2791
2792 See also: L<mkdtemp(3)>");
2793
2794   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2795    [InitISOFS, Always, TestOutputInt (
2796       [["wc_l"; "/10klines"]], 10000)],
2797    "count lines in a file",
2798    "\
2799 This command counts the lines in a file, using the
2800 C<wc -l> external command.");
2801
2802   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2803    [InitISOFS, Always, TestOutputInt (
2804       [["wc_w"; "/10klines"]], 10000)],
2805    "count words in a file",
2806    "\
2807 This command counts the words in a file, using the
2808 C<wc -w> external command.");
2809
2810   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2811    [InitISOFS, Always, TestOutputInt (
2812       [["wc_c"; "/100kallspaces"]], 102400)],
2813    "count characters in a file",
2814    "\
2815 This command counts the characters in a file, using the
2816 C<wc -c> external command.");
2817
2818   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2819    [InitISOFS, Always, TestOutputList (
2820       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2821    "return first 10 lines of a file",
2822    "\
2823 This command returns up to the first 10 lines of a file as
2824 a list of strings.");
2825
2826   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2827    [InitISOFS, Always, TestOutputList (
2828       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2829     InitISOFS, Always, TestOutputList (
2830       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2831     InitISOFS, Always, TestOutputList (
2832       [["head_n"; "0"; "/10klines"]], [])],
2833    "return first N lines of a file",
2834    "\
2835 If the parameter C<nrlines> is a positive number, this returns the first
2836 C<nrlines> lines of the file C<path>.
2837
2838 If the parameter C<nrlines> is a negative number, this returns lines
2839 from the file C<path>, excluding the last C<nrlines> lines.
2840
2841 If the parameter C<nrlines> is zero, this returns an empty list.");
2842
2843   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2844    [InitISOFS, Always, TestOutputList (
2845       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2846    "return last 10 lines of a file",
2847    "\
2848 This command returns up to the last 10 lines of a file as
2849 a list of strings.");
2850
2851   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2852    [InitISOFS, Always, TestOutputList (
2853       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2854     InitISOFS, Always, TestOutputList (
2855       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2856     InitISOFS, Always, TestOutputList (
2857       [["tail_n"; "0"; "/10klines"]], [])],
2858    "return last N lines of a file",
2859    "\
2860 If the parameter C<nrlines> is a positive number, this returns the last
2861 C<nrlines> lines of the file C<path>.
2862
2863 If the parameter C<nrlines> is a negative number, this returns lines
2864 from the file C<path>, starting with the C<-nrlines>th line.
2865
2866 If the parameter C<nrlines> is zero, this returns an empty list.");
2867
2868   ("df", (RString "output", []), 125, [],
2869    [], (* XXX Tricky to test because it depends on the exact format
2870         * of the 'df' command and other imponderables.
2871         *)
2872    "report file system disk space usage",
2873    "\
2874 This command runs the C<df> command to report disk space used.
2875
2876 This command is mostly useful for interactive sessions.  It
2877 is I<not> intended that you try to parse the output string.
2878 Use C<statvfs> from programs.");
2879
2880   ("df_h", (RString "output", []), 126, [],
2881    [], (* XXX Tricky to test because it depends on the exact format
2882         * of the 'df' command and other imponderables.
2883         *)
2884    "report file system disk space usage (human readable)",
2885    "\
2886 This command runs the C<df -h> command to report disk space used
2887 in human-readable format.
2888
2889 This command is mostly useful for interactive sessions.  It
2890 is I<not> intended that you try to parse the output string.
2891 Use C<statvfs> from programs.");
2892
2893   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2894    [InitISOFS, Always, TestOutputInt (
2895       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2896    "estimate file space usage",
2897    "\
2898 This command runs the C<du -s> command to estimate file space
2899 usage for C<path>.
2900
2901 C<path> can be a file or a directory.  If C<path> is a directory
2902 then the estimate includes the contents of the directory and all
2903 subdirectories (recursively).
2904
2905 The result is the estimated size in I<kilobytes>
2906 (ie. units of 1024 bytes).");
2907
2908   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2909    [InitISOFS, Always, TestOutputList (
2910       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2911    "list files in an initrd",
2912    "\
2913 This command lists out files contained in an initrd.
2914
2915 The files are listed without any initial C</> character.  The
2916 files are listed in the order they appear (not necessarily
2917 alphabetical).  Directory names are listed as separate items.
2918
2919 Old Linux kernels (2.4 and earlier) used a compressed ext2
2920 filesystem as initrd.  We I<only> support the newer initramfs
2921 format (compressed cpio files).");
2922
2923   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2924    [],
2925    "mount a file using the loop device",
2926    "\
2927 This command lets you mount C<file> (a filesystem image
2928 in a file) on a mount point.  It is entirely equivalent to
2929 the command C<mount -o loop file mountpoint>.");
2930
2931   ("mkswap", (RErr, [Device "device"]), 130, [],
2932    [InitEmpty, Always, TestRun (
2933       [["part_disk"; "/dev/sda"; "mbr"];
2934        ["mkswap"; "/dev/sda1"]])],
2935    "create a swap partition",
2936    "\
2937 Create a swap partition on C<device>.");
2938
2939   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2940    [InitEmpty, Always, TestRun (
2941       [["part_disk"; "/dev/sda"; "mbr"];
2942        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2943    "create a swap partition with a label",
2944    "\
2945 Create a swap partition on C<device> with label C<label>.
2946
2947 Note that you cannot attach a swap label to a block device
2948 (eg. C</dev/sda>), just to a partition.  This appears to be
2949 a limitation of the kernel or swap tools.");
2950
2951   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2952    (let uuid = uuidgen () in
2953     [InitEmpty, Always, TestRun (
2954        [["part_disk"; "/dev/sda"; "mbr"];
2955         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2956    "create a swap partition with an explicit UUID",
2957    "\
2958 Create a swap partition on C<device> with UUID C<uuid>.");
2959
2960   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2961    [InitBasicFS, Always, TestOutputStruct (
2962       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2963        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2964        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2965     InitBasicFS, Always, TestOutputStruct (
2966       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2967        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2968    "make block, character or FIFO devices",
2969    "\
2970 This call creates block or character special devices, or
2971 named pipes (FIFOs).
2972
2973 The C<mode> parameter should be the mode, using the standard
2974 constants.  C<devmajor> and C<devminor> are the
2975 device major and minor numbers, only used when creating block
2976 and character special devices.");
2977
2978   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2979    [InitBasicFS, Always, TestOutputStruct (
2980       [["mkfifo"; "0o777"; "/node"];
2981        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2982    "make FIFO (named pipe)",
2983    "\
2984 This call creates a FIFO (named pipe) called C<path> with
2985 mode C<mode>.  It is just a convenient wrapper around
2986 C<guestfs_mknod>.");
2987
2988   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2989    [InitBasicFS, Always, TestOutputStruct (
2990       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2991        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2992    "make block device node",
2993    "\
2994 This call creates a block device node called C<path> with
2995 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2996 It is just a convenient wrapper around C<guestfs_mknod>.");
2997
2998   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2999    [InitBasicFS, Always, TestOutputStruct (
3000       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3001        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3002    "make char device node",
3003    "\
3004 This call creates a char device node called C<path> with
3005 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3006 It is just a convenient wrapper around C<guestfs_mknod>.");
3007
3008   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3009    [], (* XXX umask is one of those stateful things that we should
3010         * reset between each test.
3011         *)
3012    "set file mode creation mask (umask)",
3013    "\
3014 This function sets the mask used for creating new files and
3015 device nodes to C<mask & 0777>.
3016
3017 Typical umask values would be C<022> which creates new files
3018 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3019 C<002> which creates new files with permissions like
3020 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3021
3022 The default umask is C<022>.  This is important because it
3023 means that directories and device nodes will be created with
3024 C<0644> or C<0755> mode even if you specify C<0777>.
3025
3026 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3027
3028 This call returns the previous umask.");
3029
3030   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3031    [],
3032    "read directories entries",
3033    "\
3034 This returns the list of directory entries in directory C<dir>.
3035
3036 All entries in the directory are returned, including C<.> and
3037 C<..>.  The entries are I<not> sorted, but returned in the same
3038 order as the underlying filesystem.
3039
3040 Also this call returns basic file type information about each
3041 file.  The C<ftyp> field will contain one of the following characters:
3042
3043 =over 4
3044
3045 =item 'b'
3046
3047 Block special
3048
3049 =item 'c'
3050
3051 Char special
3052
3053 =item 'd'
3054
3055 Directory
3056
3057 =item 'f'
3058
3059 FIFO (named pipe)
3060
3061 =item 'l'
3062
3063 Symbolic link
3064
3065 =item 'r'
3066
3067 Regular file
3068
3069 =item 's'
3070
3071 Socket
3072
3073 =item 'u'
3074
3075 Unknown file type
3076
3077 =item '?'
3078
3079 The L<readdir(3)> returned a C<d_type> field with an
3080 unexpected value
3081
3082 =back
3083
3084 This function is primarily intended for use by programs.  To
3085 get a simple list of names, use C<guestfs_ls>.  To get a printable
3086 directory for human consumption, use C<guestfs_ll>.");
3087
3088   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3089    [],
3090    "create partitions on a block device",
3091    "\
3092 This is a simplified interface to the C<guestfs_sfdisk>
3093 command, where partition sizes are specified in megabytes
3094 only (rounded to the nearest cylinder) and you don't need
3095 to specify the cyls, heads and sectors parameters which
3096 were rarely if ever used anyway.
3097
3098 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3099 and C<guestfs_part_disk>");
3100
3101   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3102    [],
3103    "determine file type inside a compressed file",
3104    "\
3105 This command runs C<file> after first decompressing C<path>
3106 using C<method>.
3107
3108 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3109
3110 Since 1.0.63, use C<guestfs_file> instead which can now
3111 process compressed files.");
3112
3113   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3114    [],
3115    "list extended attributes of a file or directory",
3116    "\
3117 This call lists the extended attributes of the file or directory
3118 C<path>.
3119
3120 At the system call level, this is a combination of the
3121 L<listxattr(2)> and L<getxattr(2)> calls.
3122
3123 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3124
3125   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3126    [],
3127    "list extended attributes of a file or directory",
3128    "\
3129 This is the same as C<guestfs_getxattrs>, but if C<path>
3130 is a symbolic link, then it returns the extended attributes
3131 of the link itself.");
3132
3133   ("setxattr", (RErr, [String "xattr";
3134                        String "val"; Int "vallen"; (* will be BufferIn *)
3135                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3136    [],
3137    "set extended attribute of a file or directory",
3138    "\
3139 This call sets the extended attribute named C<xattr>
3140 of the file C<path> to the value C<val> (of length C<vallen>).
3141 The value is arbitrary 8 bit data.
3142
3143 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3144
3145   ("lsetxattr", (RErr, [String "xattr";
3146                         String "val"; Int "vallen"; (* will be BufferIn *)
3147                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3148    [],
3149    "set extended attribute of a file or directory",
3150    "\
3151 This is the same as C<guestfs_setxattr>, but if C<path>
3152 is a symbolic link, then it sets an extended attribute
3153 of the link itself.");
3154
3155   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3156    [],
3157    "remove extended attribute of a file or directory",
3158    "\
3159 This call removes the extended attribute named C<xattr>
3160 of the file C<path>.
3161
3162 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3163
3164   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3165    [],
3166    "remove extended attribute of a file or directory",
3167    "\
3168 This is the same as C<guestfs_removexattr>, but if C<path>
3169 is a symbolic link, then it removes an extended attribute
3170 of the link itself.");
3171
3172   ("mountpoints", (RHashtable "mps", []), 147, [],
3173    [],
3174    "show mountpoints",
3175    "\
3176 This call is similar to C<guestfs_mounts>.  That call returns
3177 a list of devices.  This one returns a hash table (map) of
3178 device name to directory where the device is mounted.");
3179
3180   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3181    (* This is a special case: while you would expect a parameter
3182     * of type "Pathname", that doesn't work, because it implies
3183     * NEED_ROOT in the generated calling code in stubs.c, and
3184     * this function cannot use NEED_ROOT.
3185     *)
3186    [],
3187    "create a mountpoint",
3188    "\
3189 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3190 specialized calls that can be used to create extra mountpoints
3191 before mounting the first filesystem.
3192
3193 These calls are I<only> necessary in some very limited circumstances,
3194 mainly the case where you want to mount a mix of unrelated and/or
3195 read-only filesystems together.
3196
3197 For example, live CDs often contain a \"Russian doll\" nest of
3198 filesystems, an ISO outer layer, with a squashfs image inside, with
3199 an ext2/3 image inside that.  You can unpack this as follows
3200 in guestfish:
3201
3202  add-ro Fedora-11-i686-Live.iso
3203  run
3204  mkmountpoint /cd
3205  mkmountpoint /squash
3206  mkmountpoint /ext3
3207  mount /dev/sda /cd
3208  mount-loop /cd/LiveOS/squashfs.img /squash
3209  mount-loop /squash/LiveOS/ext3fs.img /ext3
3210
3211 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3212
3213   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3214    [],
3215    "remove a mountpoint",
3216    "\
3217 This calls removes a mountpoint that was previously created
3218 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3219 for full details.");
3220
3221   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3222    [InitISOFS, Always, TestOutputBuffer (
3223       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3224    "read a file",
3225    "\
3226 This calls returns the contents of the file C<path> as a
3227 buffer.
3228
3229 Unlike C<guestfs_cat>, this function can correctly
3230 handle files that contain embedded ASCII NUL characters.
3231 However unlike C<guestfs_download>, this function is limited
3232 in the total size of file that can be handled.");
3233
3234   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3235    [InitISOFS, Always, TestOutputList (
3236       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3237     InitISOFS, Always, TestOutputList (
3238       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3239    "return lines matching a pattern",
3240    "\
3241 This calls the external C<grep> program and returns the
3242 matching lines.");
3243
3244   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3245    [InitISOFS, Always, TestOutputList (
3246       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3247    "return lines matching a pattern",
3248    "\
3249 This calls the external C<egrep> program and returns the
3250 matching lines.");
3251
3252   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3253    [InitISOFS, Always, TestOutputList (
3254       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3255    "return lines matching a pattern",
3256    "\
3257 This calls the external C<fgrep> program and returns the
3258 matching lines.");
3259
3260   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3261    [InitISOFS, Always, TestOutputList (
3262       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3263    "return lines matching a pattern",
3264    "\
3265 This calls the external C<grep -i> program and returns the
3266 matching lines.");
3267
3268   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3269    [InitISOFS, Always, TestOutputList (
3270       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3271    "return lines matching a pattern",
3272    "\
3273 This calls the external C<egrep -i> program and returns the
3274 matching lines.");
3275
3276   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3277    [InitISOFS, Always, TestOutputList (
3278       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3279    "return lines matching a pattern",
3280    "\
3281 This calls the external C<fgrep -i> program and returns the
3282 matching lines.");
3283
3284   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3285    [InitISOFS, Always, TestOutputList (
3286       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3287    "return lines matching a pattern",
3288    "\
3289 This calls the external C<zgrep> program and returns the
3290 matching lines.");
3291
3292   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3293    [InitISOFS, Always, TestOutputList (
3294       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3295    "return lines matching a pattern",
3296    "\
3297 This calls the external C<zegrep> program and returns the
3298 matching lines.");
3299
3300   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3301    [InitISOFS, Always, TestOutputList (
3302       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3303    "return lines matching a pattern",
3304    "\
3305 This calls the external C<zfgrep> program and returns the
3306 matching lines.");
3307
3308   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3309    [InitISOFS, Always, TestOutputList (
3310       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3311    "return lines matching a pattern",
3312    "\
3313 This calls the external C<zgrep -i> program and returns the
3314 matching lines.");
3315
3316   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3317    [InitISOFS, Always, TestOutputList (
3318       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3319    "return lines matching a pattern",
3320    "\
3321 This calls the external C<zegrep -i> program and returns the
3322 matching lines.");
3323
3324   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3325    [InitISOFS, Always, TestOutputList (
3326       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3327    "return lines matching a pattern",
3328    "\
3329 This calls the external C<zfgrep -i> program and returns the
3330 matching lines.");
3331
3332   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3333    [InitISOFS, Always, TestOutput (
3334       [["realpath"; "/../directory"]], "/directory")],
3335    "canonicalized absolute pathname",
3336    "\
3337 Return the canonicalized absolute pathname of C<path>.  The
3338 returned path has no C<.>, C<..> or symbolic link path elements.");
3339
3340   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3341    [InitBasicFS, Always, TestOutputStruct (
3342       [["touch"; "/a"];
3343        ["ln"; "/a"; "/b"];
3344        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3345    "create a hard link",
3346    "\
3347 This command creates a hard link using the C<ln> command.");
3348
3349   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3350    [InitBasicFS, Always, TestOutputStruct (
3351       [["touch"; "/a"];
3352        ["touch"; "/b"];
3353        ["ln_f"; "/a"; "/b"];
3354        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3355    "create a hard link",
3356    "\
3357 This command creates a hard link using the C<ln -f> command.
3358 The C<-f> option removes the link (C<linkname>) if it exists already.");
3359
3360   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3361    [InitBasicFS, Always, TestOutputStruct (
3362       [["touch"; "/a"];
3363        ["ln_s"; "a"; "/b"];
3364        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3365    "create a symbolic link",
3366    "\
3367 This command creates a symbolic link using the C<ln -s> command.");
3368
3369   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3370    [InitBasicFS, Always, TestOutput (
3371       [["mkdir_p"; "/a/b"];
3372        ["touch"; "/a/b/c"];
3373        ["ln_sf"; "../d"; "/a/b/c"];
3374        ["readlink"; "/a/b/c"]], "../d")],
3375    "create a symbolic link",
3376    "\
3377 This command creates a symbolic link using the C<ln -sf> command,
3378 The C<-f> option removes the link (C<linkname>) if it exists already.");
3379
3380   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3381    [] (* XXX tested above *),
3382    "read the target of a symbolic link",
3383    "\
3384 This command reads the target of a symbolic link.");
3385
3386   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3387    [InitBasicFS, Always, TestOutputStruct (
3388       [["fallocate"; "/a"; "1000000"];
3389        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3390    "preallocate a file in the guest filesystem",
3391    "\
3392 This command preallocates a file (containing zero bytes) named
3393 C<path> of size C<len> bytes.  If the file exists already, it
3394 is overwritten.
3395
3396 Do not confuse this with the guestfish-specific
3397 C<alloc> command which allocates a file in the host and
3398 attaches it as a device.");
3399
3400   ("swapon_device", (RErr, [Device "device"]), 170, [],
3401    [InitPartition, Always, TestRun (
3402       [["mkswap"; "/dev/sda1"];
3403        ["swapon_device"; "/dev/sda1"];
3404        ["swapoff_device"; "/dev/sda1"]])],
3405    "enable swap on device",
3406    "\
3407 This command enables the libguestfs appliance to use the
3408 swap device or partition named C<device>.  The increased
3409 memory is made available for all commands, for example
3410 those run using C<guestfs_command> or C<guestfs_sh>.
3411
3412 Note that you should not swap to existing guest swap
3413 partitions unless you know what you are doing.  They may
3414 contain hibernation information, or other information that
3415 the guest doesn't want you to trash.  You also risk leaking
3416 information about the host to the guest this way.  Instead,
3417 attach a new host device to the guest and swap on that.");
3418
3419   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3420    [], (* XXX tested by swapon_device *)
3421    "disable swap on device",
3422    "\
3423 This command disables the libguestfs appliance swap
3424 device or partition named C<device>.
3425 See C<guestfs_swapon_device>.");
3426
3427   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3428    [InitBasicFS, Always, TestRun (
3429       [["fallocate"; "/swap"; "8388608"];
3430        ["mkswap_file"; "/swap"];
3431        ["swapon_file"; "/swap"];
3432        ["swapoff_file"; "/swap"]])],
3433    "enable swap on file",
3434    "\
3435 This command enables swap to a file.
3436 See C<guestfs_swapon_device> for other notes.");
3437
3438   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3439    [], (* XXX tested by swapon_file *)
3440    "disable swap on file",
3441    "\
3442 This command disables the libguestfs appliance swap on file.");
3443
3444   ("swapon_label", (RErr, [String "label"]), 174, [],
3445    [InitEmpty, Always, TestRun (
3446       [["part_disk"; "/dev/sdb"; "mbr"];
3447        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3448        ["swapon_label"; "swapit"];
3449        ["swapoff_label"; "swapit"];
3450        ["zero"; "/dev/sdb"];
3451        ["blockdev_rereadpt"; "/dev/sdb"]])],
3452    "enable swap on labeled swap partition",
3453    "\
3454 This command enables swap to a labeled swap partition.
3455 See C<guestfs_swapon_device> for other notes.");
3456
3457   ("swapoff_label", (RErr, [String "label"]), 175, [],
3458    [], (* XXX tested by swapon_label *)
3459    "disable swap on labeled swap partition",
3460    "\
3461 This command disables the libguestfs appliance swap on
3462 labeled swap partition.");
3463
3464   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3465    (let uuid = uuidgen () in
3466     [InitEmpty, Always, TestRun (
3467        [["mkswap_U"; uuid; "/dev/sdb"];
3468         ["swapon_uuid"; uuid];
3469         ["swapoff_uuid"; uuid]])]),
3470    "enable swap on swap partition by UUID",
3471    "\
3472 This command enables swap to a swap partition with the given UUID.
3473 See C<guestfs_swapon_device> for other notes.");
3474
3475   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3476    [], (* XXX tested by swapon_uuid *)
3477    "disable swap on swap partition by UUID",
3478    "\
3479 This command disables the libguestfs appliance swap partition
3480 with the given UUID.");
3481
3482   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3483    [InitBasicFS, Always, TestRun (
3484       [["fallocate"; "/swap"; "8388608"];
3485        ["mkswap_file"; "/swap"]])],
3486    "create a swap file",
3487    "\
3488 Create a swap file.
3489
3490 This command just writes a swap file signature to an existing
3491 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3492
3493   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3494    [InitISOFS, Always, TestRun (
3495       [["inotify_init"; "0"]])],
3496    "create an inotify handle",
3497    "\
3498 This command creates a new inotify handle.
3499 The inotify subsystem can be used to notify events which happen to
3500 objects in the guest filesystem.
3501
3502 C<maxevents> is the maximum number of events which will be
3503 queued up between calls to C<guestfs_inotify_read> or
3504 C<guestfs_inotify_files>.
3505 If this is passed as C<0>, then the kernel (or previously set)
3506 default is used.  For Linux 2.6.29 the default was 16384 events.
3507 Beyond this limit, the kernel throws away events, but records
3508 the fact that it threw them away by setting a flag
3509 C<IN_Q_OVERFLOW> in the returned structure list (see
3510 C<guestfs_inotify_read>).
3511
3512 Before any events are generated, you have to add some
3513 watches to the internal watch list.  See:
3514 C<guestfs_inotify_add_watch>,
3515 C<guestfs_inotify_rm_watch> and
3516 C<guestfs_inotify_watch_all>.
3517
3518 Queued up events should be read periodically by calling
3519 C<guestfs_inotify_read>
3520 (or C<guestfs_inotify_files> which is just a helpful
3521 wrapper around C<guestfs_inotify_read>).  If you don't
3522 read the events out often enough then you risk the internal
3523 queue overflowing.
3524
3525 The handle should be closed after use by calling
3526 C<guestfs_inotify_close>.  This also removes any
3527 watches automatically.
3528
3529 See also L<inotify(7)> for an overview of the inotify interface
3530 as exposed by the Linux kernel, which is roughly what we expose
3531 via libguestfs.  Note that there is one global inotify handle
3532 per libguestfs instance.");
3533
3534   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3535    [InitBasicFS, Always, TestOutputList (
3536       [["inotify_init"; "0"];
3537        ["inotify_add_watch"; "/"; "1073741823"];
3538        ["touch"; "/a"];
3539        ["touch"; "/b"];
3540        ["inotify_files"]], ["a"; "b"])],
3541    "add an inotify watch",
3542    "\
3543 Watch C<path> for the events listed in C<mask>.
3544
3545 Note that if C<path> is a directory then events within that
3546 directory are watched, but this does I<not> happen recursively
3547 (in subdirectories).
3548
3549 Note for non-C or non-Linux callers: the inotify events are
3550 defined by the Linux kernel ABI and are listed in
3551 C</usr/include/sys/inotify.h>.");
3552
3553   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3554    [],
3555    "remove an inotify watch",
3556    "\
3557 Remove a previously defined inotify watch.
3558 See C<guestfs_inotify_add_watch>.");
3559
3560   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3561    [],
3562    "return list of inotify events",
3563    "\
3564 Return the complete queue of events that have happened
3565 since the previous read call.
3566
3567 If no events have happened, this returns an empty list.
3568
3569 I<Note>: In order to make sure that all events have been
3570 read, you must call this function repeatedly until it
3571 returns an empty list.  The reason is that the call will
3572 read events up to the maximum appliance-to-host message
3573 size and leave remaining events in the queue.");
3574
3575   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3576    [],
3577    "return list of watched files that had events",
3578    "\
3579 This function is a helpful wrapper around C<guestfs_inotify_read>
3580 which just returns a list of pathnames of objects that were
3581 touched.  The returned pathnames are sorted and deduplicated.");
3582
3583   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3584    [],
3585    "close the inotify handle",
3586    "\
3587 This closes the inotify handle which was previously
3588 opened by inotify_init.  It removes all watches, throws
3589 away any pending events, and deallocates all resources.");
3590
3591   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3592    [],
3593    "set SELinux security context",
3594    "\
3595 This sets the SELinux security context of the daemon
3596 to the string C<context>.
3597
3598 See the documentation about SELINUX in L<guestfs(3)>.");
3599
3600   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3601    [],
3602    "get SELinux security context",
3603    "\
3604 This gets the SELinux security context of the daemon.
3605
3606 See the documentation about SELINUX in L<guestfs(3)>,
3607 and C<guestfs_setcon>");
3608
3609   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3610    [InitEmpty, Always, TestOutput (
3611       [["part_disk"; "/dev/sda"; "mbr"];
3612        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3613        ["mount_options"; ""; "/dev/sda1"; "/"];
3614        ["write_file"; "/new"; "new file contents"; "0"];
3615        ["cat"; "/new"]], "new file contents")],
3616    "make a filesystem with block size",
3617    "\
3618 This call is similar to C<guestfs_mkfs>, but it allows you to
3619 control the block size of the resulting filesystem.  Supported
3620 block sizes depend on the filesystem type, but typically they
3621 are C<1024>, C<2048> or C<4096> only.");
3622
3623   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3624    [InitEmpty, Always, TestOutput (
3625       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3626        ["mke2journal"; "4096"; "/dev/sda1"];
3627        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3628        ["mount_options"; ""; "/dev/sda2"; "/"];
3629        ["write_file"; "/new"; "new file contents"; "0"];
3630        ["cat"; "/new"]], "new file contents")],
3631    "make ext2/3/4 external journal",
3632    "\
3633 This creates an ext2 external journal on C<device>.  It is equivalent
3634 to the command:
3635
3636  mke2fs -O journal_dev -b blocksize device");
3637
3638   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3639    [InitEmpty, Always, TestOutput (
3640       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3641        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3642        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3643        ["mount_options"; ""; "/dev/sda2"; "/"];
3644        ["write_file"; "/new"; "new file contents"; "0"];
3645        ["cat"; "/new"]], "new file contents")],
3646    "make ext2/3/4 external journal with label",
3647    "\
3648 This creates an ext2 external journal on C<device> with label C<label>.");
3649
3650   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3651    (let uuid = uuidgen () in
3652     [InitEmpty, Always, TestOutput (
3653        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3654         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3655         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3656         ["mount_options"; ""; "/dev/sda2"; "/"];
3657         ["write_file"; "/new"; "new file contents"; "0"];
3658         ["cat"; "/new"]], "new file contents")]),
3659    "make ext2/3/4 external journal with UUID",
3660    "\
3661 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3662
3663   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3664    [],
3665    "make ext2/3/4 filesystem with external journal",
3666    "\
3667 This creates an ext2/3/4 filesystem on C<device> with
3668 an external journal on C<journal>.  It is equivalent
3669 to the command:
3670
3671  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3672
3673 See also C<guestfs_mke2journal>.");
3674
3675   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3676    [],
3677    "make ext2/3/4 filesystem with external journal",
3678    "\
3679 This creates an ext2/3/4 filesystem on C<device> with
3680 an external journal on the journal labeled C<label>.
3681
3682 See also C<guestfs_mke2journal_L>.");
3683
3684   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3685    [],
3686    "make ext2/3/4 filesystem with external journal",
3687    "\
3688 This creates an ext2/3/4 filesystem on C<device> with
3689 an external journal on the journal with UUID C<uuid>.
3690
3691 See also C<guestfs_mke2journal_U>.");
3692
3693   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3694    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3695    "load a kernel module",
3696    "\
3697 This loads a kernel module in the appliance.
3698
3699 The kernel module must have been whitelisted when libguestfs
3700 was built (see C<appliance/kmod.whitelist.in> in the source).");
3701
3702   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3703    [InitNone, Always, TestOutput (
3704       [["echo_daemon"; "This is a test"]], "This is a test"
3705     )],
3706    "echo arguments back to the client",
3707    "\
3708 This command concatenate the list of C<words> passed with single spaces between
3709 them and returns the resulting string.
3710
3711 You can use this command to test the connection through to the daemon.
3712
3713 See also C<guestfs_ping_daemon>.");
3714
3715   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3716    [], (* There is a regression test for this. *)
3717    "find all files and directories, returning NUL-separated list",
3718    "\
3719 This command lists out all files and directories, recursively,
3720 starting at C<directory>, placing the resulting list in the
3721 external file called C<files>.
3722
3723 This command works the same way as C<guestfs_find> with the
3724 following exceptions:
3725
3726 =over 4
3727
3728 =item *
3729
3730 The resulting list is written to an external file.
3731
3732 =item *
3733
3734 Items (filenames) in the result are separated
3735 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3736
3737 =item *
3738
3739 This command is not limited in the number of names that it
3740 can return.
3741
3742 =item *
3743
3744 The result list is not sorted.
3745
3746 =back");
3747
3748   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3749    [InitISOFS, Always, TestOutput (
3750       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3751     InitISOFS, Always, TestOutput (
3752       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3753     InitISOFS, Always, TestOutput (
3754       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3755     InitISOFS, Always, TestLastFail (
3756       [["case_sensitive_path"; "/Known-1/"]]);
3757     InitBasicFS, Always, TestOutput (
3758       [["mkdir"; "/a"];
3759        ["mkdir"; "/a/bbb"];
3760        ["touch"; "/a/bbb/c"];
3761        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3762     InitBasicFS, Always, TestOutput (
3763       [["mkdir"; "/a"];
3764        ["mkdir"; "/a/bbb"];
3765        ["touch"; "/a/bbb/c"];
3766        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3767     InitBasicFS, Always, TestLastFail (
3768       [["mkdir"; "/a"];
3769        ["mkdir"; "/a/bbb"];
3770        ["touch"; "/a/bbb/c"];
3771        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3772    "return true path on case-insensitive filesystem",
3773    "\
3774 This can be used to resolve case insensitive paths on
3775 a filesystem which is case sensitive.  The use case is
3776 to resolve paths which you have read from Windows configuration
3777 files or the Windows Registry, to the true path.
3778
3779 The command handles a peculiarity of the Linux ntfs-3g
3780 filesystem driver (and probably others), which is that although
3781 the underlying filesystem is case-insensitive, the driver
3782 exports the filesystem to Linux as case-sensitive.
3783
3784 One consequence of this is that special directories such
3785 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3786 (or other things) depending on the precise details of how
3787 they were created.  In Windows itself this would not be
3788 a problem.
3789
3790 Bug or feature?  You decide:
3791 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3792
3793 This function resolves the true case of each element in the
3794 path and returns the case-sensitive path.
3795
3796 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3797 might return C<\"/WINDOWS/system32\"> (the exact return value
3798 would depend on details of how the directories were originally
3799 created under Windows).
3800
3801 I<Note>:
3802 This function does not handle drive names, backslashes etc.
3803
3804 See also C<guestfs_realpath>.");
3805
3806   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3807    [InitBasicFS, Always, TestOutput (
3808       [["vfs_type"; "/dev/sda1"]], "ext2")],
3809    "get the Linux VFS type corresponding to a mounted device",
3810    "\
3811 This command gets the block device type corresponding to
3812 a mounted device called C<device>.
3813
3814 Usually the result is the name of the Linux VFS module that
3815 is used to mount this device (probably determined automatically
3816 if you used the C<guestfs_mount> call).");
3817
3818   ("truncate", (RErr, [Pathname "path"]), 199, [],
3819    [InitBasicFS, Always, TestOutputStruct (
3820       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3821        ["truncate"; "/test"];
3822        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3823    "truncate a file to zero size",
3824    "\
3825 This command truncates C<path> to a zero-length file.  The
3826 file must exist already.");
3827
3828   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3829    [InitBasicFS, Always, TestOutputStruct (
3830       [["touch"; "/test"];
3831        ["truncate_size"; "/test"; "1000"];
3832        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3833    "truncate a file to a particular size",
3834    "\
3835 This command truncates C<path> to size C<size> bytes.  The file
3836 must exist already.  If the file is smaller than C<size> then
3837 the file is extended to the required size with null bytes.");
3838
3839   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3840    [InitBasicFS, Always, TestOutputStruct (
3841       [["touch"; "/test"];
3842        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3843        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3844    "set timestamp of a file with nanosecond precision",
3845    "\
3846 This command sets the timestamps of a file with nanosecond
3847 precision.
3848
3849 C<atsecs, atnsecs> are the last access time (atime) in secs and
3850 nanoseconds from the epoch.
3851
3852 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3853 secs and nanoseconds from the epoch.
3854
3855 If the C<*nsecs> field contains the special value C<-1> then
3856 the corresponding timestamp is set to the current time.  (The
3857 C<*secs> field is ignored in this case).
3858
3859 If the C<*nsecs> field contains the special value C<-2> then
3860 the corresponding timestamp is left unchanged.  (The
3861 C<*secs> field is ignored in this case).");
3862
3863   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3864    [InitBasicFS, Always, TestOutputStruct (
3865       [["mkdir_mode"; "/test"; "0o111"];
3866        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3867    "create a directory with a particular mode",
3868    "\
3869 This command creates a directory, setting the initial permissions
3870 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3871
3872   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3873    [], (* XXX *)
3874    "change file owner and group",
3875    "\
3876 Change the file owner to C<owner> and group to C<group>.
3877 This is like C<guestfs_chown> but if C<path> is a symlink then
3878 the link itself is changed, not the target.
3879
3880 Only numeric uid and gid are supported.  If you want to use
3881 names, you will need to locate and parse the password file
3882 yourself (Augeas support makes this relatively easy).");
3883
3884   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3885    [], (* XXX *)
3886    "lstat on multiple files",
3887    "\
3888 This call allows you to perform the C<guestfs_lstat> operation
3889 on multiple files, where all files are in the directory C<path>.
3890 C<names> is the list of files from this directory.
3891
3892 On return you get a list of stat structs, with a one-to-one
3893 correspondence to the C<names> list.  If any name did not exist
3894 or could not be lstat'd, then the C<ino> field of that structure
3895 is set to C<-1>.
3896
3897 This call is intended for programs that want to efficiently
3898 list a directory contents without making many round-trips.
3899 See also C<guestfs_lxattrlist> for a similarly efficient call
3900 for getting extended attributes.  Very long directory listings
3901 might cause the protocol message size to be exceeded, causing
3902 this call to fail.  The caller must split up such requests
3903 into smaller groups of names.");
3904
3905   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3906    [], (* XXX *)
3907    "lgetxattr on multiple files",
3908    "\
3909 This call allows you to get the extended attributes
3910 of multiple files, where all files are in the directory C<path>.
3911 C<names> is the list of files from this directory.
3912
3913 On return you get a flat list of xattr structs which must be
3914 interpreted sequentially.  The first xattr struct always has a zero-length
3915 C<attrname>.  C<attrval> in this struct is zero-length
3916 to indicate there was an error doing C<lgetxattr> for this
3917 file, I<or> is a C string which is a decimal number
3918 (the number of following attributes for this file, which could
3919 be C<\"0\">).  Then after the first xattr struct are the
3920 zero or more attributes for the first named file.
3921 This repeats for the second and subsequent files.
3922
3923 This call is intended for programs that want to efficiently
3924 list a directory contents without making many round-trips.
3925 See also C<guestfs_lstatlist> for a similarly efficient call
3926 for getting standard stats.  Very long directory listings
3927 might cause the protocol message size to be exceeded, causing
3928 this call to fail.  The caller must split up such requests
3929 into smaller groups of names.");
3930
3931   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3932    [], (* XXX *)
3933    "readlink on multiple files",
3934    "\
3935 This call allows you to do a C<readlink> operation
3936 on multiple files, where all files are in the directory C<path>.
3937 C<names> is the list of files from this directory.
3938
3939 On return you get a list of strings, with a one-to-one
3940 correspondence to the C<names> list.  Each string is the
3941 value of the symbol link.
3942
3943 If the C<readlink(2)> operation fails on any name, then
3944 the corresponding result string is the empty string C<\"\">.
3945 However the whole operation is completed even if there
3946 were C<readlink(2)> errors, and so you can call this
3947 function with names where you don't know if they are
3948 symbolic links already (albeit slightly less efficient).
3949
3950 This call is intended for programs that want to efficiently
3951 list a directory contents without making many round-trips.
3952 Very long directory listings might cause the protocol
3953 message size to be exceeded, causing
3954 this call to fail.  The caller must split up such requests
3955 into smaller groups of names.");
3956
3957   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3958    [InitISOFS, Always, TestOutputBuffer (
3959       [["pread"; "/known-4"; "1"; "3"]], "\n");
3960     InitISOFS, Always, TestOutputBuffer (
3961       [["pread"; "/empty"; "0"; "100"]], "")],
3962    "read part of a file",
3963    "\
3964 This command lets you read part of a file.  It reads C<count>
3965 bytes of the file, starting at C<offset>, from file C<path>.
3966
3967 This may read fewer bytes than requested.  For further details
3968 see the L<pread(2)> system call.");
3969
3970   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3971    [InitEmpty, Always, TestRun (
3972       [["part_init"; "/dev/sda"; "gpt"]])],
3973    "create an empty partition table",
3974    "\
3975 This creates an empty partition table on C<device> of one of the
3976 partition types listed below.  Usually C<parttype> should be
3977 either C<msdos> or C<gpt> (for large disks).
3978
3979 Initially there are no partitions.  Following this, you should
3980 call C<guestfs_part_add> for each partition required.
3981
3982 Possible values for C<parttype> are:
3983
3984 =over 4
3985
3986 =item B<efi> | B<gpt>
3987
3988 Intel EFI / GPT partition table.
3989
3990 This is recommended for >= 2 TB partitions that will be accessed
3991 from Linux and Intel-based Mac OS X.  It also has limited backwards
3992 compatibility with the C<mbr> format.
3993
3994 =item B<mbr> | B<msdos>
3995
3996 The standard PC \"Master Boot Record\" (MBR) format used
3997 by MS-DOS and Windows.  This partition type will B<only> work
3998 for device sizes up to 2 TB.  For large disks we recommend
3999 using C<gpt>.
4000
4001 =back
4002
4003 Other partition table types that may work but are not
4004 supported include:
4005
4006 =over 4
4007
4008 =item B<aix>
4009
4010 AIX disk labels.
4011
4012 =item B<amiga> | B<rdb>
4013
4014 Amiga \"Rigid Disk Block\" format.
4015
4016 =item B<bsd>
4017
4018 BSD disk labels.
4019
4020 =item B<dasd>
4021
4022 DASD, used on IBM mainframes.
4023
4024 =item B<dvh>
4025
4026 MIPS/SGI volumes.
4027
4028 =item B<mac>
4029
4030 Old Mac partition format.  Modern Macs use C<gpt>.
4031
4032 =item B<pc98>
4033
4034 NEC PC-98 format, common in Japan apparently.
4035
4036 =item B<sun>
4037
4038 Sun disk labels.
4039
4040 =back");
4041
4042   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4043    [InitEmpty, Always, TestRun (
4044       [["part_init"; "/dev/sda"; "mbr"];
4045        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4046     InitEmpty, Always, TestRun (
4047       [["part_init"; "/dev/sda"; "gpt"];
4048        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4049        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4050     InitEmpty, Always, TestRun (
4051       [["part_init"; "/dev/sda"; "mbr"];
4052        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4053        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4054        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4055        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4056    "add a partition to the device",
4057    "\
4058 This command adds a partition to C<device>.  If there is no partition
4059 table on the device, call C<guestfs_part_init> first.
4060
4061 The C<prlogex> parameter is the type of partition.  Normally you
4062 should pass C<p> or C<primary> here, but MBR partition tables also
4063 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4064 types.
4065
4066 C<startsect> and C<endsect> are the start and end of the partition
4067 in I<sectors>.  C<endsect> may be negative, which means it counts
4068 backwards from the end of the disk (C<-1> is the last sector).
4069
4070 Creating a partition which covers the whole disk is not so easy.
4071 Use C<guestfs_part_disk> to do that.");
4072
4073   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4074    [InitEmpty, Always, TestRun (
4075       [["part_disk"; "/dev/sda"; "mbr"]]);
4076     InitEmpty, Always, TestRun (
4077       [["part_disk"; "/dev/sda"; "gpt"]])],
4078    "partition whole disk with a single primary partition",
4079    "\
4080 This command is simply a combination of C<guestfs_part_init>
4081 followed by C<guestfs_part_add> to create a single primary partition
4082 covering the whole disk.
4083
4084 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4085 but other possible values are described in C<guestfs_part_init>.");
4086
4087   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4088    [InitEmpty, Always, TestRun (
4089       [["part_disk"; "/dev/sda"; "mbr"];
4090        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4091    "make a partition bootable",
4092    "\
4093 This sets the bootable flag on partition numbered C<partnum> on
4094 device C<device>.  Note that partitions are numbered from 1.
4095
4096 The bootable flag is used by some operating systems (notably
4097 Windows) to determine which partition to boot from.  It is by
4098 no means universally recognized.");
4099
4100   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4101    [InitEmpty, Always, TestRun (
4102       [["part_disk"; "/dev/sda"; "gpt"];
4103        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4104    "set partition name",
4105    "\
4106 This sets the partition name on partition numbered C<partnum> on
4107 device C<device>.  Note that partitions are numbered from 1.
4108
4109 The partition name can only be set on certain types of partition
4110 table.  This works on C<gpt> but not on C<mbr> partitions.");
4111
4112   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4113    [], (* XXX Add a regression test for this. *)
4114    "list partitions on a device",
4115    "\
4116 This command parses the partition table on C<device> and
4117 returns the list of partitions found.
4118
4119 The fields in the returned structure are:
4120
4121 =over 4
4122
4123 =item B<part_num>
4124
4125 Partition number, counting from 1.
4126
4127 =item B<part_start>
4128
4129 Start of the partition I<in bytes>.  To get sectors you have to
4130 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4131
4132 =item B<part_end>
4133
4134 End of the partition in bytes.
4135
4136 =item B<part_size>
4137
4138 Size of the partition in bytes.
4139
4140 =back");
4141
4142   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4143    [InitEmpty, Always, TestOutput (
4144       [["part_disk"; "/dev/sda"; "gpt"];
4145        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4146    "get the partition table type",
4147    "\
4148 This command examines the partition table on C<device> and
4149 returns the partition table type (format) being used.
4150
4151 Common return values include: C<msdos> (a DOS/Windows style MBR
4152 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4153 values are possible, although unusual.  See C<guestfs_part_init>
4154 for a full list.");
4155
4156   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4157    [InitBasicFS, Always, TestOutputBuffer (
4158       [["fill"; "0x63"; "10"; "/test"];
4159        ["read_file"; "/test"]], "cccccccccc")],
4160    "fill a file with octets",
4161    "\
4162 This command creates a new file called C<path>.  The initial
4163 content of the file is C<len> octets of C<c>, where C<c>
4164 must be a number in the range C<[0..255]>.
4165
4166 To fill a file with zero bytes (sparsely), it is
4167 much more efficient to use C<guestfs_truncate_size>.");
4168
4169   ("available", (RErr, [StringList "groups"]), 216, [],
4170    [InitNone, Always, TestRun [["available"; ""]]],
4171    "test availability of some parts of the API",
4172    "\
4173 This command is used to check the availability of some
4174 groups of functionality in the appliance, which not all builds of
4175 the libguestfs appliance will be able to provide.
4176
4177 The libguestfs groups, and the functions that those
4178 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4179
4180 The argument C<groups> is a list of group names, eg:
4181 C<[\"inotify\", \"augeas\"]> would check for the availability of
4182 the Linux inotify functions and Augeas (configuration file
4183 editing) functions.
4184
4185 The command returns no error if I<all> requested groups are available.
4186
4187 It fails with an error if one or more of the requested
4188 groups is unavailable in the appliance.
4189
4190 If an unknown group name is included in the
4191 list of groups then an error is always returned.
4192
4193 I<Notes:>
4194
4195 =over 4
4196
4197 =item *
4198
4199 You must call C<guestfs_launch> before calling this function.
4200
4201 The reason is because we don't know what groups are
4202 supported by the appliance/daemon until it is running and can
4203 be queried.
4204
4205 =item *
4206
4207 If a group of functions is available, this does not necessarily
4208 mean that they will work.  You still have to check for errors
4209 when calling individual API functions even if they are
4210 available.
4211
4212 =item *
4213
4214 It is usually the job of distro packagers to build
4215 complete functionality into the libguestfs appliance.
4216 Upstream libguestfs, if built from source with all
4217 requirements satisfied, will support everything.
4218
4219 =item *
4220
4221 This call was added in version C<1.0.80>.  In previous
4222 versions of libguestfs all you could do would be to speculatively
4223 execute a command to find out if the daemon implemented it.
4224 See also C<guestfs_version>.
4225
4226 =back");
4227
4228   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4229    [InitBasicFS, Always, TestOutputBuffer (
4230       [["write_file"; "/src"; "hello, world"; "0"];
4231        ["dd"; "/src"; "/dest"];
4232        ["read_file"; "/dest"]], "hello, world")],
4233    "copy from source to destination using dd",
4234    "\
4235 This command copies from one source device or file C<src>
4236 to another destination device or file C<dest>.  Normally you
4237 would use this to copy to or from a device or partition, for
4238 example to duplicate a filesystem.
4239
4240 If the destination is a device, it must be as large or larger
4241 than the source file or device, otherwise the copy will fail.
4242 This command cannot do partial copies (see C<guestfs_copy_size>).");
4243
4244   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4245    [InitBasicFS, Always, TestOutputInt (
4246       [["write_file"; "/file"; "hello, world"; "0"];
4247        ["filesize"; "/file"]], 12)],
4248    "return the size of the file in bytes",
4249    "\
4250 This command returns the size of C<file> in bytes.
4251
4252 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4253 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4254 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4255
4256   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4257    [InitBasicFSonLVM, Always, TestOutputList (
4258       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4259        ["lvs"]], ["/dev/VG/LV2"])],
4260    "rename an LVM logical volume",
4261    "\
4262 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4263
4264   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4265    [InitBasicFSonLVM, Always, TestOutputList (
4266       [["umount"; "/"];
4267        ["vg_activate"; "false"; "VG"];
4268        ["vgrename"; "VG"; "VG2"];
4269        ["vg_activate"; "true"; "VG2"];
4270        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4271        ["vgs"]], ["VG2"])],
4272    "rename an LVM volume group",
4273    "\
4274 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4275
4276   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4277    [InitISOFS, Always, TestOutputBuffer (
4278       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4279    "list the contents of a single file in an initrd",
4280    "\
4281 This command unpacks the file C<filename> from the initrd file
4282 called C<initrdpath>.  The filename must be given I<without> the
4283 initial C</> character.
4284
4285 For example, in guestfish you could use the following command
4286 to examine the boot script (usually called C</init>)
4287 contained in a Linux initrd or initramfs image:
4288
4289  initrd-cat /boot/initrd-<version>.img init
4290
4291 See also C<guestfs_initrd_list>.");
4292
4293   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4294    [],
4295    "get the UUID of a physical volume",
4296    "\
4297 This command returns the UUID of the LVM PV C<device>.");
4298
4299   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4300    [],
4301    "get the UUID of a volume group",
4302    "\
4303 This command returns the UUID of the LVM VG named C<vgname>.");
4304
4305   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4306    [],
4307    "get the UUID of a logical volume",
4308    "\
4309 This command returns the UUID of the LVM LV C<device>.");
4310
4311   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4312    [],
4313    "get the PV UUIDs containing the volume group",
4314    "\
4315 Given a VG called C<vgname>, this returns the UUIDs of all
4316 the physical volumes that this volume group resides on.
4317
4318 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4319 calls to associate physical volumes and volume groups.
4320
4321 See also C<guestfs_vglvuuids>.");
4322
4323   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4324    [],
4325    "get the LV UUIDs of all LVs in the volume group",
4326    "\
4327 Given a VG called C<vgname>, this returns the UUIDs of all
4328 the logical volumes created in this volume group.
4329
4330 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4331 calls to associate logical volumes and volume groups.
4332
4333 See also C<guestfs_vgpvuuids>.");
4334
4335   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4336    [InitBasicFS, Always, TestOutputBuffer (
4337       [["write_file"; "/src"; "hello, world"; "0"];
4338        ["copy_size"; "/src"; "/dest"; "5"];
4339        ["read_file"; "/dest"]], "hello")],
4340    "copy size bytes from source to destination using dd",
4341    "\
4342 This command copies exactly C<size> bytes from one source device
4343 or file C<src> to another destination device or file C<dest>.
4344
4345 Note this will fail if the source is too short or if the destination
4346 is not large enough.");
4347
4348   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4349    [InitEmpty, Always, TestRun (
4350       [["part_init"; "/dev/sda"; "mbr"];
4351        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4352        ["part_del"; "/dev/sda"; "1"]])],
4353    "delete a partition",
4354    "\
4355 This command deletes the partition numbered C<partnum> on C<device>.
4356
4357 Note that in the case of MBR partitioning, deleting an
4358 extended partition also deletes any logical partitions
4359 it contains.");
4360
4361   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4362    [InitEmpty, Always, TestOutputTrue (
4363       [["part_init"; "/dev/sda"; "mbr"];
4364        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4365        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4366        ["part_get_bootable"; "/dev/sda"; "1"]])],
4367    "return true if a partition is bootable",
4368    "\
4369 This command returns true if the partition C<partnum> on
4370 C<device> has the bootable flag set.
4371
4372 See also C<guestfs_part_set_bootable>.");
4373
4374   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4375    [InitEmpty, Always, TestOutputInt (
4376       [["part_init"; "/dev/sda"; "mbr"];
4377        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4378        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4379        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4380    "get the MBR type byte (ID byte) from a partition",
4381    "\
4382 Returns the MBR type byte (also known as the ID byte) from
4383 the numbered partition C<partnum>.
4384
4385 Note that only MBR (old DOS-style) partitions have type bytes.
4386 You will get undefined results for other partition table
4387 types (see C<guestfs_part_get_parttype>).");
4388
4389   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4390    [], (* tested by part_get_mbr_id *)
4391    "set the MBR type byte (ID byte) of a partition",
4392    "\
4393 Sets the MBR type byte (also known as the ID byte) of
4394 the numbered partition C<partnum> to C<idbyte>.  Note
4395 that the type bytes quoted in most documentation are
4396 in fact hexadecimal numbers, but usually documented
4397 without any leading \"0x\" which might be confusing.
4398
4399 Note that only MBR (old DOS-style) partitions have type bytes.
4400 You will get undefined results for other partition table
4401 types (see C<guestfs_part_get_parttype>).");
4402
4403 ]
4404
4405 let all_functions = non_daemon_functions @ daemon_functions
4406
4407 (* In some places we want the functions to be displayed sorted
4408  * alphabetically, so this is useful:
4409  *)
4410 let all_functions_sorted =
4411   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4412                compare n1 n2) all_functions
4413
4414 (* Field types for structures. *)
4415 type field =
4416   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4417   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4418   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4419   | FUInt32
4420   | FInt32
4421   | FUInt64
4422   | FInt64
4423   | FBytes                      (* Any int measure that counts bytes. *)
4424   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4425   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4426
4427 (* Because we generate extra parsing code for LVM command line tools,
4428  * we have to pull out the LVM columns separately here.
4429  *)
4430 let lvm_pv_cols = [
4431   "pv_name", FString;
4432   "pv_uuid", FUUID;
4433   "pv_fmt", FString;
4434   "pv_size", FBytes;
4435   "dev_size", FBytes;
4436   "pv_free", FBytes;
4437   "pv_used", FBytes;
4438   "pv_attr", FString (* XXX *);
4439   "pv_pe_count", FInt64;
4440   "pv_pe_alloc_count", FInt64;
4441   "pv_tags", FString;
4442   "pe_start", FBytes;
4443   "pv_mda_count", FInt64;
4444   "pv_mda_free", FBytes;
4445   (* Not in Fedora 10:
4446      "pv_mda_size", FBytes;
4447   *)
4448 ]
4449 let lvm_vg_cols = [
4450   "vg_name", FString;
4451   "vg_uuid", FUUID;
4452   "vg_fmt", FString;
4453   "vg_attr", FString (* XXX *);
4454   "vg_size", FBytes;
4455   "vg_free", FBytes;
4456   "vg_sysid", FString;
4457   "vg_extent_size", FBytes;
4458   "vg_extent_count", FInt64;
4459   "vg_free_count", FInt64;
4460   "max_lv", FInt64;
4461   "max_pv", FInt64;
4462   "pv_count", FInt64;
4463   "lv_count", FInt64;
4464   "snap_count", FInt64;
4465   "vg_seqno", FInt64;
4466   "vg_tags", FString;
4467   "vg_mda_count", FInt64;
4468   "vg_mda_free", FBytes;
4469   (* Not in Fedora 10:
4470      "vg_mda_size", FBytes;
4471   *)
4472 ]
4473 let lvm_lv_cols = [
4474   "lv_name", FString;
4475   "lv_uuid", FUUID;
4476   "lv_attr", FString (* XXX *);
4477   "lv_major", FInt64;
4478   "lv_minor", FInt64;
4479   "lv_kernel_major", FInt64;
4480   "lv_kernel_minor", FInt64;
4481   "lv_size", FBytes;
4482   "seg_count", FInt64;
4483   "origin", FString;
4484   "snap_percent", FOptPercent;
4485   "copy_percent", FOptPercent;
4486   "move_pv", FString;
4487   "lv_tags", FString;
4488   "mirror_log", FString;
4489   "modules", FString;
4490 ]
4491
4492 (* Names and fields in all structures (in RStruct and RStructList)
4493  * that we support.
4494  *)
4495 let structs = [
4496   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4497    * not use this struct in any new code.
4498    *)
4499   "int_bool", [
4500     "i", FInt32;                (* for historical compatibility *)
4501     "b", FInt32;                (* for historical compatibility *)
4502   ];
4503
4504   (* LVM PVs, VGs, LVs. *)
4505   "lvm_pv", lvm_pv_cols;
4506   "lvm_vg", lvm_vg_cols;
4507   "lvm_lv", lvm_lv_cols;
4508
4509   (* Column names and types from stat structures.
4510    * NB. Can't use things like 'st_atime' because glibc header files
4511    * define some of these as macros.  Ugh.
4512    *)
4513   "stat", [
4514     "dev", FInt64;
4515     "ino", FInt64;
4516     "mode", FInt64;
4517     "nlink", FInt64;
4518     "uid", FInt64;
4519     "gid", FInt64;
4520     "rdev", FInt64;
4521     "size", FInt64;
4522     "blksize", FInt64;
4523     "blocks", FInt64;
4524     "atime", FInt64;
4525     "mtime", FInt64;
4526     "ctime", FInt64;
4527   ];
4528   "statvfs", [
4529     "bsize", FInt64;
4530     "frsize", FInt64;
4531     "blocks", FInt64;
4532     "bfree", FInt64;
4533     "bavail", FInt64;
4534     "files", FInt64;
4535     "ffree", FInt64;
4536     "favail", FInt64;
4537     "fsid", FInt64;
4538     "flag", FInt64;
4539     "namemax", FInt64;
4540   ];
4541
4542   (* Column names in dirent structure. *)
4543   "dirent", [
4544     "ino", FInt64;
4545     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4546     "ftyp", FChar;
4547     "name", FString;
4548   ];
4549
4550   (* Version numbers. *)
4551   "version", [
4552     "major", FInt64;
4553     "minor", FInt64;
4554     "release", FInt64;
4555     "extra", FString;
4556   ];
4557
4558   (* Extended attribute. *)
4559   "xattr", [
4560     "attrname", FString;
4561     "attrval", FBuffer;
4562   ];
4563
4564   (* Inotify events. *)
4565   "inotify_event", [
4566     "in_wd", FInt64;
4567     "in_mask", FUInt32;
4568     "in_cookie", FUInt32;
4569     "in_name", FString;
4570   ];
4571
4572   (* Partition table entry. *)
4573   "partition", [
4574     "part_num", FInt32;
4575     "part_start", FBytes;
4576     "part_end", FBytes;
4577     "part_size", FBytes;
4578   ];
4579 ] (* end of structs *)
4580
4581 (* Ugh, Java has to be different ..
4582  * These names are also used by the Haskell bindings.
4583  *)
4584 let java_structs = [
4585   "int_bool", "IntBool";
4586   "lvm_pv", "PV";
4587   "lvm_vg", "VG";
4588   "lvm_lv", "LV";
4589   "stat", "Stat";
4590   "statvfs", "StatVFS";
4591   "dirent", "Dirent";
4592   "version", "Version";
4593   "xattr", "XAttr";
4594   "inotify_event", "INotifyEvent";
4595   "partition", "Partition";
4596 ]
4597
4598 (* What structs are actually returned. *)
4599 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4600
4601 (* Returns a list of RStruct/RStructList structs that are returned
4602  * by any function.  Each element of returned list is a pair:
4603  *
4604  * (structname, RStructOnly)
4605  *    == there exists function which returns RStruct (_, structname)
4606  * (structname, RStructListOnly)
4607  *    == there exists function which returns RStructList (_, structname)
4608  * (structname, RStructAndList)
4609  *    == there are functions returning both RStruct (_, structname)
4610  *                                      and RStructList (_, structname)
4611  *)
4612 let rstructs_used_by functions =
4613   (* ||| is a "logical OR" for rstructs_used_t *)
4614   let (|||) a b =
4615     match a, b with
4616     | RStructAndList, _
4617     | _, RStructAndList -> RStructAndList
4618     | RStructOnly, RStructListOnly
4619     | RStructListOnly, RStructOnly -> RStructAndList
4620     | RStructOnly, RStructOnly -> RStructOnly
4621     | RStructListOnly, RStructListOnly -> RStructListOnly
4622   in
4623
4624   let h = Hashtbl.create 13 in
4625
4626   (* if elem->oldv exists, update entry using ||| operator,
4627    * else just add elem->newv to the hash
4628    *)
4629   let update elem newv =
4630     try  let oldv = Hashtbl.find h elem in
4631          Hashtbl.replace h elem (newv ||| oldv)
4632     with Not_found -> Hashtbl.add h elem newv
4633   in
4634
4635   List.iter (
4636     fun (_, style, _, _, _, _, _) ->
4637       match fst style with
4638       | RStruct (_, structname) -> update structname RStructOnly
4639       | RStructList (_, structname) -> update structname RStructListOnly
4640       | _ -> ()
4641   ) functions;
4642
4643   (* return key->values as a list of (key,value) *)
4644   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4645
4646 (* Used for testing language bindings. *)
4647 type callt =
4648   | CallString of string
4649   | CallOptString of string option
4650   | CallStringList of string list
4651   | CallInt of int
4652   | CallInt64 of int64
4653   | CallBool of bool
4654
4655 (* Used to memoize the result of pod2text. *)
4656 let pod2text_memo_filename = "src/.pod2text.data"
4657 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4658   try
4659     let chan = open_in pod2text_memo_filename in
4660     let v = input_value chan in
4661     close_in chan;
4662     v
4663   with
4664     _ -> Hashtbl.create 13
4665 let pod2text_memo_updated () =
4666   let chan = open_out pod2text_memo_filename in
4667   output_value chan pod2text_memo;
4668   close_out chan
4669
4670 (* Useful functions.
4671  * Note we don't want to use any external OCaml libraries which
4672  * makes this a bit harder than it should be.
4673  *)
4674 module StringMap = Map.Make (String)
4675
4676 let failwithf fs = ksprintf failwith fs
4677
4678 let unique = let i = ref 0 in fun () -> incr i; !i
4679
4680 let replace_char s c1 c2 =
4681   let s2 = String.copy s in
4682   let r = ref false in
4683   for i = 0 to String.length s2 - 1 do
4684     if String.unsafe_get s2 i = c1 then (
4685       String.unsafe_set s2 i c2;
4686       r := true
4687     )
4688   done;
4689   if not !r then s else s2
4690
4691 let isspace c =
4692   c = ' '
4693   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4694
4695 let triml ?(test = isspace) str =
4696   let i = ref 0 in
4697   let n = ref (String.length str) in
4698   while !n > 0 && test str.[!i]; do
4699     decr n;
4700     incr i
4701   done;
4702   if !i = 0 then str
4703   else String.sub str !i !n
4704
4705 let trimr ?(test = isspace) str =
4706   let n = ref (String.length str) in
4707   while !n > 0 && test str.[!n-1]; do
4708     decr n
4709   done;
4710   if !n = String.length str then str
4711   else String.sub str 0 !n
4712
4713 let trim ?(test = isspace) str =
4714   trimr ~test (triml ~test str)
4715
4716 let rec find s sub =
4717   let len = String.length s in
4718   let sublen = String.length sub in
4719   let rec loop i =
4720     if i <= len-sublen then (
4721       let rec loop2 j =
4722         if j < sublen then (
4723           if s.[i+j] = sub.[j] then loop2 (j+1)
4724           else -1
4725         ) else
4726           i (* found *)
4727       in
4728       let r = loop2 0 in
4729       if r = -1 then loop (i+1) else r
4730     ) else
4731       -1 (* not found *)
4732   in
4733   loop 0
4734
4735 let rec replace_str s s1 s2 =
4736   let len = String.length s in
4737   let sublen = String.length s1 in
4738   let i = find s s1 in
4739   if i = -1 then s
4740   else (
4741     let s' = String.sub s 0 i in
4742     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4743     s' ^ s2 ^ replace_str s'' s1 s2
4744   )
4745
4746 let rec string_split sep str =
4747   let len = String.length str in
4748   let seplen = String.length sep in
4749   let i = find str sep in
4750   if i = -1 then [str]
4751   else (
4752     let s' = String.sub str 0 i in
4753     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4754     s' :: string_split sep s''
4755   )
4756
4757 let files_equal n1 n2 =
4758   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4759   match Sys.command cmd with
4760   | 0 -> true
4761   | 1 -> false
4762   | i -> failwithf "%s: failed with error code %d" cmd i
4763
4764 let rec filter_map f = function
4765   | [] -> []
4766   | x :: xs ->
4767       match f x with
4768       | Some y -> y :: filter_map f xs
4769       | None -> filter_map f xs
4770
4771 let rec find_map f = function
4772   | [] -> raise Not_found
4773   | x :: xs ->
4774       match f x with
4775       | Some y -> y
4776       | None -> find_map f xs
4777
4778 let iteri f xs =
4779   let rec loop i = function
4780     | [] -> ()
4781     | x :: xs -> f i x; loop (i+1) xs
4782   in
4783   loop 0 xs
4784
4785 let mapi f xs =
4786   let rec loop i = function
4787     | [] -> []
4788     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4789   in
4790   loop 0 xs
4791
4792 let count_chars c str =
4793   let count = ref 0 in
4794   for i = 0 to String.length str - 1 do
4795     if c = String.unsafe_get str i then incr count
4796   done;
4797   !count
4798
4799 let name_of_argt = function
4800   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4801   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4802   | FileIn n | FileOut n -> n
4803
4804 let java_name_of_struct typ =
4805   try List.assoc typ java_structs
4806   with Not_found ->
4807     failwithf
4808       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4809
4810 let cols_of_struct typ =
4811   try List.assoc typ structs
4812   with Not_found ->
4813     failwithf "cols_of_struct: unknown struct %s" typ
4814
4815 let seq_of_test = function
4816   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4817   | TestOutputListOfDevices (s, _)
4818   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4819   | TestOutputTrue s | TestOutputFalse s
4820   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4821   | TestOutputStruct (s, _)
4822   | TestLastFail s -> s
4823
4824 (* Handling for function flags. *)
4825 let protocol_limit_warning =
4826   "Because of the message protocol, there is a transfer limit
4827 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4828
4829 let danger_will_robinson =
4830   "B<This command is dangerous.  Without careful use you
4831 can easily destroy all your data>."
4832
4833 let deprecation_notice flags =
4834   try
4835     let alt =
4836       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4837     let txt =
4838       sprintf "This function is deprecated.
4839 In new code, use the C<%s> call instead.
4840
4841 Deprecated functions will not be removed from the API, but the
4842 fact that they are deprecated indicates that there are problems
4843 with correct use of these functions." alt in
4844     Some txt
4845   with
4846     Not_found -> None
4847
4848 (* Create list of optional groups. *)
4849 let optgroups =
4850   let h = Hashtbl.create 13 in
4851   List.iter (
4852     fun (name, _, _, flags, _, _, _) ->
4853       List.iter (
4854         function
4855         | Optional group ->
4856             let names = try Hashtbl.find h group with Not_found -> [] in
4857             Hashtbl.replace h group (name :: names)
4858         | _ -> ()
4859       ) flags
4860   ) daemon_functions;
4861   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4862   let groups =
4863     List.map (
4864       fun group -> group, List.sort compare (Hashtbl.find h group)
4865     ) groups in
4866   List.sort (fun x y -> compare (fst x) (fst y)) groups
4867
4868 (* Check function names etc. for consistency. *)
4869 let check_functions () =
4870   let contains_uppercase str =
4871     let len = String.length str in
4872     let rec loop i =
4873       if i >= len then false
4874       else (
4875         let c = str.[i] in
4876         if c >= 'A' && c <= 'Z' then true
4877         else loop (i+1)
4878       )
4879     in
4880     loop 0
4881   in
4882
4883   (* Check function names. *)
4884   List.iter (
4885     fun (name, _, _, _, _, _, _) ->
4886       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4887         failwithf "function name %s does not need 'guestfs' prefix" name;
4888       if name = "" then
4889         failwithf "function name is empty";
4890       if name.[0] < 'a' || name.[0] > 'z' then
4891         failwithf "function name %s must start with lowercase a-z" name;
4892       if String.contains name '-' then
4893         failwithf "function name %s should not contain '-', use '_' instead."
4894           name
4895   ) all_functions;
4896
4897   (* Check function parameter/return names. *)
4898   List.iter (
4899     fun (name, style, _, _, _, _, _) ->
4900       let check_arg_ret_name n =
4901         if contains_uppercase n then
4902           failwithf "%s param/ret %s should not contain uppercase chars"
4903             name n;
4904         if String.contains n '-' || String.contains n '_' then
4905           failwithf "%s param/ret %s should not contain '-' or '_'"
4906             name n;
4907         if n = "value" then
4908           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;
4909         if n = "int" || n = "char" || n = "short" || n = "long" then
4910           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4911         if n = "i" || n = "n" then
4912           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4913         if n = "argv" || n = "args" then
4914           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4915
4916         (* List Haskell, OCaml and C keywords here.
4917          * http://www.haskell.org/haskellwiki/Keywords
4918          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4919          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4920          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4921          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4922          * Omitting _-containing words, since they're handled above.
4923          * Omitting the OCaml reserved word, "val", is ok,
4924          * and saves us from renaming several parameters.
4925          *)
4926         let reserved = [
4927           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4928           "char"; "class"; "const"; "constraint"; "continue"; "data";
4929           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4930           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4931           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4932           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4933           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4934           "interface";
4935           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4936           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4937           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4938           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4939           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4940           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4941           "volatile"; "when"; "where"; "while";
4942           ] in
4943         if List.mem n reserved then
4944           failwithf "%s has param/ret using reserved word %s" name n;
4945       in
4946
4947       (match fst style with
4948        | RErr -> ()
4949        | RInt n | RInt64 n | RBool n
4950        | RConstString n | RConstOptString n | RString n
4951        | RStringList n | RStruct (n, _) | RStructList (n, _)
4952        | RHashtable n | RBufferOut n ->
4953            check_arg_ret_name n
4954       );
4955       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4956   ) all_functions;
4957
4958   (* Check short descriptions. *)
4959   List.iter (
4960     fun (name, _, _, _, _, shortdesc, _) ->
4961       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4962         failwithf "short description of %s should begin with lowercase." name;
4963       let c = shortdesc.[String.length shortdesc-1] in
4964       if c = '\n' || c = '.' then
4965         failwithf "short description of %s should not end with . or \\n." name
4966   ) all_functions;
4967
4968   (* Check long dscriptions. *)
4969   List.iter (
4970     fun (name, _, _, _, _, _, longdesc) ->
4971       if longdesc.[String.length longdesc-1] = '\n' then
4972         failwithf "long description of %s should not end with \\n." name
4973   ) all_functions;
4974
4975   (* Check proc_nrs. *)
4976   List.iter (
4977     fun (name, _, proc_nr, _, _, _, _) ->
4978       if proc_nr <= 0 then
4979         failwithf "daemon function %s should have proc_nr > 0" name
4980   ) daemon_functions;
4981
4982   List.iter (
4983     fun (name, _, proc_nr, _, _, _, _) ->
4984       if proc_nr <> -1 then
4985         failwithf "non-daemon function %s should have proc_nr -1" name
4986   ) non_daemon_functions;
4987
4988   let proc_nrs =
4989     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4990       daemon_functions in
4991   let proc_nrs =
4992     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4993   let rec loop = function
4994     | [] -> ()
4995     | [_] -> ()
4996     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4997         loop rest
4998     | (name1,nr1) :: (name2,nr2) :: _ ->
4999         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5000           name1 name2 nr1 nr2
5001   in
5002   loop proc_nrs;
5003
5004   (* Check tests. *)
5005   List.iter (
5006     function
5007       (* Ignore functions that have no tests.  We generate a
5008        * warning when the user does 'make check' instead.
5009        *)
5010     | name, _, _, _, [], _, _ -> ()
5011     | name, _, _, _, tests, _, _ ->
5012         let funcs =
5013           List.map (
5014             fun (_, _, test) ->
5015               match seq_of_test test with
5016               | [] ->
5017                   failwithf "%s has a test containing an empty sequence" name
5018               | cmds -> List.map List.hd cmds
5019           ) tests in
5020         let funcs = List.flatten funcs in
5021
5022         let tested = List.mem name funcs in
5023
5024         if not tested then
5025           failwithf "function %s has tests but does not test itself" name
5026   ) all_functions
5027
5028 (* 'pr' prints to the current output file. *)
5029 let chan = ref Pervasives.stdout
5030 let lines = ref 0
5031 let pr fs =
5032   ksprintf
5033     (fun str ->
5034        let i = count_chars '\n' str in
5035        lines := !lines + i;
5036        output_string !chan str
5037     ) fs
5038
5039 let copyright_years =
5040   let this_year = 1900 + (localtime (time ())).tm_year in
5041   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5042
5043 (* Generate a header block in a number of standard styles. *)
5044 type comment_style =
5045     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5046 type license = GPLv2plus | LGPLv2plus
5047
5048 let generate_header ?(extra_inputs = []) comment license =
5049   let inputs = "src/generator.ml" :: extra_inputs in
5050   let c = match comment with
5051     | CStyle ->         pr "/* "; " *"
5052     | CPlusPlusStyle -> pr "// "; "//"
5053     | HashStyle ->      pr "# ";  "#"
5054     | OCamlStyle ->     pr "(* "; " *"
5055     | HaskellStyle ->   pr "{- "; "  " in
5056   pr "libguestfs generated file\n";
5057   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5058   List.iter (pr "%s   %s\n" c) inputs;
5059   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5060   pr "%s\n" c;
5061   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5062   pr "%s\n" c;
5063   (match license with
5064    | GPLv2plus ->
5065        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5066        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5067        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5068        pr "%s (at your option) any later version.\n" c;
5069        pr "%s\n" c;
5070        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5071        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5072        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5073        pr "%s GNU General Public License for more details.\n" c;
5074        pr "%s\n" c;
5075        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5076        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5077        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5078
5079    | LGPLv2plus ->
5080        pr "%s This library is free software; you can redistribute it and/or\n" c;
5081        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5082        pr "%s License as published by the Free Software Foundation; either\n" c;
5083        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5084        pr "%s\n" c;
5085        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5086        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5087        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5088        pr "%s Lesser General Public License for more details.\n" c;
5089        pr "%s\n" c;
5090        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5091        pr "%s License along with this library; if not, write to the Free Software\n" c;
5092        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5093   );
5094   (match comment with
5095    | CStyle -> pr " */\n"
5096    | CPlusPlusStyle
5097    | HashStyle -> ()
5098    | OCamlStyle -> pr " *)\n"
5099    | HaskellStyle -> pr "-}\n"
5100   );
5101   pr "\n"
5102
5103 (* Start of main code generation functions below this line. *)
5104
5105 (* Generate the pod documentation for the C API. *)
5106 let rec generate_actions_pod () =
5107   List.iter (
5108     fun (shortname, style, _, flags, _, _, longdesc) ->
5109       if not (List.mem NotInDocs flags) then (
5110         let name = "guestfs_" ^ shortname in
5111         pr "=head2 %s\n\n" name;
5112         pr " ";
5113         generate_prototype ~extern:false ~handle:"handle" name style;
5114         pr "\n\n";
5115         pr "%s\n\n" longdesc;
5116         (match fst style with
5117          | RErr ->
5118              pr "This function returns 0 on success or -1 on error.\n\n"
5119          | RInt _ ->
5120              pr "On error this function returns -1.\n\n"
5121          | RInt64 _ ->
5122              pr "On error this function returns -1.\n\n"
5123          | RBool _ ->
5124              pr "This function returns a C truth value on success or -1 on error.\n\n"
5125          | RConstString _ ->
5126              pr "This function returns a string, or NULL on error.
5127 The string is owned by the guest handle and must I<not> be freed.\n\n"
5128          | RConstOptString _ ->
5129              pr "This function returns a string which may be NULL.
5130 There is way to return an error from this function.
5131 The string is owned by the guest handle and must I<not> be freed.\n\n"
5132          | RString _ ->
5133              pr "This function returns a string, or NULL on error.
5134 I<The caller must free the returned string after use>.\n\n"
5135          | RStringList _ ->
5136              pr "This function returns a NULL-terminated array of strings
5137 (like L<environ(3)>), or NULL if there was an error.
5138 I<The caller must free the strings and the array after use>.\n\n"
5139          | RStruct (_, typ) ->
5140              pr "This function returns a C<struct guestfs_%s *>,
5141 or NULL if there was an error.
5142 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5143          | RStructList (_, typ) ->
5144              pr "This function returns a C<struct guestfs_%s_list *>
5145 (see E<lt>guestfs-structs.hE<gt>),
5146 or NULL if there was an error.
5147 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5148          | RHashtable _ ->
5149              pr "This function returns a NULL-terminated array of
5150 strings, or NULL if there was an error.
5151 The array of strings will always have length C<2n+1>, where
5152 C<n> keys and values alternate, followed by the trailing NULL entry.
5153 I<The caller must free the strings and the array after use>.\n\n"
5154          | RBufferOut _ ->
5155              pr "This function returns a buffer, or NULL on error.
5156 The size of the returned buffer is written to C<*size_r>.
5157 I<The caller must free the returned buffer after use>.\n\n"
5158         );
5159         if List.mem ProtocolLimitWarning flags then
5160           pr "%s\n\n" protocol_limit_warning;
5161         if List.mem DangerWillRobinson flags then
5162           pr "%s\n\n" danger_will_robinson;
5163         match deprecation_notice flags with
5164         | None -> ()
5165         | Some txt -> pr "%s\n\n" txt
5166       )
5167   ) all_functions_sorted
5168
5169 and generate_structs_pod () =
5170   (* Structs documentation. *)
5171   List.iter (
5172     fun (typ, cols) ->
5173       pr "=head2 guestfs_%s\n" typ;
5174       pr "\n";
5175       pr " struct guestfs_%s {\n" typ;
5176       List.iter (
5177         function
5178         | name, FChar -> pr "   char %s;\n" name
5179         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5180         | name, FInt32 -> pr "   int32_t %s;\n" name
5181         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5182         | name, FInt64 -> pr "   int64_t %s;\n" name
5183         | name, FString -> pr "   char *%s;\n" name
5184         | name, FBuffer ->
5185             pr "   /* The next two fields describe a byte array. */\n";
5186             pr "   uint32_t %s_len;\n" name;
5187             pr "   char *%s;\n" name
5188         | name, FUUID ->
5189             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5190             pr "   char %s[32];\n" name
5191         | name, FOptPercent ->
5192             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5193             pr "   float %s;\n" name
5194       ) cols;
5195       pr " };\n";
5196       pr " \n";
5197       pr " struct guestfs_%s_list {\n" typ;
5198       pr "   uint32_t len; /* Number of elements in list. */\n";
5199       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5200       pr " };\n";
5201       pr " \n";
5202       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5203       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5204         typ typ;
5205       pr "\n"
5206   ) structs
5207
5208 and generate_availability_pod () =
5209   (* Availability documentation. *)
5210   pr "=over 4\n";
5211   pr "\n";
5212   List.iter (
5213     fun (group, functions) ->
5214       pr "=item B<%s>\n" group;
5215       pr "\n";
5216       pr "The following functions:\n";
5217       List.iter (pr "L</guestfs_%s>\n") functions;
5218       pr "\n"
5219   ) optgroups;
5220   pr "=back\n";
5221   pr "\n"
5222
5223 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5224  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5225  *
5226  * We have to use an underscore instead of a dash because otherwise
5227  * rpcgen generates incorrect code.
5228  *
5229  * This header is NOT exported to clients, but see also generate_structs_h.
5230  *)
5231 and generate_xdr () =
5232   generate_header CStyle LGPLv2plus;
5233
5234   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5235   pr "typedef string str<>;\n";
5236   pr "\n";
5237
5238   (* Internal structures. *)
5239   List.iter (
5240     function
5241     | typ, cols ->
5242         pr "struct guestfs_int_%s {\n" typ;
5243         List.iter (function
5244                    | name, FChar -> pr "  char %s;\n" name
5245                    | name, FString -> pr "  string %s<>;\n" name
5246                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5247                    | name, FUUID -> pr "  opaque %s[32];\n" name
5248                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5249                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5250                    | name, FOptPercent -> pr "  float %s;\n" name
5251                   ) cols;
5252         pr "};\n";
5253         pr "\n";
5254         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5255         pr "\n";
5256   ) structs;
5257
5258   List.iter (
5259     fun (shortname, style, _, _, _, _, _) ->
5260       let name = "guestfs_" ^ shortname in
5261
5262       (match snd style with
5263        | [] -> ()
5264        | args ->
5265            pr "struct %s_args {\n" name;
5266            List.iter (
5267              function
5268              | Pathname n | Device n | Dev_or_Path n | String n ->
5269                  pr "  string %s<>;\n" n
5270              | OptString n -> pr "  str *%s;\n" n
5271              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5272              | Bool n -> pr "  bool %s;\n" n
5273              | Int n -> pr "  int %s;\n" n
5274              | Int64 n -> pr "  hyper %s;\n" n
5275              | FileIn _ | FileOut _ -> ()
5276            ) args;
5277            pr "};\n\n"
5278       );
5279       (match fst style with
5280        | RErr -> ()
5281        | RInt n ->
5282            pr "struct %s_ret {\n" name;
5283            pr "  int %s;\n" n;
5284            pr "};\n\n"
5285        | RInt64 n ->
5286            pr "struct %s_ret {\n" name;
5287            pr "  hyper %s;\n" n;
5288            pr "};\n\n"
5289        | RBool n ->
5290            pr "struct %s_ret {\n" name;
5291            pr "  bool %s;\n" n;
5292            pr "};\n\n"
5293        | RConstString _ | RConstOptString _ ->
5294            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5295        | RString n ->
5296            pr "struct %s_ret {\n" name;
5297            pr "  string %s<>;\n" n;
5298            pr "};\n\n"
5299        | RStringList n ->
5300            pr "struct %s_ret {\n" name;
5301            pr "  str %s<>;\n" n;
5302            pr "};\n\n"
5303        | RStruct (n, typ) ->
5304            pr "struct %s_ret {\n" name;
5305            pr "  guestfs_int_%s %s;\n" typ n;
5306            pr "};\n\n"
5307        | RStructList (n, typ) ->
5308            pr "struct %s_ret {\n" name;
5309            pr "  guestfs_int_%s_list %s;\n" typ n;
5310            pr "};\n\n"
5311        | RHashtable n ->
5312            pr "struct %s_ret {\n" name;
5313            pr "  str %s<>;\n" n;
5314            pr "};\n\n"
5315        | RBufferOut n ->
5316            pr "struct %s_ret {\n" name;
5317            pr "  opaque %s<>;\n" n;
5318            pr "};\n\n"
5319       );
5320   ) daemon_functions;
5321
5322   (* Table of procedure numbers. *)
5323   pr "enum guestfs_procedure {\n";
5324   List.iter (
5325     fun (shortname, _, proc_nr, _, _, _, _) ->
5326       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5327   ) daemon_functions;
5328   pr "  GUESTFS_PROC_NR_PROCS\n";
5329   pr "};\n";
5330   pr "\n";
5331
5332   (* Having to choose a maximum message size is annoying for several
5333    * reasons (it limits what we can do in the API), but it (a) makes
5334    * the protocol a lot simpler, and (b) provides a bound on the size
5335    * of the daemon which operates in limited memory space.
5336    *)
5337   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5338   pr "\n";
5339
5340   (* Message header, etc. *)
5341   pr "\
5342 /* The communication protocol is now documented in the guestfs(3)
5343  * manpage.
5344  */
5345
5346 const GUESTFS_PROGRAM = 0x2000F5F5;
5347 const GUESTFS_PROTOCOL_VERSION = 1;
5348
5349 /* These constants must be larger than any possible message length. */
5350 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5351 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5352
5353 enum guestfs_message_direction {
5354   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5355   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5356 };
5357
5358 enum guestfs_message_status {
5359   GUESTFS_STATUS_OK = 0,
5360   GUESTFS_STATUS_ERROR = 1
5361 };
5362
5363 const GUESTFS_ERROR_LEN = 256;
5364
5365 struct guestfs_message_error {
5366   string error_message<GUESTFS_ERROR_LEN>;
5367 };
5368
5369 struct guestfs_message_header {
5370   unsigned prog;                     /* GUESTFS_PROGRAM */
5371   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5372   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5373   guestfs_message_direction direction;
5374   unsigned serial;                   /* message serial number */
5375   guestfs_message_status status;
5376 };
5377
5378 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5379
5380 struct guestfs_chunk {
5381   int cancel;                        /* if non-zero, transfer is cancelled */
5382   /* data size is 0 bytes if the transfer has finished successfully */
5383   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5384 };
5385 "
5386
5387 (* Generate the guestfs-structs.h file. *)
5388 and generate_structs_h () =
5389   generate_header CStyle LGPLv2plus;
5390
5391   (* This is a public exported header file containing various
5392    * structures.  The structures are carefully written to have
5393    * exactly the same in-memory format as the XDR structures that
5394    * we use on the wire to the daemon.  The reason for creating
5395    * copies of these structures here is just so we don't have to
5396    * export the whole of guestfs_protocol.h (which includes much
5397    * unrelated and XDR-dependent stuff that we don't want to be
5398    * public, or required by clients).
5399    *
5400    * To reiterate, we will pass these structures to and from the
5401    * client with a simple assignment or memcpy, so the format
5402    * must be identical to what rpcgen / the RFC defines.
5403    *)
5404
5405   (* Public structures. *)
5406   List.iter (
5407     fun (typ, cols) ->
5408       pr "struct guestfs_%s {\n" typ;
5409       List.iter (
5410         function
5411         | name, FChar -> pr "  char %s;\n" name
5412         | name, FString -> pr "  char *%s;\n" name
5413         | name, FBuffer ->
5414             pr "  uint32_t %s_len;\n" name;
5415             pr "  char *%s;\n" name
5416         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5417         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5418         | name, FInt32 -> pr "  int32_t %s;\n" name
5419         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5420         | name, FInt64 -> pr "  int64_t %s;\n" name
5421         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5422       ) cols;
5423       pr "};\n";
5424       pr "\n";
5425       pr "struct guestfs_%s_list {\n" typ;
5426       pr "  uint32_t len;\n";
5427       pr "  struct guestfs_%s *val;\n" typ;
5428       pr "};\n";
5429       pr "\n";
5430       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5431       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5432       pr "\n"
5433   ) structs
5434
5435 (* Generate the guestfs-actions.h file. *)
5436 and generate_actions_h () =
5437   generate_header CStyle LGPLv2plus;
5438   List.iter (
5439     fun (shortname, style, _, _, _, _, _) ->
5440       let name = "guestfs_" ^ shortname in
5441       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5442         name style
5443   ) all_functions
5444
5445 (* Generate the guestfs-internal-actions.h file. *)
5446 and generate_internal_actions_h () =
5447   generate_header CStyle LGPLv2plus;
5448   List.iter (
5449     fun (shortname, style, _, _, _, _, _) ->
5450       let name = "guestfs__" ^ shortname in
5451       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5452         name style
5453   ) non_daemon_functions
5454
5455 (* Generate the client-side dispatch stubs. *)
5456 and generate_client_actions () =
5457   generate_header CStyle LGPLv2plus;
5458
5459   pr "\
5460 #include <stdio.h>
5461 #include <stdlib.h>
5462 #include <stdint.h>
5463 #include <string.h>
5464 #include <inttypes.h>
5465
5466 #include \"guestfs.h\"
5467 #include \"guestfs-internal.h\"
5468 #include \"guestfs-internal-actions.h\"
5469 #include \"guestfs_protocol.h\"
5470
5471 #define error guestfs_error
5472 //#define perrorf guestfs_perrorf
5473 #define safe_malloc guestfs_safe_malloc
5474 #define safe_realloc guestfs_safe_realloc
5475 //#define safe_strdup guestfs_safe_strdup
5476 #define safe_memdup guestfs_safe_memdup
5477
5478 /* Check the return message from a call for validity. */
5479 static int
5480 check_reply_header (guestfs_h *g,
5481                     const struct guestfs_message_header *hdr,
5482                     unsigned int proc_nr, unsigned int serial)
5483 {
5484   if (hdr->prog != GUESTFS_PROGRAM) {
5485     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5486     return -1;
5487   }
5488   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5489     error (g, \"wrong protocol version (%%d/%%d)\",
5490            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5491     return -1;
5492   }
5493   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5494     error (g, \"unexpected message direction (%%d/%%d)\",
5495            hdr->direction, GUESTFS_DIRECTION_REPLY);
5496     return -1;
5497   }
5498   if (hdr->proc != proc_nr) {
5499     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5500     return -1;
5501   }
5502   if (hdr->serial != serial) {
5503     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5504     return -1;
5505   }
5506
5507   return 0;
5508 }
5509
5510 /* Check we are in the right state to run a high-level action. */
5511 static int
5512 check_state (guestfs_h *g, const char *caller)
5513 {
5514   if (!guestfs__is_ready (g)) {
5515     if (guestfs__is_config (g) || guestfs__is_launching (g))
5516       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5517         caller);
5518     else
5519       error (g, \"%%s called from the wrong state, %%d != READY\",
5520         caller, guestfs__get_state (g));
5521     return -1;
5522   }
5523   return 0;
5524 }
5525
5526 ";
5527
5528   (* Generate code to generate guestfish call traces. *)
5529   let trace_call shortname style =
5530     pr "  if (guestfs__get_trace (g)) {\n";
5531
5532     let needs_i =
5533       List.exists (function
5534                    | StringList _ | DeviceList _ -> true
5535                    | _ -> false) (snd style) in
5536     if needs_i then (
5537       pr "    int i;\n";
5538       pr "\n"
5539     );
5540
5541     pr "    printf (\"%s\");\n" shortname;
5542     List.iter (
5543       function
5544       | String n                        (* strings *)
5545       | Device n
5546       | Pathname n
5547       | Dev_or_Path n
5548       | FileIn n
5549       | FileOut n ->
5550           (* guestfish doesn't support string escaping, so neither do we *)
5551           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5552       | OptString n ->                  (* string option *)
5553           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5554           pr "    else printf (\" null\");\n"
5555       | StringList n
5556       | DeviceList n ->                 (* string list *)
5557           pr "    putchar (' ');\n";
5558           pr "    putchar ('\"');\n";
5559           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5560           pr "      if (i > 0) putchar (' ');\n";
5561           pr "      fputs (%s[i], stdout);\n" n;
5562           pr "    }\n";
5563           pr "    putchar ('\"');\n";
5564       | Bool n ->                       (* boolean *)
5565           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5566       | Int n ->                        (* int *)
5567           pr "    printf (\" %%d\", %s);\n" n
5568       | Int64 n ->
5569           pr "    printf (\" %%\" PRIi64, %s);\n" n
5570     ) (snd style);
5571     pr "    putchar ('\\n');\n";
5572     pr "  }\n";
5573     pr "\n";
5574   in
5575
5576   (* For non-daemon functions, generate a wrapper around each function. *)
5577   List.iter (
5578     fun (shortname, style, _, _, _, _, _) ->
5579       let name = "guestfs_" ^ shortname in
5580
5581       generate_prototype ~extern:false ~semicolon:false ~newline:true
5582         ~handle:"g" name style;
5583       pr "{\n";
5584       trace_call shortname style;
5585       pr "  return guestfs__%s " shortname;
5586       generate_c_call_args ~handle:"g" style;
5587       pr ";\n";
5588       pr "}\n";
5589       pr "\n"
5590   ) non_daemon_functions;
5591
5592   (* Client-side stubs for each function. *)
5593   List.iter (
5594     fun (shortname, style, _, _, _, _, _) ->
5595       let name = "guestfs_" ^ shortname in
5596
5597       (* Generate the action stub. *)
5598       generate_prototype ~extern:false ~semicolon:false ~newline:true
5599         ~handle:"g" name style;
5600
5601       let error_code =
5602         match fst style with
5603         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5604         | RConstString _ | RConstOptString _ ->
5605             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5606         | RString _ | RStringList _
5607         | RStruct _ | RStructList _
5608         | RHashtable _ | RBufferOut _ ->
5609             "NULL" in
5610
5611       pr "{\n";
5612
5613       (match snd style with
5614        | [] -> ()
5615        | _ -> pr "  struct %s_args args;\n" name
5616       );
5617
5618       pr "  guestfs_message_header hdr;\n";
5619       pr "  guestfs_message_error err;\n";
5620       let has_ret =
5621         match fst style with
5622         | RErr -> false
5623         | RConstString _ | RConstOptString _ ->
5624             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5625         | RInt _ | RInt64 _
5626         | RBool _ | RString _ | RStringList _
5627         | RStruct _ | RStructList _
5628         | RHashtable _ | RBufferOut _ ->
5629             pr "  struct %s_ret ret;\n" name;
5630             true in
5631
5632       pr "  int serial;\n";
5633       pr "  int r;\n";
5634       pr "\n";
5635       trace_call shortname style;
5636       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5637       pr "  guestfs___set_busy (g);\n";
5638       pr "\n";
5639
5640       (* Send the main header and arguments. *)
5641       (match snd style with
5642        | [] ->
5643            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5644              (String.uppercase shortname)
5645        | args ->
5646            List.iter (
5647              function
5648              | Pathname n | Device n | Dev_or_Path n | String n ->
5649                  pr "  args.%s = (char *) %s;\n" n n
5650              | OptString n ->
5651                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5652              | StringList n | DeviceList n ->
5653                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5654                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5655              | Bool n ->
5656                  pr "  args.%s = %s;\n" n n
5657              | Int n ->
5658                  pr "  args.%s = %s;\n" n n
5659              | Int64 n ->
5660                  pr "  args.%s = %s;\n" n n
5661              | FileIn _ | FileOut _ -> ()
5662            ) args;
5663            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5664              (String.uppercase shortname);
5665            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5666              name;
5667       );
5668       pr "  if (serial == -1) {\n";
5669       pr "    guestfs___end_busy (g);\n";
5670       pr "    return %s;\n" error_code;
5671       pr "  }\n";
5672       pr "\n";
5673
5674       (* Send any additional files (FileIn) requested. *)
5675       let need_read_reply_label = ref false in
5676       List.iter (
5677         function
5678         | FileIn n ->
5679             pr "  r = guestfs___send_file (g, %s);\n" n;
5680             pr "  if (r == -1) {\n";
5681             pr "    guestfs___end_busy (g);\n";
5682             pr "    return %s;\n" error_code;
5683             pr "  }\n";
5684             pr "  if (r == -2) /* daemon cancelled */\n";
5685             pr "    goto read_reply;\n";
5686             need_read_reply_label := true;
5687             pr "\n";
5688         | _ -> ()
5689       ) (snd style);
5690
5691       (* Wait for the reply from the remote end. *)
5692       if !need_read_reply_label then pr " read_reply:\n";
5693       pr "  memset (&hdr, 0, sizeof hdr);\n";
5694       pr "  memset (&err, 0, sizeof err);\n";
5695       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5696       pr "\n";
5697       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5698       if not has_ret then
5699         pr "NULL, NULL"
5700       else
5701         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5702       pr ");\n";
5703
5704       pr "  if (r == -1) {\n";
5705       pr "    guestfs___end_busy (g);\n";
5706       pr "    return %s;\n" error_code;
5707       pr "  }\n";
5708       pr "\n";
5709
5710       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5711         (String.uppercase shortname);
5712       pr "    guestfs___end_busy (g);\n";
5713       pr "    return %s;\n" error_code;
5714       pr "  }\n";
5715       pr "\n";
5716
5717       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5718       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5719       pr "    free (err.error_message);\n";
5720       pr "    guestfs___end_busy (g);\n";
5721       pr "    return %s;\n" error_code;
5722       pr "  }\n";
5723       pr "\n";
5724
5725       (* Expecting to receive further files (FileOut)? *)
5726       List.iter (
5727         function
5728         | FileOut n ->
5729             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5730             pr "    guestfs___end_busy (g);\n";
5731             pr "    return %s;\n" error_code;
5732             pr "  }\n";
5733             pr "\n";
5734         | _ -> ()
5735       ) (snd style);
5736
5737       pr "  guestfs___end_busy (g);\n";
5738
5739       (match fst style with
5740        | RErr -> pr "  return 0;\n"
5741        | RInt n | RInt64 n | RBool n ->
5742            pr "  return ret.%s;\n" n
5743        | RConstString _ | RConstOptString _ ->
5744            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5745        | RString n ->
5746            pr "  return ret.%s; /* caller will free */\n" n
5747        | RStringList n | RHashtable n ->
5748            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5749            pr "  ret.%s.%s_val =\n" n n;
5750            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5751            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5752              n n;
5753            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5754            pr "  return ret.%s.%s_val;\n" n n
5755        | RStruct (n, _) ->
5756            pr "  /* caller will free this */\n";
5757            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5758        | RStructList (n, _) ->
5759            pr "  /* caller will free this */\n";
5760            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5761        | RBufferOut n ->
5762            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5763            pr "   * _val might be NULL here.  To make the API saner for\n";
5764            pr "   * callers, we turn this case into a unique pointer (using\n";
5765            pr "   * malloc(1)).\n";
5766            pr "   */\n";
5767            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5768            pr "    *size_r = ret.%s.%s_len;\n" n n;
5769            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5770            pr "  } else {\n";
5771            pr "    free (ret.%s.%s_val);\n" n n;
5772            pr "    char *p = safe_malloc (g, 1);\n";
5773            pr "    *size_r = ret.%s.%s_len;\n" n n;
5774            pr "    return p;\n";
5775            pr "  }\n";
5776       );
5777
5778       pr "}\n\n"
5779   ) daemon_functions;
5780
5781   (* Functions to free structures. *)
5782   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5783   pr " * structure format is identical to the XDR format.  See note in\n";
5784   pr " * generator.ml.\n";
5785   pr " */\n";
5786   pr "\n";
5787
5788   List.iter (
5789     fun (typ, _) ->
5790       pr "void\n";
5791       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5792       pr "{\n";
5793       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5794       pr "  free (x);\n";
5795       pr "}\n";
5796       pr "\n";
5797
5798       pr "void\n";
5799       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5800       pr "{\n";
5801       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5802       pr "  free (x);\n";
5803       pr "}\n";
5804       pr "\n";
5805
5806   ) structs;
5807
5808 (* Generate daemon/actions.h. *)
5809 and generate_daemon_actions_h () =
5810   generate_header CStyle GPLv2plus;
5811
5812   pr "#include \"../src/guestfs_protocol.h\"\n";
5813   pr "\n";
5814
5815   List.iter (
5816     fun (name, style, _, _, _, _, _) ->
5817       generate_prototype
5818         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5819         name style;
5820   ) daemon_functions
5821
5822 (* Generate the linker script which controls the visibility of
5823  * symbols in the public ABI and ensures no other symbols get
5824  * exported accidentally.
5825  *)
5826 and generate_linker_script () =
5827   generate_header HashStyle GPLv2plus;
5828
5829   let globals = [
5830     "guestfs_create";
5831     "guestfs_close";
5832     "guestfs_get_error_handler";
5833     "guestfs_get_out_of_memory_handler";
5834     "guestfs_last_error";
5835     "guestfs_set_error_handler";
5836     "guestfs_set_launch_done_callback";
5837     "guestfs_set_log_message_callback";
5838     "guestfs_set_out_of_memory_handler";
5839     "guestfs_set_subprocess_quit_callback";
5840
5841     (* Unofficial parts of the API: the bindings code use these
5842      * functions, so it is useful to export them.
5843      *)
5844     "guestfs_safe_calloc";
5845     "guestfs_safe_malloc";
5846   ] in
5847   let functions =
5848     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5849       all_functions in
5850   let structs =
5851     List.concat (
5852       List.map (fun (typ, _) ->
5853                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5854         structs
5855     ) in
5856   let globals = List.sort compare (globals @ functions @ structs) in
5857
5858   pr "{\n";
5859   pr "    global:\n";
5860   List.iter (pr "        %s;\n") globals;
5861   pr "\n";
5862
5863   pr "    local:\n";
5864   pr "        *;\n";
5865   pr "};\n"
5866
5867 (* Generate the server-side stubs. *)
5868 and generate_daemon_actions () =
5869   generate_header CStyle GPLv2plus;
5870
5871   pr "#include <config.h>\n";
5872   pr "\n";
5873   pr "#include <stdio.h>\n";
5874   pr "#include <stdlib.h>\n";
5875   pr "#include <string.h>\n";
5876   pr "#include <inttypes.h>\n";
5877   pr "#include <rpc/types.h>\n";
5878   pr "#include <rpc/xdr.h>\n";
5879   pr "\n";
5880   pr "#include \"daemon.h\"\n";
5881   pr "#include \"c-ctype.h\"\n";
5882   pr "#include \"../src/guestfs_protocol.h\"\n";
5883   pr "#include \"actions.h\"\n";
5884   pr "\n";
5885
5886   List.iter (
5887     fun (name, style, _, _, _, _, _) ->
5888       (* Generate server-side stubs. *)
5889       pr "static void %s_stub (XDR *xdr_in)\n" name;
5890       pr "{\n";
5891       let error_code =
5892         match fst style with
5893         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5894         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5895         | RBool _ -> pr "  int r;\n"; "-1"
5896         | RConstString _ | RConstOptString _ ->
5897             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5898         | RString _ -> pr "  char *r;\n"; "NULL"
5899         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5900         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5901         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5902         | RBufferOut _ ->
5903             pr "  size_t size = 1;\n";
5904             pr "  char *r;\n";
5905             "NULL" in
5906
5907       (match snd style with
5908        | [] -> ()
5909        | args ->
5910            pr "  struct guestfs_%s_args args;\n" name;
5911            List.iter (
5912              function
5913              | Device n | Dev_or_Path n
5914              | Pathname n
5915              | String n -> ()
5916              | OptString n -> pr "  char *%s;\n" n
5917              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5918              | Bool n -> pr "  int %s;\n" n
5919              | Int n -> pr "  int %s;\n" n
5920              | Int64 n -> pr "  int64_t %s;\n" n
5921              | FileIn _ | FileOut _ -> ()
5922            ) args
5923       );
5924       pr "\n";
5925
5926       (match snd style with
5927        | [] -> ()
5928        | args ->
5929            pr "  memset (&args, 0, sizeof args);\n";
5930            pr "\n";
5931            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5932            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5933            pr "    return;\n";
5934            pr "  }\n";
5935            let pr_args n =
5936              pr "  char *%s = args.%s;\n" n n
5937            in
5938            let pr_list_handling_code n =
5939              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5940              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5941              pr "  if (%s == NULL) {\n" n;
5942              pr "    reply_with_perror (\"realloc\");\n";
5943              pr "    goto done;\n";
5944              pr "  }\n";
5945              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5946              pr "  args.%s.%s_val = %s;\n" n n n;
5947            in
5948            List.iter (
5949              function
5950              | Pathname n ->
5951                  pr_args n;
5952                  pr "  ABS_PATH (%s, goto done);\n" n;
5953              | Device n ->
5954                  pr_args n;
5955                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5956              | Dev_or_Path n ->
5957                  pr_args n;
5958                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5959              | String n -> pr_args n
5960              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5961              | StringList n ->
5962                  pr_list_handling_code n;
5963              | DeviceList n ->
5964                  pr_list_handling_code n;
5965                  pr "  /* Ensure that each is a device,\n";
5966                  pr "   * and perform device name translation. */\n";
5967                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5968                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5969                  pr "  }\n";
5970              | Bool n -> pr "  %s = args.%s;\n" n n
5971              | Int n -> pr "  %s = args.%s;\n" n n
5972              | Int64 n -> pr "  %s = args.%s;\n" n n
5973              | FileIn _ | FileOut _ -> ()
5974            ) args;
5975            pr "\n"
5976       );
5977
5978
5979       (* this is used at least for do_equal *)
5980       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5981         (* Emit NEED_ROOT just once, even when there are two or
5982            more Pathname args *)
5983         pr "  NEED_ROOT (goto done);\n";
5984       );
5985
5986       (* Don't want to call the impl with any FileIn or FileOut
5987        * parameters, since these go "outside" the RPC protocol.
5988        *)
5989       let args' =
5990         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5991           (snd style) in
5992       pr "  r = do_%s " name;
5993       generate_c_call_args (fst style, args');
5994       pr ";\n";
5995
5996       (match fst style with
5997        | RErr | RInt _ | RInt64 _ | RBool _
5998        | RConstString _ | RConstOptString _
5999        | RString _ | RStringList _ | RHashtable _
6000        | RStruct (_, _) | RStructList (_, _) ->
6001            pr "  if (r == %s)\n" error_code;
6002            pr "    /* do_%s has already called reply_with_error */\n" name;
6003            pr "    goto done;\n";
6004            pr "\n"
6005        | RBufferOut _ ->
6006            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6007            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6008            pr "   */\n";
6009            pr "  if (size == 1 && r == %s)\n" error_code;
6010            pr "    /* do_%s has already called reply_with_error */\n" name;
6011            pr "    goto done;\n";
6012            pr "\n"
6013       );
6014
6015       (* If there are any FileOut parameters, then the impl must
6016        * send its own reply.
6017        *)
6018       let no_reply =
6019         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6020       if no_reply then
6021         pr "  /* do_%s has already sent a reply */\n" name
6022       else (
6023         match fst style with
6024         | RErr -> pr "  reply (NULL, NULL);\n"
6025         | RInt n | RInt64 n | RBool n ->
6026             pr "  struct guestfs_%s_ret ret;\n" name;
6027             pr "  ret.%s = r;\n" n;
6028             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6029               name
6030         | RConstString _ | RConstOptString _ ->
6031             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6032         | RString n ->
6033             pr "  struct guestfs_%s_ret ret;\n" name;
6034             pr "  ret.%s = r;\n" n;
6035             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6036               name;
6037             pr "  free (r);\n"
6038         | RStringList n | RHashtable n ->
6039             pr "  struct guestfs_%s_ret ret;\n" name;
6040             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6041             pr "  ret.%s.%s_val = r;\n" n n;
6042             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6043               name;
6044             pr "  free_strings (r);\n"
6045         | RStruct (n, _) ->
6046             pr "  struct guestfs_%s_ret ret;\n" name;
6047             pr "  ret.%s = *r;\n" n;
6048             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6049               name;
6050             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6051               name
6052         | RStructList (n, _) ->
6053             pr "  struct guestfs_%s_ret ret;\n" name;
6054             pr "  ret.%s = *r;\n" n;
6055             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6056               name;
6057             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6058               name
6059         | RBufferOut n ->
6060             pr "  struct guestfs_%s_ret ret;\n" name;
6061             pr "  ret.%s.%s_val = r;\n" n n;
6062             pr "  ret.%s.%s_len = size;\n" n n;
6063             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6064               name;
6065             pr "  free (r);\n"
6066       );
6067
6068       (* Free the args. *)
6069       (match snd style with
6070        | [] ->
6071            pr "done: ;\n";
6072        | _ ->
6073            pr "done:\n";
6074            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6075              name
6076       );
6077
6078       pr "}\n\n";
6079   ) daemon_functions;
6080
6081   (* Dispatch function. *)
6082   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6083   pr "{\n";
6084   pr "  switch (proc_nr) {\n";
6085
6086   List.iter (
6087     fun (name, style, _, _, _, _, _) ->
6088       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6089       pr "      %s_stub (xdr_in);\n" name;
6090       pr "      break;\n"
6091   ) daemon_functions;
6092
6093   pr "    default:\n";
6094   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";
6095   pr "  }\n";
6096   pr "}\n";
6097   pr "\n";
6098
6099   (* LVM columns and tokenization functions. *)
6100   (* XXX This generates crap code.  We should rethink how we
6101    * do this parsing.
6102    *)
6103   List.iter (
6104     function
6105     | typ, cols ->
6106         pr "static const char *lvm_%s_cols = \"%s\";\n"
6107           typ (String.concat "," (List.map fst cols));
6108         pr "\n";
6109
6110         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6111         pr "{\n";
6112         pr "  char *tok, *p, *next;\n";
6113         pr "  int i, j;\n";
6114         pr "\n";
6115         (*
6116           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6117           pr "\n";
6118         *)
6119         pr "  if (!str) {\n";
6120         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6121         pr "    return -1;\n";
6122         pr "  }\n";
6123         pr "  if (!*str || c_isspace (*str)) {\n";
6124         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6125         pr "    return -1;\n";
6126         pr "  }\n";
6127         pr "  tok = str;\n";
6128         List.iter (
6129           fun (name, coltype) ->
6130             pr "  if (!tok) {\n";
6131             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6132             pr "    return -1;\n";
6133             pr "  }\n";
6134             pr "  p = strchrnul (tok, ',');\n";
6135             pr "  if (*p) next = p+1; else next = NULL;\n";
6136             pr "  *p = '\\0';\n";
6137             (match coltype with
6138              | FString ->
6139                  pr "  r->%s = strdup (tok);\n" name;
6140                  pr "  if (r->%s == NULL) {\n" name;
6141                  pr "    perror (\"strdup\");\n";
6142                  pr "    return -1;\n";
6143                  pr "  }\n"
6144              | FUUID ->
6145                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6146                  pr "    if (tok[j] == '\\0') {\n";
6147                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6148                  pr "      return -1;\n";
6149                  pr "    } else if (tok[j] != '-')\n";
6150                  pr "      r->%s[i++] = tok[j];\n" name;
6151                  pr "  }\n";
6152              | FBytes ->
6153                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6154                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6155                  pr "    return -1;\n";
6156                  pr "  }\n";
6157              | FInt64 ->
6158                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6159                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6160                  pr "    return -1;\n";
6161                  pr "  }\n";
6162              | FOptPercent ->
6163                  pr "  if (tok[0] == '\\0')\n";
6164                  pr "    r->%s = -1;\n" name;
6165                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6166                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6167                  pr "    return -1;\n";
6168                  pr "  }\n";
6169              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6170                  assert false (* can never be an LVM column *)
6171             );
6172             pr "  tok = next;\n";
6173         ) cols;
6174
6175         pr "  if (tok != NULL) {\n";
6176         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6177         pr "    return -1;\n";
6178         pr "  }\n";
6179         pr "  return 0;\n";
6180         pr "}\n";
6181         pr "\n";
6182
6183         pr "guestfs_int_lvm_%s_list *\n" typ;
6184         pr "parse_command_line_%ss (void)\n" typ;
6185         pr "{\n";
6186         pr "  char *out, *err;\n";
6187         pr "  char *p, *pend;\n";
6188         pr "  int r, i;\n";
6189         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6190         pr "  void *newp;\n";
6191         pr "\n";
6192         pr "  ret = malloc (sizeof *ret);\n";
6193         pr "  if (!ret) {\n";
6194         pr "    reply_with_perror (\"malloc\");\n";
6195         pr "    return NULL;\n";
6196         pr "  }\n";
6197         pr "\n";
6198         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6199         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6200         pr "\n";
6201         pr "  r = command (&out, &err,\n";
6202         pr "           \"lvm\", \"%ss\",\n" typ;
6203         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6204         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6205         pr "  if (r == -1) {\n";
6206         pr "    reply_with_error (\"%%s\", err);\n";
6207         pr "    free (out);\n";
6208         pr "    free (err);\n";
6209         pr "    free (ret);\n";
6210         pr "    return NULL;\n";
6211         pr "  }\n";
6212         pr "\n";
6213         pr "  free (err);\n";
6214         pr "\n";
6215         pr "  /* Tokenize each line of the output. */\n";
6216         pr "  p = out;\n";
6217         pr "  i = 0;\n";
6218         pr "  while (p) {\n";
6219         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6220         pr "    if (pend) {\n";
6221         pr "      *pend = '\\0';\n";
6222         pr "      pend++;\n";
6223         pr "    }\n";
6224         pr "\n";
6225         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6226         pr "      p++;\n";
6227         pr "\n";
6228         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6229         pr "      p = pend;\n";
6230         pr "      continue;\n";
6231         pr "    }\n";
6232         pr "\n";
6233         pr "    /* Allocate some space to store this next entry. */\n";
6234         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6235         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6236         pr "    if (newp == NULL) {\n";
6237         pr "      reply_with_perror (\"realloc\");\n";
6238         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6239         pr "      free (ret);\n";
6240         pr "      free (out);\n";
6241         pr "      return NULL;\n";
6242         pr "    }\n";
6243         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6244         pr "\n";
6245         pr "    /* Tokenize the next entry. */\n";
6246         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6247         pr "    if (r == -1) {\n";
6248         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6249         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6250         pr "      free (ret);\n";
6251         pr "      free (out);\n";
6252         pr "      return NULL;\n";
6253         pr "    }\n";
6254         pr "\n";
6255         pr "    ++i;\n";
6256         pr "    p = pend;\n";
6257         pr "  }\n";
6258         pr "\n";
6259         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6260         pr "\n";
6261         pr "  free (out);\n";
6262         pr "  return ret;\n";
6263         pr "}\n"
6264
6265   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6266
6267 (* Generate a list of function names, for debugging in the daemon.. *)
6268 and generate_daemon_names () =
6269   generate_header CStyle GPLv2plus;
6270
6271   pr "#include <config.h>\n";
6272   pr "\n";
6273   pr "#include \"daemon.h\"\n";
6274   pr "\n";
6275
6276   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6277   pr "const char *function_names[] = {\n";
6278   List.iter (
6279     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6280   ) daemon_functions;
6281   pr "};\n";
6282
6283 (* Generate the optional groups for the daemon to implement
6284  * guestfs_available.
6285  *)
6286 and generate_daemon_optgroups_c () =
6287   generate_header CStyle GPLv2plus;
6288
6289   pr "#include <config.h>\n";
6290   pr "\n";
6291   pr "#include \"daemon.h\"\n";
6292   pr "#include \"optgroups.h\"\n";
6293   pr "\n";
6294
6295   pr "struct optgroup optgroups[] = {\n";
6296   List.iter (
6297     fun (group, _) ->
6298       pr "  { \"%s\", optgroup_%s_available },\n" group group
6299   ) optgroups;
6300   pr "  { NULL, NULL }\n";
6301   pr "};\n"
6302
6303 and generate_daemon_optgroups_h () =
6304   generate_header CStyle GPLv2plus;
6305
6306   List.iter (
6307     fun (group, _) ->
6308       pr "extern int optgroup_%s_available (void);\n" group
6309   ) optgroups
6310
6311 (* Generate the tests. *)
6312 and generate_tests () =
6313   generate_header CStyle GPLv2plus;
6314
6315   pr "\
6316 #include <stdio.h>
6317 #include <stdlib.h>
6318 #include <string.h>
6319 #include <unistd.h>
6320 #include <sys/types.h>
6321 #include <fcntl.h>
6322
6323 #include \"guestfs.h\"
6324 #include \"guestfs-internal.h\"
6325
6326 static guestfs_h *g;
6327 static int suppress_error = 0;
6328
6329 static void print_error (guestfs_h *g, void *data, const char *msg)
6330 {
6331   if (!suppress_error)
6332     fprintf (stderr, \"%%s\\n\", msg);
6333 }
6334
6335 /* FIXME: nearly identical code appears in fish.c */
6336 static void print_strings (char *const *argv)
6337 {
6338   int argc;
6339
6340   for (argc = 0; argv[argc] != NULL; ++argc)
6341     printf (\"\\t%%s\\n\", argv[argc]);
6342 }
6343
6344 /*
6345 static void print_table (char const *const *argv)
6346 {
6347   int i;
6348
6349   for (i = 0; argv[i] != NULL; i += 2)
6350     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6351 }
6352 */
6353
6354 ";
6355
6356   (* Generate a list of commands which are not tested anywhere. *)
6357   pr "static void no_test_warnings (void)\n";
6358   pr "{\n";
6359
6360   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6361   List.iter (
6362     fun (_, _, _, _, tests, _, _) ->
6363       let tests = filter_map (
6364         function
6365         | (_, (Always|If _|Unless _), test) -> Some test
6366         | (_, Disabled, _) -> None
6367       ) tests in
6368       let seq = List.concat (List.map seq_of_test tests) in
6369       let cmds_tested = List.map List.hd seq in
6370       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6371   ) all_functions;
6372
6373   List.iter (
6374     fun (name, _, _, _, _, _, _) ->
6375       if not (Hashtbl.mem hash name) then
6376         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6377   ) all_functions;
6378
6379   pr "}\n";
6380   pr "\n";
6381
6382   (* Generate the actual tests.  Note that we generate the tests
6383    * in reverse order, deliberately, so that (in general) the
6384    * newest tests run first.  This makes it quicker and easier to
6385    * debug them.
6386    *)
6387   let test_names =
6388     List.map (
6389       fun (name, _, _, flags, tests, _, _) ->
6390         mapi (generate_one_test name flags) tests
6391     ) (List.rev all_functions) in
6392   let test_names = List.concat test_names in
6393   let nr_tests = List.length test_names in
6394
6395   pr "\
6396 int main (int argc, char *argv[])
6397 {
6398   char c = 0;
6399   unsigned long int n_failed = 0;
6400   const char *filename;
6401   int fd;
6402   int nr_tests, test_num = 0;
6403
6404   setbuf (stdout, NULL);
6405
6406   no_test_warnings ();
6407
6408   g = guestfs_create ();
6409   if (g == NULL) {
6410     printf (\"guestfs_create FAILED\\n\");
6411     exit (EXIT_FAILURE);
6412   }
6413
6414   guestfs_set_error_handler (g, print_error, NULL);
6415
6416   guestfs_set_path (g, \"../appliance\");
6417
6418   filename = \"test1.img\";
6419   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6420   if (fd == -1) {
6421     perror (filename);
6422     exit (EXIT_FAILURE);
6423   }
6424   if (lseek (fd, %d, SEEK_SET) == -1) {
6425     perror (\"lseek\");
6426     close (fd);
6427     unlink (filename);
6428     exit (EXIT_FAILURE);
6429   }
6430   if (write (fd, &c, 1) == -1) {
6431     perror (\"write\");
6432     close (fd);
6433     unlink (filename);
6434     exit (EXIT_FAILURE);
6435   }
6436   if (close (fd) == -1) {
6437     perror (filename);
6438     unlink (filename);
6439     exit (EXIT_FAILURE);
6440   }
6441   if (guestfs_add_drive (g, filename) == -1) {
6442     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6443     exit (EXIT_FAILURE);
6444   }
6445
6446   filename = \"test2.img\";
6447   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6448   if (fd == -1) {
6449     perror (filename);
6450     exit (EXIT_FAILURE);
6451   }
6452   if (lseek (fd, %d, SEEK_SET) == -1) {
6453     perror (\"lseek\");
6454     close (fd);
6455     unlink (filename);
6456     exit (EXIT_FAILURE);
6457   }
6458   if (write (fd, &c, 1) == -1) {
6459     perror (\"write\");
6460     close (fd);
6461     unlink (filename);
6462     exit (EXIT_FAILURE);
6463   }
6464   if (close (fd) == -1) {
6465     perror (filename);
6466     unlink (filename);
6467     exit (EXIT_FAILURE);
6468   }
6469   if (guestfs_add_drive (g, filename) == -1) {
6470     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6471     exit (EXIT_FAILURE);
6472   }
6473
6474   filename = \"test3.img\";
6475   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6476   if (fd == -1) {
6477     perror (filename);
6478     exit (EXIT_FAILURE);
6479   }
6480   if (lseek (fd, %d, SEEK_SET) == -1) {
6481     perror (\"lseek\");
6482     close (fd);
6483     unlink (filename);
6484     exit (EXIT_FAILURE);
6485   }
6486   if (write (fd, &c, 1) == -1) {
6487     perror (\"write\");
6488     close (fd);
6489     unlink (filename);
6490     exit (EXIT_FAILURE);
6491   }
6492   if (close (fd) == -1) {
6493     perror (filename);
6494     unlink (filename);
6495     exit (EXIT_FAILURE);
6496   }
6497   if (guestfs_add_drive (g, filename) == -1) {
6498     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6499     exit (EXIT_FAILURE);
6500   }
6501
6502   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6503     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6504     exit (EXIT_FAILURE);
6505   }
6506
6507   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6508   alarm (600);
6509
6510   if (guestfs_launch (g) == -1) {
6511     printf (\"guestfs_launch FAILED\\n\");
6512     exit (EXIT_FAILURE);
6513   }
6514
6515   /* Cancel previous alarm. */
6516   alarm (0);
6517
6518   nr_tests = %d;
6519
6520 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6521
6522   iteri (
6523     fun i test_name ->
6524       pr "  test_num++;\n";
6525       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6526       pr "  if (%s () == -1) {\n" test_name;
6527       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6528       pr "    n_failed++;\n";
6529       pr "  }\n";
6530   ) test_names;
6531   pr "\n";
6532
6533   pr "  guestfs_close (g);\n";
6534   pr "  unlink (\"test1.img\");\n";
6535   pr "  unlink (\"test2.img\");\n";
6536   pr "  unlink (\"test3.img\");\n";
6537   pr "\n";
6538
6539   pr "  if (n_failed > 0) {\n";
6540   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6541   pr "    exit (EXIT_FAILURE);\n";
6542   pr "  }\n";
6543   pr "\n";
6544
6545   pr "  exit (EXIT_SUCCESS);\n";
6546   pr "}\n"
6547
6548 and generate_one_test name flags i (init, prereq, test) =
6549   let test_name = sprintf "test_%s_%d" name i in
6550
6551   pr "\
6552 static int %s_skip (void)
6553 {
6554   const char *str;
6555
6556   str = getenv (\"TEST_ONLY\");
6557   if (str)
6558     return strstr (str, \"%s\") == NULL;
6559   str = getenv (\"SKIP_%s\");
6560   if (str && STREQ (str, \"1\")) return 1;
6561   str = getenv (\"SKIP_TEST_%s\");
6562   if (str && STREQ (str, \"1\")) return 1;
6563   return 0;
6564 }
6565
6566 " test_name name (String.uppercase test_name) (String.uppercase name);
6567
6568   (match prereq with
6569    | Disabled | Always -> ()
6570    | If code | Unless code ->
6571        pr "static int %s_prereq (void)\n" test_name;
6572        pr "{\n";
6573        pr "  %s\n" code;
6574        pr "}\n";
6575        pr "\n";
6576   );
6577
6578   pr "\
6579 static int %s (void)
6580 {
6581   if (%s_skip ()) {
6582     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6583     return 0;
6584   }
6585
6586 " test_name test_name test_name;
6587
6588   (* Optional functions should only be tested if the relevant
6589    * support is available in the daemon.
6590    *)
6591   List.iter (
6592     function
6593     | Optional group ->
6594         pr "  {\n";
6595         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6596         pr "    int r;\n";
6597         pr "    suppress_error = 1;\n";
6598         pr "    r = guestfs_available (g, (char **) groups);\n";
6599         pr "    suppress_error = 0;\n";
6600         pr "    if (r == -1) {\n";
6601         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6602         pr "      return 0;\n";
6603         pr "    }\n";
6604         pr "  }\n";
6605     | _ -> ()
6606   ) flags;
6607
6608   (match prereq with
6609    | Disabled ->
6610        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6611    | If _ ->
6612        pr "  if (! %s_prereq ()) {\n" test_name;
6613        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6614        pr "    return 0;\n";
6615        pr "  }\n";
6616        pr "\n";
6617        generate_one_test_body name i test_name init test;
6618    | Unless _ ->
6619        pr "  if (%s_prereq ()) {\n" test_name;
6620        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6621        pr "    return 0;\n";
6622        pr "  }\n";
6623        pr "\n";
6624        generate_one_test_body name i test_name init test;
6625    | Always ->
6626        generate_one_test_body name i test_name init test
6627   );
6628
6629   pr "  return 0;\n";
6630   pr "}\n";
6631   pr "\n";
6632   test_name
6633
6634 and generate_one_test_body name i test_name init test =
6635   (match init with
6636    | InitNone (* XXX at some point, InitNone and InitEmpty became
6637                * folded together as the same thing.  Really we should
6638                * make InitNone do nothing at all, but the tests may
6639                * need to be checked to make sure this is OK.
6640                *)
6641    | InitEmpty ->
6642        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6643        List.iter (generate_test_command_call test_name)
6644          [["blockdev_setrw"; "/dev/sda"];
6645           ["umount_all"];
6646           ["lvm_remove_all"]]
6647    | InitPartition ->
6648        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6649        List.iter (generate_test_command_call test_name)
6650          [["blockdev_setrw"; "/dev/sda"];
6651           ["umount_all"];
6652           ["lvm_remove_all"];
6653           ["part_disk"; "/dev/sda"; "mbr"]]
6654    | InitBasicFS ->
6655        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6656        List.iter (generate_test_command_call test_name)
6657          [["blockdev_setrw"; "/dev/sda"];
6658           ["umount_all"];
6659           ["lvm_remove_all"];
6660           ["part_disk"; "/dev/sda"; "mbr"];
6661           ["mkfs"; "ext2"; "/dev/sda1"];
6662           ["mount_options"; ""; "/dev/sda1"; "/"]]
6663    | InitBasicFSonLVM ->
6664        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6665          test_name;
6666        List.iter (generate_test_command_call test_name)
6667          [["blockdev_setrw"; "/dev/sda"];
6668           ["umount_all"];
6669           ["lvm_remove_all"];
6670           ["part_disk"; "/dev/sda"; "mbr"];
6671           ["pvcreate"; "/dev/sda1"];
6672           ["vgcreate"; "VG"; "/dev/sda1"];
6673           ["lvcreate"; "LV"; "VG"; "8"];
6674           ["mkfs"; "ext2"; "/dev/VG/LV"];
6675           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6676    | InitISOFS ->
6677        pr "  /* InitISOFS for %s */\n" test_name;
6678        List.iter (generate_test_command_call test_name)
6679          [["blockdev_setrw"; "/dev/sda"];
6680           ["umount_all"];
6681           ["lvm_remove_all"];
6682           ["mount_ro"; "/dev/sdd"; "/"]]
6683   );
6684
6685   let get_seq_last = function
6686     | [] ->
6687         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6688           test_name
6689     | seq ->
6690         let seq = List.rev seq in
6691         List.rev (List.tl seq), List.hd seq
6692   in
6693
6694   match test with
6695   | TestRun seq ->
6696       pr "  /* TestRun for %s (%d) */\n" name i;
6697       List.iter (generate_test_command_call test_name) seq
6698   | TestOutput (seq, expected) ->
6699       pr "  /* TestOutput for %s (%d) */\n" name i;
6700       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6701       let seq, last = get_seq_last seq in
6702       let test () =
6703         pr "    if (STRNEQ (r, expected)) {\n";
6704         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6705         pr "      return -1;\n";
6706         pr "    }\n"
6707       in
6708       List.iter (generate_test_command_call test_name) seq;
6709       generate_test_command_call ~test test_name last
6710   | TestOutputList (seq, expected) ->
6711       pr "  /* TestOutputList for %s (%d) */\n" name i;
6712       let seq, last = get_seq_last seq in
6713       let test () =
6714         iteri (
6715           fun i str ->
6716             pr "    if (!r[%d]) {\n" i;
6717             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6718             pr "      print_strings (r);\n";
6719             pr "      return -1;\n";
6720             pr "    }\n";
6721             pr "    {\n";
6722             pr "      const char *expected = \"%s\";\n" (c_quote str);
6723             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6724             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6725             pr "        return -1;\n";
6726             pr "      }\n";
6727             pr "    }\n"
6728         ) expected;
6729         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6730         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6731           test_name;
6732         pr "      print_strings (r);\n";
6733         pr "      return -1;\n";
6734         pr "    }\n"
6735       in
6736       List.iter (generate_test_command_call test_name) seq;
6737       generate_test_command_call ~test test_name last
6738   | TestOutputListOfDevices (seq, expected) ->
6739       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6740       let seq, last = get_seq_last seq in
6741       let test () =
6742         iteri (
6743           fun i str ->
6744             pr "    if (!r[%d]) {\n" i;
6745             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6746             pr "      print_strings (r);\n";
6747             pr "      return -1;\n";
6748             pr "    }\n";
6749             pr "    {\n";
6750             pr "      const char *expected = \"%s\";\n" (c_quote str);
6751             pr "      r[%d][5] = 's';\n" i;
6752             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6753             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6754             pr "        return -1;\n";
6755             pr "      }\n";
6756             pr "    }\n"
6757         ) expected;
6758         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6759         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6760           test_name;
6761         pr "      print_strings (r);\n";
6762         pr "      return -1;\n";
6763         pr "    }\n"
6764       in
6765       List.iter (generate_test_command_call test_name) seq;
6766       generate_test_command_call ~test test_name last
6767   | TestOutputInt (seq, expected) ->
6768       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6769       let seq, last = get_seq_last seq in
6770       let test () =
6771         pr "    if (r != %d) {\n" expected;
6772         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6773           test_name expected;
6774         pr "               (int) r);\n";
6775         pr "      return -1;\n";
6776         pr "    }\n"
6777       in
6778       List.iter (generate_test_command_call test_name) seq;
6779       generate_test_command_call ~test test_name last
6780   | TestOutputIntOp (seq, op, expected) ->
6781       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6782       let seq, last = get_seq_last seq in
6783       let test () =
6784         pr "    if (! (r %s %d)) {\n" op expected;
6785         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6786           test_name op expected;
6787         pr "               (int) r);\n";
6788         pr "      return -1;\n";
6789         pr "    }\n"
6790       in
6791       List.iter (generate_test_command_call test_name) seq;
6792       generate_test_command_call ~test test_name last
6793   | TestOutputTrue seq ->
6794       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6795       let seq, last = get_seq_last seq in
6796       let test () =
6797         pr "    if (!r) {\n";
6798         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6799           test_name;
6800         pr "      return -1;\n";
6801         pr "    }\n"
6802       in
6803       List.iter (generate_test_command_call test_name) seq;
6804       generate_test_command_call ~test test_name last
6805   | TestOutputFalse seq ->
6806       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6807       let seq, last = get_seq_last seq in
6808       let test () =
6809         pr "    if (r) {\n";
6810         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6811           test_name;
6812         pr "      return -1;\n";
6813         pr "    }\n"
6814       in
6815       List.iter (generate_test_command_call test_name) seq;
6816       generate_test_command_call ~test test_name last
6817   | TestOutputLength (seq, expected) ->
6818       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6819       let seq, last = get_seq_last seq in
6820       let test () =
6821         pr "    int j;\n";
6822         pr "    for (j = 0; j < %d; ++j)\n" expected;
6823         pr "      if (r[j] == NULL) {\n";
6824         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6825           test_name;
6826         pr "        print_strings (r);\n";
6827         pr "        return -1;\n";
6828         pr "      }\n";
6829         pr "    if (r[j] != NULL) {\n";
6830         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6831           test_name;
6832         pr "      print_strings (r);\n";
6833         pr "      return -1;\n";
6834         pr "    }\n"
6835       in
6836       List.iter (generate_test_command_call test_name) seq;
6837       generate_test_command_call ~test test_name last
6838   | TestOutputBuffer (seq, expected) ->
6839       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6840       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6841       let seq, last = get_seq_last seq in
6842       let len = String.length expected in
6843       let test () =
6844         pr "    if (size != %d) {\n" len;
6845         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6846         pr "      return -1;\n";
6847         pr "    }\n";
6848         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6849         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6850         pr "      return -1;\n";
6851         pr "    }\n"
6852       in
6853       List.iter (generate_test_command_call test_name) seq;
6854       generate_test_command_call ~test test_name last
6855   | TestOutputStruct (seq, checks) ->
6856       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6857       let seq, last = get_seq_last seq in
6858       let test () =
6859         List.iter (
6860           function
6861           | CompareWithInt (field, expected) ->
6862               pr "    if (r->%s != %d) {\n" field expected;
6863               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6864                 test_name field expected;
6865               pr "               (int) r->%s);\n" field;
6866               pr "      return -1;\n";
6867               pr "    }\n"
6868           | CompareWithIntOp (field, op, expected) ->
6869               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6870               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6871                 test_name field op expected;
6872               pr "               (int) r->%s);\n" field;
6873               pr "      return -1;\n";
6874               pr "    }\n"
6875           | CompareWithString (field, expected) ->
6876               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6877               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6878                 test_name field expected;
6879               pr "               r->%s);\n" field;
6880               pr "      return -1;\n";
6881               pr "    }\n"
6882           | CompareFieldsIntEq (field1, field2) ->
6883               pr "    if (r->%s != r->%s) {\n" field1 field2;
6884               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6885                 test_name field1 field2;
6886               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6887               pr "      return -1;\n";
6888               pr "    }\n"
6889           | CompareFieldsStrEq (field1, field2) ->
6890               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6891               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6892                 test_name field1 field2;
6893               pr "               r->%s, r->%s);\n" field1 field2;
6894               pr "      return -1;\n";
6895               pr "    }\n"
6896         ) checks
6897       in
6898       List.iter (generate_test_command_call test_name) seq;
6899       generate_test_command_call ~test test_name last
6900   | TestLastFail seq ->
6901       pr "  /* TestLastFail for %s (%d) */\n" name i;
6902       let seq, last = get_seq_last seq in
6903       List.iter (generate_test_command_call test_name) seq;
6904       generate_test_command_call test_name ~expect_error:true last
6905
6906 (* Generate the code to run a command, leaving the result in 'r'.
6907  * If you expect to get an error then you should set expect_error:true.
6908  *)
6909 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6910   match cmd with
6911   | [] -> assert false
6912   | name :: args ->
6913       (* Look up the command to find out what args/ret it has. *)
6914       let style =
6915         try
6916           let _, style, _, _, _, _, _ =
6917             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6918           style
6919         with Not_found ->
6920           failwithf "%s: in test, command %s was not found" test_name name in
6921
6922       if List.length (snd style) <> List.length args then
6923         failwithf "%s: in test, wrong number of args given to %s"
6924           test_name name;
6925
6926       pr "  {\n";
6927
6928       List.iter (
6929         function
6930         | OptString n, "NULL" -> ()
6931         | Pathname n, arg
6932         | Device n, arg
6933         | Dev_or_Path n, arg
6934         | String n, arg
6935         | OptString n, arg ->
6936             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6937         | Int _, _
6938         | Int64 _, _
6939         | Bool _, _
6940         | FileIn _, _ | FileOut _, _ -> ()
6941         | StringList n, "" | DeviceList n, "" ->
6942             pr "    const char *const %s[1] = { NULL };\n" n
6943         | StringList n, arg | DeviceList n, arg ->
6944             let strs = string_split " " arg in
6945             iteri (
6946               fun i str ->
6947                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6948             ) strs;
6949             pr "    const char *const %s[] = {\n" n;
6950             iteri (
6951               fun i _ -> pr "      %s_%d,\n" n i
6952             ) strs;
6953             pr "      NULL\n";
6954             pr "    };\n";
6955       ) (List.combine (snd style) args);
6956
6957       let error_code =
6958         match fst style with
6959         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6960         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6961         | RConstString _ | RConstOptString _ ->
6962             pr "    const char *r;\n"; "NULL"
6963         | RString _ -> pr "    char *r;\n"; "NULL"
6964         | RStringList _ | RHashtable _ ->
6965             pr "    char **r;\n";
6966             pr "    int i;\n";
6967             "NULL"
6968         | RStruct (_, typ) ->
6969             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6970         | RStructList (_, typ) ->
6971             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6972         | RBufferOut _ ->
6973             pr "    char *r;\n";
6974             pr "    size_t size;\n";
6975             "NULL" in
6976
6977       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6978       pr "    r = guestfs_%s (g" name;
6979
6980       (* Generate the parameters. *)
6981       List.iter (
6982         function
6983         | OptString _, "NULL" -> pr ", NULL"
6984         | Pathname n, _
6985         | Device n, _ | Dev_or_Path n, _
6986         | String n, _
6987         | OptString n, _ ->
6988             pr ", %s" n
6989         | FileIn _, arg | FileOut _, arg ->
6990             pr ", \"%s\"" (c_quote arg)
6991         | StringList n, _ | DeviceList n, _ ->
6992             pr ", (char **) %s" n
6993         | Int _, arg ->
6994             let i =
6995               try int_of_string arg
6996               with Failure "int_of_string" ->
6997                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6998             pr ", %d" i
6999         | Int64 _, arg ->
7000             let i =
7001               try Int64.of_string arg
7002               with Failure "int_of_string" ->
7003                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7004             pr ", %Ld" i
7005         | Bool _, arg ->
7006             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7007       ) (List.combine (snd style) args);
7008
7009       (match fst style with
7010        | RBufferOut _ -> pr ", &size"
7011        | _ -> ()
7012       );
7013
7014       pr ");\n";
7015
7016       if not expect_error then
7017         pr "    if (r == %s)\n" error_code
7018       else
7019         pr "    if (r != %s)\n" error_code;
7020       pr "      return -1;\n";
7021
7022       (* Insert the test code. *)
7023       (match test with
7024        | None -> ()
7025        | Some f -> f ()
7026       );
7027
7028       (match fst style with
7029        | RErr | RInt _ | RInt64 _ | RBool _
7030        | RConstString _ | RConstOptString _ -> ()
7031        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7032        | RStringList _ | RHashtable _ ->
7033            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7034            pr "      free (r[i]);\n";
7035            pr "    free (r);\n"
7036        | RStruct (_, typ) ->
7037            pr "    guestfs_free_%s (r);\n" typ
7038        | RStructList (_, typ) ->
7039            pr "    guestfs_free_%s_list (r);\n" typ
7040       );
7041
7042       pr "  }\n"
7043
7044 and c_quote str =
7045   let str = replace_str str "\r" "\\r" in
7046   let str = replace_str str "\n" "\\n" in
7047   let str = replace_str str "\t" "\\t" in
7048   let str = replace_str str "\000" "\\0" in
7049   str
7050
7051 (* Generate a lot of different functions for guestfish. *)
7052 and generate_fish_cmds () =
7053   generate_header CStyle GPLv2plus;
7054
7055   let all_functions =
7056     List.filter (
7057       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7058     ) all_functions in
7059   let all_functions_sorted =
7060     List.filter (
7061       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7062     ) all_functions_sorted in
7063
7064   pr "#include <config.h>\n";
7065   pr "\n";
7066   pr "#include <stdio.h>\n";
7067   pr "#include <stdlib.h>\n";
7068   pr "#include <string.h>\n";
7069   pr "#include <inttypes.h>\n";
7070   pr "\n";
7071   pr "#include <guestfs.h>\n";
7072   pr "#include \"c-ctype.h\"\n";
7073   pr "#include \"full-write.h\"\n";
7074   pr "#include \"xstrtol.h\"\n";
7075   pr "#include \"fish.h\"\n";
7076   pr "\n";
7077
7078   (* list_commands function, which implements guestfish -h *)
7079   pr "void list_commands (void)\n";
7080   pr "{\n";
7081   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7082   pr "  list_builtin_commands ();\n";
7083   List.iter (
7084     fun (name, _, _, flags, _, shortdesc, _) ->
7085       let name = replace_char name '_' '-' in
7086       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7087         name shortdesc
7088   ) all_functions_sorted;
7089   pr "  printf (\"    %%s\\n\",";
7090   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7091   pr "}\n";
7092   pr "\n";
7093
7094   (* display_command function, which implements guestfish -h cmd *)
7095   pr "void display_command (const char *cmd)\n";
7096   pr "{\n";
7097   List.iter (
7098     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7099       let name2 = replace_char name '_' '-' in
7100       let alias =
7101         try find_map (function FishAlias n -> Some n | _ -> None) flags
7102         with Not_found -> name in
7103       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7104       let synopsis =
7105         match snd style with
7106         | [] -> name2
7107         | args ->
7108             sprintf "%s %s"
7109               name2 (String.concat " " (List.map name_of_argt args)) in
7110
7111       let warnings =
7112         if List.mem ProtocolLimitWarning flags then
7113           ("\n\n" ^ protocol_limit_warning)
7114         else "" in
7115
7116       (* For DangerWillRobinson commands, we should probably have
7117        * guestfish prompt before allowing you to use them (especially
7118        * in interactive mode). XXX
7119        *)
7120       let warnings =
7121         warnings ^
7122           if List.mem DangerWillRobinson flags then
7123             ("\n\n" ^ danger_will_robinson)
7124           else "" in
7125
7126       let warnings =
7127         warnings ^
7128           match deprecation_notice flags with
7129           | None -> ""
7130           | Some txt -> "\n\n" ^ txt in
7131
7132       let describe_alias =
7133         if name <> alias then
7134           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7135         else "" in
7136
7137       pr "  if (";
7138       pr "STRCASEEQ (cmd, \"%s\")" name;
7139       if name <> name2 then
7140         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7141       if name <> alias then
7142         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7143       pr ")\n";
7144       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7145         name2 shortdesc
7146         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7147          "=head1 DESCRIPTION\n\n" ^
7148          longdesc ^ warnings ^ describe_alias);
7149       pr "  else\n"
7150   ) all_functions;
7151   pr "    display_builtin_command (cmd);\n";
7152   pr "}\n";
7153   pr "\n";
7154
7155   let emit_print_list_function typ =
7156     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7157       typ typ typ;
7158     pr "{\n";
7159     pr "  unsigned int i;\n";
7160     pr "\n";
7161     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7162     pr "    printf (\"[%%d] = {\\n\", i);\n";
7163     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7164     pr "    printf (\"}\\n\");\n";
7165     pr "  }\n";
7166     pr "}\n";
7167     pr "\n";
7168   in
7169
7170   (* print_* functions *)
7171   List.iter (
7172     fun (typ, cols) ->
7173       let needs_i =
7174         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7175
7176       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7177       pr "{\n";
7178       if needs_i then (
7179         pr "  unsigned int i;\n";
7180         pr "\n"
7181       );
7182       List.iter (
7183         function
7184         | name, FString ->
7185             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7186         | name, FUUID ->
7187             pr "  printf (\"%%s%s: \", indent);\n" name;
7188             pr "  for (i = 0; i < 32; ++i)\n";
7189             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7190             pr "  printf (\"\\n\");\n"
7191         | name, FBuffer ->
7192             pr "  printf (\"%%s%s: \", indent);\n" name;
7193             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7194             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7195             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7196             pr "    else\n";
7197             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7198             pr "  printf (\"\\n\");\n"
7199         | name, (FUInt64|FBytes) ->
7200             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7201               name typ name
7202         | name, FInt64 ->
7203             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7204               name typ name
7205         | name, FUInt32 ->
7206             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7207               name typ name
7208         | name, FInt32 ->
7209             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7210               name typ name
7211         | name, FChar ->
7212             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7213               name typ name
7214         | name, FOptPercent ->
7215             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7216               typ name name typ name;
7217             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7218       ) cols;
7219       pr "}\n";
7220       pr "\n";
7221   ) structs;
7222
7223   (* Emit a print_TYPE_list function definition only if that function is used. *)
7224   List.iter (
7225     function
7226     | typ, (RStructListOnly | RStructAndList) ->
7227         (* generate the function for typ *)
7228         emit_print_list_function typ
7229     | typ, _ -> () (* empty *)
7230   ) (rstructs_used_by all_functions);
7231
7232   (* Emit a print_TYPE function definition only if that function is used. *)
7233   List.iter (
7234     function
7235     | typ, (RStructOnly | RStructAndList) ->
7236         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7237         pr "{\n";
7238         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7239         pr "}\n";
7240         pr "\n";
7241     | typ, _ -> () (* empty *)
7242   ) (rstructs_used_by all_functions);
7243
7244   (* run_<action> actions *)
7245   List.iter (
7246     fun (name, style, _, flags, _, _, _) ->
7247       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7248       pr "{\n";
7249       (match fst style with
7250        | RErr
7251        | RInt _
7252        | RBool _ -> pr "  int r;\n"
7253        | RInt64 _ -> pr "  int64_t r;\n"
7254        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7255        | RString _ -> pr "  char *r;\n"
7256        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7257        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7258        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7259        | RBufferOut _ ->
7260            pr "  char *r;\n";
7261            pr "  size_t size;\n";
7262       );
7263       List.iter (
7264         function
7265         | Device n
7266         | String n
7267         | OptString n
7268         | FileIn n
7269         | FileOut n -> pr "  const char *%s;\n" n
7270         | Pathname n
7271         | Dev_or_Path n -> pr "  char *%s;\n" n
7272         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7273         | Bool n -> pr "  int %s;\n" n
7274         | Int n -> pr "  int %s;\n" n
7275         | Int64 n -> pr "  int64_t %s;\n" n
7276       ) (snd style);
7277
7278       (* Check and convert parameters. *)
7279       let argc_expected = List.length (snd style) in
7280       pr "  if (argc != %d) {\n" argc_expected;
7281       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7282         argc_expected;
7283       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7284       pr "    return -1;\n";
7285       pr "  }\n";
7286
7287       let parse_integer fn fntyp rtyp range name i =
7288         pr "  {\n";
7289         pr "    strtol_error xerr;\n";
7290         pr "    %s r;\n" fntyp;
7291         pr "\n";
7292         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7293         pr "    if (xerr != LONGINT_OK) {\n";
7294         pr "      fprintf (stderr,\n";
7295         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7296         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7297         pr "      return -1;\n";
7298         pr "    }\n";
7299         (match range with
7300          | None -> ()
7301          | Some (min, max, comment) ->
7302              pr "    /* %s */\n" comment;
7303              pr "    if (r < %s || r > %s) {\n" min max;
7304              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7305                name;
7306              pr "      return -1;\n";
7307              pr "    }\n";
7308              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7309         );
7310         pr "    %s = r;\n" name;
7311         pr "  }\n";
7312       in
7313
7314       iteri (
7315         fun i ->
7316           function
7317           | Device name
7318           | String name ->
7319               pr "  %s = argv[%d];\n" name i
7320           | Pathname name
7321           | Dev_or_Path name ->
7322               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7323               pr "  if (%s == NULL) return -1;\n" name
7324           | OptString name ->
7325               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7326                 name i i
7327           | FileIn name ->
7328               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7329                 name i i
7330           | FileOut name ->
7331               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7332                 name i i
7333           | StringList name | DeviceList name ->
7334               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7335               pr "  if (%s == NULL) return -1;\n" name;
7336           | Bool name ->
7337               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7338           | Int name ->
7339               let range =
7340                 let min = "(-(2LL<<30))"
7341                 and max = "((2LL<<30)-1)"
7342                 and comment =
7343                   "The Int type in the generator is a signed 31 bit int." in
7344                 Some (min, max, comment) in
7345               parse_integer "xstrtoll" "long long" "int" range name i
7346           | Int64 name ->
7347               parse_integer "xstrtoll" "long long" "int64_t" None name i
7348       ) (snd style);
7349
7350       (* Call C API function. *)
7351       let fn =
7352         try find_map (function FishAction n -> Some n | _ -> None) flags
7353         with Not_found -> sprintf "guestfs_%s" name in
7354       pr "  r = %s " fn;
7355       generate_c_call_args ~handle:"g" style;
7356       pr ";\n";
7357
7358       List.iter (
7359         function
7360         | Device name | String name
7361         | OptString name | FileIn name | FileOut name | Bool name
7362         | Int name | Int64 name -> ()
7363         | Pathname name | Dev_or_Path name ->
7364             pr "  free (%s);\n" name
7365         | StringList name | DeviceList name ->
7366             pr "  free_strings (%s);\n" name
7367       ) (snd style);
7368
7369       (* Check return value for errors and display command results. *)
7370       (match fst style with
7371        | RErr -> pr "  return r;\n"
7372        | RInt _ ->
7373            pr "  if (r == -1) return -1;\n";
7374            pr "  printf (\"%%d\\n\", r);\n";
7375            pr "  return 0;\n"
7376        | RInt64 _ ->
7377            pr "  if (r == -1) return -1;\n";
7378            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7379            pr "  return 0;\n"
7380        | RBool _ ->
7381            pr "  if (r == -1) return -1;\n";
7382            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7383            pr "  return 0;\n"
7384        | RConstString _ ->
7385            pr "  if (r == NULL) return -1;\n";
7386            pr "  printf (\"%%s\\n\", r);\n";
7387            pr "  return 0;\n"
7388        | RConstOptString _ ->
7389            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7390            pr "  return 0;\n"
7391        | RString _ ->
7392            pr "  if (r == NULL) return -1;\n";
7393            pr "  printf (\"%%s\\n\", r);\n";
7394            pr "  free (r);\n";
7395            pr "  return 0;\n"
7396        | RStringList _ ->
7397            pr "  if (r == NULL) return -1;\n";
7398            pr "  print_strings (r);\n";
7399            pr "  free_strings (r);\n";
7400            pr "  return 0;\n"
7401        | RStruct (_, typ) ->
7402            pr "  if (r == NULL) return -1;\n";
7403            pr "  print_%s (r);\n" typ;
7404            pr "  guestfs_free_%s (r);\n" typ;
7405            pr "  return 0;\n"
7406        | RStructList (_, typ) ->
7407            pr "  if (r == NULL) return -1;\n";
7408            pr "  print_%s_list (r);\n" typ;
7409            pr "  guestfs_free_%s_list (r);\n" typ;
7410            pr "  return 0;\n"
7411        | RHashtable _ ->
7412            pr "  if (r == NULL) return -1;\n";
7413            pr "  print_table (r);\n";
7414            pr "  free_strings (r);\n";
7415            pr "  return 0;\n"
7416        | RBufferOut _ ->
7417            pr "  if (r == NULL) return -1;\n";
7418            pr "  if (full_write (1, r, size) != size) {\n";
7419            pr "    perror (\"write\");\n";
7420            pr "    free (r);\n";
7421            pr "    return -1;\n";
7422            pr "  }\n";
7423            pr "  free (r);\n";
7424            pr "  return 0;\n"
7425       );
7426       pr "}\n";
7427       pr "\n"
7428   ) all_functions;
7429
7430   (* run_action function *)
7431   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7432   pr "{\n";
7433   List.iter (
7434     fun (name, _, _, flags, _, _, _) ->
7435       let name2 = replace_char name '_' '-' in
7436       let alias =
7437         try find_map (function FishAlias n -> Some n | _ -> None) flags
7438         with Not_found -> name in
7439       pr "  if (";
7440       pr "STRCASEEQ (cmd, \"%s\")" name;
7441       if name <> name2 then
7442         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7443       if name <> alias then
7444         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7445       pr ")\n";
7446       pr "    return run_%s (cmd, argc, argv);\n" name;
7447       pr "  else\n";
7448   ) all_functions;
7449   pr "    {\n";
7450   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7451   pr "      if (command_num == 1)\n";
7452   pr "        extended_help_message ();\n";
7453   pr "      return -1;\n";
7454   pr "    }\n";
7455   pr "  return 0;\n";
7456   pr "}\n";
7457   pr "\n"
7458
7459 (* Readline completion for guestfish. *)
7460 and generate_fish_completion () =
7461   generate_header CStyle GPLv2plus;
7462
7463   let all_functions =
7464     List.filter (
7465       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7466     ) all_functions in
7467
7468   pr "\
7469 #include <config.h>
7470
7471 #include <stdio.h>
7472 #include <stdlib.h>
7473 #include <string.h>
7474
7475 #ifdef HAVE_LIBREADLINE
7476 #include <readline/readline.h>
7477 #endif
7478
7479 #include \"fish.h\"
7480
7481 #ifdef HAVE_LIBREADLINE
7482
7483 static const char *const commands[] = {
7484   BUILTIN_COMMANDS_FOR_COMPLETION,
7485 ";
7486
7487   (* Get the commands, including the aliases.  They don't need to be
7488    * sorted - the generator() function just does a dumb linear search.
7489    *)
7490   let commands =
7491     List.map (
7492       fun (name, _, _, flags, _, _, _) ->
7493         let name2 = replace_char name '_' '-' in
7494         let alias =
7495           try find_map (function FishAlias n -> Some n | _ -> None) flags
7496           with Not_found -> name in
7497
7498         if name <> alias then [name2; alias] else [name2]
7499     ) all_functions in
7500   let commands = List.flatten commands in
7501
7502   List.iter (pr "  \"%s\",\n") commands;
7503
7504   pr "  NULL
7505 };
7506
7507 static char *
7508 generator (const char *text, int state)
7509 {
7510   static int index, len;
7511   const char *name;
7512
7513   if (!state) {
7514     index = 0;
7515     len = strlen (text);
7516   }
7517
7518   rl_attempted_completion_over = 1;
7519
7520   while ((name = commands[index]) != NULL) {
7521     index++;
7522     if (STRCASEEQLEN (name, text, len))
7523       return strdup (name);
7524   }
7525
7526   return NULL;
7527 }
7528
7529 #endif /* HAVE_LIBREADLINE */
7530
7531 #ifdef HAVE_RL_COMPLETION_MATCHES
7532 #define RL_COMPLETION_MATCHES rl_completion_matches
7533 #else
7534 #ifdef HAVE_COMPLETION_MATCHES
7535 #define RL_COMPLETION_MATCHES completion_matches
7536 #endif
7537 #endif /* else just fail if we don't have either symbol */
7538
7539 char **
7540 do_completion (const char *text, int start, int end)
7541 {
7542   char **matches = NULL;
7543
7544 #ifdef HAVE_LIBREADLINE
7545   rl_completion_append_character = ' ';
7546
7547   if (start == 0)
7548     matches = RL_COMPLETION_MATCHES (text, generator);
7549   else if (complete_dest_paths)
7550     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7551 #endif
7552
7553   return matches;
7554 }
7555 ";
7556
7557 (* Generate the POD documentation for guestfish. *)
7558 and generate_fish_actions_pod () =
7559   let all_functions_sorted =
7560     List.filter (
7561       fun (_, _, _, flags, _, _, _) ->
7562         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7563     ) all_functions_sorted in
7564
7565   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7566
7567   List.iter (
7568     fun (name, style, _, flags, _, _, longdesc) ->
7569       let longdesc =
7570         Str.global_substitute rex (
7571           fun s ->
7572             let sub =
7573               try Str.matched_group 1 s
7574               with Not_found ->
7575                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7576             "C<" ^ replace_char sub '_' '-' ^ ">"
7577         ) longdesc in
7578       let name = replace_char name '_' '-' in
7579       let alias =
7580         try find_map (function FishAlias n -> Some n | _ -> None) flags
7581         with Not_found -> name in
7582
7583       pr "=head2 %s" name;
7584       if name <> alias then
7585         pr " | %s" alias;
7586       pr "\n";
7587       pr "\n";
7588       pr " %s" name;
7589       List.iter (
7590         function
7591         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7592         | OptString n -> pr " %s" n
7593         | StringList n | DeviceList n -> pr " '%s ...'" n
7594         | Bool _ -> pr " true|false"
7595         | Int n -> pr " %s" n
7596         | Int64 n -> pr " %s" n
7597         | FileIn n | FileOut n -> pr " (%s|-)" n
7598       ) (snd style);
7599       pr "\n";
7600       pr "\n";
7601       pr "%s\n\n" longdesc;
7602
7603       if List.exists (function FileIn _ | FileOut _ -> true
7604                       | _ -> false) (snd style) then
7605         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7606
7607       if List.mem ProtocolLimitWarning flags then
7608         pr "%s\n\n" protocol_limit_warning;
7609
7610       if List.mem DangerWillRobinson flags then
7611         pr "%s\n\n" danger_will_robinson;
7612
7613       match deprecation_notice flags with
7614       | None -> ()
7615       | Some txt -> pr "%s\n\n" txt
7616   ) all_functions_sorted
7617
7618 (* Generate a C function prototype. *)
7619 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7620     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7621     ?(prefix = "")
7622     ?handle name style =
7623   if extern then pr "extern ";
7624   if static then pr "static ";
7625   (match fst style with
7626    | RErr -> pr "int "
7627    | RInt _ -> pr "int "
7628    | RInt64 _ -> pr "int64_t "
7629    | RBool _ -> pr "int "
7630    | RConstString _ | RConstOptString _ -> pr "const char *"
7631    | RString _ | RBufferOut _ -> pr "char *"
7632    | RStringList _ | RHashtable _ -> pr "char **"
7633    | RStruct (_, typ) ->
7634        if not in_daemon then pr "struct guestfs_%s *" typ
7635        else pr "guestfs_int_%s *" typ
7636    | RStructList (_, typ) ->
7637        if not in_daemon then pr "struct guestfs_%s_list *" typ
7638        else pr "guestfs_int_%s_list *" typ
7639   );
7640   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7641   pr "%s%s (" prefix name;
7642   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7643     pr "void"
7644   else (
7645     let comma = ref false in
7646     (match handle with
7647      | None -> ()
7648      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7649     );
7650     let next () =
7651       if !comma then (
7652         if single_line then pr ", " else pr ",\n\t\t"
7653       );
7654       comma := true
7655     in
7656     List.iter (
7657       function
7658       | Pathname n
7659       | Device n | Dev_or_Path n
7660       | String n
7661       | OptString n ->
7662           next ();
7663           pr "const char *%s" n
7664       | StringList n | DeviceList n ->
7665           next ();
7666           pr "char *const *%s" n
7667       | Bool n -> next (); pr "int %s" n
7668       | Int n -> next (); pr "int %s" n
7669       | Int64 n -> next (); pr "int64_t %s" n
7670       | FileIn n
7671       | FileOut n ->
7672           if not in_daemon then (next (); pr "const char *%s" n)
7673     ) (snd style);
7674     if is_RBufferOut then (next (); pr "size_t *size_r");
7675   );
7676   pr ")";
7677   if semicolon then pr ";";
7678   if newline then pr "\n"
7679
7680 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7681 and generate_c_call_args ?handle ?(decl = false) style =
7682   pr "(";
7683   let comma = ref false in
7684   let next () =
7685     if !comma then pr ", ";
7686     comma := true
7687   in
7688   (match handle with
7689    | None -> ()
7690    | Some handle -> pr "%s" handle; comma := true
7691   );
7692   List.iter (
7693     fun arg ->
7694       next ();
7695       pr "%s" (name_of_argt arg)
7696   ) (snd style);
7697   (* For RBufferOut calls, add implicit &size parameter. *)
7698   if not decl then (
7699     match fst style with
7700     | RBufferOut _ ->
7701         next ();
7702         pr "&size"
7703     | _ -> ()
7704   );
7705   pr ")"
7706
7707 (* Generate the OCaml bindings interface. *)
7708 and generate_ocaml_mli () =
7709   generate_header OCamlStyle LGPLv2plus;
7710
7711   pr "\
7712 (** For API documentation you should refer to the C API
7713     in the guestfs(3) manual page.  The OCaml API uses almost
7714     exactly the same calls. *)
7715
7716 type t
7717 (** A [guestfs_h] handle. *)
7718
7719 exception Error of string
7720 (** This exception is raised when there is an error. *)
7721
7722 exception Handle_closed of string
7723 (** This exception is raised if you use a {!Guestfs.t} handle
7724     after calling {!close} on it.  The string is the name of
7725     the function. *)
7726
7727 val create : unit -> t
7728 (** Create a {!Guestfs.t} handle. *)
7729
7730 val close : t -> unit
7731 (** Close the {!Guestfs.t} handle and free up all resources used
7732     by it immediately.
7733
7734     Handles are closed by the garbage collector when they become
7735     unreferenced, but callers can call this in order to provide
7736     predictable cleanup. *)
7737
7738 ";
7739   generate_ocaml_structure_decls ();
7740
7741   (* The actions. *)
7742   List.iter (
7743     fun (name, style, _, _, _, shortdesc, _) ->
7744       generate_ocaml_prototype name style;
7745       pr "(** %s *)\n" shortdesc;
7746       pr "\n"
7747   ) all_functions_sorted
7748
7749 (* Generate the OCaml bindings implementation. *)
7750 and generate_ocaml_ml () =
7751   generate_header OCamlStyle LGPLv2plus;
7752
7753   pr "\
7754 type t
7755
7756 exception Error of string
7757 exception Handle_closed of string
7758
7759 external create : unit -> t = \"ocaml_guestfs_create\"
7760 external close : t -> unit = \"ocaml_guestfs_close\"
7761
7762 (* Give the exceptions names, so they can be raised from the C code. *)
7763 let () =
7764   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7765   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7766
7767 ";
7768
7769   generate_ocaml_structure_decls ();
7770
7771   (* The actions. *)
7772   List.iter (
7773     fun (name, style, _, _, _, shortdesc, _) ->
7774       generate_ocaml_prototype ~is_external:true name style;
7775   ) all_functions_sorted
7776
7777 (* Generate the OCaml bindings C implementation. *)
7778 and generate_ocaml_c () =
7779   generate_header CStyle LGPLv2plus;
7780
7781   pr "\
7782 #include <stdio.h>
7783 #include <stdlib.h>
7784 #include <string.h>
7785
7786 #include <caml/config.h>
7787 #include <caml/alloc.h>
7788 #include <caml/callback.h>
7789 #include <caml/fail.h>
7790 #include <caml/memory.h>
7791 #include <caml/mlvalues.h>
7792 #include <caml/signals.h>
7793
7794 #include <guestfs.h>
7795
7796 #include \"guestfs_c.h\"
7797
7798 /* Copy a hashtable of string pairs into an assoc-list.  We return
7799  * the list in reverse order, but hashtables aren't supposed to be
7800  * ordered anyway.
7801  */
7802 static CAMLprim value
7803 copy_table (char * const * argv)
7804 {
7805   CAMLparam0 ();
7806   CAMLlocal5 (rv, pairv, kv, vv, cons);
7807   int i;
7808
7809   rv = Val_int (0);
7810   for (i = 0; argv[i] != NULL; i += 2) {
7811     kv = caml_copy_string (argv[i]);
7812     vv = caml_copy_string (argv[i+1]);
7813     pairv = caml_alloc (2, 0);
7814     Store_field (pairv, 0, kv);
7815     Store_field (pairv, 1, vv);
7816     cons = caml_alloc (2, 0);
7817     Store_field (cons, 1, rv);
7818     rv = cons;
7819     Store_field (cons, 0, pairv);
7820   }
7821
7822   CAMLreturn (rv);
7823 }
7824
7825 ";
7826
7827   (* Struct copy functions. *)
7828
7829   let emit_ocaml_copy_list_function typ =
7830     pr "static CAMLprim value\n";
7831     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7832     pr "{\n";
7833     pr "  CAMLparam0 ();\n";
7834     pr "  CAMLlocal2 (rv, v);\n";
7835     pr "  unsigned int i;\n";
7836     pr "\n";
7837     pr "  if (%ss->len == 0)\n" typ;
7838     pr "    CAMLreturn (Atom (0));\n";
7839     pr "  else {\n";
7840     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7841     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7842     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7843     pr "      caml_modify (&Field (rv, i), v);\n";
7844     pr "    }\n";
7845     pr "    CAMLreturn (rv);\n";
7846     pr "  }\n";
7847     pr "}\n";
7848     pr "\n";
7849   in
7850
7851   List.iter (
7852     fun (typ, cols) ->
7853       let has_optpercent_col =
7854         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7855
7856       pr "static CAMLprim value\n";
7857       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7858       pr "{\n";
7859       pr "  CAMLparam0 ();\n";
7860       if has_optpercent_col then
7861         pr "  CAMLlocal3 (rv, v, v2);\n"
7862       else
7863         pr "  CAMLlocal2 (rv, v);\n";
7864       pr "\n";
7865       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7866       iteri (
7867         fun i col ->
7868           (match col with
7869            | name, FString ->
7870                pr "  v = caml_copy_string (%s->%s);\n" typ name
7871            | name, FBuffer ->
7872                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7873                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7874                  typ name typ name
7875            | name, FUUID ->
7876                pr "  v = caml_alloc_string (32);\n";
7877                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7878            | name, (FBytes|FInt64|FUInt64) ->
7879                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7880            | name, (FInt32|FUInt32) ->
7881                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7882            | name, FOptPercent ->
7883                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7884                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7885                pr "    v = caml_alloc (1, 0);\n";
7886                pr "    Store_field (v, 0, v2);\n";
7887                pr "  } else /* None */\n";
7888                pr "    v = Val_int (0);\n";
7889            | name, FChar ->
7890                pr "  v = Val_int (%s->%s);\n" typ name
7891           );
7892           pr "  Store_field (rv, %d, v);\n" i
7893       ) cols;
7894       pr "  CAMLreturn (rv);\n";
7895       pr "}\n";
7896       pr "\n";
7897   ) structs;
7898
7899   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7900   List.iter (
7901     function
7902     | typ, (RStructListOnly | RStructAndList) ->
7903         (* generate the function for typ *)
7904         emit_ocaml_copy_list_function typ
7905     | typ, _ -> () (* empty *)
7906   ) (rstructs_used_by all_functions);
7907
7908   (* The wrappers. *)
7909   List.iter (
7910     fun (name, style, _, _, _, _, _) ->
7911       pr "/* Automatically generated wrapper for function\n";
7912       pr " * ";
7913       generate_ocaml_prototype name style;
7914       pr " */\n";
7915       pr "\n";
7916
7917       let params =
7918         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7919
7920       let needs_extra_vs =
7921         match fst style with RConstOptString _ -> true | _ -> false in
7922
7923       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7924       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7925       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7926       pr "\n";
7927
7928       pr "CAMLprim value\n";
7929       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7930       List.iter (pr ", value %s") (List.tl params);
7931       pr ")\n";
7932       pr "{\n";
7933
7934       (match params with
7935        | [p1; p2; p3; p4; p5] ->
7936            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7937        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7938            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7939            pr "  CAMLxparam%d (%s);\n"
7940              (List.length rest) (String.concat ", " rest)
7941        | ps ->
7942            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7943       );
7944       if not needs_extra_vs then
7945         pr "  CAMLlocal1 (rv);\n"
7946       else
7947         pr "  CAMLlocal3 (rv, v, v2);\n";
7948       pr "\n";
7949
7950       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7951       pr "  if (g == NULL)\n";
7952       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7953       pr "\n";
7954
7955       List.iter (
7956         function
7957         | Pathname n
7958         | Device n | Dev_or_Path n
7959         | String n
7960         | FileIn n
7961         | FileOut n ->
7962             pr "  const char *%s = String_val (%sv);\n" n n
7963         | OptString n ->
7964             pr "  const char *%s =\n" n;
7965             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7966               n n
7967         | StringList n | DeviceList n ->
7968             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7969         | Bool n ->
7970             pr "  int %s = Bool_val (%sv);\n" n n
7971         | Int n ->
7972             pr "  int %s = Int_val (%sv);\n" n n
7973         | Int64 n ->
7974             pr "  int64_t %s = Int64_val (%sv);\n" n n
7975       ) (snd style);
7976       let error_code =
7977         match fst style with
7978         | RErr -> pr "  int r;\n"; "-1"
7979         | RInt _ -> pr "  int r;\n"; "-1"
7980         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7981         | RBool _ -> pr "  int r;\n"; "-1"
7982         | RConstString _ | RConstOptString _ ->
7983             pr "  const char *r;\n"; "NULL"
7984         | RString _ -> pr "  char *r;\n"; "NULL"
7985         | RStringList _ ->
7986             pr "  int i;\n";
7987             pr "  char **r;\n";
7988             "NULL"
7989         | RStruct (_, typ) ->
7990             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7991         | RStructList (_, typ) ->
7992             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7993         | RHashtable _ ->
7994             pr "  int i;\n";
7995             pr "  char **r;\n";
7996             "NULL"
7997         | RBufferOut _ ->
7998             pr "  char *r;\n";
7999             pr "  size_t size;\n";
8000             "NULL" in
8001       pr "\n";
8002
8003       pr "  caml_enter_blocking_section ();\n";
8004       pr "  r = guestfs_%s " name;
8005       generate_c_call_args ~handle:"g" style;
8006       pr ";\n";
8007       pr "  caml_leave_blocking_section ();\n";
8008
8009       List.iter (
8010         function
8011         | StringList n | DeviceList n ->
8012             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8013         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8014         | Bool _ | Int _ | Int64 _
8015         | FileIn _ | FileOut _ -> ()
8016       ) (snd style);
8017
8018       pr "  if (r == %s)\n" error_code;
8019       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8020       pr "\n";
8021
8022       (match fst style with
8023        | RErr -> pr "  rv = Val_unit;\n"
8024        | RInt _ -> pr "  rv = Val_int (r);\n"
8025        | RInt64 _ ->
8026            pr "  rv = caml_copy_int64 (r);\n"
8027        | RBool _ -> pr "  rv = Val_bool (r);\n"
8028        | RConstString _ ->
8029            pr "  rv = caml_copy_string (r);\n"
8030        | RConstOptString _ ->
8031            pr "  if (r) { /* Some string */\n";
8032            pr "    v = caml_alloc (1, 0);\n";
8033            pr "    v2 = caml_copy_string (r);\n";
8034            pr "    Store_field (v, 0, v2);\n";
8035            pr "  } else /* None */\n";
8036            pr "    v = Val_int (0);\n";
8037        | RString _ ->
8038            pr "  rv = caml_copy_string (r);\n";
8039            pr "  free (r);\n"
8040        | RStringList _ ->
8041            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8042            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8043            pr "  free (r);\n"
8044        | RStruct (_, typ) ->
8045            pr "  rv = copy_%s (r);\n" typ;
8046            pr "  guestfs_free_%s (r);\n" typ;
8047        | RStructList (_, typ) ->
8048            pr "  rv = copy_%s_list (r);\n" typ;
8049            pr "  guestfs_free_%s_list (r);\n" typ;
8050        | RHashtable _ ->
8051            pr "  rv = copy_table (r);\n";
8052            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8053            pr "  free (r);\n";
8054        | RBufferOut _ ->
8055            pr "  rv = caml_alloc_string (size);\n";
8056            pr "  memcpy (String_val (rv), r, size);\n";
8057       );
8058
8059       pr "  CAMLreturn (rv);\n";
8060       pr "}\n";
8061       pr "\n";
8062
8063       if List.length params > 5 then (
8064         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8065         pr "CAMLprim value ";
8066         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8067         pr "CAMLprim value\n";
8068         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8069         pr "{\n";
8070         pr "  return ocaml_guestfs_%s (argv[0]" name;
8071         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8072         pr ");\n";
8073         pr "}\n";
8074         pr "\n"
8075       )
8076   ) all_functions_sorted
8077
8078 and generate_ocaml_structure_decls () =
8079   List.iter (
8080     fun (typ, cols) ->
8081       pr "type %s = {\n" typ;
8082       List.iter (
8083         function
8084         | name, FString -> pr "  %s : string;\n" name
8085         | name, FBuffer -> pr "  %s : string;\n" name
8086         | name, FUUID -> pr "  %s : string;\n" name
8087         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8088         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8089         | name, FChar -> pr "  %s : char;\n" name
8090         | name, FOptPercent -> pr "  %s : float option;\n" name
8091       ) cols;
8092       pr "}\n";
8093       pr "\n"
8094   ) structs
8095
8096 and generate_ocaml_prototype ?(is_external = false) name style =
8097   if is_external then pr "external " else pr "val ";
8098   pr "%s : t -> " name;
8099   List.iter (
8100     function
8101     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8102     | OptString _ -> pr "string option -> "
8103     | StringList _ | DeviceList _ -> pr "string array -> "
8104     | Bool _ -> pr "bool -> "
8105     | Int _ -> pr "int -> "
8106     | Int64 _ -> pr "int64 -> "
8107   ) (snd style);
8108   (match fst style with
8109    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8110    | RInt _ -> pr "int"
8111    | RInt64 _ -> pr "int64"
8112    | RBool _ -> pr "bool"
8113    | RConstString _ -> pr "string"
8114    | RConstOptString _ -> pr "string option"
8115    | RString _ | RBufferOut _ -> pr "string"
8116    | RStringList _ -> pr "string array"
8117    | RStruct (_, typ) -> pr "%s" typ
8118    | RStructList (_, typ) -> pr "%s array" typ
8119    | RHashtable _ -> pr "(string * string) list"
8120   );
8121   if is_external then (
8122     pr " = ";
8123     if List.length (snd style) + 1 > 5 then
8124       pr "\"ocaml_guestfs_%s_byte\" " name;
8125     pr "\"ocaml_guestfs_%s\"" name
8126   );
8127   pr "\n"
8128
8129 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8130 and generate_perl_xs () =
8131   generate_header CStyle LGPLv2plus;
8132
8133   pr "\
8134 #include \"EXTERN.h\"
8135 #include \"perl.h\"
8136 #include \"XSUB.h\"
8137
8138 #include <guestfs.h>
8139
8140 #ifndef PRId64
8141 #define PRId64 \"lld\"
8142 #endif
8143
8144 static SV *
8145 my_newSVll(long long val) {
8146 #ifdef USE_64_BIT_ALL
8147   return newSViv(val);
8148 #else
8149   char buf[100];
8150   int len;
8151   len = snprintf(buf, 100, \"%%\" PRId64, val);
8152   return newSVpv(buf, len);
8153 #endif
8154 }
8155
8156 #ifndef PRIu64
8157 #define PRIu64 \"llu\"
8158 #endif
8159
8160 static SV *
8161 my_newSVull(unsigned long long val) {
8162 #ifdef USE_64_BIT_ALL
8163   return newSVuv(val);
8164 #else
8165   char buf[100];
8166   int len;
8167   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8168   return newSVpv(buf, len);
8169 #endif
8170 }
8171
8172 /* http://www.perlmonks.org/?node_id=680842 */
8173 static char **
8174 XS_unpack_charPtrPtr (SV *arg) {
8175   char **ret;
8176   AV *av;
8177   I32 i;
8178
8179   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8180     croak (\"array reference expected\");
8181
8182   av = (AV *)SvRV (arg);
8183   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8184   if (!ret)
8185     croak (\"malloc failed\");
8186
8187   for (i = 0; i <= av_len (av); i++) {
8188     SV **elem = av_fetch (av, i, 0);
8189
8190     if (!elem || !*elem)
8191       croak (\"missing element in list\");
8192
8193     ret[i] = SvPV_nolen (*elem);
8194   }
8195
8196   ret[i] = NULL;
8197
8198   return ret;
8199 }
8200
8201 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8202
8203 PROTOTYPES: ENABLE
8204
8205 guestfs_h *
8206 _create ()
8207    CODE:
8208       RETVAL = guestfs_create ();
8209       if (!RETVAL)
8210         croak (\"could not create guestfs handle\");
8211       guestfs_set_error_handler (RETVAL, NULL, NULL);
8212  OUTPUT:
8213       RETVAL
8214
8215 void
8216 DESTROY (g)
8217       guestfs_h *g;
8218  PPCODE:
8219       guestfs_close (g);
8220
8221 ";
8222
8223   List.iter (
8224     fun (name, style, _, _, _, _, _) ->
8225       (match fst style with
8226        | RErr -> pr "void\n"
8227        | RInt _ -> pr "SV *\n"
8228        | RInt64 _ -> pr "SV *\n"
8229        | RBool _ -> pr "SV *\n"
8230        | RConstString _ -> pr "SV *\n"
8231        | RConstOptString _ -> pr "SV *\n"
8232        | RString _ -> pr "SV *\n"
8233        | RBufferOut _ -> pr "SV *\n"
8234        | RStringList _
8235        | RStruct _ | RStructList _
8236        | RHashtable _ ->
8237            pr "void\n" (* all lists returned implictly on the stack *)
8238       );
8239       (* Call and arguments. *)
8240       pr "%s " name;
8241       generate_c_call_args ~handle:"g" ~decl:true style;
8242       pr "\n";
8243       pr "      guestfs_h *g;\n";
8244       iteri (
8245         fun i ->
8246           function
8247           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8248               pr "      char *%s;\n" n
8249           | OptString n ->
8250               (* http://www.perlmonks.org/?node_id=554277
8251                * Note that the implicit handle argument means we have
8252                * to add 1 to the ST(x) operator.
8253                *)
8254               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8255           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8256           | Bool n -> pr "      int %s;\n" n
8257           | Int n -> pr "      int %s;\n" n
8258           | Int64 n -> pr "      int64_t %s;\n" n
8259       ) (snd style);
8260
8261       let do_cleanups () =
8262         List.iter (
8263           function
8264           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8265           | Bool _ | Int _ | Int64 _
8266           | FileIn _ | FileOut _ -> ()
8267           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8268         ) (snd style)
8269       in
8270
8271       (* Code. *)
8272       (match fst style with
8273        | RErr ->
8274            pr "PREINIT:\n";
8275            pr "      int r;\n";
8276            pr " PPCODE:\n";
8277            pr "      r = guestfs_%s " name;
8278            generate_c_call_args ~handle:"g" style;
8279            pr ";\n";
8280            do_cleanups ();
8281            pr "      if (r == -1)\n";
8282            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8283        | RInt n
8284        | RBool n ->
8285            pr "PREINIT:\n";
8286            pr "      int %s;\n" n;
8287            pr "   CODE:\n";
8288            pr "      %s = guestfs_%s " n name;
8289            generate_c_call_args ~handle:"g" style;
8290            pr ";\n";
8291            do_cleanups ();
8292            pr "      if (%s == -1)\n" n;
8293            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8294            pr "      RETVAL = newSViv (%s);\n" n;
8295            pr " OUTPUT:\n";
8296            pr "      RETVAL\n"
8297        | RInt64 n ->
8298            pr "PREINIT:\n";
8299            pr "      int64_t %s;\n" n;
8300            pr "   CODE:\n";
8301            pr "      %s = guestfs_%s " n name;
8302            generate_c_call_args ~handle:"g" style;
8303            pr ";\n";
8304            do_cleanups ();
8305            pr "      if (%s == -1)\n" n;
8306            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8307            pr "      RETVAL = my_newSVll (%s);\n" n;
8308            pr " OUTPUT:\n";
8309            pr "      RETVAL\n"
8310        | RConstString n ->
8311            pr "PREINIT:\n";
8312            pr "      const char *%s;\n" n;
8313            pr "   CODE:\n";
8314            pr "      %s = guestfs_%s " n name;
8315            generate_c_call_args ~handle:"g" style;
8316            pr ";\n";
8317            do_cleanups ();
8318            pr "      if (%s == NULL)\n" n;
8319            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8320            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8321            pr " OUTPUT:\n";
8322            pr "      RETVAL\n"
8323        | RConstOptString n ->
8324            pr "PREINIT:\n";
8325            pr "      const char *%s;\n" n;
8326            pr "   CODE:\n";
8327            pr "      %s = guestfs_%s " n name;
8328            generate_c_call_args ~handle:"g" style;
8329            pr ";\n";
8330            do_cleanups ();
8331            pr "      if (%s == NULL)\n" n;
8332            pr "        RETVAL = &PL_sv_undef;\n";
8333            pr "      else\n";
8334            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8335            pr " OUTPUT:\n";
8336            pr "      RETVAL\n"
8337        | RString n ->
8338            pr "PREINIT:\n";
8339            pr "      char *%s;\n" n;
8340            pr "   CODE:\n";
8341            pr "      %s = guestfs_%s " n name;
8342            generate_c_call_args ~handle:"g" style;
8343            pr ";\n";
8344            do_cleanups ();
8345            pr "      if (%s == NULL)\n" n;
8346            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8347            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8348            pr "      free (%s);\n" n;
8349            pr " OUTPUT:\n";
8350            pr "      RETVAL\n"
8351        | RStringList n | RHashtable n ->
8352            pr "PREINIT:\n";
8353            pr "      char **%s;\n" n;
8354            pr "      int i, n;\n";
8355            pr " PPCODE:\n";
8356            pr "      %s = guestfs_%s " n name;
8357            generate_c_call_args ~handle:"g" style;
8358            pr ";\n";
8359            do_cleanups ();
8360            pr "      if (%s == NULL)\n" n;
8361            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8362            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8363            pr "      EXTEND (SP, n);\n";
8364            pr "      for (i = 0; i < n; ++i) {\n";
8365            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8366            pr "        free (%s[i]);\n" n;
8367            pr "      }\n";
8368            pr "      free (%s);\n" n;
8369        | RStruct (n, typ) ->
8370            let cols = cols_of_struct typ in
8371            generate_perl_struct_code typ cols name style n do_cleanups
8372        | RStructList (n, typ) ->
8373            let cols = cols_of_struct typ in
8374            generate_perl_struct_list_code typ cols name style n do_cleanups
8375        | RBufferOut n ->
8376            pr "PREINIT:\n";
8377            pr "      char *%s;\n" n;
8378            pr "      size_t size;\n";
8379            pr "   CODE:\n";
8380            pr "      %s = guestfs_%s " n name;
8381            generate_c_call_args ~handle:"g" style;
8382            pr ";\n";
8383            do_cleanups ();
8384            pr "      if (%s == NULL)\n" n;
8385            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8386            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8387            pr "      free (%s);\n" n;
8388            pr " OUTPUT:\n";
8389            pr "      RETVAL\n"
8390       );
8391
8392       pr "\n"
8393   ) all_functions
8394
8395 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8396   pr "PREINIT:\n";
8397   pr "      struct guestfs_%s_list *%s;\n" typ n;
8398   pr "      int i;\n";
8399   pr "      HV *hv;\n";
8400   pr " PPCODE:\n";
8401   pr "      %s = guestfs_%s " n name;
8402   generate_c_call_args ~handle:"g" style;
8403   pr ";\n";
8404   do_cleanups ();
8405   pr "      if (%s == NULL)\n" n;
8406   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8407   pr "      EXTEND (SP, %s->len);\n" n;
8408   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8409   pr "        hv = newHV ();\n";
8410   List.iter (
8411     function
8412     | name, FString ->
8413         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8414           name (String.length name) n name
8415     | name, FUUID ->
8416         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8417           name (String.length name) n name
8418     | name, FBuffer ->
8419         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8420           name (String.length name) n name n name
8421     | name, (FBytes|FUInt64) ->
8422         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8423           name (String.length name) n name
8424     | name, FInt64 ->
8425         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8426           name (String.length name) n name
8427     | name, (FInt32|FUInt32) ->
8428         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8429           name (String.length name) n name
8430     | name, FChar ->
8431         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8432           name (String.length name) n name
8433     | name, FOptPercent ->
8434         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8435           name (String.length name) n name
8436   ) cols;
8437   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8438   pr "      }\n";
8439   pr "      guestfs_free_%s_list (%s);\n" typ n
8440
8441 and generate_perl_struct_code typ cols name style n do_cleanups =
8442   pr "PREINIT:\n";
8443   pr "      struct guestfs_%s *%s;\n" typ n;
8444   pr " PPCODE:\n";
8445   pr "      %s = guestfs_%s " n name;
8446   generate_c_call_args ~handle:"g" style;
8447   pr ";\n";
8448   do_cleanups ();
8449   pr "      if (%s == NULL)\n" n;
8450   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8451   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8452   List.iter (
8453     fun ((name, _) as col) ->
8454       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8455
8456       match col with
8457       | name, FString ->
8458           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8459             n name
8460       | name, FBuffer ->
8461           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8462             n name n name
8463       | name, FUUID ->
8464           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8465             n name
8466       | name, (FBytes|FUInt64) ->
8467           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8468             n name
8469       | name, FInt64 ->
8470           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8471             n name
8472       | name, (FInt32|FUInt32) ->
8473           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8474             n name
8475       | name, FChar ->
8476           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8477             n name
8478       | name, FOptPercent ->
8479           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8480             n name
8481   ) cols;
8482   pr "      free (%s);\n" n
8483
8484 (* Generate Sys/Guestfs.pm. *)
8485 and generate_perl_pm () =
8486   generate_header HashStyle LGPLv2plus;
8487
8488   pr "\
8489 =pod
8490
8491 =head1 NAME
8492
8493 Sys::Guestfs - Perl bindings for libguestfs
8494
8495 =head1 SYNOPSIS
8496
8497  use Sys::Guestfs;
8498
8499  my $h = Sys::Guestfs->new ();
8500  $h->add_drive ('guest.img');
8501  $h->launch ();
8502  $h->mount ('/dev/sda1', '/');
8503  $h->touch ('/hello');
8504  $h->sync ();
8505
8506 =head1 DESCRIPTION
8507
8508 The C<Sys::Guestfs> module provides a Perl XS binding to the
8509 libguestfs API for examining and modifying virtual machine
8510 disk images.
8511
8512 Amongst the things this is good for: making batch configuration
8513 changes to guests, getting disk used/free statistics (see also:
8514 virt-df), migrating between virtualization systems (see also:
8515 virt-p2v), performing partial backups, performing partial guest
8516 clones, cloning guests and changing registry/UUID/hostname info, and
8517 much else besides.
8518
8519 Libguestfs uses Linux kernel and qemu code, and can access any type of
8520 guest filesystem that Linux and qemu can, including but not limited
8521 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8522 schemes, qcow, qcow2, vmdk.
8523
8524 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8525 LVs, what filesystem is in each LV, etc.).  It can also run commands
8526 in the context of the guest.  Also you can access filesystems over
8527 FUSE.
8528
8529 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8530 functions for using libguestfs from Perl, including integration
8531 with libvirt.
8532
8533 =head1 ERRORS
8534
8535 All errors turn into calls to C<croak> (see L<Carp(3)>).
8536
8537 =head1 METHODS
8538
8539 =over 4
8540
8541 =cut
8542
8543 package Sys::Guestfs;
8544
8545 use strict;
8546 use warnings;
8547
8548 require XSLoader;
8549 XSLoader::load ('Sys::Guestfs');
8550
8551 =item $h = Sys::Guestfs->new ();
8552
8553 Create a new guestfs handle.
8554
8555 =cut
8556
8557 sub new {
8558   my $proto = shift;
8559   my $class = ref ($proto) || $proto;
8560
8561   my $self = Sys::Guestfs::_create ();
8562   bless $self, $class;
8563   return $self;
8564 }
8565
8566 ";
8567
8568   (* Actions.  We only need to print documentation for these as
8569    * they are pulled in from the XS code automatically.
8570    *)
8571   List.iter (
8572     fun (name, style, _, flags, _, _, longdesc) ->
8573       if not (List.mem NotInDocs flags) then (
8574         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8575         pr "=item ";
8576         generate_perl_prototype name style;
8577         pr "\n\n";
8578         pr "%s\n\n" longdesc;
8579         if List.mem ProtocolLimitWarning flags then
8580           pr "%s\n\n" protocol_limit_warning;
8581         if List.mem DangerWillRobinson flags then
8582           pr "%s\n\n" danger_will_robinson;
8583         match deprecation_notice flags with
8584         | None -> ()
8585         | Some txt -> pr "%s\n\n" txt
8586       )
8587   ) all_functions_sorted;
8588
8589   (* End of file. *)
8590   pr "\
8591 =cut
8592
8593 1;
8594
8595 =back
8596
8597 =head1 COPYRIGHT
8598
8599 Copyright (C) %s Red Hat Inc.
8600
8601 =head1 LICENSE
8602
8603 Please see the file COPYING.LIB for the full license.
8604
8605 =head1 SEE ALSO
8606
8607 L<guestfs(3)>,
8608 L<guestfish(1)>,
8609 L<http://libguestfs.org>,
8610 L<Sys::Guestfs::Lib(3)>.
8611
8612 =cut
8613 " copyright_years
8614
8615 and generate_perl_prototype name style =
8616   (match fst style with
8617    | RErr -> ()
8618    | RBool n
8619    | RInt n
8620    | RInt64 n
8621    | RConstString n
8622    | RConstOptString n
8623    | RString n
8624    | RBufferOut n -> pr "$%s = " n
8625    | RStruct (n,_)
8626    | RHashtable n -> pr "%%%s = " n
8627    | RStringList n
8628    | RStructList (n,_) -> pr "@%s = " n
8629   );
8630   pr "$h->%s (" name;
8631   let comma = ref false in
8632   List.iter (
8633     fun arg ->
8634       if !comma then pr ", ";
8635       comma := true;
8636       match arg with
8637       | Pathname n | Device n | Dev_or_Path n | String n
8638       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8639           pr "$%s" n
8640       | StringList n | DeviceList n ->
8641           pr "\\@%s" n
8642   ) (snd style);
8643   pr ");"
8644
8645 (* Generate Python C module. *)
8646 and generate_python_c () =
8647   generate_header CStyle LGPLv2plus;
8648
8649   pr "\
8650 #include <Python.h>
8651
8652 #include <stdio.h>
8653 #include <stdlib.h>
8654 #include <assert.h>
8655
8656 #include \"guestfs.h\"
8657
8658 typedef struct {
8659   PyObject_HEAD
8660   guestfs_h *g;
8661 } Pyguestfs_Object;
8662
8663 static guestfs_h *
8664 get_handle (PyObject *obj)
8665 {
8666   assert (obj);
8667   assert (obj != Py_None);
8668   return ((Pyguestfs_Object *) obj)->g;
8669 }
8670
8671 static PyObject *
8672 put_handle (guestfs_h *g)
8673 {
8674   assert (g);
8675   return
8676     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8677 }
8678
8679 /* This list should be freed (but not the strings) after use. */
8680 static char **
8681 get_string_list (PyObject *obj)
8682 {
8683   int i, len;
8684   char **r;
8685
8686   assert (obj);
8687
8688   if (!PyList_Check (obj)) {
8689     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8690     return NULL;
8691   }
8692
8693   len = PyList_Size (obj);
8694   r = malloc (sizeof (char *) * (len+1));
8695   if (r == NULL) {
8696     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8697     return NULL;
8698   }
8699
8700   for (i = 0; i < len; ++i)
8701     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8702   r[len] = NULL;
8703
8704   return r;
8705 }
8706
8707 static PyObject *
8708 put_string_list (char * const * const argv)
8709 {
8710   PyObject *list;
8711   int argc, i;
8712
8713   for (argc = 0; argv[argc] != NULL; ++argc)
8714     ;
8715
8716   list = PyList_New (argc);
8717   for (i = 0; i < argc; ++i)
8718     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8719
8720   return list;
8721 }
8722
8723 static PyObject *
8724 put_table (char * const * const argv)
8725 {
8726   PyObject *list, *item;
8727   int argc, i;
8728
8729   for (argc = 0; argv[argc] != NULL; ++argc)
8730     ;
8731
8732   list = PyList_New (argc >> 1);
8733   for (i = 0; i < argc; i += 2) {
8734     item = PyTuple_New (2);
8735     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8736     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8737     PyList_SetItem (list, i >> 1, item);
8738   }
8739
8740   return list;
8741 }
8742
8743 static void
8744 free_strings (char **argv)
8745 {
8746   int argc;
8747
8748   for (argc = 0; argv[argc] != NULL; ++argc)
8749     free (argv[argc]);
8750   free (argv);
8751 }
8752
8753 static PyObject *
8754 py_guestfs_create (PyObject *self, PyObject *args)
8755 {
8756   guestfs_h *g;
8757
8758   g = guestfs_create ();
8759   if (g == NULL) {
8760     PyErr_SetString (PyExc_RuntimeError,
8761                      \"guestfs.create: failed to allocate handle\");
8762     return NULL;
8763   }
8764   guestfs_set_error_handler (g, NULL, NULL);
8765   return put_handle (g);
8766 }
8767
8768 static PyObject *
8769 py_guestfs_close (PyObject *self, PyObject *args)
8770 {
8771   PyObject *py_g;
8772   guestfs_h *g;
8773
8774   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8775     return NULL;
8776   g = get_handle (py_g);
8777
8778   guestfs_close (g);
8779
8780   Py_INCREF (Py_None);
8781   return Py_None;
8782 }
8783
8784 ";
8785
8786   let emit_put_list_function typ =
8787     pr "static PyObject *\n";
8788     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8789     pr "{\n";
8790     pr "  PyObject *list;\n";
8791     pr "  int i;\n";
8792     pr "\n";
8793     pr "  list = PyList_New (%ss->len);\n" typ;
8794     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8795     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8796     pr "  return list;\n";
8797     pr "};\n";
8798     pr "\n"
8799   in
8800
8801   (* Structures, turned into Python dictionaries. *)
8802   List.iter (
8803     fun (typ, cols) ->
8804       pr "static PyObject *\n";
8805       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8806       pr "{\n";
8807       pr "  PyObject *dict;\n";
8808       pr "\n";
8809       pr "  dict = PyDict_New ();\n";
8810       List.iter (
8811         function
8812         | name, FString ->
8813             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8814             pr "                        PyString_FromString (%s->%s));\n"
8815               typ name
8816         | name, FBuffer ->
8817             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8818             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8819               typ name typ name
8820         | name, FUUID ->
8821             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8822             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8823               typ name
8824         | name, (FBytes|FUInt64) ->
8825             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8826             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8827               typ name
8828         | name, FInt64 ->
8829             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8830             pr "                        PyLong_FromLongLong (%s->%s));\n"
8831               typ name
8832         | name, FUInt32 ->
8833             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8834             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8835               typ name
8836         | name, FInt32 ->
8837             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8838             pr "                        PyLong_FromLong (%s->%s));\n"
8839               typ name
8840         | name, FOptPercent ->
8841             pr "  if (%s->%s >= 0)\n" typ name;
8842             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8843             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8844               typ name;
8845             pr "  else {\n";
8846             pr "    Py_INCREF (Py_None);\n";
8847             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8848             pr "  }\n"
8849         | name, FChar ->
8850             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8851             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8852       ) cols;
8853       pr "  return dict;\n";
8854       pr "};\n";
8855       pr "\n";
8856
8857   ) structs;
8858
8859   (* Emit a put_TYPE_list function definition only if that function is used. *)
8860   List.iter (
8861     function
8862     | typ, (RStructListOnly | RStructAndList) ->
8863         (* generate the function for typ *)
8864         emit_put_list_function typ
8865     | typ, _ -> () (* empty *)
8866   ) (rstructs_used_by all_functions);
8867
8868   (* Python wrapper functions. *)
8869   List.iter (
8870     fun (name, style, _, _, _, _, _) ->
8871       pr "static PyObject *\n";
8872       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8873       pr "{\n";
8874
8875       pr "  PyObject *py_g;\n";
8876       pr "  guestfs_h *g;\n";
8877       pr "  PyObject *py_r;\n";
8878
8879       let error_code =
8880         match fst style with
8881         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8882         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8883         | RConstString _ | RConstOptString _ ->
8884             pr "  const char *r;\n"; "NULL"
8885         | RString _ -> pr "  char *r;\n"; "NULL"
8886         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8887         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8888         | RStructList (_, typ) ->
8889             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8890         | RBufferOut _ ->
8891             pr "  char *r;\n";
8892             pr "  size_t size;\n";
8893             "NULL" in
8894
8895       List.iter (
8896         function
8897         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8898             pr "  const char *%s;\n" n
8899         | OptString n -> pr "  const char *%s;\n" n
8900         | StringList n | DeviceList n ->
8901             pr "  PyObject *py_%s;\n" n;
8902             pr "  char **%s;\n" n
8903         | Bool n -> pr "  int %s;\n" n
8904         | Int n -> pr "  int %s;\n" n
8905         | Int64 n -> pr "  long long %s;\n" n
8906       ) (snd style);
8907
8908       pr "\n";
8909
8910       (* Convert the parameters. *)
8911       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8912       List.iter (
8913         function
8914         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8915         | OptString _ -> pr "z"
8916         | StringList _ | DeviceList _ -> pr "O"
8917         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8918         | Int _ -> pr "i"
8919         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8920                              * emulate C's int/long/long long in Python?
8921                              *)
8922       ) (snd style);
8923       pr ":guestfs_%s\",\n" name;
8924       pr "                         &py_g";
8925       List.iter (
8926         function
8927         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8928         | OptString n -> pr ", &%s" n
8929         | StringList n | DeviceList n -> pr ", &py_%s" n
8930         | Bool n -> pr ", &%s" n
8931         | Int n -> pr ", &%s" n
8932         | Int64 n -> pr ", &%s" n
8933       ) (snd style);
8934
8935       pr "))\n";
8936       pr "    return NULL;\n";
8937
8938       pr "  g = get_handle (py_g);\n";
8939       List.iter (
8940         function
8941         | Pathname _ | Device _ | Dev_or_Path _ | String _
8942         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8943         | StringList n | DeviceList n ->
8944             pr "  %s = get_string_list (py_%s);\n" n n;
8945             pr "  if (!%s) return NULL;\n" n
8946       ) (snd style);
8947
8948       pr "\n";
8949
8950       pr "  r = guestfs_%s " name;
8951       generate_c_call_args ~handle:"g" style;
8952       pr ";\n";
8953
8954       List.iter (
8955         function
8956         | Pathname _ | Device _ | Dev_or_Path _ | String _
8957         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8958         | StringList n | DeviceList n ->
8959             pr "  free (%s);\n" n
8960       ) (snd style);
8961
8962       pr "  if (r == %s) {\n" error_code;
8963       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8964       pr "    return NULL;\n";
8965       pr "  }\n";
8966       pr "\n";
8967
8968       (match fst style with
8969        | RErr ->
8970            pr "  Py_INCREF (Py_None);\n";
8971            pr "  py_r = Py_None;\n"
8972        | RInt _
8973        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8974        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8975        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8976        | RConstOptString _ ->
8977            pr "  if (r)\n";
8978            pr "    py_r = PyString_FromString (r);\n";
8979            pr "  else {\n";
8980            pr "    Py_INCREF (Py_None);\n";
8981            pr "    py_r = Py_None;\n";
8982            pr "  }\n"
8983        | RString _ ->
8984            pr "  py_r = PyString_FromString (r);\n";
8985            pr "  free (r);\n"
8986        | RStringList _ ->
8987            pr "  py_r = put_string_list (r);\n";
8988            pr "  free_strings (r);\n"
8989        | RStruct (_, typ) ->
8990            pr "  py_r = put_%s (r);\n" typ;
8991            pr "  guestfs_free_%s (r);\n" typ
8992        | RStructList (_, typ) ->
8993            pr "  py_r = put_%s_list (r);\n" typ;
8994            pr "  guestfs_free_%s_list (r);\n" typ
8995        | RHashtable n ->
8996            pr "  py_r = put_table (r);\n";
8997            pr "  free_strings (r);\n"
8998        | RBufferOut _ ->
8999            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9000            pr "  free (r);\n"
9001       );
9002
9003       pr "  return py_r;\n";
9004       pr "}\n";
9005       pr "\n"
9006   ) all_functions;
9007
9008   (* Table of functions. *)
9009   pr "static PyMethodDef methods[] = {\n";
9010   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9011   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9012   List.iter (
9013     fun (name, _, _, _, _, _, _) ->
9014       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9015         name name
9016   ) all_functions;
9017   pr "  { NULL, NULL, 0, NULL }\n";
9018   pr "};\n";
9019   pr "\n";
9020
9021   (* Init function. *)
9022   pr "\
9023 void
9024 initlibguestfsmod (void)
9025 {
9026   static int initialized = 0;
9027
9028   if (initialized) return;
9029   Py_InitModule ((char *) \"libguestfsmod\", methods);
9030   initialized = 1;
9031 }
9032 "
9033
9034 (* Generate Python module. *)
9035 and generate_python_py () =
9036   generate_header HashStyle LGPLv2plus;
9037
9038   pr "\
9039 u\"\"\"Python bindings for libguestfs
9040
9041 import guestfs
9042 g = guestfs.GuestFS ()
9043 g.add_drive (\"guest.img\")
9044 g.launch ()
9045 parts = g.list_partitions ()
9046
9047 The guestfs module provides a Python binding to the libguestfs API
9048 for examining and modifying virtual machine disk images.
9049
9050 Amongst the things this is good for: making batch configuration
9051 changes to guests, getting disk used/free statistics (see also:
9052 virt-df), migrating between virtualization systems (see also:
9053 virt-p2v), performing partial backups, performing partial guest
9054 clones, cloning guests and changing registry/UUID/hostname info, and
9055 much else besides.
9056
9057 Libguestfs uses Linux kernel and qemu code, and can access any type of
9058 guest filesystem that Linux and qemu can, including but not limited
9059 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9060 schemes, qcow, qcow2, vmdk.
9061
9062 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9063 LVs, what filesystem is in each LV, etc.).  It can also run commands
9064 in the context of the guest.  Also you can access filesystems over
9065 FUSE.
9066
9067 Errors which happen while using the API are turned into Python
9068 RuntimeError exceptions.
9069
9070 To create a guestfs handle you usually have to perform the following
9071 sequence of calls:
9072
9073 # Create the handle, call add_drive at least once, and possibly
9074 # several times if the guest has multiple block devices:
9075 g = guestfs.GuestFS ()
9076 g.add_drive (\"guest.img\")
9077
9078 # Launch the qemu subprocess and wait for it to become ready:
9079 g.launch ()
9080
9081 # Now you can issue commands, for example:
9082 logvols = g.lvs ()
9083
9084 \"\"\"
9085
9086 import libguestfsmod
9087
9088 class GuestFS:
9089     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9090
9091     def __init__ (self):
9092         \"\"\"Create a new libguestfs handle.\"\"\"
9093         self._o = libguestfsmod.create ()
9094
9095     def __del__ (self):
9096         libguestfsmod.close (self._o)
9097
9098 ";
9099
9100   List.iter (
9101     fun (name, style, _, flags, _, _, longdesc) ->
9102       pr "    def %s " name;
9103       generate_py_call_args ~handle:"self" (snd style);
9104       pr ":\n";
9105
9106       if not (List.mem NotInDocs flags) then (
9107         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9108         let doc =
9109           match fst style with
9110           | RErr | RInt _ | RInt64 _ | RBool _
9111           | RConstOptString _ | RConstString _
9112           | RString _ | RBufferOut _ -> doc
9113           | RStringList _ ->
9114               doc ^ "\n\nThis function returns a list of strings."
9115           | RStruct (_, typ) ->
9116               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9117           | RStructList (_, typ) ->
9118               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9119           | RHashtable _ ->
9120               doc ^ "\n\nThis function returns a dictionary." in
9121         let doc =
9122           if List.mem ProtocolLimitWarning flags then
9123             doc ^ "\n\n" ^ protocol_limit_warning
9124           else doc in
9125         let doc =
9126           if List.mem DangerWillRobinson flags then
9127             doc ^ "\n\n" ^ danger_will_robinson
9128           else doc in
9129         let doc =
9130           match deprecation_notice flags with
9131           | None -> doc
9132           | Some txt -> doc ^ "\n\n" ^ txt in
9133         let doc = pod2text ~width:60 name doc in
9134         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9135         let doc = String.concat "\n        " doc in
9136         pr "        u\"\"\"%s\"\"\"\n" doc;
9137       );
9138       pr "        return libguestfsmod.%s " name;
9139       generate_py_call_args ~handle:"self._o" (snd style);
9140       pr "\n";
9141       pr "\n";
9142   ) all_functions
9143
9144 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9145 and generate_py_call_args ~handle args =
9146   pr "(%s" handle;
9147   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9148   pr ")"
9149
9150 (* Useful if you need the longdesc POD text as plain text.  Returns a
9151  * list of lines.
9152  *
9153  * Because this is very slow (the slowest part of autogeneration),
9154  * we memoize the results.
9155  *)
9156 and pod2text ~width name longdesc =
9157   let key = width, name, longdesc in
9158   try Hashtbl.find pod2text_memo key
9159   with Not_found ->
9160     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9161     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9162     close_out chan;
9163     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9164     let chan = open_process_in cmd in
9165     let lines = ref [] in
9166     let rec loop i =
9167       let line = input_line chan in
9168       if i = 1 then             (* discard the first line of output *)
9169         loop (i+1)
9170       else (
9171         let line = triml line in
9172         lines := line :: !lines;
9173         loop (i+1)
9174       ) in
9175     let lines = try loop 1 with End_of_file -> List.rev !lines in
9176     unlink filename;
9177     (match close_process_in chan with
9178      | WEXITED 0 -> ()
9179      | WEXITED i ->
9180          failwithf "pod2text: process exited with non-zero status (%d)" i
9181      | WSIGNALED i | WSTOPPED i ->
9182          failwithf "pod2text: process signalled or stopped by signal %d" i
9183     );
9184     Hashtbl.add pod2text_memo key lines;
9185     pod2text_memo_updated ();
9186     lines
9187
9188 (* Generate ruby bindings. *)
9189 and generate_ruby_c () =
9190   generate_header CStyle LGPLv2plus;
9191
9192   pr "\
9193 #include <stdio.h>
9194 #include <stdlib.h>
9195
9196 #include <ruby.h>
9197
9198 #include \"guestfs.h\"
9199
9200 #include \"extconf.h\"
9201
9202 /* For Ruby < 1.9 */
9203 #ifndef RARRAY_LEN
9204 #define RARRAY_LEN(r) (RARRAY((r))->len)
9205 #endif
9206
9207 static VALUE m_guestfs;                 /* guestfs module */
9208 static VALUE c_guestfs;                 /* guestfs_h handle */
9209 static VALUE e_Error;                   /* used for all errors */
9210
9211 static void ruby_guestfs_free (void *p)
9212 {
9213   if (!p) return;
9214   guestfs_close ((guestfs_h *) p);
9215 }
9216
9217 static VALUE ruby_guestfs_create (VALUE m)
9218 {
9219   guestfs_h *g;
9220
9221   g = guestfs_create ();
9222   if (!g)
9223     rb_raise (e_Error, \"failed to create guestfs handle\");
9224
9225   /* Don't print error messages to stderr by default. */
9226   guestfs_set_error_handler (g, NULL, NULL);
9227
9228   /* Wrap it, and make sure the close function is called when the
9229    * handle goes away.
9230    */
9231   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9232 }
9233
9234 static VALUE ruby_guestfs_close (VALUE gv)
9235 {
9236   guestfs_h *g;
9237   Data_Get_Struct (gv, guestfs_h, g);
9238
9239   ruby_guestfs_free (g);
9240   DATA_PTR (gv) = NULL;
9241
9242   return Qnil;
9243 }
9244
9245 ";
9246
9247   List.iter (
9248     fun (name, style, _, _, _, _, _) ->
9249       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9250       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9251       pr ")\n";
9252       pr "{\n";
9253       pr "  guestfs_h *g;\n";
9254       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9255       pr "  if (!g)\n";
9256       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9257         name;
9258       pr "\n";
9259
9260       List.iter (
9261         function
9262         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9263             pr "  Check_Type (%sv, T_STRING);\n" n;
9264             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9265             pr "  if (!%s)\n" n;
9266             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9267             pr "              \"%s\", \"%s\");\n" n name
9268         | OptString n ->
9269             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9270         | StringList n | DeviceList n ->
9271             pr "  char **%s;\n" n;
9272             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9273             pr "  {\n";
9274             pr "    int i, len;\n";
9275             pr "    len = RARRAY_LEN (%sv);\n" n;
9276             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9277               n;
9278             pr "    for (i = 0; i < len; ++i) {\n";
9279             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9280             pr "      %s[i] = StringValueCStr (v);\n" n;
9281             pr "    }\n";
9282             pr "    %s[len] = NULL;\n" n;
9283             pr "  }\n";
9284         | Bool n ->
9285             pr "  int %s = RTEST (%sv);\n" n n
9286         | Int n ->
9287             pr "  int %s = NUM2INT (%sv);\n" n n
9288         | Int64 n ->
9289             pr "  long long %s = NUM2LL (%sv);\n" n n
9290       ) (snd style);
9291       pr "\n";
9292
9293       let error_code =
9294         match fst style with
9295         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9296         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9297         | RConstString _ | RConstOptString _ ->
9298             pr "  const char *r;\n"; "NULL"
9299         | RString _ -> pr "  char *r;\n"; "NULL"
9300         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9301         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9302         | RStructList (_, typ) ->
9303             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9304         | RBufferOut _ ->
9305             pr "  char *r;\n";
9306             pr "  size_t size;\n";
9307             "NULL" in
9308       pr "\n";
9309
9310       pr "  r = guestfs_%s " name;
9311       generate_c_call_args ~handle:"g" style;
9312       pr ";\n";
9313
9314       List.iter (
9315         function
9316         | Pathname _ | Device _ | Dev_or_Path _ | String _
9317         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9318         | StringList n | DeviceList n ->
9319             pr "  free (%s);\n" n
9320       ) (snd style);
9321
9322       pr "  if (r == %s)\n" error_code;
9323       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9324       pr "\n";
9325
9326       (match fst style with
9327        | RErr ->
9328            pr "  return Qnil;\n"
9329        | RInt _ | RBool _ ->
9330            pr "  return INT2NUM (r);\n"
9331        | RInt64 _ ->
9332            pr "  return ULL2NUM (r);\n"
9333        | RConstString _ ->
9334            pr "  return rb_str_new2 (r);\n";
9335        | RConstOptString _ ->
9336            pr "  if (r)\n";
9337            pr "    return rb_str_new2 (r);\n";
9338            pr "  else\n";
9339            pr "    return Qnil;\n";
9340        | RString _ ->
9341            pr "  VALUE rv = rb_str_new2 (r);\n";
9342            pr "  free (r);\n";
9343            pr "  return rv;\n";
9344        | RStringList _ ->
9345            pr "  int i, len = 0;\n";
9346            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9347            pr "  VALUE rv = rb_ary_new2 (len);\n";
9348            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9349            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9350            pr "    free (r[i]);\n";
9351            pr "  }\n";
9352            pr "  free (r);\n";
9353            pr "  return rv;\n"
9354        | RStruct (_, typ) ->
9355            let cols = cols_of_struct typ in
9356            generate_ruby_struct_code typ cols
9357        | RStructList (_, typ) ->
9358            let cols = cols_of_struct typ in
9359            generate_ruby_struct_list_code typ cols
9360        | RHashtable _ ->
9361            pr "  VALUE rv = rb_hash_new ();\n";
9362            pr "  int i;\n";
9363            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9364            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9365            pr "    free (r[i]);\n";
9366            pr "    free (r[i+1]);\n";
9367            pr "  }\n";
9368            pr "  free (r);\n";
9369            pr "  return rv;\n"
9370        | RBufferOut _ ->
9371            pr "  VALUE rv = rb_str_new (r, size);\n";
9372            pr "  free (r);\n";
9373            pr "  return rv;\n";
9374       );
9375
9376       pr "}\n";
9377       pr "\n"
9378   ) all_functions;
9379
9380   pr "\
9381 /* Initialize the module. */
9382 void Init__guestfs ()
9383 {
9384   m_guestfs = rb_define_module (\"Guestfs\");
9385   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9386   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9387
9388   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9389   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9390
9391 ";
9392   (* Define the rest of the methods. *)
9393   List.iter (
9394     fun (name, style, _, _, _, _, _) ->
9395       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9396       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9397   ) all_functions;
9398
9399   pr "}\n"
9400
9401 (* Ruby code to return a struct. *)
9402 and generate_ruby_struct_code typ cols =
9403   pr "  VALUE rv = rb_hash_new ();\n";
9404   List.iter (
9405     function
9406     | name, FString ->
9407         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9408     | name, FBuffer ->
9409         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9410     | name, FUUID ->
9411         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9412     | name, (FBytes|FUInt64) ->
9413         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9414     | name, FInt64 ->
9415         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9416     | name, FUInt32 ->
9417         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9418     | name, FInt32 ->
9419         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9420     | name, FOptPercent ->
9421         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9422     | name, FChar -> (* XXX wrong? *)
9423         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9424   ) cols;
9425   pr "  guestfs_free_%s (r);\n" typ;
9426   pr "  return rv;\n"
9427
9428 (* Ruby code to return a struct list. *)
9429 and generate_ruby_struct_list_code typ cols =
9430   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9431   pr "  int i;\n";
9432   pr "  for (i = 0; i < r->len; ++i) {\n";
9433   pr "    VALUE hv = rb_hash_new ();\n";
9434   List.iter (
9435     function
9436     | name, FString ->
9437         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9438     | name, FBuffer ->
9439         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
9440     | name, FUUID ->
9441         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9442     | name, (FBytes|FUInt64) ->
9443         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9444     | name, FInt64 ->
9445         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9446     | name, FUInt32 ->
9447         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9448     | name, FInt32 ->
9449         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9450     | name, FOptPercent ->
9451         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9452     | name, FChar -> (* XXX wrong? *)
9453         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9454   ) cols;
9455   pr "    rb_ary_push (rv, hv);\n";
9456   pr "  }\n";
9457   pr "  guestfs_free_%s_list (r);\n" typ;
9458   pr "  return rv;\n"
9459
9460 (* Generate Java bindings GuestFS.java file. *)
9461 and generate_java_java () =
9462   generate_header CStyle LGPLv2plus;
9463
9464   pr "\
9465 package com.redhat.et.libguestfs;
9466
9467 import java.util.HashMap;
9468 import com.redhat.et.libguestfs.LibGuestFSException;
9469 import com.redhat.et.libguestfs.PV;
9470 import com.redhat.et.libguestfs.VG;
9471 import com.redhat.et.libguestfs.LV;
9472 import com.redhat.et.libguestfs.Stat;
9473 import com.redhat.et.libguestfs.StatVFS;
9474 import com.redhat.et.libguestfs.IntBool;
9475 import com.redhat.et.libguestfs.Dirent;
9476
9477 /**
9478  * The GuestFS object is a libguestfs handle.
9479  *
9480  * @author rjones
9481  */
9482 public class GuestFS {
9483   // Load the native code.
9484   static {
9485     System.loadLibrary (\"guestfs_jni\");
9486   }
9487
9488   /**
9489    * The native guestfs_h pointer.
9490    */
9491   long g;
9492
9493   /**
9494    * Create a libguestfs handle.
9495    *
9496    * @throws LibGuestFSException
9497    */
9498   public GuestFS () throws LibGuestFSException
9499   {
9500     g = _create ();
9501   }
9502   private native long _create () throws LibGuestFSException;
9503
9504   /**
9505    * Close a libguestfs handle.
9506    *
9507    * You can also leave handles to be collected by the garbage
9508    * collector, but this method ensures that the resources used
9509    * by the handle are freed up immediately.  If you call any
9510    * other methods after closing the handle, you will get an
9511    * exception.
9512    *
9513    * @throws LibGuestFSException
9514    */
9515   public void close () throws LibGuestFSException
9516   {
9517     if (g != 0)
9518       _close (g);
9519     g = 0;
9520   }
9521   private native void _close (long g) throws LibGuestFSException;
9522
9523   public void finalize () throws LibGuestFSException
9524   {
9525     close ();
9526   }
9527
9528 ";
9529
9530   List.iter (
9531     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9532       if not (List.mem NotInDocs flags); then (
9533         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9534         let doc =
9535           if List.mem ProtocolLimitWarning flags then
9536             doc ^ "\n\n" ^ protocol_limit_warning
9537           else doc in
9538         let doc =
9539           if List.mem DangerWillRobinson flags then
9540             doc ^ "\n\n" ^ danger_will_robinson
9541           else doc in
9542         let doc =
9543           match deprecation_notice flags with
9544           | None -> doc
9545           | Some txt -> doc ^ "\n\n" ^ txt in
9546         let doc = pod2text ~width:60 name doc in
9547         let doc = List.map (            (* RHBZ#501883 *)
9548           function
9549           | "" -> "<p>"
9550           | nonempty -> nonempty
9551         ) doc in
9552         let doc = String.concat "\n   * " doc in
9553
9554         pr "  /**\n";
9555         pr "   * %s\n" shortdesc;
9556         pr "   * <p>\n";
9557         pr "   * %s\n" doc;
9558         pr "   * @throws LibGuestFSException\n";
9559         pr "   */\n";
9560         pr "  ";
9561       );
9562       generate_java_prototype ~public:true ~semicolon:false name style;
9563       pr "\n";
9564       pr "  {\n";
9565       pr "    if (g == 0)\n";
9566       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9567         name;
9568       pr "    ";
9569       if fst style <> RErr then pr "return ";
9570       pr "_%s " name;
9571       generate_java_call_args ~handle:"g" (snd style);
9572       pr ";\n";
9573       pr "  }\n";
9574       pr "  ";
9575       generate_java_prototype ~privat:true ~native:true name style;
9576       pr "\n";
9577       pr "\n";
9578   ) all_functions;
9579
9580   pr "}\n"
9581
9582 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9583 and generate_java_call_args ~handle args =
9584   pr "(%s" handle;
9585   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9586   pr ")"
9587
9588 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9589     ?(semicolon=true) name style =
9590   if privat then pr "private ";
9591   if public then pr "public ";
9592   if native then pr "native ";
9593
9594   (* return type *)
9595   (match fst style with
9596    | RErr -> pr "void ";
9597    | RInt _ -> pr "int ";
9598    | RInt64 _ -> pr "long ";
9599    | RBool _ -> pr "boolean ";
9600    | RConstString _ | RConstOptString _ | RString _
9601    | RBufferOut _ -> pr "String ";
9602    | RStringList _ -> pr "String[] ";
9603    | RStruct (_, typ) ->
9604        let name = java_name_of_struct typ in
9605        pr "%s " name;
9606    | RStructList (_, typ) ->
9607        let name = java_name_of_struct typ in
9608        pr "%s[] " name;
9609    | RHashtable _ -> pr "HashMap<String,String> ";
9610   );
9611
9612   if native then pr "_%s " name else pr "%s " name;
9613   pr "(";
9614   let needs_comma = ref false in
9615   if native then (
9616     pr "long g";
9617     needs_comma := true
9618   );
9619
9620   (* args *)
9621   List.iter (
9622     fun arg ->
9623       if !needs_comma then pr ", ";
9624       needs_comma := true;
9625
9626       match arg with
9627       | Pathname n
9628       | Device n | Dev_or_Path n
9629       | String n
9630       | OptString n
9631       | FileIn n
9632       | FileOut n ->
9633           pr "String %s" n
9634       | StringList n | DeviceList n ->
9635           pr "String[] %s" n
9636       | Bool n ->
9637           pr "boolean %s" n
9638       | Int n ->
9639           pr "int %s" n
9640       | Int64 n ->
9641           pr "long %s" n
9642   ) (snd style);
9643
9644   pr ")\n";
9645   pr "    throws LibGuestFSException";
9646   if semicolon then pr ";"
9647
9648 and generate_java_struct jtyp cols () =
9649   generate_header CStyle LGPLv2plus;
9650
9651   pr "\
9652 package com.redhat.et.libguestfs;
9653
9654 /**
9655  * Libguestfs %s structure.
9656  *
9657  * @author rjones
9658  * @see GuestFS
9659  */
9660 public class %s {
9661 " jtyp jtyp;
9662
9663   List.iter (
9664     function
9665     | name, FString
9666     | name, FUUID
9667     | name, FBuffer -> pr "  public String %s;\n" name
9668     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9669     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9670     | name, FChar -> pr "  public char %s;\n" name
9671     | name, FOptPercent ->
9672         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9673         pr "  public float %s;\n" name
9674   ) cols;
9675
9676   pr "}\n"
9677
9678 and generate_java_c () =
9679   generate_header CStyle LGPLv2plus;
9680
9681   pr "\
9682 #include <stdio.h>
9683 #include <stdlib.h>
9684 #include <string.h>
9685
9686 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9687 #include \"guestfs.h\"
9688
9689 /* Note that this function returns.  The exception is not thrown
9690  * until after the wrapper function returns.
9691  */
9692 static void
9693 throw_exception (JNIEnv *env, const char *msg)
9694 {
9695   jclass cl;
9696   cl = (*env)->FindClass (env,
9697                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9698   (*env)->ThrowNew (env, cl, msg);
9699 }
9700
9701 JNIEXPORT jlong JNICALL
9702 Java_com_redhat_et_libguestfs_GuestFS__1create
9703   (JNIEnv *env, jobject obj)
9704 {
9705   guestfs_h *g;
9706
9707   g = guestfs_create ();
9708   if (g == NULL) {
9709     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9710     return 0;
9711   }
9712   guestfs_set_error_handler (g, NULL, NULL);
9713   return (jlong) (long) g;
9714 }
9715
9716 JNIEXPORT void JNICALL
9717 Java_com_redhat_et_libguestfs_GuestFS__1close
9718   (JNIEnv *env, jobject obj, jlong jg)
9719 {
9720   guestfs_h *g = (guestfs_h *) (long) jg;
9721   guestfs_close (g);
9722 }
9723
9724 ";
9725
9726   List.iter (
9727     fun (name, style, _, _, _, _, _) ->
9728       pr "JNIEXPORT ";
9729       (match fst style with
9730        | RErr -> pr "void ";
9731        | RInt _ -> pr "jint ";
9732        | RInt64 _ -> pr "jlong ";
9733        | RBool _ -> pr "jboolean ";
9734        | RConstString _ | RConstOptString _ | RString _
9735        | RBufferOut _ -> pr "jstring ";
9736        | RStruct _ | RHashtable _ ->
9737            pr "jobject ";
9738        | RStringList _ | RStructList _ ->
9739            pr "jobjectArray ";
9740       );
9741       pr "JNICALL\n";
9742       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9743       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9744       pr "\n";
9745       pr "  (JNIEnv *env, jobject obj, jlong jg";
9746       List.iter (
9747         function
9748         | Pathname n
9749         | Device n | Dev_or_Path n
9750         | String n
9751         | OptString n
9752         | FileIn n
9753         | FileOut n ->
9754             pr ", jstring j%s" n
9755         | StringList n | DeviceList n ->
9756             pr ", jobjectArray j%s" n
9757         | Bool n ->
9758             pr ", jboolean j%s" n
9759         | Int n ->
9760             pr ", jint j%s" n
9761         | Int64 n ->
9762             pr ", jlong j%s" n
9763       ) (snd style);
9764       pr ")\n";
9765       pr "{\n";
9766       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9767       let error_code, no_ret =
9768         match fst style with
9769         | RErr -> pr "  int r;\n"; "-1", ""
9770         | RBool _
9771         | RInt _ -> pr "  int r;\n"; "-1", "0"
9772         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9773         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9774         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9775         | RString _ ->
9776             pr "  jstring jr;\n";
9777             pr "  char *r;\n"; "NULL", "NULL"
9778         | RStringList _ ->
9779             pr "  jobjectArray jr;\n";
9780             pr "  int r_len;\n";
9781             pr "  jclass cl;\n";
9782             pr "  jstring jstr;\n";
9783             pr "  char **r;\n"; "NULL", "NULL"
9784         | RStruct (_, typ) ->
9785             pr "  jobject jr;\n";
9786             pr "  jclass cl;\n";
9787             pr "  jfieldID fl;\n";
9788             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9789         | RStructList (_, typ) ->
9790             pr "  jobjectArray jr;\n";
9791             pr "  jclass cl;\n";
9792             pr "  jfieldID fl;\n";
9793             pr "  jobject jfl;\n";
9794             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9795         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9796         | RBufferOut _ ->
9797             pr "  jstring jr;\n";
9798             pr "  char *r;\n";
9799             pr "  size_t size;\n";
9800             "NULL", "NULL" in
9801       List.iter (
9802         function
9803         | Pathname n
9804         | Device n | Dev_or_Path n
9805         | String n
9806         | OptString n
9807         | FileIn n
9808         | FileOut n ->
9809             pr "  const char *%s;\n" n
9810         | StringList n | DeviceList n ->
9811             pr "  int %s_len;\n" n;
9812             pr "  const char **%s;\n" n
9813         | Bool n
9814         | Int n ->
9815             pr "  int %s;\n" n
9816         | Int64 n ->
9817             pr "  int64_t %s;\n" n
9818       ) (snd style);
9819
9820       let needs_i =
9821         (match fst style with
9822          | RStringList _ | RStructList _ -> true
9823          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9824          | RConstOptString _
9825          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9826           List.exists (function
9827                        | StringList _ -> true
9828                        | DeviceList _ -> true
9829                        | _ -> false) (snd style) in
9830       if needs_i then
9831         pr "  int i;\n";
9832
9833       pr "\n";
9834
9835       (* Get the parameters. *)
9836       List.iter (
9837         function
9838         | Pathname n
9839         | Device n | Dev_or_Path n
9840         | String n
9841         | FileIn n
9842         | FileOut n ->
9843             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9844         | OptString n ->
9845             (* This is completely undocumented, but Java null becomes
9846              * a NULL parameter.
9847              *)
9848             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9849         | StringList n | DeviceList n ->
9850             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9851             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9852             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9853             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9854               n;
9855             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9856             pr "  }\n";
9857             pr "  %s[%s_len] = NULL;\n" n n;
9858         | Bool n
9859         | Int n
9860         | Int64 n ->
9861             pr "  %s = j%s;\n" n n
9862       ) (snd style);
9863
9864       (* Make the call. *)
9865       pr "  r = guestfs_%s " name;
9866       generate_c_call_args ~handle:"g" style;
9867       pr ";\n";
9868
9869       (* Release the parameters. *)
9870       List.iter (
9871         function
9872         | Pathname n
9873         | Device n | Dev_or_Path n
9874         | String n
9875         | FileIn n
9876         | FileOut n ->
9877             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9878         | OptString n ->
9879             pr "  if (j%s)\n" n;
9880             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9881         | StringList n | DeviceList n ->
9882             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9883             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9884               n;
9885             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9886             pr "  }\n";
9887             pr "  free (%s);\n" n
9888         | Bool n
9889         | Int n
9890         | Int64 n -> ()
9891       ) (snd style);
9892
9893       (* Check for errors. *)
9894       pr "  if (r == %s) {\n" error_code;
9895       pr "    throw_exception (env, guestfs_last_error (g));\n";
9896       pr "    return %s;\n" no_ret;
9897       pr "  }\n";
9898
9899       (* Return value. *)
9900       (match fst style with
9901        | RErr -> ()
9902        | RInt _ -> pr "  return (jint) r;\n"
9903        | RBool _ -> pr "  return (jboolean) r;\n"
9904        | RInt64 _ -> pr "  return (jlong) r;\n"
9905        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9906        | RConstOptString _ ->
9907            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9908        | RString _ ->
9909            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9910            pr "  free (r);\n";
9911            pr "  return jr;\n"
9912        | RStringList _ ->
9913            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9914            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9915            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9916            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9917            pr "  for (i = 0; i < r_len; ++i) {\n";
9918            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9919            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9920            pr "    free (r[i]);\n";
9921            pr "  }\n";
9922            pr "  free (r);\n";
9923            pr "  return jr;\n"
9924        | RStruct (_, typ) ->
9925            let jtyp = java_name_of_struct typ in
9926            let cols = cols_of_struct typ in
9927            generate_java_struct_return typ jtyp cols
9928        | RStructList (_, typ) ->
9929            let jtyp = java_name_of_struct typ in
9930            let cols = cols_of_struct typ in
9931            generate_java_struct_list_return typ jtyp cols
9932        | RHashtable _ ->
9933            (* XXX *)
9934            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9935            pr "  return NULL;\n"
9936        | RBufferOut _ ->
9937            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9938            pr "  free (r);\n";
9939            pr "  return jr;\n"
9940       );
9941
9942       pr "}\n";
9943       pr "\n"
9944   ) all_functions
9945
9946 and generate_java_struct_return typ jtyp cols =
9947   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9948   pr "  jr = (*env)->AllocObject (env, cl);\n";
9949   List.iter (
9950     function
9951     | name, FString ->
9952         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9953         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9954     | name, FUUID ->
9955         pr "  {\n";
9956         pr "    char s[33];\n";
9957         pr "    memcpy (s, r->%s, 32);\n" name;
9958         pr "    s[32] = 0;\n";
9959         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9960         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9961         pr "  }\n";
9962     | name, FBuffer ->
9963         pr "  {\n";
9964         pr "    int len = r->%s_len;\n" name;
9965         pr "    char s[len+1];\n";
9966         pr "    memcpy (s, r->%s, len);\n" name;
9967         pr "    s[len] = 0;\n";
9968         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9969         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9970         pr "  }\n";
9971     | name, (FBytes|FUInt64|FInt64) ->
9972         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9973         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9974     | name, (FUInt32|FInt32) ->
9975         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9976         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9977     | name, FOptPercent ->
9978         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9979         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9980     | name, FChar ->
9981         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9982         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9983   ) cols;
9984   pr "  free (r);\n";
9985   pr "  return jr;\n"
9986
9987 and generate_java_struct_list_return typ jtyp cols =
9988   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9989   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9990   pr "  for (i = 0; i < r->len; ++i) {\n";
9991   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9992   List.iter (
9993     function
9994     | name, FString ->
9995         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9996         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9997     | name, FUUID ->
9998         pr "    {\n";
9999         pr "      char s[33];\n";
10000         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10001         pr "      s[32] = 0;\n";
10002         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10003         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10004         pr "    }\n";
10005     | name, FBuffer ->
10006         pr "    {\n";
10007         pr "      int len = r->val[i].%s_len;\n" name;
10008         pr "      char s[len+1];\n";
10009         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10010         pr "      s[len] = 0;\n";
10011         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10012         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10013         pr "    }\n";
10014     | name, (FBytes|FUInt64|FInt64) ->
10015         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10016         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10017     | name, (FUInt32|FInt32) ->
10018         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10019         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10020     | name, FOptPercent ->
10021         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10022         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10023     | name, FChar ->
10024         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10025         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10026   ) cols;
10027   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10028   pr "  }\n";
10029   pr "  guestfs_free_%s_list (r);\n" typ;
10030   pr "  return jr;\n"
10031
10032 and generate_java_makefile_inc () =
10033   generate_header HashStyle GPLv2plus;
10034
10035   pr "java_built_sources = \\\n";
10036   List.iter (
10037     fun (typ, jtyp) ->
10038         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10039   ) java_structs;
10040   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10041
10042 and generate_haskell_hs () =
10043   generate_header HaskellStyle LGPLv2plus;
10044
10045   (* XXX We only know how to generate partial FFI for Haskell
10046    * at the moment.  Please help out!
10047    *)
10048   let can_generate style =
10049     match style with
10050     | RErr, _
10051     | RInt _, _
10052     | RInt64 _, _ -> true
10053     | RBool _, _
10054     | RConstString _, _
10055     | RConstOptString _, _
10056     | RString _, _
10057     | RStringList _, _
10058     | RStruct _, _
10059     | RStructList _, _
10060     | RHashtable _, _
10061     | RBufferOut _, _ -> false in
10062
10063   pr "\
10064 {-# INCLUDE <guestfs.h> #-}
10065 {-# LANGUAGE ForeignFunctionInterface #-}
10066
10067 module Guestfs (
10068   create";
10069
10070   (* List out the names of the actions we want to export. *)
10071   List.iter (
10072     fun (name, style, _, _, _, _, _) ->
10073       if can_generate style then pr ",\n  %s" name
10074   ) all_functions;
10075
10076   pr "
10077   ) where
10078
10079 -- Unfortunately some symbols duplicate ones already present
10080 -- in Prelude.  We don't know which, so we hard-code a list
10081 -- here.
10082 import Prelude hiding (truncate)
10083
10084 import Foreign
10085 import Foreign.C
10086 import Foreign.C.Types
10087 import IO
10088 import Control.Exception
10089 import Data.Typeable
10090
10091 data GuestfsS = GuestfsS            -- represents the opaque C struct
10092 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10093 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10094
10095 -- XXX define properly later XXX
10096 data PV = PV
10097 data VG = VG
10098 data LV = LV
10099 data IntBool = IntBool
10100 data Stat = Stat
10101 data StatVFS = StatVFS
10102 data Hashtable = Hashtable
10103
10104 foreign import ccall unsafe \"guestfs_create\" c_create
10105   :: IO GuestfsP
10106 foreign import ccall unsafe \"&guestfs_close\" c_close
10107   :: FunPtr (GuestfsP -> IO ())
10108 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10109   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10110
10111 create :: IO GuestfsH
10112 create = do
10113   p <- c_create
10114   c_set_error_handler p nullPtr nullPtr
10115   h <- newForeignPtr c_close p
10116   return h
10117
10118 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10119   :: GuestfsP -> IO CString
10120
10121 -- last_error :: GuestfsH -> IO (Maybe String)
10122 -- last_error h = do
10123 --   str <- withForeignPtr h (\\p -> c_last_error p)
10124 --   maybePeek peekCString str
10125
10126 last_error :: GuestfsH -> IO (String)
10127 last_error h = do
10128   str <- withForeignPtr h (\\p -> c_last_error p)
10129   if (str == nullPtr)
10130     then return \"no error\"
10131     else peekCString str
10132
10133 ";
10134
10135   (* Generate wrappers for each foreign function. *)
10136   List.iter (
10137     fun (name, style, _, _, _, _, _) ->
10138       if can_generate style then (
10139         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10140         pr "  :: ";
10141         generate_haskell_prototype ~handle:"GuestfsP" style;
10142         pr "\n";
10143         pr "\n";
10144         pr "%s :: " name;
10145         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10146         pr "\n";
10147         pr "%s %s = do\n" name
10148           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10149         pr "  r <- ";
10150         (* Convert pointer arguments using with* functions. *)
10151         List.iter (
10152           function
10153           | FileIn n
10154           | FileOut n
10155           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10156           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10157           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10158           | Bool _ | Int _ | Int64 _ -> ()
10159         ) (snd style);
10160         (* Convert integer arguments. *)
10161         let args =
10162           List.map (
10163             function
10164             | Bool n -> sprintf "(fromBool %s)" n
10165             | Int n -> sprintf "(fromIntegral %s)" n
10166             | Int64 n -> sprintf "(fromIntegral %s)" n
10167             | FileIn n | FileOut n
10168             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10169           ) (snd style) in
10170         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10171           (String.concat " " ("p" :: args));
10172         (match fst style with
10173          | RErr | RInt _ | RInt64 _ | RBool _ ->
10174              pr "  if (r == -1)\n";
10175              pr "    then do\n";
10176              pr "      err <- last_error h\n";
10177              pr "      fail err\n";
10178          | RConstString _ | RConstOptString _ | RString _
10179          | RStringList _ | RStruct _
10180          | RStructList _ | RHashtable _ | RBufferOut _ ->
10181              pr "  if (r == nullPtr)\n";
10182              pr "    then do\n";
10183              pr "      err <- last_error h\n";
10184              pr "      fail err\n";
10185         );
10186         (match fst style with
10187          | RErr ->
10188              pr "    else return ()\n"
10189          | RInt _ ->
10190              pr "    else return (fromIntegral r)\n"
10191          | RInt64 _ ->
10192              pr "    else return (fromIntegral r)\n"
10193          | RBool _ ->
10194              pr "    else return (toBool r)\n"
10195          | RConstString _
10196          | RConstOptString _
10197          | RString _
10198          | RStringList _
10199          | RStruct _
10200          | RStructList _
10201          | RHashtable _
10202          | RBufferOut _ ->
10203              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10204         );
10205         pr "\n";
10206       )
10207   ) all_functions
10208
10209 and generate_haskell_prototype ~handle ?(hs = false) style =
10210   pr "%s -> " handle;
10211   let string = if hs then "String" else "CString" in
10212   let int = if hs then "Int" else "CInt" in
10213   let bool = if hs then "Bool" else "CInt" in
10214   let int64 = if hs then "Integer" else "Int64" in
10215   List.iter (
10216     fun arg ->
10217       (match arg with
10218        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10219        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10220        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10221        | Bool _ -> pr "%s" bool
10222        | Int _ -> pr "%s" int
10223        | Int64 _ -> pr "%s" int
10224        | FileIn _ -> pr "%s" string
10225        | FileOut _ -> pr "%s" string
10226       );
10227       pr " -> ";
10228   ) (snd style);
10229   pr "IO (";
10230   (match fst style with
10231    | RErr -> if not hs then pr "CInt"
10232    | RInt _ -> pr "%s" int
10233    | RInt64 _ -> pr "%s" int64
10234    | RBool _ -> pr "%s" bool
10235    | RConstString _ -> pr "%s" string
10236    | RConstOptString _ -> pr "Maybe %s" string
10237    | RString _ -> pr "%s" string
10238    | RStringList _ -> pr "[%s]" string
10239    | RStruct (_, typ) ->
10240        let name = java_name_of_struct typ in
10241        pr "%s" name
10242    | RStructList (_, typ) ->
10243        let name = java_name_of_struct typ in
10244        pr "[%s]" name
10245    | RHashtable _ -> pr "Hashtable"
10246    | RBufferOut _ -> pr "%s" string
10247   );
10248   pr ")"
10249
10250 and generate_csharp () =
10251   generate_header CPlusPlusStyle LGPLv2plus;
10252
10253   (* XXX Make this configurable by the C# assembly users. *)
10254   let library = "libguestfs.so.0" in
10255
10256   pr "\
10257 // These C# bindings are highly experimental at present.
10258 //
10259 // Firstly they only work on Linux (ie. Mono).  In order to get them
10260 // to work on Windows (ie. .Net) you would need to port the library
10261 // itself to Windows first.
10262 //
10263 // The second issue is that some calls are known to be incorrect and
10264 // can cause Mono to segfault.  Particularly: calls which pass or
10265 // return string[], or return any structure value.  This is because
10266 // we haven't worked out the correct way to do this from C#.
10267 //
10268 // The third issue is that when compiling you get a lot of warnings.
10269 // We are not sure whether the warnings are important or not.
10270 //
10271 // Fourthly we do not routinely build or test these bindings as part
10272 // of the make && make check cycle, which means that regressions might
10273 // go unnoticed.
10274 //
10275 // Suggestions and patches are welcome.
10276
10277 // To compile:
10278 //
10279 // gmcs Libguestfs.cs
10280 // mono Libguestfs.exe
10281 //
10282 // (You'll probably want to add a Test class / static main function
10283 // otherwise this won't do anything useful).
10284
10285 using System;
10286 using System.IO;
10287 using System.Runtime.InteropServices;
10288 using System.Runtime.Serialization;
10289 using System.Collections;
10290
10291 namespace Guestfs
10292 {
10293   class Error : System.ApplicationException
10294   {
10295     public Error (string message) : base (message) {}
10296     protected Error (SerializationInfo info, StreamingContext context) {}
10297   }
10298
10299   class Guestfs
10300   {
10301     IntPtr _handle;
10302
10303     [DllImport (\"%s\")]
10304     static extern IntPtr guestfs_create ();
10305
10306     public Guestfs ()
10307     {
10308       _handle = guestfs_create ();
10309       if (_handle == IntPtr.Zero)
10310         throw new Error (\"could not create guestfs handle\");
10311     }
10312
10313     [DllImport (\"%s\")]
10314     static extern void guestfs_close (IntPtr h);
10315
10316     ~Guestfs ()
10317     {
10318       guestfs_close (_handle);
10319     }
10320
10321     [DllImport (\"%s\")]
10322     static extern string guestfs_last_error (IntPtr h);
10323
10324 " library library library;
10325
10326   (* Generate C# structure bindings.  We prefix struct names with
10327    * underscore because C# cannot have conflicting struct names and
10328    * method names (eg. "class stat" and "stat").
10329    *)
10330   List.iter (
10331     fun (typ, cols) ->
10332       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10333       pr "    public class _%s {\n" typ;
10334       List.iter (
10335         function
10336         | name, FChar -> pr "      char %s;\n" name
10337         | name, FString -> pr "      string %s;\n" name
10338         | name, FBuffer ->
10339             pr "      uint %s_len;\n" name;
10340             pr "      string %s;\n" name
10341         | name, FUUID ->
10342             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10343             pr "      string %s;\n" name
10344         | name, FUInt32 -> pr "      uint %s;\n" name
10345         | name, FInt32 -> pr "      int %s;\n" name
10346         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10347         | name, FInt64 -> pr "      long %s;\n" name
10348         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10349       ) cols;
10350       pr "    }\n";
10351       pr "\n"
10352   ) structs;
10353
10354   (* Generate C# function bindings. *)
10355   List.iter (
10356     fun (name, style, _, _, _, shortdesc, _) ->
10357       let rec csharp_return_type () =
10358         match fst style with
10359         | RErr -> "void"
10360         | RBool n -> "bool"
10361         | RInt n -> "int"
10362         | RInt64 n -> "long"
10363         | RConstString n
10364         | RConstOptString n
10365         | RString n
10366         | RBufferOut n -> "string"
10367         | RStruct (_,n) -> "_" ^ n
10368         | RHashtable n -> "Hashtable"
10369         | RStringList n -> "string[]"
10370         | RStructList (_,n) -> sprintf "_%s[]" n
10371
10372       and c_return_type () =
10373         match fst style with
10374         | RErr
10375         | RBool _
10376         | RInt _ -> "int"
10377         | RInt64 _ -> "long"
10378         | RConstString _
10379         | RConstOptString _
10380         | RString _
10381         | RBufferOut _ -> "string"
10382         | RStruct (_,n) -> "_" ^ n
10383         | RHashtable _
10384         | RStringList _ -> "string[]"
10385         | RStructList (_,n) -> sprintf "_%s[]" n
10386
10387       and c_error_comparison () =
10388         match fst style with
10389         | RErr
10390         | RBool _
10391         | RInt _
10392         | RInt64 _ -> "== -1"
10393         | RConstString _
10394         | RConstOptString _
10395         | RString _
10396         | RBufferOut _
10397         | RStruct (_,_)
10398         | RHashtable _
10399         | RStringList _
10400         | RStructList (_,_) -> "== null"
10401
10402       and generate_extern_prototype () =
10403         pr "    static extern %s guestfs_%s (IntPtr h"
10404           (c_return_type ()) name;
10405         List.iter (
10406           function
10407           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10408           | FileIn n | FileOut n ->
10409               pr ", [In] string %s" n
10410           | StringList n | DeviceList n ->
10411               pr ", [In] string[] %s" n
10412           | Bool n ->
10413               pr ", bool %s" n
10414           | Int n ->
10415               pr ", int %s" n
10416           | Int64 n ->
10417               pr ", long %s" n
10418         ) (snd style);
10419         pr ");\n"
10420
10421       and generate_public_prototype () =
10422         pr "    public %s %s (" (csharp_return_type ()) name;
10423         let comma = ref false in
10424         let next () =
10425           if !comma then pr ", ";
10426           comma := true
10427         in
10428         List.iter (
10429           function
10430           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10431           | FileIn n | FileOut n ->
10432               next (); pr "string %s" n
10433           | StringList n | DeviceList n ->
10434               next (); pr "string[] %s" n
10435           | Bool n ->
10436               next (); pr "bool %s" n
10437           | Int n ->
10438               next (); pr "int %s" n
10439           | Int64 n ->
10440               next (); pr "long %s" n
10441         ) (snd style);
10442         pr ")\n"
10443
10444       and generate_call () =
10445         pr "guestfs_%s (_handle" name;
10446         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10447         pr ");\n";
10448       in
10449
10450       pr "    [DllImport (\"%s\")]\n" library;
10451       generate_extern_prototype ();
10452       pr "\n";
10453       pr "    /// <summary>\n";
10454       pr "    /// %s\n" shortdesc;
10455       pr "    /// </summary>\n";
10456       generate_public_prototype ();
10457       pr "    {\n";
10458       pr "      %s r;\n" (c_return_type ());
10459       pr "      r = ";
10460       generate_call ();
10461       pr "      if (r %s)\n" (c_error_comparison ());
10462       pr "        throw new Error (guestfs_last_error (_handle));\n";
10463       (match fst style with
10464        | RErr -> ()
10465        | RBool _ ->
10466            pr "      return r != 0 ? true : false;\n"
10467        | RHashtable _ ->
10468            pr "      Hashtable rr = new Hashtable ();\n";
10469            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10470            pr "        rr.Add (r[i], r[i+1]);\n";
10471            pr "      return rr;\n"
10472        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10473        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10474        | RStructList _ ->
10475            pr "      return r;\n"
10476       );
10477       pr "    }\n";
10478       pr "\n";
10479   ) all_functions_sorted;
10480
10481   pr "  }
10482 }
10483 "
10484
10485 and generate_bindtests () =
10486   generate_header CStyle LGPLv2plus;
10487
10488   pr "\
10489 #include <stdio.h>
10490 #include <stdlib.h>
10491 #include <inttypes.h>
10492 #include <string.h>
10493
10494 #include \"guestfs.h\"
10495 #include \"guestfs-internal.h\"
10496 #include \"guestfs-internal-actions.h\"
10497 #include \"guestfs_protocol.h\"
10498
10499 #define error guestfs_error
10500 #define safe_calloc guestfs_safe_calloc
10501 #define safe_malloc guestfs_safe_malloc
10502
10503 static void
10504 print_strings (char *const *argv)
10505 {
10506   int argc;
10507
10508   printf (\"[\");
10509   for (argc = 0; argv[argc] != NULL; ++argc) {
10510     if (argc > 0) printf (\", \");
10511     printf (\"\\\"%%s\\\"\", argv[argc]);
10512   }
10513   printf (\"]\\n\");
10514 }
10515
10516 /* The test0 function prints its parameters to stdout. */
10517 ";
10518
10519   let test0, tests =
10520     match test_functions with
10521     | [] -> assert false
10522     | test0 :: tests -> test0, tests in
10523
10524   let () =
10525     let (name, style, _, _, _, _, _) = test0 in
10526     generate_prototype ~extern:false ~semicolon:false ~newline:true
10527       ~handle:"g" ~prefix:"guestfs__" name style;
10528     pr "{\n";
10529     List.iter (
10530       function
10531       | Pathname n
10532       | Device n | Dev_or_Path n
10533       | String n
10534       | FileIn n
10535       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10536       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10537       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10538       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10539       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10540       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10541     ) (snd style);
10542     pr "  /* Java changes stdout line buffering so we need this: */\n";
10543     pr "  fflush (stdout);\n";
10544     pr "  return 0;\n";
10545     pr "}\n";
10546     pr "\n" in
10547
10548   List.iter (
10549     fun (name, style, _, _, _, _, _) ->
10550       if String.sub name (String.length name - 3) 3 <> "err" then (
10551         pr "/* Test normal return. */\n";
10552         generate_prototype ~extern:false ~semicolon:false ~newline:true
10553           ~handle:"g" ~prefix:"guestfs__" name style;
10554         pr "{\n";
10555         (match fst style with
10556          | RErr ->
10557              pr "  return 0;\n"
10558          | RInt _ ->
10559              pr "  int r;\n";
10560              pr "  sscanf (val, \"%%d\", &r);\n";
10561              pr "  return r;\n"
10562          | RInt64 _ ->
10563              pr "  int64_t r;\n";
10564              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10565              pr "  return r;\n"
10566          | RBool _ ->
10567              pr "  return STREQ (val, \"true\");\n"
10568          | RConstString _
10569          | RConstOptString _ ->
10570              (* Can't return the input string here.  Return a static
10571               * string so we ensure we get a segfault if the caller
10572               * tries to free it.
10573               *)
10574              pr "  return \"static string\";\n"
10575          | RString _ ->
10576              pr "  return strdup (val);\n"
10577          | RStringList _ ->
10578              pr "  char **strs;\n";
10579              pr "  int n, i;\n";
10580              pr "  sscanf (val, \"%%d\", &n);\n";
10581              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10582              pr "  for (i = 0; i < n; ++i) {\n";
10583              pr "    strs[i] = safe_malloc (g, 16);\n";
10584              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10585              pr "  }\n";
10586              pr "  strs[n] = NULL;\n";
10587              pr "  return strs;\n"
10588          | RStruct (_, typ) ->
10589              pr "  struct guestfs_%s *r;\n" typ;
10590              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10591              pr "  return r;\n"
10592          | RStructList (_, typ) ->
10593              pr "  struct guestfs_%s_list *r;\n" typ;
10594              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10595              pr "  sscanf (val, \"%%d\", &r->len);\n";
10596              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10597              pr "  return r;\n"
10598          | RHashtable _ ->
10599              pr "  char **strs;\n";
10600              pr "  int n, i;\n";
10601              pr "  sscanf (val, \"%%d\", &n);\n";
10602              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10603              pr "  for (i = 0; i < n; ++i) {\n";
10604              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10605              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10606              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10607              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10608              pr "  }\n";
10609              pr "  strs[n*2] = NULL;\n";
10610              pr "  return strs;\n"
10611          | RBufferOut _ ->
10612              pr "  return strdup (val);\n"
10613         );
10614         pr "}\n";
10615         pr "\n"
10616       ) else (
10617         pr "/* Test error return. */\n";
10618         generate_prototype ~extern:false ~semicolon:false ~newline:true
10619           ~handle:"g" ~prefix:"guestfs__" name style;
10620         pr "{\n";
10621         pr "  error (g, \"error\");\n";
10622         (match fst style with
10623          | RErr | RInt _ | RInt64 _ | RBool _ ->
10624              pr "  return -1;\n"
10625          | RConstString _ | RConstOptString _
10626          | RString _ | RStringList _ | RStruct _
10627          | RStructList _
10628          | RHashtable _
10629          | RBufferOut _ ->
10630              pr "  return NULL;\n"
10631         );
10632         pr "}\n";
10633         pr "\n"
10634       )
10635   ) tests
10636
10637 and generate_ocaml_bindtests () =
10638   generate_header OCamlStyle GPLv2plus;
10639
10640   pr "\
10641 let () =
10642   let g = Guestfs.create () in
10643 ";
10644
10645   let mkargs args =
10646     String.concat " " (
10647       List.map (
10648         function
10649         | CallString s -> "\"" ^ s ^ "\""
10650         | CallOptString None -> "None"
10651         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10652         | CallStringList xs ->
10653             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10654         | CallInt i when i >= 0 -> string_of_int i
10655         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10656         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10657         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10658         | CallBool b -> string_of_bool b
10659       ) args
10660     )
10661   in
10662
10663   generate_lang_bindtests (
10664     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10665   );
10666
10667   pr "print_endline \"EOF\"\n"
10668
10669 and generate_perl_bindtests () =
10670   pr "#!/usr/bin/perl -w\n";
10671   generate_header HashStyle GPLv2plus;
10672
10673   pr "\
10674 use strict;
10675
10676 use Sys::Guestfs;
10677
10678 my $g = Sys::Guestfs->new ();
10679 ";
10680
10681   let mkargs args =
10682     String.concat ", " (
10683       List.map (
10684         function
10685         | CallString s -> "\"" ^ s ^ "\""
10686         | CallOptString None -> "undef"
10687         | CallOptString (Some s) -> sprintf "\"%s\"" s
10688         | CallStringList xs ->
10689             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10690         | CallInt i -> string_of_int i
10691         | CallInt64 i -> Int64.to_string i
10692         | CallBool b -> if b then "1" else "0"
10693       ) args
10694     )
10695   in
10696
10697   generate_lang_bindtests (
10698     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10699   );
10700
10701   pr "print \"EOF\\n\"\n"
10702
10703 and generate_python_bindtests () =
10704   generate_header HashStyle GPLv2plus;
10705
10706   pr "\
10707 import guestfs
10708
10709 g = guestfs.GuestFS ()
10710 ";
10711
10712   let mkargs args =
10713     String.concat ", " (
10714       List.map (
10715         function
10716         | CallString s -> "\"" ^ s ^ "\""
10717         | CallOptString None -> "None"
10718         | CallOptString (Some s) -> sprintf "\"%s\"" s
10719         | CallStringList xs ->
10720             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10721         | CallInt i -> string_of_int i
10722         | CallInt64 i -> Int64.to_string i
10723         | CallBool b -> if b then "1" else "0"
10724       ) args
10725     )
10726   in
10727
10728   generate_lang_bindtests (
10729     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10730   );
10731
10732   pr "print \"EOF\"\n"
10733
10734 and generate_ruby_bindtests () =
10735   generate_header HashStyle GPLv2plus;
10736
10737   pr "\
10738 require 'guestfs'
10739
10740 g = Guestfs::create()
10741 ";
10742
10743   let mkargs args =
10744     String.concat ", " (
10745       List.map (
10746         function
10747         | CallString s -> "\"" ^ s ^ "\""
10748         | CallOptString None -> "nil"
10749         | CallOptString (Some s) -> sprintf "\"%s\"" s
10750         | CallStringList xs ->
10751             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10752         | CallInt i -> string_of_int i
10753         | CallInt64 i -> Int64.to_string i
10754         | CallBool b -> string_of_bool b
10755       ) args
10756     )
10757   in
10758
10759   generate_lang_bindtests (
10760     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10761   );
10762
10763   pr "print \"EOF\\n\"\n"
10764
10765 and generate_java_bindtests () =
10766   generate_header CStyle GPLv2plus;
10767
10768   pr "\
10769 import com.redhat.et.libguestfs.*;
10770
10771 public class Bindtests {
10772     public static void main (String[] argv)
10773     {
10774         try {
10775             GuestFS g = new GuestFS ();
10776 ";
10777
10778   let mkargs args =
10779     String.concat ", " (
10780       List.map (
10781         function
10782         | CallString s -> "\"" ^ s ^ "\""
10783         | CallOptString None -> "null"
10784         | CallOptString (Some s) -> sprintf "\"%s\"" s
10785         | CallStringList xs ->
10786             "new String[]{" ^
10787               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10788         | CallInt i -> string_of_int i
10789         | CallInt64 i -> Int64.to_string i
10790         | CallBool b -> string_of_bool b
10791       ) args
10792     )
10793   in
10794
10795   generate_lang_bindtests (
10796     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10797   );
10798
10799   pr "
10800             System.out.println (\"EOF\");
10801         }
10802         catch (Exception exn) {
10803             System.err.println (exn);
10804             System.exit (1);
10805         }
10806     }
10807 }
10808 "
10809
10810 and generate_haskell_bindtests () =
10811   generate_header HaskellStyle GPLv2plus;
10812
10813   pr "\
10814 module Bindtests where
10815 import qualified Guestfs
10816
10817 main = do
10818   g <- Guestfs.create
10819 ";
10820
10821   let mkargs args =
10822     String.concat " " (
10823       List.map (
10824         function
10825         | CallString s -> "\"" ^ s ^ "\""
10826         | CallOptString None -> "Nothing"
10827         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10828         | CallStringList xs ->
10829             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10830         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10831         | CallInt i -> string_of_int i
10832         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10833         | CallInt64 i -> Int64.to_string i
10834         | CallBool true -> "True"
10835         | CallBool false -> "False"
10836       ) args
10837     )
10838   in
10839
10840   generate_lang_bindtests (
10841     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10842   );
10843
10844   pr "  putStrLn \"EOF\"\n"
10845
10846 (* Language-independent bindings tests - we do it this way to
10847  * ensure there is parity in testing bindings across all languages.
10848  *)
10849 and generate_lang_bindtests call =
10850   call "test0" [CallString "abc"; CallOptString (Some "def");
10851                 CallStringList []; CallBool false;
10852                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10853   call "test0" [CallString "abc"; CallOptString None;
10854                 CallStringList []; CallBool false;
10855                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10856   call "test0" [CallString ""; CallOptString (Some "def");
10857                 CallStringList []; CallBool false;
10858                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10859   call "test0" [CallString ""; CallOptString (Some "");
10860                 CallStringList []; CallBool false;
10861                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10862   call "test0" [CallString "abc"; CallOptString (Some "def");
10863                 CallStringList ["1"]; CallBool false;
10864                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10865   call "test0" [CallString "abc"; CallOptString (Some "def");
10866                 CallStringList ["1"; "2"]; CallBool false;
10867                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10868   call "test0" [CallString "abc"; CallOptString (Some "def");
10869                 CallStringList ["1"]; CallBool true;
10870                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10871   call "test0" [CallString "abc"; CallOptString (Some "def");
10872                 CallStringList ["1"]; CallBool false;
10873                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10874   call "test0" [CallString "abc"; CallOptString (Some "def");
10875                 CallStringList ["1"]; CallBool false;
10876                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10877   call "test0" [CallString "abc"; CallOptString (Some "def");
10878                 CallStringList ["1"]; CallBool false;
10879                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10880   call "test0" [CallString "abc"; CallOptString (Some "def");
10881                 CallStringList ["1"]; CallBool false;
10882                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10883   call "test0" [CallString "abc"; CallOptString (Some "def");
10884                 CallStringList ["1"]; CallBool false;
10885                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10886   call "test0" [CallString "abc"; CallOptString (Some "def");
10887                 CallStringList ["1"]; CallBool false;
10888                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10889
10890 (* XXX Add here tests of the return and error functions. *)
10891
10892 (* Code to generator bindings for virt-inspector.  Currently only
10893  * implemented for OCaml code (for virt-p2v 2.0).
10894  *)
10895 let rng_input = "inspector/virt-inspector.rng"
10896
10897 (* Read the input file and parse it into internal structures.  This is
10898  * by no means a complete RELAX NG parser, but is just enough to be
10899  * able to parse the specific input file.
10900  *)
10901 type rng =
10902   | Element of string * rng list        (* <element name=name/> *)
10903   | Attribute of string * rng list        (* <attribute name=name/> *)
10904   | Interleave of rng list                (* <interleave/> *)
10905   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10906   | OneOrMore of rng                        (* <oneOrMore/> *)
10907   | Optional of rng                        (* <optional/> *)
10908   | Choice of string list                (* <choice><value/>*</choice> *)
10909   | Value of string                        (* <value>str</value> *)
10910   | Text                                (* <text/> *)
10911
10912 let rec string_of_rng = function
10913   | Element (name, xs) ->
10914       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10915   | Attribute (name, xs) ->
10916       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10917   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10918   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10919   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10920   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10921   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10922   | Value value -> "Value \"" ^ value ^ "\""
10923   | Text -> "Text"
10924
10925 and string_of_rng_list xs =
10926   String.concat ", " (List.map string_of_rng xs)
10927
10928 let rec parse_rng ?defines context = function
10929   | [] -> []
10930   | Xml.Element ("element", ["name", name], children) :: rest ->
10931       Element (name, parse_rng ?defines context children)
10932       :: parse_rng ?defines context rest
10933   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10934       Attribute (name, parse_rng ?defines context children)
10935       :: parse_rng ?defines context rest
10936   | Xml.Element ("interleave", [], children) :: rest ->
10937       Interleave (parse_rng ?defines context children)
10938       :: parse_rng ?defines context rest
10939   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10940       let rng = parse_rng ?defines context [child] in
10941       (match rng with
10942        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10943        | _ ->
10944            failwithf "%s: <zeroOrMore> contains more than one child element"
10945              context
10946       )
10947   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10948       let rng = parse_rng ?defines context [child] in
10949       (match rng with
10950        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10951        | _ ->
10952            failwithf "%s: <oneOrMore> contains more than one child element"
10953              context
10954       )
10955   | Xml.Element ("optional", [], [child]) :: rest ->
10956       let rng = parse_rng ?defines context [child] in
10957       (match rng with
10958        | [child] -> Optional child :: parse_rng ?defines context rest
10959        | _ ->
10960            failwithf "%s: <optional> contains more than one child element"
10961              context
10962       )
10963   | Xml.Element ("choice", [], children) :: rest ->
10964       let values = List.map (
10965         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10966         | _ ->
10967             failwithf "%s: can't handle anything except <value> in <choice>"
10968               context
10969       ) children in
10970       Choice values
10971       :: parse_rng ?defines context rest
10972   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10973       Value value :: parse_rng ?defines context rest
10974   | Xml.Element ("text", [], []) :: rest ->
10975       Text :: parse_rng ?defines context rest
10976   | Xml.Element ("ref", ["name", name], []) :: rest ->
10977       (* Look up the reference.  Because of limitations in this parser,
10978        * we can't handle arbitrarily nested <ref> yet.  You can only
10979        * use <ref> from inside <start>.
10980        *)
10981       (match defines with
10982        | None ->
10983            failwithf "%s: contains <ref>, but no refs are defined yet" context
10984        | Some map ->
10985            let rng = StringMap.find name map in
10986            rng @ parse_rng ?defines context rest
10987       )
10988   | x :: _ ->
10989       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10990
10991 let grammar =
10992   let xml = Xml.parse_file rng_input in
10993   match xml with
10994   | Xml.Element ("grammar", _,
10995                  Xml.Element ("start", _, gram) :: defines) ->
10996       (* The <define/> elements are referenced in the <start> section,
10997        * so build a map of those first.
10998        *)
10999       let defines = List.fold_left (
11000         fun map ->
11001           function Xml.Element ("define", ["name", name], defn) ->
11002             StringMap.add name defn map
11003           | _ ->
11004               failwithf "%s: expected <define name=name/>" rng_input
11005       ) StringMap.empty defines in
11006       let defines = StringMap.mapi parse_rng defines in
11007
11008       (* Parse the <start> clause, passing the defines. *)
11009       parse_rng ~defines "<start>" gram
11010   | _ ->
11011       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11012         rng_input
11013
11014 let name_of_field = function
11015   | Element (name, _) | Attribute (name, _)
11016   | ZeroOrMore (Element (name, _))
11017   | OneOrMore (Element (name, _))
11018   | Optional (Element (name, _)) -> name
11019   | Optional (Attribute (name, _)) -> name
11020   | Text -> (* an unnamed field in an element *)
11021       "data"
11022   | rng ->
11023       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11024
11025 (* At the moment this function only generates OCaml types.  However we
11026  * should parameterize it later so it can generate types/structs in a
11027  * variety of languages.
11028  *)
11029 let generate_types xs =
11030   (* A simple type is one that can be printed out directly, eg.
11031    * "string option".  A complex type is one which has a name and has
11032    * to be defined via another toplevel definition, eg. a struct.
11033    *
11034    * generate_type generates code for either simple or complex types.
11035    * In the simple case, it returns the string ("string option").  In
11036    * the complex case, it returns the name ("mountpoint").  In the
11037    * complex case it has to print out the definition before returning,
11038    * so it should only be called when we are at the beginning of a
11039    * new line (BOL context).
11040    *)
11041   let rec generate_type = function
11042     | Text ->                                (* string *)
11043         "string", true
11044     | Choice values ->                        (* [`val1|`val2|...] *)
11045         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11046     | ZeroOrMore rng ->                        (* <rng> list *)
11047         let t, is_simple = generate_type rng in
11048         t ^ " list (* 0 or more *)", is_simple
11049     | OneOrMore rng ->                        (* <rng> list *)
11050         let t, is_simple = generate_type rng in
11051         t ^ " list (* 1 or more *)", is_simple
11052                                         (* virt-inspector hack: bool *)
11053     | Optional (Attribute (name, [Value "1"])) ->
11054         "bool", true
11055     | Optional rng ->                        (* <rng> list *)
11056         let t, is_simple = generate_type rng in
11057         t ^ " option", is_simple
11058                                         (* type name = { fields ... } *)
11059     | Element (name, fields) when is_attrs_interleave fields ->
11060         generate_type_struct name (get_attrs_interleave fields)
11061     | Element (name, [field])                (* type name = field *)
11062     | Attribute (name, [field]) ->
11063         let t, is_simple = generate_type field in
11064         if is_simple then (t, true)
11065         else (
11066           pr "type %s = %s\n" name t;
11067           name, false
11068         )
11069     | Element (name, fields) ->              (* type name = { fields ... } *)
11070         generate_type_struct name fields
11071     | rng ->
11072         failwithf "generate_type failed at: %s" (string_of_rng rng)
11073
11074   and is_attrs_interleave = function
11075     | [Interleave _] -> true
11076     | Attribute _ :: fields -> is_attrs_interleave fields
11077     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11078     | _ -> false
11079
11080   and get_attrs_interleave = function
11081     | [Interleave fields] -> fields
11082     | ((Attribute _) as field) :: fields
11083     | ((Optional (Attribute _)) as field) :: fields ->
11084         field :: get_attrs_interleave fields
11085     | _ -> assert false
11086
11087   and generate_types xs =
11088     List.iter (fun x -> ignore (generate_type x)) xs
11089
11090   and generate_type_struct name fields =
11091     (* Calculate the types of the fields first.  We have to do this
11092      * before printing anything so we are still in BOL context.
11093      *)
11094     let types = List.map fst (List.map generate_type fields) in
11095
11096     (* Special case of a struct containing just a string and another
11097      * field.  Turn it into an assoc list.
11098      *)
11099     match types with
11100     | ["string"; other] ->
11101         let fname1, fname2 =
11102           match fields with
11103           | [f1; f2] -> name_of_field f1, name_of_field f2
11104           | _ -> assert false in
11105         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11106         name, false
11107
11108     | types ->
11109         pr "type %s = {\n" name;
11110         List.iter (
11111           fun (field, ftype) ->
11112             let fname = name_of_field field in
11113             pr "  %s_%s : %s;\n" name fname ftype
11114         ) (List.combine fields types);
11115         pr "}\n";
11116         (* Return the name of this type, and
11117          * false because it's not a simple type.
11118          *)
11119         name, false
11120   in
11121
11122   generate_types xs
11123
11124 let generate_parsers xs =
11125   (* As for generate_type above, generate_parser makes a parser for
11126    * some type, and returns the name of the parser it has generated.
11127    * Because it (may) need to print something, it should always be
11128    * called in BOL context.
11129    *)
11130   let rec generate_parser = function
11131     | Text ->                                (* string *)
11132         "string_child_or_empty"
11133     | Choice values ->                        (* [`val1|`val2|...] *)
11134         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11135           (String.concat "|"
11136              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11137     | ZeroOrMore rng ->                        (* <rng> list *)
11138         let pa = generate_parser rng in
11139         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11140     | OneOrMore rng ->                        (* <rng> list *)
11141         let pa = generate_parser rng in
11142         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11143                                         (* virt-inspector hack: bool *)
11144     | Optional (Attribute (name, [Value "1"])) ->
11145         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11146     | Optional rng ->                        (* <rng> list *)
11147         let pa = generate_parser rng in
11148         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11149                                         (* type name = { fields ... } *)
11150     | Element (name, fields) when is_attrs_interleave fields ->
11151         generate_parser_struct name (get_attrs_interleave fields)
11152     | Element (name, [field]) ->        (* type name = field *)
11153         let pa = generate_parser field in
11154         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11155         pr "let %s =\n" parser_name;
11156         pr "  %s\n" pa;
11157         pr "let parse_%s = %s\n" name parser_name;
11158         parser_name
11159     | Attribute (name, [field]) ->
11160         let pa = generate_parser field in
11161         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11162         pr "let %s =\n" parser_name;
11163         pr "  %s\n" pa;
11164         pr "let parse_%s = %s\n" name parser_name;
11165         parser_name
11166     | Element (name, fields) ->              (* type name = { fields ... } *)
11167         generate_parser_struct name ([], fields)
11168     | rng ->
11169         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11170
11171   and is_attrs_interleave = function
11172     | [Interleave _] -> true
11173     | Attribute _ :: fields -> is_attrs_interleave fields
11174     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11175     | _ -> false
11176
11177   and get_attrs_interleave = function
11178     | [Interleave fields] -> [], fields
11179     | ((Attribute _) as field) :: fields
11180     | ((Optional (Attribute _)) as field) :: fields ->
11181         let attrs, interleaves = get_attrs_interleave fields in
11182         (field :: attrs), interleaves
11183     | _ -> assert false
11184
11185   and generate_parsers xs =
11186     List.iter (fun x -> ignore (generate_parser x)) xs
11187
11188   and generate_parser_struct name (attrs, interleaves) =
11189     (* Generate parsers for the fields first.  We have to do this
11190      * before printing anything so we are still in BOL context.
11191      *)
11192     let fields = attrs @ interleaves in
11193     let pas = List.map generate_parser fields in
11194
11195     (* Generate an intermediate tuple from all the fields first.
11196      * If the type is just a string + another field, then we will
11197      * return this directly, otherwise it is turned into a record.
11198      *
11199      * RELAX NG note: This code treats <interleave> and plain lists of
11200      * fields the same.  In other words, it doesn't bother enforcing
11201      * any ordering of fields in the XML.
11202      *)
11203     pr "let parse_%s x =\n" name;
11204     pr "  let t = (\n    ";
11205     let comma = ref false in
11206     List.iter (
11207       fun x ->
11208         if !comma then pr ",\n    ";
11209         comma := true;
11210         match x with
11211         | Optional (Attribute (fname, [field])), pa ->
11212             pr "%s x" pa
11213         | Optional (Element (fname, [field])), pa ->
11214             pr "%s (optional_child %S x)" pa fname
11215         | Attribute (fname, [Text]), _ ->
11216             pr "attribute %S x" fname
11217         | (ZeroOrMore _ | OneOrMore _), pa ->
11218             pr "%s x" pa
11219         | Text, pa ->
11220             pr "%s x" pa
11221         | (field, pa) ->
11222             let fname = name_of_field field in
11223             pr "%s (child %S x)" pa fname
11224     ) (List.combine fields pas);
11225     pr "\n  ) in\n";
11226
11227     (match fields with
11228      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11229          pr "  t\n"
11230
11231      | _ ->
11232          pr "  (Obj.magic t : %s)\n" name
11233 (*
11234          List.iter (
11235            function
11236            | (Optional (Attribute (fname, [field])), pa) ->
11237                pr "  %s_%s =\n" name fname;
11238                pr "    %s x;\n" pa
11239            | (Optional (Element (fname, [field])), pa) ->
11240                pr "  %s_%s =\n" name fname;
11241                pr "    (let x = optional_child %S x in\n" fname;
11242                pr "     %s x);\n" pa
11243            | (field, pa) ->
11244                let fname = name_of_field field in
11245                pr "  %s_%s =\n" name fname;
11246                pr "    (let x = child %S x in\n" fname;
11247                pr "     %s x);\n" pa
11248          ) (List.combine fields pas);
11249          pr "}\n"
11250 *)
11251     );
11252     sprintf "parse_%s" name
11253   in
11254
11255   generate_parsers xs
11256
11257 (* Generate ocaml/guestfs_inspector.mli. *)
11258 let generate_ocaml_inspector_mli () =
11259   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11260
11261   pr "\
11262 (** This is an OCaml language binding to the external [virt-inspector]
11263     program.
11264
11265     For more information, please read the man page [virt-inspector(1)].
11266 *)
11267
11268 ";
11269
11270   generate_types grammar;
11271   pr "(** The nested information returned from the {!inspect} function. *)\n";
11272   pr "\n";
11273
11274   pr "\
11275 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11276 (** To inspect a libvirt domain called [name], pass a singleton
11277     list: [inspect [name]].  When using libvirt only, you may
11278     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11279
11280     To inspect a disk image or images, pass a list of the filenames
11281     of the disk images: [inspect filenames]
11282
11283     This function inspects the given guest or disk images and
11284     returns a list of operating system(s) found and a large amount
11285     of information about them.  In the vast majority of cases,
11286     a virtual machine only contains a single operating system.
11287
11288     If the optional [~xml] parameter is given, then this function
11289     skips running the external virt-inspector program and just
11290     parses the given XML directly (which is expected to be XML
11291     produced from a previous run of virt-inspector).  The list of
11292     names and connect URI are ignored in this case.
11293
11294     This function can throw a wide variety of exceptions, for example
11295     if the external virt-inspector program cannot be found, or if
11296     it doesn't generate valid XML.
11297 *)
11298 "
11299
11300 (* Generate ocaml/guestfs_inspector.ml. *)
11301 let generate_ocaml_inspector_ml () =
11302   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11303
11304   pr "open Unix\n";
11305   pr "\n";
11306
11307   generate_types grammar;
11308   pr "\n";
11309
11310   pr "\
11311 (* Misc functions which are used by the parser code below. *)
11312 let first_child = function
11313   | Xml.Element (_, _, c::_) -> c
11314   | Xml.Element (name, _, []) ->
11315       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11316   | Xml.PCData str ->
11317       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11318
11319 let string_child_or_empty = function
11320   | Xml.Element (_, _, [Xml.PCData s]) -> s
11321   | Xml.Element (_, _, []) -> \"\"
11322   | Xml.Element (x, _, _) ->
11323       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11324                 x ^ \" instead\")
11325   | Xml.PCData str ->
11326       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11327
11328 let optional_child name xml =
11329   let children = Xml.children xml in
11330   try
11331     Some (List.find (function
11332                      | Xml.Element (n, _, _) when n = name -> true
11333                      | _ -> false) children)
11334   with
11335     Not_found -> None
11336
11337 let child name xml =
11338   match optional_child name xml with
11339   | Some c -> c
11340   | None ->
11341       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11342
11343 let attribute name xml =
11344   try Xml.attrib xml name
11345   with Xml.No_attribute _ ->
11346     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11347
11348 ";
11349
11350   generate_parsers grammar;
11351   pr "\n";
11352
11353   pr "\
11354 (* Run external virt-inspector, then use parser to parse the XML. *)
11355 let inspect ?connect ?xml names =
11356   let xml =
11357     match xml with
11358     | None ->
11359         if names = [] then invalid_arg \"inspect: no names given\";
11360         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11361           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11362           names in
11363         let cmd = List.map Filename.quote cmd in
11364         let cmd = String.concat \" \" cmd in
11365         let chan = open_process_in cmd in
11366         let xml = Xml.parse_in chan in
11367         (match close_process_in chan with
11368          | WEXITED 0 -> ()
11369          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11370          | WSIGNALED i | WSTOPPED i ->
11371              failwith (\"external virt-inspector command died or stopped on sig \" ^
11372                        string_of_int i)
11373         );
11374         xml
11375     | Some doc ->
11376         Xml.parse_string doc in
11377   parse_operatingsystems xml
11378 "
11379
11380 (* This is used to generate the src/MAX_PROC_NR file which
11381  * contains the maximum procedure number, a surrogate for the
11382  * ABI version number.  See src/Makefile.am for the details.
11383  *)
11384 and generate_max_proc_nr () =
11385   let proc_nrs = List.map (
11386     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11387   ) daemon_functions in
11388
11389   let max_proc_nr = List.fold_left max 0 proc_nrs in
11390
11391   pr "%d\n" max_proc_nr
11392
11393 let output_to filename k =
11394   let filename_new = filename ^ ".new" in
11395   chan := open_out filename_new;
11396   k ();
11397   close_out !chan;
11398   chan := Pervasives.stdout;
11399
11400   (* Is the new file different from the current file? *)
11401   if Sys.file_exists filename && files_equal filename filename_new then
11402     unlink filename_new                 (* same, so skip it *)
11403   else (
11404     (* different, overwrite old one *)
11405     (try chmod filename 0o644 with Unix_error _ -> ());
11406     rename filename_new filename;
11407     chmod filename 0o444;
11408     printf "written %s\n%!" filename;
11409   )
11410
11411 let perror msg = function
11412   | Unix_error (err, _, _) ->
11413       eprintf "%s: %s\n" msg (error_message err)
11414   | exn ->
11415       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11416
11417 (* Main program. *)
11418 let () =
11419   let lock_fd =
11420     try openfile "HACKING" [O_RDWR] 0
11421     with
11422     | Unix_error (ENOENT, _, _) ->
11423         eprintf "\
11424 You are probably running this from the wrong directory.
11425 Run it from the top source directory using the command
11426   src/generator.ml
11427 ";
11428         exit 1
11429     | exn ->
11430         perror "open: HACKING" exn;
11431         exit 1 in
11432
11433   (* Acquire a lock so parallel builds won't try to run the generator
11434    * twice at the same time.  Subsequent builds will wait for the first
11435    * one to finish.  Note the lock is released implicitly when the
11436    * program exits.
11437    *)
11438   (try lockf lock_fd F_LOCK 1
11439    with exn ->
11440      perror "lock: HACKING" exn;
11441      exit 1);
11442
11443   check_functions ();
11444
11445   output_to "src/guestfs_protocol.x" generate_xdr;
11446   output_to "src/guestfs-structs.h" generate_structs_h;
11447   output_to "src/guestfs-actions.h" generate_actions_h;
11448   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11449   output_to "src/guestfs-actions.c" generate_client_actions;
11450   output_to "src/guestfs-bindtests.c" generate_bindtests;
11451   output_to "src/guestfs-structs.pod" generate_structs_pod;
11452   output_to "src/guestfs-actions.pod" generate_actions_pod;
11453   output_to "src/guestfs-availability.pod" generate_availability_pod;
11454   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11455   output_to "src/libguestfs.syms" generate_linker_script;
11456   output_to "daemon/actions.h" generate_daemon_actions_h;
11457   output_to "daemon/stubs.c" generate_daemon_actions;
11458   output_to "daemon/names.c" generate_daemon_names;
11459   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11460   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11461   output_to "capitests/tests.c" generate_tests;
11462   output_to "fish/cmds.c" generate_fish_cmds;
11463   output_to "fish/completion.c" generate_fish_completion;
11464   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11465   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11466   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11467   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11468   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11469   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11470   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11471   output_to "perl/Guestfs.xs" generate_perl_xs;
11472   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11473   output_to "perl/bindtests.pl" generate_perl_bindtests;
11474   output_to "python/guestfs-py.c" generate_python_c;
11475   output_to "python/guestfs.py" generate_python_py;
11476   output_to "python/bindtests.py" generate_python_bindtests;
11477   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11478   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11479   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11480
11481   List.iter (
11482     fun (typ, jtyp) ->
11483       let cols = cols_of_struct typ in
11484       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11485       output_to filename (generate_java_struct jtyp cols);
11486   ) java_structs;
11487
11488   output_to "java/Makefile.inc" generate_java_makefile_inc;
11489   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11490   output_to "java/Bindtests.java" generate_java_bindtests;
11491   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11492   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11493   output_to "csharp/Libguestfs.cs" generate_csharp;
11494
11495   (* Always generate this file last, and unconditionally.  It's used
11496    * by the Makefile to know when we must re-run the generator.
11497    *)
11498   let chan = open_out "src/stamp-generator" in
11499   fprintf chan "1\n";
11500   close_out chan;
11501
11502   printf "generated %d lines of code\n" !lines