73ab8fa1fb32a91847df09d9b1b45ee0876342fc
[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   | FishOutput of fish_output_t (* how to display output 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 and fish_output_t =
191   | FishOutputOctal       (* for int return, print in octal *)
192   | FishOutputHexadecimal (* for int return, print in hex *)
193
194 (* You can supply zero or as many tests as you want per API call.
195  *
196  * Note that the test environment has 3 block devices, of size 500MB,
197  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
198  * a fourth ISO block device with some known files on it (/dev/sdd).
199  *
200  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
201  * Number of cylinders was 63 for IDE emulated disks with precisely
202  * the same size.  How exactly this is calculated is a mystery.
203  *
204  * The ISO block device (/dev/sdd) comes from images/test.iso.
205  *
206  * To be able to run the tests in a reasonable amount of time,
207  * the virtual machine and block devices are reused between tests.
208  * So don't try testing kill_subprocess :-x
209  *
210  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
211  *
212  * Don't assume anything about the previous contents of the block
213  * devices.  Use 'Init*' to create some initial scenarios.
214  *
215  * You can add a prerequisite clause to any individual test.  This
216  * is a run-time check, which, if it fails, causes the test to be
217  * skipped.  Useful if testing a command which might not work on
218  * all variations of libguestfs builds.  A test that has prerequisite
219  * of 'Always' is run unconditionally.
220  *
221  * In addition, packagers can skip individual tests by setting the
222  * environment variables:     eg:
223  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
224  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
225  *)
226 type tests = (test_init * test_prereq * test) list
227 and test =
228     (* Run the command sequence and just expect nothing to fail. *)
229   | TestRun of seq
230
231     (* Run the command sequence and expect the output of the final
232      * command to be the string.
233      *)
234   | TestOutput of seq * string
235
236     (* Run the command sequence and expect the output of the final
237      * command to be the list of strings.
238      *)
239   | TestOutputList of seq * string list
240
241     (* Run the command sequence and expect the output of the final
242      * command to be the list of block devices (could be either
243      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
244      * character of each string).
245      *)
246   | TestOutputListOfDevices of seq * string list
247
248     (* Run the command sequence and expect the output of the final
249      * command to be the integer.
250      *)
251   | TestOutputInt of seq * int
252
253     (* Run the command sequence and expect the output of the final
254      * command to be <op> <int>, eg. ">=", "1".
255      *)
256   | TestOutputIntOp of seq * string * int
257
258     (* Run the command sequence and expect the output of the final
259      * command to be a true value (!= 0 or != NULL).
260      *)
261   | TestOutputTrue of seq
262
263     (* Run the command sequence and expect the output of the final
264      * command to be a false value (== 0 or == NULL, but not an error).
265      *)
266   | TestOutputFalse of seq
267
268     (* Run the command sequence and expect the output of the final
269      * command to be a list of the given length (but don't care about
270      * content).
271      *)
272   | TestOutputLength of seq * int
273
274     (* Run the command sequence and expect the output of the final
275      * command to be a buffer (RBufferOut), ie. string + size.
276      *)
277   | TestOutputBuffer of seq * string
278
279     (* Run the command sequence and expect the output of the final
280      * command to be a structure.
281      *)
282   | TestOutputStruct of seq * test_field_compare list
283
284     (* Run the command sequence and expect the final command (only)
285      * to fail.
286      *)
287   | TestLastFail of seq
288
289 and test_field_compare =
290   | CompareWithInt of string * int
291   | CompareWithIntOp of string * string * int
292   | CompareWithString of string * string
293   | CompareFieldsIntEq of string * string
294   | CompareFieldsStrEq of string * string
295
296 (* Test prerequisites. *)
297 and test_prereq =
298     (* Test always runs. *)
299   | Always
300
301     (* Test is currently disabled - eg. it fails, or it tests some
302      * unimplemented feature.
303      *)
304   | Disabled
305
306     (* 'string' is some C code (a function body) that should return
307      * true or false.  The test will run if the code returns true.
308      *)
309   | If of string
310
311     (* As for 'If' but the test runs _unless_ the code returns true. *)
312   | Unless of string
313
314 (* Some initial scenarios for testing. *)
315 and test_init =
316     (* Do nothing, block devices could contain random stuff including
317      * LVM PVs, and some filesystems might be mounted.  This is usually
318      * a bad idea.
319      *)
320   | InitNone
321
322     (* Block devices are empty and no filesystems are mounted. *)
323   | InitEmpty
324
325     (* /dev/sda contains a single partition /dev/sda1, with random
326      * content.  /dev/sdb and /dev/sdc may have random content.
327      * No LVM.
328      *)
329   | InitPartition
330
331     (* /dev/sda contains a single partition /dev/sda1, which is formatted
332      * as ext2, empty [except for lost+found] and mounted on /.
333      * /dev/sdb and /dev/sdc may have random content.
334      * No LVM.
335      *)
336   | InitBasicFS
337
338     (* /dev/sda:
339      *   /dev/sda1 (is a PV):
340      *     /dev/VG/LV (size 8MB):
341      *       formatted as ext2, empty [except for lost+found], mounted on /
342      * /dev/sdb and /dev/sdc may have random content.
343      *)
344   | InitBasicFSonLVM
345
346     (* /dev/sdd (the ISO, see images/ directory in source)
347      * is mounted on /
348      *)
349   | InitISOFS
350
351 (* Sequence of commands for testing. *)
352 and seq = cmd list
353 and cmd = string list
354
355 (* Note about long descriptions: When referring to another
356  * action, use the format C<guestfs_other> (ie. the full name of
357  * the C function).  This will be replaced as appropriate in other
358  * language bindings.
359  *
360  * Apart from that, long descriptions are just perldoc paragraphs.
361  *)
362
363 (* Generate a random UUID (used in tests). *)
364 let uuidgen () =
365   let chan = open_process_in "uuidgen" in
366   let uuid = input_line chan in
367   (match close_process_in chan with
368    | WEXITED 0 -> ()
369    | WEXITED _ ->
370        failwith "uuidgen: process exited with non-zero status"
371    | WSIGNALED _ | WSTOPPED _ ->
372        failwith "uuidgen: process signalled or stopped by signal"
373   );
374   uuid
375
376 (* These test functions are used in the language binding tests. *)
377
378 let test_all_args = [
379   String "str";
380   OptString "optstr";
381   StringList "strlist";
382   Bool "b";
383   Int "integer";
384   Int64 "integer64";
385   FileIn "filein";
386   FileOut "fileout";
387 ]
388
389 let test_all_rets = [
390   (* except for RErr, which is tested thoroughly elsewhere *)
391   "test0rint",         RInt "valout";
392   "test0rint64",       RInt64 "valout";
393   "test0rbool",        RBool "valout";
394   "test0rconststring", RConstString "valout";
395   "test0rconstoptstring", RConstOptString "valout";
396   "test0rstring",      RString "valout";
397   "test0rstringlist",  RStringList "valout";
398   "test0rstruct",      RStruct ("valout", "lvm_pv");
399   "test0rstructlist",  RStructList ("valout", "lvm_pv");
400   "test0rhashtable",   RHashtable "valout";
401 ]
402
403 let test_functions = [
404   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
405    [],
406    "internal test function - do not use",
407    "\
408 This is an internal test function which is used to test whether
409 the automatically generated bindings can handle every possible
410 parameter type correctly.
411
412 It echos the contents of each parameter to stdout.
413
414 You probably don't want to call this function.");
415 ] @ List.flatten (
416   List.map (
417     fun (name, ret) ->
418       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
419         [],
420         "internal test function - do not use",
421         "\
422 This is an internal test function which is used to test whether
423 the automatically generated bindings can handle every possible
424 return type correctly.
425
426 It converts string C<val> to the return type.
427
428 You probably don't want to call this function.");
429        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
430         [],
431         "internal test function - do not use",
432         "\
433 This is an internal test function which is used to test whether
434 the automatically generated bindings can handle every possible
435 return type correctly.
436
437 This function always returns an error.
438
439 You probably don't want to call this function.")]
440   ) test_all_rets
441 )
442
443 (* non_daemon_functions are any functions which don't get processed
444  * in the daemon, eg. functions for setting and getting local
445  * configuration values.
446  *)
447
448 let non_daemon_functions = test_functions @ [
449   ("launch", (RErr, []), -1, [FishAlias "run"],
450    [],
451    "launch the qemu subprocess",
452    "\
453 Internally libguestfs is implemented by running a virtual machine
454 using L<qemu(1)>.
455
456 You should call this after configuring the handle
457 (eg. adding drives) but before performing any actions.");
458
459   ("wait_ready", (RErr, []), -1, [NotInFish],
460    [],
461    "wait until the qemu subprocess launches (no op)",
462    "\
463 This function is a no op.
464
465 In versions of the API E<lt> 1.0.71 you had to call this function
466 just after calling C<guestfs_launch> to wait for the launch
467 to complete.  However this is no longer necessary because
468 C<guestfs_launch> now does the waiting.
469
470 If you see any calls to this function in code then you can just
471 remove them, unless you want to retain compatibility with older
472 versions of the API.");
473
474   ("kill_subprocess", (RErr, []), -1, [],
475    [],
476    "kill the qemu subprocess",
477    "\
478 This kills the qemu subprocess.  You should never need to call this.");
479
480   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
481    [],
482    "add an image to examine or modify",
483    "\
484 This function adds a virtual machine disk image C<filename> to the
485 guest.  The first time you call this function, the disk appears as IDE
486 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
487 so on.
488
489 You don't necessarily need to be root when using libguestfs.  However
490 you obviously do need sufficient permissions to access the filename
491 for whatever operations you want to perform (ie. read access if you
492 just want to read the image or write access if you want to modify the
493 image).
494
495 This is equivalent to the qemu parameter
496 C<-drive file=filename,cache=off,if=...>.
497
498 C<cache=off> is omitted in cases where it is not supported by
499 the underlying filesystem.
500
501 C<if=...> is set at compile time by the configuration option
502 C<./configure --with-drive-if=...>.  In the rare case where you
503 might need to change this at run time, use C<guestfs_add_drive_with_if>
504 or C<guestfs_add_drive_ro_with_if>.
505
506 Note that this call checks for the existence of C<filename>.  This
507 stops you from specifying other types of drive which are supported
508 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
509 the general C<guestfs_config> call instead.");
510
511   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
512    [],
513    "add a CD-ROM disk image to examine",
514    "\
515 This function adds a virtual CD-ROM disk image to the guest.
516
517 This is equivalent to the qemu parameter C<-cdrom filename>.
518
519 Notes:
520
521 =over 4
522
523 =item *
524
525 This call checks for the existence of C<filename>.  This
526 stops you from specifying other types of drive which are supported
527 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
528 the general C<guestfs_config> call instead.
529
530 =item *
531
532 If you just want to add an ISO file (often you use this as an
533 efficient way to transfer large files into the guest), then you
534 should probably use C<guestfs_add_drive_ro> instead.
535
536 =back");
537
538   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
539    [],
540    "add a drive in snapshot mode (read-only)",
541    "\
542 This adds a drive in snapshot mode, making it effectively
543 read-only.
544
545 Note that writes to the device are allowed, and will be seen for
546 the duration of the guestfs handle, but they are written
547 to a temporary file which is discarded as soon as the guestfs
548 handle is closed.  We don't currently have any method to enable
549 changes to be committed, although qemu can support this.
550
551 This is equivalent to the qemu parameter
552 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
553
554 C<if=...> is set at compile time by the configuration option
555 C<./configure --with-drive-if=...>.  In the rare case where you
556 might need to change this at run time, use C<guestfs_add_drive_with_if>
557 or C<guestfs_add_drive_ro_with_if>.
558
559 C<readonly=on> is only added where qemu supports this option.
560
561 Note that this call checks for the existence of C<filename>.  This
562 stops you from specifying other types of drive which are supported
563 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
564 the general C<guestfs_config> call instead.");
565
566   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
567    [],
568    "add qemu parameters",
569    "\
570 This can be used to add arbitrary qemu command line parameters
571 of the form C<-param value>.  Actually it's not quite arbitrary - we
572 prevent you from setting some parameters which would interfere with
573 parameters that we use.
574
575 The first character of C<param> string must be a C<-> (dash).
576
577 C<value> can be NULL.");
578
579   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
580    [],
581    "set the qemu binary",
582    "\
583 Set the qemu binary that we will use.
584
585 The default is chosen when the library was compiled by the
586 configure script.
587
588 You can also override this by setting the C<LIBGUESTFS_QEMU>
589 environment variable.
590
591 Setting C<qemu> to C<NULL> restores the default qemu binary.
592
593 Note that you should call this function as early as possible
594 after creating the handle.  This is because some pre-launch
595 operations depend on testing qemu features (by running C<qemu -help>).
596 If the qemu binary changes, we don't retest features, and
597 so you might see inconsistent results.  Using the environment
598 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
599 the qemu binary at the same time as the handle is created.");
600
601   ("get_qemu", (RConstString "qemu", []), -1, [],
602    [InitNone, Always, TestRun (
603       [["get_qemu"]])],
604    "get the qemu binary",
605    "\
606 Return the current qemu binary.
607
608 This is always non-NULL.  If it wasn't set already, then this will
609 return the default qemu binary name.");
610
611   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
612    [],
613    "set the search path",
614    "\
615 Set the path that libguestfs searches for kernel and initrd.img.
616
617 The default is C<$libdir/guestfs> unless overridden by setting
618 C<LIBGUESTFS_PATH> environment variable.
619
620 Setting C<path> to C<NULL> restores the default path.");
621
622   ("get_path", (RConstString "path", []), -1, [],
623    [InitNone, Always, TestRun (
624       [["get_path"]])],
625    "get the search path",
626    "\
627 Return the current search path.
628
629 This is always non-NULL.  If it wasn't set already, then this will
630 return the default path.");
631
632   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
633    [],
634    "add options to kernel command line",
635    "\
636 This function is used to add additional options to the
637 guest kernel command line.
638
639 The default is C<NULL> unless overridden by setting
640 C<LIBGUESTFS_APPEND> environment variable.
641
642 Setting C<append> to C<NULL> means I<no> additional options
643 are passed (libguestfs always adds a few of its own).");
644
645   ("get_append", (RConstOptString "append", []), -1, [],
646    (* This cannot be tested with the current framework.  The
647     * function can return NULL in normal operations, which the
648     * test framework interprets as an error.
649     *)
650    [],
651    "get the additional kernel options",
652    "\
653 Return the additional kernel options which are added to the
654 guest kernel command line.
655
656 If C<NULL> then no options are added.");
657
658   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
659    [],
660    "set autosync mode",
661    "\
662 If C<autosync> is true, this enables autosync.  Libguestfs will make a
663 best effort attempt to run C<guestfs_umount_all> followed by
664 C<guestfs_sync> when the handle is closed
665 (also if the program exits without closing handles).
666
667 This is disabled by default (except in guestfish where it is
668 enabled by default).");
669
670   ("get_autosync", (RBool "autosync", []), -1, [],
671    [InitNone, Always, TestRun (
672       [["get_autosync"]])],
673    "get autosync mode",
674    "\
675 Get the autosync flag.");
676
677   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
678    [],
679    "set verbose mode",
680    "\
681 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
682
683 Verbose messages are disabled unless the environment variable
684 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
685
686   ("get_verbose", (RBool "verbose", []), -1, [],
687    [],
688    "get verbose mode",
689    "\
690 This returns the verbose messages flag.");
691
692   ("is_ready", (RBool "ready", []), -1, [],
693    [InitNone, Always, TestOutputTrue (
694       [["is_ready"]])],
695    "is ready to accept commands",
696    "\
697 This returns true iff this handle is ready to accept commands
698 (in the C<READY> state).
699
700 For more information on states, see L<guestfs(3)>.");
701
702   ("is_config", (RBool "config", []), -1, [],
703    [InitNone, Always, TestOutputFalse (
704       [["is_config"]])],
705    "is in configuration state",
706    "\
707 This returns true iff this handle is being configured
708 (in the C<CONFIG> state).
709
710 For more information on states, see L<guestfs(3)>.");
711
712   ("is_launching", (RBool "launching", []), -1, [],
713    [InitNone, Always, TestOutputFalse (
714       [["is_launching"]])],
715    "is launching subprocess",
716    "\
717 This returns true iff this handle is launching the subprocess
718 (in the C<LAUNCHING> state).
719
720 For more information on states, see L<guestfs(3)>.");
721
722   ("is_busy", (RBool "busy", []), -1, [],
723    [InitNone, Always, TestOutputFalse (
724       [["is_busy"]])],
725    "is busy processing a command",
726    "\
727 This returns true iff this handle is busy processing a command
728 (in the C<BUSY> state).
729
730 For more information on states, see L<guestfs(3)>.");
731
732   ("get_state", (RInt "state", []), -1, [],
733    [],
734    "get the current state",
735    "\
736 This returns the current state as an opaque integer.  This is
737 only useful for printing debug and internal error messages.
738
739 For more information on states, see L<guestfs(3)>.");
740
741   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
742    [InitNone, Always, TestOutputInt (
743       [["set_memsize"; "500"];
744        ["get_memsize"]], 500)],
745    "set memory allocated to the qemu subprocess",
746    "\
747 This sets the memory size in megabytes allocated to the
748 qemu subprocess.  This only has any effect if called before
749 C<guestfs_launch>.
750
751 You can also change this by setting the environment
752 variable C<LIBGUESTFS_MEMSIZE> before the handle is
753 created.
754
755 For more information on the architecture of libguestfs,
756 see L<guestfs(3)>.");
757
758   ("get_memsize", (RInt "memsize", []), -1, [],
759    [InitNone, Always, TestOutputIntOp (
760       [["get_memsize"]], ">=", 256)],
761    "get memory allocated to the qemu subprocess",
762    "\
763 This gets the memory size in megabytes allocated to the
764 qemu subprocess.
765
766 If C<guestfs_set_memsize> was not called
767 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
768 then this returns the compiled-in default value for memsize.
769
770 For more information on the architecture of libguestfs,
771 see L<guestfs(3)>.");
772
773   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
774    [InitNone, Always, TestOutputIntOp (
775       [["get_pid"]], ">=", 1)],
776    "get PID of qemu subprocess",
777    "\
778 Return the process ID of the qemu subprocess.  If there is no
779 qemu subprocess, then this will return an error.
780
781 This is an internal call used for debugging and testing.");
782
783   ("version", (RStruct ("version", "version"), []), -1, [],
784    [InitNone, Always, TestOutputStruct (
785       [["version"]], [CompareWithInt ("major", 1)])],
786    "get the library version number",
787    "\
788 Return the libguestfs version number that the program is linked
789 against.
790
791 Note that because of dynamic linking this is not necessarily
792 the version of libguestfs that you compiled against.  You can
793 compile the program, and then at runtime dynamically link
794 against a completely different C<libguestfs.so> library.
795
796 This call was added in version C<1.0.58>.  In previous
797 versions of libguestfs there was no way to get the version
798 number.  From C code you can use ELF weak linking tricks to find out if
799 this symbol exists (if it doesn't, then it's an earlier version).
800
801 The call returns a structure with four elements.  The first
802 three (C<major>, C<minor> and C<release>) are numbers and
803 correspond to the usual version triplet.  The fourth element
804 (C<extra>) is a string and is normally empty, but may be
805 used for distro-specific information.
806
807 To construct the original version string:
808 C<$major.$minor.$release$extra>
809
810 I<Note:> Don't use this call to test for availability
811 of features.  Distro backports makes this unreliable.  Use
812 C<guestfs_available> instead.");
813
814   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
815    [InitNone, Always, TestOutputTrue (
816       [["set_selinux"; "true"];
817        ["get_selinux"]])],
818    "set SELinux enabled or disabled at appliance boot",
819    "\
820 This sets the selinux flag that is passed to the appliance
821 at boot time.  The default is C<selinux=0> (disabled).
822
823 Note that if SELinux is enabled, it is always in
824 Permissive mode (C<enforcing=0>).
825
826 For more information on the architecture of libguestfs,
827 see L<guestfs(3)>.");
828
829   ("get_selinux", (RBool "selinux", []), -1, [],
830    [],
831    "get SELinux enabled flag",
832    "\
833 This returns the current setting of the selinux flag which
834 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
835
836 For more information on the architecture of libguestfs,
837 see L<guestfs(3)>.");
838
839   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
840    [InitNone, Always, TestOutputFalse (
841       [["set_trace"; "false"];
842        ["get_trace"]])],
843    "enable or disable command traces",
844    "\
845 If the command trace flag is set to 1, then commands are
846 printed on stdout before they are executed in a format
847 which is very similar to the one used by guestfish.  In
848 other words, you can run a program with this enabled, and
849 you will get out a script which you can feed to guestfish
850 to perform the same set of actions.
851
852 If you want to trace C API calls into libguestfs (and
853 other libraries) then possibly a better way is to use
854 the external ltrace(1) command.
855
856 Command traces are disabled unless the environment variable
857 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
858
859   ("get_trace", (RBool "trace", []), -1, [],
860    [],
861    "get command trace enabled flag",
862    "\
863 Return the command trace flag.");
864
865   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
866    [InitNone, Always, TestOutputFalse (
867       [["set_direct"; "false"];
868        ["get_direct"]])],
869    "enable or disable direct appliance mode",
870    "\
871 If the direct appliance mode flag is enabled, then stdin and
872 stdout are passed directly through to the appliance once it
873 is launched.
874
875 One consequence of this is that log messages aren't caught
876 by the library and handled by C<guestfs_set_log_message_callback>,
877 but go straight to stdout.
878
879 You probably don't want to use this unless you know what you
880 are doing.
881
882 The default is disabled.");
883
884   ("get_direct", (RBool "direct", []), -1, [],
885    [],
886    "get direct appliance mode flag",
887    "\
888 Return the direct appliance mode flag.");
889
890   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
891    [InitNone, Always, TestOutputTrue (
892       [["set_recovery_proc"; "true"];
893        ["get_recovery_proc"]])],
894    "enable or disable the recovery process",
895    "\
896 If this is called with the parameter C<false> then
897 C<guestfs_launch> does not create a recovery process.  The
898 purpose of the recovery process is to stop runaway qemu
899 processes in the case where the main program aborts abruptly.
900
901 This only has any effect if called before C<guestfs_launch>,
902 and the default is true.
903
904 About the only time when you would want to disable this is
905 if the main process will fork itself into the background
906 (\"daemonize\" itself).  In this case the recovery process
907 thinks that the main program has disappeared and so kills
908 qemu, which is not very helpful.");
909
910   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
911    [],
912    "get recovery process enabled flag",
913    "\
914 Return the recovery process enabled flag.");
915
916   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
917    [],
918    "add a drive specifying the QEMU block emulation to use",
919    "\
920 This is the same as C<guestfs_add_drive> but it allows you
921 to specify the QEMU interface emulation to use at run time.");
922
923   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
924    [],
925    "add a drive read-only specifying the QEMU block emulation to use",
926    "\
927 This is the same as C<guestfs_add_drive_ro> but it allows you
928 to specify the QEMU interface emulation to use at run time.");
929
930 ]
931
932 (* daemon_functions are any functions which cause some action
933  * to take place in the daemon.
934  *)
935
936 let daemon_functions = [
937   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
938    [InitEmpty, Always, TestOutput (
939       [["part_disk"; "/dev/sda"; "mbr"];
940        ["mkfs"; "ext2"; "/dev/sda1"];
941        ["mount"; "/dev/sda1"; "/"];
942        ["write_file"; "/new"; "new file contents"; "0"];
943        ["cat"; "/new"]], "new file contents")],
944    "mount a guest disk at a position in the filesystem",
945    "\
946 Mount a guest disk at a position in the filesystem.  Block devices
947 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
948 the guest.  If those block devices contain partitions, they will have
949 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
950 names can be used.
951
952 The rules are the same as for L<mount(2)>:  A filesystem must
953 first be mounted on C</> before others can be mounted.  Other
954 filesystems can only be mounted on directories which already
955 exist.
956
957 The mounted filesystem is writable, if we have sufficient permissions
958 on the underlying device.
959
960 B<Important note:>
961 When you use this call, the filesystem options C<sync> and C<noatime>
962 are set implicitly.  This was originally done because we thought it
963 would improve reliability, but it turns out that I<-o sync> has a
964 very large negative performance impact and negligible effect on
965 reliability.  Therefore we recommend that you avoid using
966 C<guestfs_mount> in any code that needs performance, and instead
967 use C<guestfs_mount_options> (use an empty string for the first
968 parameter if you don't want any options).");
969
970   ("sync", (RErr, []), 2, [],
971    [ InitEmpty, Always, TestRun [["sync"]]],
972    "sync disks, writes are flushed through to the disk image",
973    "\
974 This syncs the disk, so that any writes are flushed through to the
975 underlying disk image.
976
977 You should always call this if you have modified a disk image, before
978 closing the handle.");
979
980   ("touch", (RErr, [Pathname "path"]), 3, [],
981    [InitBasicFS, Always, TestOutputTrue (
982       [["touch"; "/new"];
983        ["exists"; "/new"]])],
984    "update file timestamps or create a new file",
985    "\
986 Touch acts like the L<touch(1)> command.  It can be used to
987 update the timestamps on a file, or, if the file does not exist,
988 to create a new zero-length file.");
989
990   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
991    [InitISOFS, Always, TestOutput (
992       [["cat"; "/known-2"]], "abcdef\n")],
993    "list the contents of a file",
994    "\
995 Return the contents of the file named C<path>.
996
997 Note that this function cannot correctly handle binary files
998 (specifically, files containing C<\\0> character which is treated
999 as end of string).  For those you need to use the C<guestfs_read_file>
1000 or C<guestfs_download> functions which have a more complex interface.");
1001
1002   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1003    [], (* XXX Tricky to test because it depends on the exact format
1004         * of the 'ls -l' command, which changes between F10 and F11.
1005         *)
1006    "list the files in a directory (long format)",
1007    "\
1008 List the files in C<directory> (relative to the root directory,
1009 there is no cwd) in the format of 'ls -la'.
1010
1011 This command is mostly useful for interactive sessions.  It
1012 is I<not> intended that you try to parse the output string.");
1013
1014   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1015    [InitBasicFS, Always, TestOutputList (
1016       [["touch"; "/new"];
1017        ["touch"; "/newer"];
1018        ["touch"; "/newest"];
1019        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1020    "list the files in a directory",
1021    "\
1022 List the files in C<directory> (relative to the root directory,
1023 there is no cwd).  The '.' and '..' entries are not returned, but
1024 hidden files are shown.
1025
1026 This command is mostly useful for interactive sessions.  Programs
1027 should probably use C<guestfs_readdir> instead.");
1028
1029   ("list_devices", (RStringList "devices", []), 7, [],
1030    [InitEmpty, Always, TestOutputListOfDevices (
1031       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1032    "list the block devices",
1033    "\
1034 List all the block devices.
1035
1036 The full block device names are returned, eg. C</dev/sda>");
1037
1038   ("list_partitions", (RStringList "partitions", []), 8, [],
1039    [InitBasicFS, Always, TestOutputListOfDevices (
1040       [["list_partitions"]], ["/dev/sda1"]);
1041     InitEmpty, Always, TestOutputListOfDevices (
1042       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1043        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1044    "list the partitions",
1045    "\
1046 List all the partitions detected on all block devices.
1047
1048 The full partition device names are returned, eg. C</dev/sda1>
1049
1050 This does not return logical volumes.  For that you will need to
1051 call C<guestfs_lvs>.");
1052
1053   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1054    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1055       [["pvs"]], ["/dev/sda1"]);
1056     InitEmpty, Always, TestOutputListOfDevices (
1057       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1058        ["pvcreate"; "/dev/sda1"];
1059        ["pvcreate"; "/dev/sda2"];
1060        ["pvcreate"; "/dev/sda3"];
1061        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1062    "list the LVM physical volumes (PVs)",
1063    "\
1064 List all the physical volumes detected.  This is the equivalent
1065 of the L<pvs(8)> command.
1066
1067 This returns a list of just the device names that contain
1068 PVs (eg. C</dev/sda2>).
1069
1070 See also C<guestfs_pvs_full>.");
1071
1072   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1073    [InitBasicFSonLVM, Always, TestOutputList (
1074       [["vgs"]], ["VG"]);
1075     InitEmpty, Always, TestOutputList (
1076       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1077        ["pvcreate"; "/dev/sda1"];
1078        ["pvcreate"; "/dev/sda2"];
1079        ["pvcreate"; "/dev/sda3"];
1080        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1081        ["vgcreate"; "VG2"; "/dev/sda3"];
1082        ["vgs"]], ["VG1"; "VG2"])],
1083    "list the LVM volume groups (VGs)",
1084    "\
1085 List all the volumes groups detected.  This is the equivalent
1086 of the L<vgs(8)> command.
1087
1088 This returns a list of just the volume group names that were
1089 detected (eg. C<VolGroup00>).
1090
1091 See also C<guestfs_vgs_full>.");
1092
1093   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1094    [InitBasicFSonLVM, Always, TestOutputList (
1095       [["lvs"]], ["/dev/VG/LV"]);
1096     InitEmpty, Always, TestOutputList (
1097       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1098        ["pvcreate"; "/dev/sda1"];
1099        ["pvcreate"; "/dev/sda2"];
1100        ["pvcreate"; "/dev/sda3"];
1101        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1102        ["vgcreate"; "VG2"; "/dev/sda3"];
1103        ["lvcreate"; "LV1"; "VG1"; "50"];
1104        ["lvcreate"; "LV2"; "VG1"; "50"];
1105        ["lvcreate"; "LV3"; "VG2"; "50"];
1106        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1107    "list the LVM logical volumes (LVs)",
1108    "\
1109 List all the logical volumes detected.  This is the equivalent
1110 of the L<lvs(8)> command.
1111
1112 This returns a list of the logical volume device names
1113 (eg. C</dev/VolGroup00/LogVol00>).
1114
1115 See also C<guestfs_lvs_full>.");
1116
1117   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1118    [], (* XXX how to test? *)
1119    "list the LVM physical volumes (PVs)",
1120    "\
1121 List all the physical volumes detected.  This is the equivalent
1122 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1123
1124   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1125    [], (* XXX how to test? *)
1126    "list the LVM volume groups (VGs)",
1127    "\
1128 List all the volumes groups detected.  This is the equivalent
1129 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1130
1131   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1132    [], (* XXX how to test? *)
1133    "list the LVM logical volumes (LVs)",
1134    "\
1135 List all the logical volumes detected.  This is the equivalent
1136 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1137
1138   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1139    [InitISOFS, Always, TestOutputList (
1140       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1141     InitISOFS, Always, TestOutputList (
1142       [["read_lines"; "/empty"]], [])],
1143    "read file as lines",
1144    "\
1145 Return the contents of the file named C<path>.
1146
1147 The file contents are returned as a list of lines.  Trailing
1148 C<LF> and C<CRLF> character sequences are I<not> returned.
1149
1150 Note that this function cannot correctly handle binary files
1151 (specifically, files containing C<\\0> character which is treated
1152 as end of line).  For those you need to use the C<guestfs_read_file>
1153 function which has a more complex interface.");
1154
1155   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1156    [], (* XXX Augeas code needs tests. *)
1157    "create a new Augeas handle",
1158    "\
1159 Create a new Augeas handle for editing configuration files.
1160 If there was any previous Augeas handle associated with this
1161 guestfs session, then it is closed.
1162
1163 You must call this before using any other C<guestfs_aug_*>
1164 commands.
1165
1166 C<root> is the filesystem root.  C<root> must not be NULL,
1167 use C</> instead.
1168
1169 The flags are the same as the flags defined in
1170 E<lt>augeas.hE<gt>, the logical I<or> of the following
1171 integers:
1172
1173 =over 4
1174
1175 =item C<AUG_SAVE_BACKUP> = 1
1176
1177 Keep the original file with a C<.augsave> extension.
1178
1179 =item C<AUG_SAVE_NEWFILE> = 2
1180
1181 Save changes into a file with extension C<.augnew>, and
1182 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1183
1184 =item C<AUG_TYPE_CHECK> = 4
1185
1186 Typecheck lenses (can be expensive).
1187
1188 =item C<AUG_NO_STDINC> = 8
1189
1190 Do not use standard load path for modules.
1191
1192 =item C<AUG_SAVE_NOOP> = 16
1193
1194 Make save a no-op, just record what would have been changed.
1195
1196 =item C<AUG_NO_LOAD> = 32
1197
1198 Do not load the tree in C<guestfs_aug_init>.
1199
1200 =back
1201
1202 To close the handle, you can call C<guestfs_aug_close>.
1203
1204 To find out more about Augeas, see L<http://augeas.net/>.");
1205
1206   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1207    [], (* XXX Augeas code needs tests. *)
1208    "close the current Augeas handle",
1209    "\
1210 Close the current Augeas handle and free up any resources
1211 used by it.  After calling this, you have to call
1212 C<guestfs_aug_init> again before you can use any other
1213 Augeas functions.");
1214
1215   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas variable",
1218    "\
1219 Defines an Augeas variable C<name> whose value is the result
1220 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1221 undefined.
1222
1223 On success this returns the number of nodes in C<expr>, or
1224 C<0> if C<expr> evaluates to something which is not a nodeset.");
1225
1226   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1227    [], (* XXX Augeas code needs tests. *)
1228    "define an Augeas node",
1229    "\
1230 Defines a variable C<name> whose value is the result of
1231 evaluating C<expr>.
1232
1233 If C<expr> evaluates to an empty nodeset, a node is created,
1234 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1235 C<name> will be the nodeset containing that single node.
1236
1237 On success this returns a pair containing the
1238 number of nodes in the nodeset, and a boolean flag
1239 if a node was created.");
1240
1241   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1242    [], (* XXX Augeas code needs tests. *)
1243    "look up the value of an Augeas path",
1244    "\
1245 Look up the value associated with C<path>.  If C<path>
1246 matches exactly one node, the C<value> is returned.");
1247
1248   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1249    [], (* XXX Augeas code needs tests. *)
1250    "set Augeas path to value",
1251    "\
1252 Set the value associated with C<path> to C<val>.
1253
1254 In the Augeas API, it is possible to clear a node by setting
1255 the value to NULL.  Due to an oversight in the libguestfs API
1256 you cannot do that with this call.  Instead you must use the
1257 C<guestfs_aug_clear> call.");
1258
1259   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1260    [], (* XXX Augeas code needs tests. *)
1261    "insert a sibling Augeas node",
1262    "\
1263 Create a new sibling C<label> for C<path>, inserting it into
1264 the tree before or after C<path> (depending on the boolean
1265 flag C<before>).
1266
1267 C<path> must match exactly one existing node in the tree, and
1268 C<label> must be a label, ie. not contain C</>, C<*> or end
1269 with a bracketed index C<[N]>.");
1270
1271   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1272    [], (* XXX Augeas code needs tests. *)
1273    "remove an Augeas path",
1274    "\
1275 Remove C<path> and all of its children.
1276
1277 On success this returns the number of entries which were removed.");
1278
1279   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1280    [], (* XXX Augeas code needs tests. *)
1281    "move Augeas node",
1282    "\
1283 Move the node C<src> to C<dest>.  C<src> must match exactly
1284 one node.  C<dest> is overwritten if it exists.");
1285
1286   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1287    [], (* XXX Augeas code needs tests. *)
1288    "return Augeas nodes which match augpath",
1289    "\
1290 Returns a list of paths which match the path expression C<path>.
1291 The returned paths are sufficiently qualified so that they match
1292 exactly one node in the current tree.");
1293
1294   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1295    [], (* XXX Augeas code needs tests. *)
1296    "write all pending Augeas changes to disk",
1297    "\
1298 This writes all pending changes to disk.
1299
1300 The flags which were passed to C<guestfs_aug_init> affect exactly
1301 how files are saved.");
1302
1303   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1304    [], (* XXX Augeas code needs tests. *)
1305    "load files into the tree",
1306    "\
1307 Load files into the tree.
1308
1309 See C<aug_load> in the Augeas documentation for the full gory
1310 details.");
1311
1312   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1313    [], (* XXX Augeas code needs tests. *)
1314    "list Augeas nodes under augpath",
1315    "\
1316 This is just a shortcut for listing C<guestfs_aug_match>
1317 C<path/*> and sorting the resulting nodes into alphabetical order.");
1318
1319   ("rm", (RErr, [Pathname "path"]), 29, [],
1320    [InitBasicFS, Always, TestRun
1321       [["touch"; "/new"];
1322        ["rm"; "/new"]];
1323     InitBasicFS, Always, TestLastFail
1324       [["rm"; "/new"]];
1325     InitBasicFS, Always, TestLastFail
1326       [["mkdir"; "/new"];
1327        ["rm"; "/new"]]],
1328    "remove a file",
1329    "\
1330 Remove the single file C<path>.");
1331
1332   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1333    [InitBasicFS, Always, TestRun
1334       [["mkdir"; "/new"];
1335        ["rmdir"; "/new"]];
1336     InitBasicFS, Always, TestLastFail
1337       [["rmdir"; "/new"]];
1338     InitBasicFS, Always, TestLastFail
1339       [["touch"; "/new"];
1340        ["rmdir"; "/new"]]],
1341    "remove a directory",
1342    "\
1343 Remove the single directory C<path>.");
1344
1345   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1346    [InitBasicFS, Always, TestOutputFalse
1347       [["mkdir"; "/new"];
1348        ["mkdir"; "/new/foo"];
1349        ["touch"; "/new/foo/bar"];
1350        ["rm_rf"; "/new"];
1351        ["exists"; "/new"]]],
1352    "remove a file or directory recursively",
1353    "\
1354 Remove the file or directory C<path>, recursively removing the
1355 contents if its a directory.  This is like the C<rm -rf> shell
1356 command.");
1357
1358   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1359    [InitBasicFS, Always, TestOutputTrue
1360       [["mkdir"; "/new"];
1361        ["is_dir"; "/new"]];
1362     InitBasicFS, Always, TestLastFail
1363       [["mkdir"; "/new/foo/bar"]]],
1364    "create a directory",
1365    "\
1366 Create a directory named C<path>.");
1367
1368   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1369    [InitBasicFS, Always, TestOutputTrue
1370       [["mkdir_p"; "/new/foo/bar"];
1371        ["is_dir"; "/new/foo/bar"]];
1372     InitBasicFS, Always, TestOutputTrue
1373       [["mkdir_p"; "/new/foo/bar"];
1374        ["is_dir"; "/new/foo"]];
1375     InitBasicFS, Always, TestOutputTrue
1376       [["mkdir_p"; "/new/foo/bar"];
1377        ["is_dir"; "/new"]];
1378     (* Regression tests for RHBZ#503133: *)
1379     InitBasicFS, Always, TestRun
1380       [["mkdir"; "/new"];
1381        ["mkdir_p"; "/new"]];
1382     InitBasicFS, Always, TestLastFail
1383       [["touch"; "/new"];
1384        ["mkdir_p"; "/new"]]],
1385    "create a directory and parents",
1386    "\
1387 Create a directory named C<path>, creating any parent directories
1388 as necessary.  This is like the C<mkdir -p> shell command.");
1389
1390   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1391    [], (* XXX Need stat command to test *)
1392    "change file mode",
1393    "\
1394 Change the mode (permissions) of C<path> to C<mode>.  Only
1395 numeric modes are supported.
1396
1397 I<Note>: When using this command from guestfish, C<mode>
1398 by default would be decimal, unless you prefix it with
1399 C<0> to get octal, ie. use C<0700> not C<700>.
1400
1401 The mode actually set is affected by the umask.");
1402
1403   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1404    [], (* XXX Need stat command to test *)
1405    "change file owner and group",
1406    "\
1407 Change the file owner to C<owner> and group to C<group>.
1408
1409 Only numeric uid and gid are supported.  If you want to use
1410 names, you will need to locate and parse the password file
1411 yourself (Augeas support makes this relatively easy).");
1412
1413   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1414    [InitISOFS, Always, TestOutputTrue (
1415       [["exists"; "/empty"]]);
1416     InitISOFS, Always, TestOutputTrue (
1417       [["exists"; "/directory"]])],
1418    "test if file or directory exists",
1419    "\
1420 This returns C<true> if and only if there is a file, directory
1421 (or anything) with the given C<path> name.
1422
1423 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1424
1425   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1426    [InitISOFS, Always, TestOutputTrue (
1427       [["is_file"; "/known-1"]]);
1428     InitISOFS, Always, TestOutputFalse (
1429       [["is_file"; "/directory"]])],
1430    "test if file exists",
1431    "\
1432 This returns C<true> if and only if there is a file
1433 with the given C<path> name.  Note that it returns false for
1434 other objects like directories.
1435
1436 See also C<guestfs_stat>.");
1437
1438   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1439    [InitISOFS, Always, TestOutputFalse (
1440       [["is_dir"; "/known-3"]]);
1441     InitISOFS, Always, TestOutputTrue (
1442       [["is_dir"; "/directory"]])],
1443    "test if file exists",
1444    "\
1445 This returns C<true> if and only if there is a directory
1446 with the given C<path> name.  Note that it returns false for
1447 other objects like files.
1448
1449 See also C<guestfs_stat>.");
1450
1451   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1452    [InitEmpty, Always, TestOutputListOfDevices (
1453       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1454        ["pvcreate"; "/dev/sda1"];
1455        ["pvcreate"; "/dev/sda2"];
1456        ["pvcreate"; "/dev/sda3"];
1457        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1458    "create an LVM physical volume",
1459    "\
1460 This creates an LVM physical volume on the named C<device>,
1461 where C<device> should usually be a partition name such
1462 as C</dev/sda1>.");
1463
1464   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1465    [InitEmpty, Always, TestOutputList (
1466       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1467        ["pvcreate"; "/dev/sda1"];
1468        ["pvcreate"; "/dev/sda2"];
1469        ["pvcreate"; "/dev/sda3"];
1470        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1471        ["vgcreate"; "VG2"; "/dev/sda3"];
1472        ["vgs"]], ["VG1"; "VG2"])],
1473    "create an LVM volume group",
1474    "\
1475 This creates an LVM volume group called C<volgroup>
1476 from the non-empty list of physical volumes C<physvols>.");
1477
1478   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1479    [InitEmpty, Always, TestOutputList (
1480       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1481        ["pvcreate"; "/dev/sda1"];
1482        ["pvcreate"; "/dev/sda2"];
1483        ["pvcreate"; "/dev/sda3"];
1484        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1485        ["vgcreate"; "VG2"; "/dev/sda3"];
1486        ["lvcreate"; "LV1"; "VG1"; "50"];
1487        ["lvcreate"; "LV2"; "VG1"; "50"];
1488        ["lvcreate"; "LV3"; "VG2"; "50"];
1489        ["lvcreate"; "LV4"; "VG2"; "50"];
1490        ["lvcreate"; "LV5"; "VG2"; "50"];
1491        ["lvs"]],
1492       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1493        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1494    "create an LVM logical volume",
1495    "\
1496 This creates an LVM logical volume called C<logvol>
1497 on the volume group C<volgroup>, with C<size> megabytes.");
1498
1499   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1500    [InitEmpty, Always, TestOutput (
1501       [["part_disk"; "/dev/sda"; "mbr"];
1502        ["mkfs"; "ext2"; "/dev/sda1"];
1503        ["mount_options"; ""; "/dev/sda1"; "/"];
1504        ["write_file"; "/new"; "new file contents"; "0"];
1505        ["cat"; "/new"]], "new file contents")],
1506    "make a filesystem",
1507    "\
1508 This creates a filesystem on C<device> (usually a partition
1509 or LVM logical volume).  The filesystem type is C<fstype>, for
1510 example C<ext3>.");
1511
1512   ("sfdisk", (RErr, [Device "device";
1513                      Int "cyls"; Int "heads"; Int "sectors";
1514                      StringList "lines"]), 43, [DangerWillRobinson],
1515    [],
1516    "create partitions on a block device",
1517    "\
1518 This is a direct interface to the L<sfdisk(8)> program for creating
1519 partitions on block devices.
1520
1521 C<device> should be a block device, for example C</dev/sda>.
1522
1523 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1524 and sectors on the device, which are passed directly to sfdisk as
1525 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1526 of these, then the corresponding parameter is omitted.  Usually for
1527 'large' disks, you can just pass C<0> for these, but for small
1528 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1529 out the right geometry and you will need to tell it.
1530
1531 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1532 information refer to the L<sfdisk(8)> manpage.
1533
1534 To create a single partition occupying the whole disk, you would
1535 pass C<lines> as a single element list, when the single element being
1536 the string C<,> (comma).
1537
1538 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1539 C<guestfs_part_init>");
1540
1541   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1542    [InitBasicFS, Always, TestOutput (
1543       [["write_file"; "/new"; "new file contents"; "0"];
1544        ["cat"; "/new"]], "new file contents");
1545     InitBasicFS, Always, TestOutput (
1546       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1547        ["cat"; "/new"]], "\nnew file contents\n");
1548     InitBasicFS, Always, TestOutput (
1549       [["write_file"; "/new"; "\n\n"; "0"];
1550        ["cat"; "/new"]], "\n\n");
1551     InitBasicFS, Always, TestOutput (
1552       [["write_file"; "/new"; ""; "0"];
1553        ["cat"; "/new"]], "");
1554     InitBasicFS, Always, TestOutput (
1555       [["write_file"; "/new"; "\n\n\n"; "0"];
1556        ["cat"; "/new"]], "\n\n\n");
1557     InitBasicFS, Always, TestOutput (
1558       [["write_file"; "/new"; "\n"; "0"];
1559        ["cat"; "/new"]], "\n")],
1560    "create a file",
1561    "\
1562 This call creates a file called C<path>.  The contents of the
1563 file is the string C<content> (which can contain any 8 bit data),
1564 with length C<size>.
1565
1566 As a special case, if C<size> is C<0>
1567 then the length is calculated using C<strlen> (so in this case
1568 the content cannot contain embedded ASCII NULs).
1569
1570 I<NB.> Owing to a bug, writing content containing ASCII NUL
1571 characters does I<not> work, even if the length is specified.
1572 We hope to resolve this bug in a future version.  In the meantime
1573 use C<guestfs_upload>.");
1574
1575   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1576    [InitEmpty, Always, TestOutputListOfDevices (
1577       [["part_disk"; "/dev/sda"; "mbr"];
1578        ["mkfs"; "ext2"; "/dev/sda1"];
1579        ["mount_options"; ""; "/dev/sda1"; "/"];
1580        ["mounts"]], ["/dev/sda1"]);
1581     InitEmpty, Always, TestOutputList (
1582       [["part_disk"; "/dev/sda"; "mbr"];
1583        ["mkfs"; "ext2"; "/dev/sda1"];
1584        ["mount_options"; ""; "/dev/sda1"; "/"];
1585        ["umount"; "/"];
1586        ["mounts"]], [])],
1587    "unmount a filesystem",
1588    "\
1589 This unmounts the given filesystem.  The filesystem may be
1590 specified either by its mountpoint (path) or the device which
1591 contains the filesystem.");
1592
1593   ("mounts", (RStringList "devices", []), 46, [],
1594    [InitBasicFS, Always, TestOutputListOfDevices (
1595       [["mounts"]], ["/dev/sda1"])],
1596    "show mounted filesystems",
1597    "\
1598 This returns the list of currently mounted filesystems.  It returns
1599 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1600
1601 Some internal mounts are not shown.
1602
1603 See also: C<guestfs_mountpoints>");
1604
1605   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1606    [InitBasicFS, Always, TestOutputList (
1607       [["umount_all"];
1608        ["mounts"]], []);
1609     (* check that umount_all can unmount nested mounts correctly: *)
1610     InitEmpty, Always, TestOutputList (
1611       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1612        ["mkfs"; "ext2"; "/dev/sda1"];
1613        ["mkfs"; "ext2"; "/dev/sda2"];
1614        ["mkfs"; "ext2"; "/dev/sda3"];
1615        ["mount_options"; ""; "/dev/sda1"; "/"];
1616        ["mkdir"; "/mp1"];
1617        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1618        ["mkdir"; "/mp1/mp2"];
1619        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1620        ["mkdir"; "/mp1/mp2/mp3"];
1621        ["umount_all"];
1622        ["mounts"]], [])],
1623    "unmount all filesystems",
1624    "\
1625 This unmounts all mounted filesystems.
1626
1627 Some internal mounts are not unmounted by this call.");
1628
1629   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1630    [],
1631    "remove all LVM LVs, VGs and PVs",
1632    "\
1633 This command removes all LVM logical volumes, volume groups
1634 and physical volumes.");
1635
1636   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1637    [InitISOFS, Always, TestOutput (
1638       [["file"; "/empty"]], "empty");
1639     InitISOFS, Always, TestOutput (
1640       [["file"; "/known-1"]], "ASCII text");
1641     InitISOFS, Always, TestLastFail (
1642       [["file"; "/notexists"]])],
1643    "determine file type",
1644    "\
1645 This call uses the standard L<file(1)> command to determine
1646 the type or contents of the file.  This also works on devices,
1647 for example to find out whether a partition contains a filesystem.
1648
1649 This call will also transparently look inside various types
1650 of compressed file.
1651
1652 The exact command which runs is C<file -zbsL path>.  Note in
1653 particular that the filename is not prepended to the output
1654 (the C<-b> option).");
1655
1656   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1657    [InitBasicFS, Always, TestOutput (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command"; "/test-command 1"]], "Result1");
1661     InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 2"]], "Result2\n");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 3"]], "\nResult3");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 4"]], "\nResult4\n");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 5"]], "\nResult5\n\n");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1681     InitBasicFS, Always, TestOutput (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command 7"]], "");
1685     InitBasicFS, Always, TestOutput (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command"; "/test-command 8"]], "\n");
1689     InitBasicFS, Always, TestOutput (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command"; "/test-command 9"]], "\n\n");
1693     InitBasicFS, Always, TestOutput (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1697     InitBasicFS, Always, TestOutput (
1698       [["upload"; "test-command"; "/test-command"];
1699        ["chmod"; "0o755"; "/test-command"];
1700        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1701     InitBasicFS, Always, TestLastFail (
1702       [["upload"; "test-command"; "/test-command"];
1703        ["chmod"; "0o755"; "/test-command"];
1704        ["command"; "/test-command"]])],
1705    "run a command from the guest filesystem",
1706    "\
1707 This call runs a command from the guest filesystem.  The
1708 filesystem must be mounted, and must contain a compatible
1709 operating system (ie. something Linux, with the same
1710 or compatible processor architecture).
1711
1712 The single parameter is an argv-style list of arguments.
1713 The first element is the name of the program to run.
1714 Subsequent elements are parameters.  The list must be
1715 non-empty (ie. must contain a program name).  Note that
1716 the command runs directly, and is I<not> invoked via
1717 the shell (see C<guestfs_sh>).
1718
1719 The return value is anything printed to I<stdout> by
1720 the command.
1721
1722 If the command returns a non-zero exit status, then
1723 this function returns an error message.  The error message
1724 string is the content of I<stderr> from the command.
1725
1726 The C<$PATH> environment variable will contain at least
1727 C</usr/bin> and C</bin>.  If you require a program from
1728 another location, you should provide the full path in the
1729 first parameter.
1730
1731 Shared libraries and data files required by the program
1732 must be available on filesystems which are mounted in the
1733 correct places.  It is the caller's responsibility to ensure
1734 all filesystems that are needed are mounted at the right
1735 locations.");
1736
1737   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1738    [InitBasicFS, Always, TestOutputList (
1739       [["upload"; "test-command"; "/test-command"];
1740        ["chmod"; "0o755"; "/test-command"];
1741        ["command_lines"; "/test-command 1"]], ["Result1"]);
1742     InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 2"]], ["Result2"]);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1762     InitBasicFS, Always, TestOutputList (
1763       [["upload"; "test-command"; "/test-command"];
1764        ["chmod"; "0o755"; "/test-command"];
1765        ["command_lines"; "/test-command 7"]], []);
1766     InitBasicFS, Always, TestOutputList (
1767       [["upload"; "test-command"; "/test-command"];
1768        ["chmod"; "0o755"; "/test-command"];
1769        ["command_lines"; "/test-command 8"]], [""]);
1770     InitBasicFS, Always, TestOutputList (
1771       [["upload"; "test-command"; "/test-command"];
1772        ["chmod"; "0o755"; "/test-command"];
1773        ["command_lines"; "/test-command 9"]], ["";""]);
1774     InitBasicFS, Always, TestOutputList (
1775       [["upload"; "test-command"; "/test-command"];
1776        ["chmod"; "0o755"; "/test-command"];
1777        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1778     InitBasicFS, Always, TestOutputList (
1779       [["upload"; "test-command"; "/test-command"];
1780        ["chmod"; "0o755"; "/test-command"];
1781        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1782    "run a command, returning lines",
1783    "\
1784 This is the same as C<guestfs_command>, but splits the
1785 result into a list of lines.
1786
1787 See also: C<guestfs_sh_lines>");
1788
1789   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1790    [InitISOFS, Always, TestOutputStruct (
1791       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1792    "get file information",
1793    "\
1794 Returns file information for the given C<path>.
1795
1796 This is the same as the C<stat(2)> system call.");
1797
1798   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1799    [InitISOFS, Always, TestOutputStruct (
1800       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1801    "get file information for a symbolic link",
1802    "\
1803 Returns file information for the given C<path>.
1804
1805 This is the same as C<guestfs_stat> except that if C<path>
1806 is a symbolic link, then the link is stat-ed, not the file it
1807 refers to.
1808
1809 This is the same as the C<lstat(2)> system call.");
1810
1811   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1812    [InitISOFS, Always, TestOutputStruct (
1813       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1814    "get file system statistics",
1815    "\
1816 Returns file system statistics for any mounted file system.
1817 C<path> should be a file or directory in the mounted file system
1818 (typically it is the mount point itself, but it doesn't need to be).
1819
1820 This is the same as the C<statvfs(2)> system call.");
1821
1822   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1823    [], (* XXX test *)
1824    "get ext2/ext3/ext4 superblock details",
1825    "\
1826 This returns the contents of the ext2, ext3 or ext4 filesystem
1827 superblock on C<device>.
1828
1829 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1830 manpage for more details.  The list of fields returned isn't
1831 clearly defined, and depends on both the version of C<tune2fs>
1832 that libguestfs was built against, and the filesystem itself.");
1833
1834   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1835    [InitEmpty, Always, TestOutputTrue (
1836       [["blockdev_setro"; "/dev/sda"];
1837        ["blockdev_getro"; "/dev/sda"]])],
1838    "set block device to read-only",
1839    "\
1840 Sets the block device named C<device> to read-only.
1841
1842 This uses the L<blockdev(8)> command.");
1843
1844   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1845    [InitEmpty, Always, TestOutputFalse (
1846       [["blockdev_setrw"; "/dev/sda"];
1847        ["blockdev_getro"; "/dev/sda"]])],
1848    "set block device to read-write",
1849    "\
1850 Sets the block device named C<device> to read-write.
1851
1852 This uses the L<blockdev(8)> command.");
1853
1854   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1855    [InitEmpty, Always, TestOutputTrue (
1856       [["blockdev_setro"; "/dev/sda"];
1857        ["blockdev_getro"; "/dev/sda"]])],
1858    "is block device set to read-only",
1859    "\
1860 Returns a boolean indicating if the block device is read-only
1861 (true if read-only, false if not).
1862
1863 This uses the L<blockdev(8)> command.");
1864
1865   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1866    [InitEmpty, Always, TestOutputInt (
1867       [["blockdev_getss"; "/dev/sda"]], 512)],
1868    "get sectorsize of block device",
1869    "\
1870 This returns the size of sectors on a block device.
1871 Usually 512, but can be larger for modern devices.
1872
1873 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1874 for that).
1875
1876 This uses the L<blockdev(8)> command.");
1877
1878   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1879    [InitEmpty, Always, TestOutputInt (
1880       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1881    "get blocksize of block device",
1882    "\
1883 This returns the block size of a device.
1884
1885 (Note this is different from both I<size in blocks> and
1886 I<filesystem block size>).
1887
1888 This uses the L<blockdev(8)> command.");
1889
1890   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1891    [], (* XXX test *)
1892    "set blocksize of block device",
1893    "\
1894 This sets the block size of a device.
1895
1896 (Note this is different from both I<size in blocks> and
1897 I<filesystem block size>).
1898
1899 This uses the L<blockdev(8)> command.");
1900
1901   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1902    [InitEmpty, Always, TestOutputInt (
1903       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1904    "get total size of device in 512-byte sectors",
1905    "\
1906 This returns the size of the device in units of 512-byte sectors
1907 (even if the sectorsize isn't 512 bytes ... weird).
1908
1909 See also C<guestfs_blockdev_getss> for the real sector size of
1910 the device, and C<guestfs_blockdev_getsize64> for the more
1911 useful I<size in bytes>.
1912
1913 This uses the L<blockdev(8)> command.");
1914
1915   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1916    [InitEmpty, Always, TestOutputInt (
1917       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1918    "get total size of device in bytes",
1919    "\
1920 This returns the size of the device in bytes.
1921
1922 See also C<guestfs_blockdev_getsz>.
1923
1924 This uses the L<blockdev(8)> command.");
1925
1926   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1927    [InitEmpty, Always, TestRun
1928       [["blockdev_flushbufs"; "/dev/sda"]]],
1929    "flush device buffers",
1930    "\
1931 This tells the kernel to flush internal buffers associated
1932 with C<device>.
1933
1934 This uses the L<blockdev(8)> command.");
1935
1936   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1937    [InitEmpty, Always, TestRun
1938       [["blockdev_rereadpt"; "/dev/sda"]]],
1939    "reread partition table",
1940    "\
1941 Reread the partition table on C<device>.
1942
1943 This uses the L<blockdev(8)> command.");
1944
1945   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1946    [InitBasicFS, Always, TestOutput (
1947       (* Pick a file from cwd which isn't likely to change. *)
1948       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1949        ["checksum"; "md5"; "/COPYING.LIB"]],
1950       Digest.to_hex (Digest.file "COPYING.LIB"))],
1951    "upload a file from the local machine",
1952    "\
1953 Upload local file C<filename> to C<remotefilename> on the
1954 filesystem.
1955
1956 C<filename> can also be a named pipe.
1957
1958 See also C<guestfs_download>.");
1959
1960   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1961    [InitBasicFS, Always, TestOutput (
1962       (* Pick a file from cwd which isn't likely to change. *)
1963       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1964        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1965        ["upload"; "testdownload.tmp"; "/upload"];
1966        ["checksum"; "md5"; "/upload"]],
1967       Digest.to_hex (Digest.file "COPYING.LIB"))],
1968    "download a file to the local machine",
1969    "\
1970 Download file C<remotefilename> and save it as C<filename>
1971 on the local machine.
1972
1973 C<filename> can also be a named pipe.
1974
1975 See also C<guestfs_upload>, C<guestfs_cat>.");
1976
1977   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1978    [InitISOFS, Always, TestOutput (
1979       [["checksum"; "crc"; "/known-3"]], "2891671662");
1980     InitISOFS, Always, TestLastFail (
1981       [["checksum"; "crc"; "/notexists"]]);
1982     InitISOFS, Always, TestOutput (
1983       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1984     InitISOFS, Always, TestOutput (
1985       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1986     InitISOFS, Always, TestOutput (
1987       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1988     InitISOFS, Always, TestOutput (
1989       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1990     InitISOFS, Always, TestOutput (
1991       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1992     InitISOFS, Always, TestOutput (
1993       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1994     (* Test for RHBZ#579608, absolute symbolic links. *)
1995     InitISOFS, Always, TestOutput (
1996       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1997    "compute MD5, SHAx or CRC checksum of file",
1998    "\
1999 This call computes the MD5, SHAx or CRC checksum of the
2000 file named C<path>.
2001
2002 The type of checksum to compute is given by the C<csumtype>
2003 parameter which must have one of the following values:
2004
2005 =over 4
2006
2007 =item C<crc>
2008
2009 Compute the cyclic redundancy check (CRC) specified by POSIX
2010 for the C<cksum> command.
2011
2012 =item C<md5>
2013
2014 Compute the MD5 hash (using the C<md5sum> program).
2015
2016 =item C<sha1>
2017
2018 Compute the SHA1 hash (using the C<sha1sum> program).
2019
2020 =item C<sha224>
2021
2022 Compute the SHA224 hash (using the C<sha224sum> program).
2023
2024 =item C<sha256>
2025
2026 Compute the SHA256 hash (using the C<sha256sum> program).
2027
2028 =item C<sha384>
2029
2030 Compute the SHA384 hash (using the C<sha384sum> program).
2031
2032 =item C<sha512>
2033
2034 Compute the SHA512 hash (using the C<sha512sum> program).
2035
2036 =back
2037
2038 The checksum is returned as a printable string.
2039
2040 To get the checksum for a device, use C<guestfs_checksum_device>.
2041
2042 To get the checksums for many files, use C<guestfs_checksums_out>.");
2043
2044   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2045    [InitBasicFS, Always, TestOutput (
2046       [["tar_in"; "../images/helloworld.tar"; "/"];
2047        ["cat"; "/hello"]], "hello\n")],
2048    "unpack tarfile to directory",
2049    "\
2050 This command uploads and unpacks local file C<tarfile> (an
2051 I<uncompressed> tar file) into C<directory>.
2052
2053 To upload a compressed tarball, use C<guestfs_tgz_in>
2054 or C<guestfs_txz_in>.");
2055
2056   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2057    [],
2058    "pack directory into tarfile",
2059    "\
2060 This command packs the contents of C<directory> and downloads
2061 it to local file C<tarfile>.
2062
2063 To download a compressed tarball, use C<guestfs_tgz_out>
2064 or C<guestfs_txz_out>.");
2065
2066   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2067    [InitBasicFS, Always, TestOutput (
2068       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2069        ["cat"; "/hello"]], "hello\n")],
2070    "unpack compressed tarball to directory",
2071    "\
2072 This command uploads and unpacks local file C<tarball> (a
2073 I<gzip compressed> tar file) into C<directory>.
2074
2075 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2076
2077   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2078    [],
2079    "pack directory into compressed tarball",
2080    "\
2081 This command packs the contents of C<directory> and downloads
2082 it to local file C<tarball>.
2083
2084 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2085
2086   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2087    [InitBasicFS, Always, TestLastFail (
2088       [["umount"; "/"];
2089        ["mount_ro"; "/dev/sda1"; "/"];
2090        ["touch"; "/new"]]);
2091     InitBasicFS, Always, TestOutput (
2092       [["write_file"; "/new"; "data"; "0"];
2093        ["umount"; "/"];
2094        ["mount_ro"; "/dev/sda1"; "/"];
2095        ["cat"; "/new"]], "data")],
2096    "mount a guest disk, read-only",
2097    "\
2098 This is the same as the C<guestfs_mount> command, but it
2099 mounts the filesystem with the read-only (I<-o ro>) flag.");
2100
2101   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2102    [],
2103    "mount a guest disk with mount options",
2104    "\
2105 This is the same as the C<guestfs_mount> command, but it
2106 allows you to set the mount options as for the
2107 L<mount(8)> I<-o> flag.
2108
2109 If the C<options> parameter is an empty string, then
2110 no options are passed (all options default to whatever
2111 the filesystem uses).");
2112
2113   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2114    [],
2115    "mount a guest disk with mount options and vfstype",
2116    "\
2117 This is the same as the C<guestfs_mount> command, but it
2118 allows you to set both the mount options and the vfstype
2119 as for the L<mount(8)> I<-o> and I<-t> flags.");
2120
2121   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2122    [],
2123    "debugging and internals",
2124    "\
2125 The C<guestfs_debug> command exposes some internals of
2126 C<guestfsd> (the guestfs daemon) that runs inside the
2127 qemu subprocess.
2128
2129 There is no comprehensive help for this command.  You have
2130 to look at the file C<daemon/debug.c> in the libguestfs source
2131 to find out what you can do.");
2132
2133   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2134    [InitEmpty, Always, TestOutputList (
2135       [["part_disk"; "/dev/sda"; "mbr"];
2136        ["pvcreate"; "/dev/sda1"];
2137        ["vgcreate"; "VG"; "/dev/sda1"];
2138        ["lvcreate"; "LV1"; "VG"; "50"];
2139        ["lvcreate"; "LV2"; "VG"; "50"];
2140        ["lvremove"; "/dev/VG/LV1"];
2141        ["lvs"]], ["/dev/VG/LV2"]);
2142     InitEmpty, Always, TestOutputList (
2143       [["part_disk"; "/dev/sda"; "mbr"];
2144        ["pvcreate"; "/dev/sda1"];
2145        ["vgcreate"; "VG"; "/dev/sda1"];
2146        ["lvcreate"; "LV1"; "VG"; "50"];
2147        ["lvcreate"; "LV2"; "VG"; "50"];
2148        ["lvremove"; "/dev/VG"];
2149        ["lvs"]], []);
2150     InitEmpty, Always, TestOutputList (
2151       [["part_disk"; "/dev/sda"; "mbr"];
2152        ["pvcreate"; "/dev/sda1"];
2153        ["vgcreate"; "VG"; "/dev/sda1"];
2154        ["lvcreate"; "LV1"; "VG"; "50"];
2155        ["lvcreate"; "LV2"; "VG"; "50"];
2156        ["lvremove"; "/dev/VG"];
2157        ["vgs"]], ["VG"])],
2158    "remove an LVM logical volume",
2159    "\
2160 Remove an LVM logical volume C<device>, where C<device> is
2161 the path to the LV, such as C</dev/VG/LV>.
2162
2163 You can also remove all LVs in a volume group by specifying
2164 the VG name, C</dev/VG>.");
2165
2166   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2167    [InitEmpty, Always, TestOutputList (
2168       [["part_disk"; "/dev/sda"; "mbr"];
2169        ["pvcreate"; "/dev/sda1"];
2170        ["vgcreate"; "VG"; "/dev/sda1"];
2171        ["lvcreate"; "LV1"; "VG"; "50"];
2172        ["lvcreate"; "LV2"; "VG"; "50"];
2173        ["vgremove"; "VG"];
2174        ["lvs"]], []);
2175     InitEmpty, Always, TestOutputList (
2176       [["part_disk"; "/dev/sda"; "mbr"];
2177        ["pvcreate"; "/dev/sda1"];
2178        ["vgcreate"; "VG"; "/dev/sda1"];
2179        ["lvcreate"; "LV1"; "VG"; "50"];
2180        ["lvcreate"; "LV2"; "VG"; "50"];
2181        ["vgremove"; "VG"];
2182        ["vgs"]], [])],
2183    "remove an LVM volume group",
2184    "\
2185 Remove an LVM volume group C<vgname>, (for example C<VG>).
2186
2187 This also forcibly removes all logical volumes in the volume
2188 group (if any).");
2189
2190   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2191    [InitEmpty, Always, TestOutputListOfDevices (
2192       [["part_disk"; "/dev/sda"; "mbr"];
2193        ["pvcreate"; "/dev/sda1"];
2194        ["vgcreate"; "VG"; "/dev/sda1"];
2195        ["lvcreate"; "LV1"; "VG"; "50"];
2196        ["lvcreate"; "LV2"; "VG"; "50"];
2197        ["vgremove"; "VG"];
2198        ["pvremove"; "/dev/sda1"];
2199        ["lvs"]], []);
2200     InitEmpty, Always, TestOutputListOfDevices (
2201       [["part_disk"; "/dev/sda"; "mbr"];
2202        ["pvcreate"; "/dev/sda1"];
2203        ["vgcreate"; "VG"; "/dev/sda1"];
2204        ["lvcreate"; "LV1"; "VG"; "50"];
2205        ["lvcreate"; "LV2"; "VG"; "50"];
2206        ["vgremove"; "VG"];
2207        ["pvremove"; "/dev/sda1"];
2208        ["vgs"]], []);
2209     InitEmpty, Always, TestOutputListOfDevices (
2210       [["part_disk"; "/dev/sda"; "mbr"];
2211        ["pvcreate"; "/dev/sda1"];
2212        ["vgcreate"; "VG"; "/dev/sda1"];
2213        ["lvcreate"; "LV1"; "VG"; "50"];
2214        ["lvcreate"; "LV2"; "VG"; "50"];
2215        ["vgremove"; "VG"];
2216        ["pvremove"; "/dev/sda1"];
2217        ["pvs"]], [])],
2218    "remove an LVM physical volume",
2219    "\
2220 This wipes a physical volume C<device> so that LVM will no longer
2221 recognise it.
2222
2223 The implementation uses the C<pvremove> command which refuses to
2224 wipe physical volumes that contain any volume groups, so you have
2225 to remove those first.");
2226
2227   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2228    [InitBasicFS, Always, TestOutput (
2229       [["set_e2label"; "/dev/sda1"; "testlabel"];
2230        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2231    "set the ext2/3/4 filesystem label",
2232    "\
2233 This sets the ext2/3/4 filesystem label of the filesystem on
2234 C<device> to C<label>.  Filesystem labels are limited to
2235 16 characters.
2236
2237 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2238 to return the existing label on a filesystem.");
2239
2240   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2241    [],
2242    "get the ext2/3/4 filesystem label",
2243    "\
2244 This returns the ext2/3/4 filesystem label of the filesystem on
2245 C<device>.");
2246
2247   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2248    (let uuid = uuidgen () in
2249     [InitBasicFS, Always, TestOutput (
2250        [["set_e2uuid"; "/dev/sda1"; uuid];
2251         ["get_e2uuid"; "/dev/sda1"]], uuid);
2252      InitBasicFS, Always, TestOutput (
2253        [["set_e2uuid"; "/dev/sda1"; "clear"];
2254         ["get_e2uuid"; "/dev/sda1"]], "");
2255      (* We can't predict what UUIDs will be, so just check the commands run. *)
2256      InitBasicFS, Always, TestRun (
2257        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2258      InitBasicFS, Always, TestRun (
2259        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2260    "set the ext2/3/4 filesystem UUID",
2261    "\
2262 This sets the ext2/3/4 filesystem UUID of the filesystem on
2263 C<device> to C<uuid>.  The format of the UUID and alternatives
2264 such as C<clear>, C<random> and C<time> are described in the
2265 L<tune2fs(8)> manpage.
2266
2267 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2268 to return the existing UUID of a filesystem.");
2269
2270   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2271    [],
2272    "get the ext2/3/4 filesystem UUID",
2273    "\
2274 This returns the ext2/3/4 filesystem UUID of the filesystem on
2275 C<device>.");
2276
2277   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2278    [InitBasicFS, Always, TestOutputInt (
2279       [["umount"; "/dev/sda1"];
2280        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2281     InitBasicFS, Always, TestOutputInt (
2282       [["umount"; "/dev/sda1"];
2283        ["zero"; "/dev/sda1"];
2284        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2285    "run the filesystem checker",
2286    "\
2287 This runs the filesystem checker (fsck) on C<device> which
2288 should have filesystem type C<fstype>.
2289
2290 The returned integer is the status.  See L<fsck(8)> for the
2291 list of status codes from C<fsck>.
2292
2293 Notes:
2294
2295 =over 4
2296
2297 =item *
2298
2299 Multiple status codes can be summed together.
2300
2301 =item *
2302
2303 A non-zero return code can mean \"success\", for example if
2304 errors have been corrected on the filesystem.
2305
2306 =item *
2307
2308 Checking or repairing NTFS volumes is not supported
2309 (by linux-ntfs).
2310
2311 =back
2312
2313 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2314
2315   ("zero", (RErr, [Device "device"]), 85, [],
2316    [InitBasicFS, Always, TestOutput (
2317       [["umount"; "/dev/sda1"];
2318        ["zero"; "/dev/sda1"];
2319        ["file"; "/dev/sda1"]], "data")],
2320    "write zeroes to the device",
2321    "\
2322 This command writes zeroes over the first few blocks of C<device>.
2323
2324 How many blocks are zeroed isn't specified (but it's I<not> enough
2325 to securely wipe the device).  It should be sufficient to remove
2326 any partition tables, filesystem superblocks and so on.
2327
2328 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2329
2330   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2331    (* Test disabled because grub-install incompatible with virtio-blk driver.
2332     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2333     *)
2334    [InitBasicFS, Disabled, TestOutputTrue (
2335       [["grub_install"; "/"; "/dev/sda1"];
2336        ["is_dir"; "/boot"]])],
2337    "install GRUB",
2338    "\
2339 This command installs GRUB (the Grand Unified Bootloader) on
2340 C<device>, with the root directory being C<root>.");
2341
2342   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2343    [InitBasicFS, Always, TestOutput (
2344       [["write_file"; "/old"; "file content"; "0"];
2345        ["cp"; "/old"; "/new"];
2346        ["cat"; "/new"]], "file content");
2347     InitBasicFS, Always, TestOutputTrue (
2348       [["write_file"; "/old"; "file content"; "0"];
2349        ["cp"; "/old"; "/new"];
2350        ["is_file"; "/old"]]);
2351     InitBasicFS, Always, TestOutput (
2352       [["write_file"; "/old"; "file content"; "0"];
2353        ["mkdir"; "/dir"];
2354        ["cp"; "/old"; "/dir/new"];
2355        ["cat"; "/dir/new"]], "file content")],
2356    "copy a file",
2357    "\
2358 This copies a file from C<src> to C<dest> where C<dest> is
2359 either a destination filename or destination directory.");
2360
2361   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2362    [InitBasicFS, Always, TestOutput (
2363       [["mkdir"; "/olddir"];
2364        ["mkdir"; "/newdir"];
2365        ["write_file"; "/olddir/file"; "file content"; "0"];
2366        ["cp_a"; "/olddir"; "/newdir"];
2367        ["cat"; "/newdir/olddir/file"]], "file content")],
2368    "copy a file or directory recursively",
2369    "\
2370 This copies a file or directory from C<src> to C<dest>
2371 recursively using the C<cp -a> command.");
2372
2373   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2374    [InitBasicFS, Always, TestOutput (
2375       [["write_file"; "/old"; "file content"; "0"];
2376        ["mv"; "/old"; "/new"];
2377        ["cat"; "/new"]], "file content");
2378     InitBasicFS, Always, TestOutputFalse (
2379       [["write_file"; "/old"; "file content"; "0"];
2380        ["mv"; "/old"; "/new"];
2381        ["is_file"; "/old"]])],
2382    "move a file",
2383    "\
2384 This moves a file from C<src> to C<dest> where C<dest> is
2385 either a destination filename or destination directory.");
2386
2387   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2388    [InitEmpty, Always, TestRun (
2389       [["drop_caches"; "3"]])],
2390    "drop kernel page cache, dentries and inodes",
2391    "\
2392 This instructs the guest kernel to drop its page cache,
2393 and/or dentries and inode caches.  The parameter C<whattodrop>
2394 tells the kernel what precisely to drop, see
2395 L<http://linux-mm.org/Drop_Caches>
2396
2397 Setting C<whattodrop> to 3 should drop everything.
2398
2399 This automatically calls L<sync(2)> before the operation,
2400 so that the maximum guest memory is freed.");
2401
2402   ("dmesg", (RString "kmsgs", []), 91, [],
2403    [InitEmpty, Always, TestRun (
2404       [["dmesg"]])],
2405    "return kernel messages",
2406    "\
2407 This returns the kernel messages (C<dmesg> output) from
2408 the guest kernel.  This is sometimes useful for extended
2409 debugging of problems.
2410
2411 Another way to get the same information is to enable
2412 verbose messages with C<guestfs_set_verbose> or by setting
2413 the environment variable C<LIBGUESTFS_DEBUG=1> before
2414 running the program.");
2415
2416   ("ping_daemon", (RErr, []), 92, [],
2417    [InitEmpty, Always, TestRun (
2418       [["ping_daemon"]])],
2419    "ping the guest daemon",
2420    "\
2421 This is a test probe into the guestfs daemon running inside
2422 the qemu subprocess.  Calling this function checks that the
2423 daemon responds to the ping message, without affecting the daemon
2424 or attached block device(s) in any other way.");
2425
2426   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2427    [InitBasicFS, Always, TestOutputTrue (
2428       [["write_file"; "/file1"; "contents of a file"; "0"];
2429        ["cp"; "/file1"; "/file2"];
2430        ["equal"; "/file1"; "/file2"]]);
2431     InitBasicFS, Always, TestOutputFalse (
2432       [["write_file"; "/file1"; "contents of a file"; "0"];
2433        ["write_file"; "/file2"; "contents of another file"; "0"];
2434        ["equal"; "/file1"; "/file2"]]);
2435     InitBasicFS, Always, TestLastFail (
2436       [["equal"; "/file1"; "/file2"]])],
2437    "test if two files have equal contents",
2438    "\
2439 This compares the two files C<file1> and C<file2> and returns
2440 true if their content is exactly equal, or false otherwise.
2441
2442 The external L<cmp(1)> program is used for the comparison.");
2443
2444   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2445    [InitISOFS, Always, TestOutputList (
2446       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2447     InitISOFS, Always, TestOutputList (
2448       [["strings"; "/empty"]], []);
2449     (* Test for RHBZ#579608, absolute symbolic links. *)
2450     InitISOFS, Always, TestRun (
2451       [["strings"; "/abssymlink"]])],
2452    "print the printable strings in a file",
2453    "\
2454 This runs the L<strings(1)> command on a file and returns
2455 the list of printable strings found.");
2456
2457   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2458    [InitISOFS, Always, TestOutputList (
2459       [["strings_e"; "b"; "/known-5"]], []);
2460     InitBasicFS, Disabled, TestOutputList (
2461       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2462        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2463    "print the printable strings in a file",
2464    "\
2465 This is like the C<guestfs_strings> command, but allows you to
2466 specify the encoding of strings that are looked for in
2467 the source file C<path>.
2468
2469 Allowed encodings are:
2470
2471 =over 4
2472
2473 =item s
2474
2475 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2476 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2477
2478 =item S
2479
2480 Single 8-bit-byte characters.
2481
2482 =item b
2483
2484 16-bit big endian strings such as those encoded in
2485 UTF-16BE or UCS-2BE.
2486
2487 =item l (lower case letter L)
2488
2489 16-bit little endian such as UTF-16LE and UCS-2LE.
2490 This is useful for examining binaries in Windows guests.
2491
2492 =item B
2493
2494 32-bit big endian such as UCS-4BE.
2495
2496 =item L
2497
2498 32-bit little endian such as UCS-4LE.
2499
2500 =back
2501
2502 The returned strings are transcoded to UTF-8.");
2503
2504   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2505    [InitISOFS, Always, TestOutput (
2506       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2507     (* Test for RHBZ#501888c2 regression which caused large hexdump
2508      * commands to segfault.
2509      *)
2510     InitISOFS, Always, TestRun (
2511       [["hexdump"; "/100krandom"]]);
2512     (* Test for RHBZ#579608, absolute symbolic links. *)
2513     InitISOFS, Always, TestRun (
2514       [["hexdump"; "/abssymlink"]])],
2515    "dump a file in hexadecimal",
2516    "\
2517 This runs C<hexdump -C> on the given C<path>.  The result is
2518 the human-readable, canonical hex dump of the file.");
2519
2520   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2521    [InitNone, Always, TestOutput (
2522       [["part_disk"; "/dev/sda"; "mbr"];
2523        ["mkfs"; "ext3"; "/dev/sda1"];
2524        ["mount_options"; ""; "/dev/sda1"; "/"];
2525        ["write_file"; "/new"; "test file"; "0"];
2526        ["umount"; "/dev/sda1"];
2527        ["zerofree"; "/dev/sda1"];
2528        ["mount_options"; ""; "/dev/sda1"; "/"];
2529        ["cat"; "/new"]], "test file")],
2530    "zero unused inodes and disk blocks on ext2/3 filesystem",
2531    "\
2532 This runs the I<zerofree> program on C<device>.  This program
2533 claims to zero unused inodes and disk blocks on an ext2/3
2534 filesystem, thus making it possible to compress the filesystem
2535 more effectively.
2536
2537 You should B<not> run this program if the filesystem is
2538 mounted.
2539
2540 It is possible that using this program can damage the filesystem
2541 or data on the filesystem.");
2542
2543   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2544    [],
2545    "resize an LVM physical volume",
2546    "\
2547 This resizes (expands or shrinks) an existing LVM physical
2548 volume to match the new size of the underlying device.");
2549
2550   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2551                        Int "cyls"; Int "heads"; Int "sectors";
2552                        String "line"]), 99, [DangerWillRobinson],
2553    [],
2554    "modify a single partition on a block device",
2555    "\
2556 This runs L<sfdisk(8)> option to modify just the single
2557 partition C<n> (note: C<n> counts from 1).
2558
2559 For other parameters, see C<guestfs_sfdisk>.  You should usually
2560 pass C<0> for the cyls/heads/sectors parameters.
2561
2562 See also: C<guestfs_part_add>");
2563
2564   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2565    [],
2566    "display the partition table",
2567    "\
2568 This displays the partition table on C<device>, in the
2569 human-readable output of the L<sfdisk(8)> command.  It is
2570 not intended to be parsed.
2571
2572 See also: C<guestfs_part_list>");
2573
2574   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2575    [],
2576    "display the kernel geometry",
2577    "\
2578 This displays the kernel's idea of the geometry of C<device>.
2579
2580 The result is in human-readable format, and not designed to
2581 be parsed.");
2582
2583   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2584    [],
2585    "display the disk geometry from the partition table",
2586    "\
2587 This displays the disk geometry of C<device> read from the
2588 partition table.  Especially in the case where the underlying
2589 block device has been resized, this can be different from the
2590 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2591
2592 The result is in human-readable format, and not designed to
2593 be parsed.");
2594
2595   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2596    [],
2597    "activate or deactivate all volume groups",
2598    "\
2599 This command activates or (if C<activate> is false) deactivates
2600 all logical volumes in all volume groups.
2601 If activated, then they are made known to the
2602 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2603 then those devices disappear.
2604
2605 This command is the same as running C<vgchange -a y|n>");
2606
2607   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2608    [],
2609    "activate or deactivate some volume groups",
2610    "\
2611 This command activates or (if C<activate> is false) deactivates
2612 all logical volumes in the listed volume groups C<volgroups>.
2613 If activated, then they are made known to the
2614 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2615 then those devices disappear.
2616
2617 This command is the same as running C<vgchange -a y|n volgroups...>
2618
2619 Note that if C<volgroups> is an empty list then B<all> volume groups
2620 are activated or deactivated.");
2621
2622   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2623    [InitNone, Always, TestOutput (
2624       [["part_disk"; "/dev/sda"; "mbr"];
2625        ["pvcreate"; "/dev/sda1"];
2626        ["vgcreate"; "VG"; "/dev/sda1"];
2627        ["lvcreate"; "LV"; "VG"; "10"];
2628        ["mkfs"; "ext2"; "/dev/VG/LV"];
2629        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2630        ["write_file"; "/new"; "test content"; "0"];
2631        ["umount"; "/"];
2632        ["lvresize"; "/dev/VG/LV"; "20"];
2633        ["e2fsck_f"; "/dev/VG/LV"];
2634        ["resize2fs"; "/dev/VG/LV"];
2635        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2636        ["cat"; "/new"]], "test content");
2637     InitNone, Always, TestRun (
2638       (* Make an LV smaller to test RHBZ#587484. *)
2639       [["part_disk"; "/dev/sda"; "mbr"];
2640        ["pvcreate"; "/dev/sda1"];
2641        ["vgcreate"; "VG"; "/dev/sda1"];
2642        ["lvcreate"; "LV"; "VG"; "20"];
2643        ["lvresize"; "/dev/VG/LV"; "10"]])],
2644    "resize an LVM logical volume",
2645    "\
2646 This resizes (expands or shrinks) an existing LVM logical
2647 volume to C<mbytes>.  When reducing, data in the reduced part
2648 is lost.");
2649
2650   ("resize2fs", (RErr, [Device "device"]), 106, [],
2651    [], (* lvresize tests this *)
2652    "resize an ext2/ext3 filesystem",
2653    "\
2654 This resizes an ext2 or ext3 filesystem to match the size of
2655 the underlying device.
2656
2657 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2658 on the C<device> before calling this command.  For unknown reasons
2659 C<resize2fs> sometimes gives an error about this and sometimes not.
2660 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2661 calling this function.");
2662
2663   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2664    [InitBasicFS, Always, TestOutputList (
2665       [["find"; "/"]], ["lost+found"]);
2666     InitBasicFS, Always, TestOutputList (
2667       [["touch"; "/a"];
2668        ["mkdir"; "/b"];
2669        ["touch"; "/b/c"];
2670        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2671     InitBasicFS, Always, TestOutputList (
2672       [["mkdir_p"; "/a/b/c"];
2673        ["touch"; "/a/b/c/d"];
2674        ["find"; "/a/b/"]], ["c"; "c/d"])],
2675    "find all files and directories",
2676    "\
2677 This command lists out all files and directories, recursively,
2678 starting at C<directory>.  It is essentially equivalent to
2679 running the shell command C<find directory -print> but some
2680 post-processing happens on the output, described below.
2681
2682 This returns a list of strings I<without any prefix>.  Thus
2683 if the directory structure was:
2684
2685  /tmp/a
2686  /tmp/b
2687  /tmp/c/d
2688
2689 then the returned list from C<guestfs_find> C</tmp> would be
2690 4 elements:
2691
2692  a
2693  b
2694  c
2695  c/d
2696
2697 If C<directory> is not a directory, then this command returns
2698 an error.
2699
2700 The returned list is sorted.
2701
2702 See also C<guestfs_find0>.");
2703
2704   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2705    [], (* lvresize tests this *)
2706    "check an ext2/ext3 filesystem",
2707    "\
2708 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2709 filesystem checker on C<device>, noninteractively (C<-p>),
2710 even if the filesystem appears to be clean (C<-f>).
2711
2712 This command is only needed because of C<guestfs_resize2fs>
2713 (q.v.).  Normally you should use C<guestfs_fsck>.");
2714
2715   ("sleep", (RErr, [Int "secs"]), 109, [],
2716    [InitNone, Always, TestRun (
2717       [["sleep"; "1"]])],
2718    "sleep for some seconds",
2719    "\
2720 Sleep for C<secs> seconds.");
2721
2722   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2723    [InitNone, Always, TestOutputInt (
2724       [["part_disk"; "/dev/sda"; "mbr"];
2725        ["mkfs"; "ntfs"; "/dev/sda1"];
2726        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2727     InitNone, Always, TestOutputInt (
2728       [["part_disk"; "/dev/sda"; "mbr"];
2729        ["mkfs"; "ext2"; "/dev/sda1"];
2730        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2731    "probe NTFS volume",
2732    "\
2733 This command runs the L<ntfs-3g.probe(8)> command which probes
2734 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2735 be mounted read-write, and some cannot be mounted at all).
2736
2737 C<rw> is a boolean flag.  Set it to true if you want to test
2738 if the volume can be mounted read-write.  Set it to false if
2739 you want to test if the volume can be mounted read-only.
2740
2741 The return value is an integer which C<0> if the operation
2742 would succeed, or some non-zero value documented in the
2743 L<ntfs-3g.probe(8)> manual page.");
2744
2745   ("sh", (RString "output", [String "command"]), 111, [],
2746    [], (* XXX needs tests *)
2747    "run a command via the shell",
2748    "\
2749 This call runs a command from the guest filesystem via the
2750 guest's C</bin/sh>.
2751
2752 This is like C<guestfs_command>, but passes the command to:
2753
2754  /bin/sh -c \"command\"
2755
2756 Depending on the guest's shell, this usually results in
2757 wildcards being expanded, shell expressions being interpolated
2758 and so on.
2759
2760 All the provisos about C<guestfs_command> apply to this call.");
2761
2762   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2763    [], (* XXX needs tests *)
2764    "run a command via the shell returning lines",
2765    "\
2766 This is the same as C<guestfs_sh>, but splits the result
2767 into a list of lines.
2768
2769 See also: C<guestfs_command_lines>");
2770
2771   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2772    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2773     * code in stubs.c, since all valid glob patterns must start with "/".
2774     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2775     *)
2776    [InitBasicFS, Always, TestOutputList (
2777       [["mkdir_p"; "/a/b/c"];
2778        ["touch"; "/a/b/c/d"];
2779        ["touch"; "/a/b/c/e"];
2780        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2781     InitBasicFS, Always, TestOutputList (
2782       [["mkdir_p"; "/a/b/c"];
2783        ["touch"; "/a/b/c/d"];
2784        ["touch"; "/a/b/c/e"];
2785        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2786     InitBasicFS, Always, TestOutputList (
2787       [["mkdir_p"; "/a/b/c"];
2788        ["touch"; "/a/b/c/d"];
2789        ["touch"; "/a/b/c/e"];
2790        ["glob_expand"; "/a/*/x/*"]], [])],
2791    "expand a wildcard path",
2792    "\
2793 This command searches for all the pathnames matching
2794 C<pattern> according to the wildcard expansion rules
2795 used by the shell.
2796
2797 If no paths match, then this returns an empty list
2798 (note: not an error).
2799
2800 It is just a wrapper around the C L<glob(3)> function
2801 with flags C<GLOB_MARK|GLOB_BRACE>.
2802 See that manual page for more details.");
2803
2804   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2805    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2806       [["scrub_device"; "/dev/sdc"]])],
2807    "scrub (securely wipe) a device",
2808    "\
2809 This command writes patterns over C<device> to make data retrieval
2810 more difficult.
2811
2812 It is an interface to the L<scrub(1)> program.  See that
2813 manual page for more details.");
2814
2815   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2816    [InitBasicFS, Always, TestRun (
2817       [["write_file"; "/file"; "content"; "0"];
2818        ["scrub_file"; "/file"]])],
2819    "scrub (securely wipe) a file",
2820    "\
2821 This command writes patterns over a file to make data retrieval
2822 more difficult.
2823
2824 The file is I<removed> after scrubbing.
2825
2826 It is an interface to the L<scrub(1)> program.  See that
2827 manual page for more details.");
2828
2829   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2830    [], (* XXX needs testing *)
2831    "scrub (securely wipe) free space",
2832    "\
2833 This command creates the directory C<dir> and then fills it
2834 with files until the filesystem is full, and scrubs the files
2835 as for C<guestfs_scrub_file>, and deletes them.
2836 The intention is to scrub any free space on the partition
2837 containing C<dir>.
2838
2839 It is an interface to the L<scrub(1)> program.  See that
2840 manual page for more details.");
2841
2842   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2843    [InitBasicFS, Always, TestRun (
2844       [["mkdir"; "/tmp"];
2845        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2846    "create a temporary directory",
2847    "\
2848 This command creates a temporary directory.  The
2849 C<template> parameter should be a full pathname for the
2850 temporary directory name with the final six characters being
2851 \"XXXXXX\".
2852
2853 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2854 the second one being suitable for Windows filesystems.
2855
2856 The name of the temporary directory that was created
2857 is returned.
2858
2859 The temporary directory is created with mode 0700
2860 and is owned by root.
2861
2862 The caller is responsible for deleting the temporary
2863 directory and its contents after use.
2864
2865 See also: L<mkdtemp(3)>");
2866
2867   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2868    [InitISOFS, Always, TestOutputInt (
2869       [["wc_l"; "/10klines"]], 10000);
2870     (* Test for RHBZ#579608, absolute symbolic links. *)
2871     InitISOFS, Always, TestOutputInt (
2872       [["wc_l"; "/abssymlink"]], 10000)],
2873    "count lines in a file",
2874    "\
2875 This command counts the lines in a file, using the
2876 C<wc -l> external command.");
2877
2878   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2879    [InitISOFS, Always, TestOutputInt (
2880       [["wc_w"; "/10klines"]], 10000)],
2881    "count words in a file",
2882    "\
2883 This command counts the words in a file, using the
2884 C<wc -w> external command.");
2885
2886   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2887    [InitISOFS, Always, TestOutputInt (
2888       [["wc_c"; "/100kallspaces"]], 102400)],
2889    "count characters in a file",
2890    "\
2891 This command counts the characters in a file, using the
2892 C<wc -c> external command.");
2893
2894   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2895    [InitISOFS, Always, TestOutputList (
2896       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2897     (* Test for RHBZ#579608, absolute symbolic links. *)
2898     InitISOFS, Always, TestOutputList (
2899       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2900    "return first 10 lines of a file",
2901    "\
2902 This command returns up to the first 10 lines of a file as
2903 a list of strings.");
2904
2905   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2906    [InitISOFS, Always, TestOutputList (
2907       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2908     InitISOFS, Always, TestOutputList (
2909       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2910     InitISOFS, Always, TestOutputList (
2911       [["head_n"; "0"; "/10klines"]], [])],
2912    "return first N lines of a file",
2913    "\
2914 If the parameter C<nrlines> is a positive number, this returns the first
2915 C<nrlines> lines of the file C<path>.
2916
2917 If the parameter C<nrlines> is a negative number, this returns lines
2918 from the file C<path>, excluding the last C<nrlines> lines.
2919
2920 If the parameter C<nrlines> is zero, this returns an empty list.");
2921
2922   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2923    [InitISOFS, Always, TestOutputList (
2924       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2925    "return last 10 lines of a file",
2926    "\
2927 This command returns up to the last 10 lines of a file as
2928 a list of strings.");
2929
2930   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2931    [InitISOFS, Always, TestOutputList (
2932       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2933     InitISOFS, Always, TestOutputList (
2934       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2935     InitISOFS, Always, TestOutputList (
2936       [["tail_n"; "0"; "/10klines"]], [])],
2937    "return last N lines of a file",
2938    "\
2939 If the parameter C<nrlines> is a positive number, this returns the last
2940 C<nrlines> lines of the file C<path>.
2941
2942 If the parameter C<nrlines> is a negative number, this returns lines
2943 from the file C<path>, starting with the C<-nrlines>th line.
2944
2945 If the parameter C<nrlines> is zero, this returns an empty list.");
2946
2947   ("df", (RString "output", []), 125, [],
2948    [], (* XXX Tricky to test because it depends on the exact format
2949         * of the 'df' command and other imponderables.
2950         *)
2951    "report file system disk space usage",
2952    "\
2953 This command runs the C<df> command to report disk space used.
2954
2955 This command is mostly useful for interactive sessions.  It
2956 is I<not> intended that you try to parse the output string.
2957 Use C<statvfs> from programs.");
2958
2959   ("df_h", (RString "output", []), 126, [],
2960    [], (* XXX Tricky to test because it depends on the exact format
2961         * of the 'df' command and other imponderables.
2962         *)
2963    "report file system disk space usage (human readable)",
2964    "\
2965 This command runs the C<df -h> command to report disk space used
2966 in human-readable format.
2967
2968 This command is mostly useful for interactive sessions.  It
2969 is I<not> intended that you try to parse the output string.
2970 Use C<statvfs> from programs.");
2971
2972   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2973    [InitISOFS, Always, TestOutputInt (
2974       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2975    "estimate file space usage",
2976    "\
2977 This command runs the C<du -s> command to estimate file space
2978 usage for C<path>.
2979
2980 C<path> can be a file or a directory.  If C<path> is a directory
2981 then the estimate includes the contents of the directory and all
2982 subdirectories (recursively).
2983
2984 The result is the estimated size in I<kilobytes>
2985 (ie. units of 1024 bytes).");
2986
2987   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2988    [InitISOFS, Always, TestOutputList (
2989       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2990    "list files in an initrd",
2991    "\
2992 This command lists out files contained in an initrd.
2993
2994 The files are listed without any initial C</> character.  The
2995 files are listed in the order they appear (not necessarily
2996 alphabetical).  Directory names are listed as separate items.
2997
2998 Old Linux kernels (2.4 and earlier) used a compressed ext2
2999 filesystem as initrd.  We I<only> support the newer initramfs
3000 format (compressed cpio files).");
3001
3002   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3003    [],
3004    "mount a file using the loop device",
3005    "\
3006 This command lets you mount C<file> (a filesystem image
3007 in a file) on a mount point.  It is entirely equivalent to
3008 the command C<mount -o loop file mountpoint>.");
3009
3010   ("mkswap", (RErr, [Device "device"]), 130, [],
3011    [InitEmpty, Always, TestRun (
3012       [["part_disk"; "/dev/sda"; "mbr"];
3013        ["mkswap"; "/dev/sda1"]])],
3014    "create a swap partition",
3015    "\
3016 Create a swap partition on C<device>.");
3017
3018   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3019    [InitEmpty, Always, TestRun (
3020       [["part_disk"; "/dev/sda"; "mbr"];
3021        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3022    "create a swap partition with a label",
3023    "\
3024 Create a swap partition on C<device> with label C<label>.
3025
3026 Note that you cannot attach a swap label to a block device
3027 (eg. C</dev/sda>), just to a partition.  This appears to be
3028 a limitation of the kernel or swap tools.");
3029
3030   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3031    (let uuid = uuidgen () in
3032     [InitEmpty, Always, TestRun (
3033        [["part_disk"; "/dev/sda"; "mbr"];
3034         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3035    "create a swap partition with an explicit UUID",
3036    "\
3037 Create a swap partition on C<device> with UUID C<uuid>.");
3038
3039   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3040    [InitBasicFS, Always, TestOutputStruct (
3041       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3042        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3043        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3044     InitBasicFS, Always, TestOutputStruct (
3045       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3046        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3047    "make block, character or FIFO devices",
3048    "\
3049 This call creates block or character special devices, or
3050 named pipes (FIFOs).
3051
3052 The C<mode> parameter should be the mode, using the standard
3053 constants.  C<devmajor> and C<devminor> are the
3054 device major and minor numbers, only used when creating block
3055 and character special devices.
3056
3057 Note that, just like L<mknod(2)>, the mode must be bitwise
3058 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3059 just creates a regular file).  These constants are
3060 available in the standard Linux header files, or you can use
3061 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3062 which are wrappers around this command which bitwise OR
3063 in the appropriate constant for you.
3064
3065 The mode actually set is affected by the umask.");
3066
3067   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3068    [InitBasicFS, Always, TestOutputStruct (
3069       [["mkfifo"; "0o777"; "/node"];
3070        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3071    "make FIFO (named pipe)",
3072    "\
3073 This call creates a FIFO (named pipe) called C<path> with
3074 mode C<mode>.  It is just a convenient wrapper around
3075 C<guestfs_mknod>.
3076
3077 The mode actually set is affected by the umask.");
3078
3079   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3080    [InitBasicFS, Always, TestOutputStruct (
3081       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3082        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3083    "make block device node",
3084    "\
3085 This call creates a block device node called C<path> with
3086 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3087 It is just a convenient wrapper around C<guestfs_mknod>.
3088
3089 The mode actually set is affected by the umask.");
3090
3091   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3092    [InitBasicFS, Always, TestOutputStruct (
3093       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3094        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3095    "make char device node",
3096    "\
3097 This call creates a char device node called C<path> with
3098 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3099 It is just a convenient wrapper around C<guestfs_mknod>.
3100
3101 The mode actually set is affected by the umask.");
3102
3103   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3104    [InitEmpty, Always, TestOutputInt (
3105       [["umask"; "0o22"]], 0o22)],
3106    "set file mode creation mask (umask)",
3107    "\
3108 This function sets the mask used for creating new files and
3109 device nodes to C<mask & 0777>.
3110
3111 Typical umask values would be C<022> which creates new files
3112 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3113 C<002> which creates new files with permissions like
3114 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3115
3116 The default umask is C<022>.  This is important because it
3117 means that directories and device nodes will be created with
3118 C<0644> or C<0755> mode even if you specify C<0777>.
3119
3120 See also C<guestfs_get_umask>,
3121 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3122
3123 This call returns the previous umask.");
3124
3125   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3126    [],
3127    "read directories entries",
3128    "\
3129 This returns the list of directory entries in directory C<dir>.
3130
3131 All entries in the directory are returned, including C<.> and
3132 C<..>.  The entries are I<not> sorted, but returned in the same
3133 order as the underlying filesystem.
3134
3135 Also this call returns basic file type information about each
3136 file.  The C<ftyp> field will contain one of the following characters:
3137
3138 =over 4
3139
3140 =item 'b'
3141
3142 Block special
3143
3144 =item 'c'
3145
3146 Char special
3147
3148 =item 'd'
3149
3150 Directory
3151
3152 =item 'f'
3153
3154 FIFO (named pipe)
3155
3156 =item 'l'
3157
3158 Symbolic link
3159
3160 =item 'r'
3161
3162 Regular file
3163
3164 =item 's'
3165
3166 Socket
3167
3168 =item 'u'
3169
3170 Unknown file type
3171
3172 =item '?'
3173
3174 The L<readdir(3)> returned a C<d_type> field with an
3175 unexpected value
3176
3177 =back
3178
3179 This function is primarily intended for use by programs.  To
3180 get a simple list of names, use C<guestfs_ls>.  To get a printable
3181 directory for human consumption, use C<guestfs_ll>.");
3182
3183   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3184    [],
3185    "create partitions on a block device",
3186    "\
3187 This is a simplified interface to the C<guestfs_sfdisk>
3188 command, where partition sizes are specified in megabytes
3189 only (rounded to the nearest cylinder) and you don't need
3190 to specify the cyls, heads and sectors parameters which
3191 were rarely if ever used anyway.
3192
3193 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3194 and C<guestfs_part_disk>");
3195
3196   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3197    [],
3198    "determine file type inside a compressed file",
3199    "\
3200 This command runs C<file> after first decompressing C<path>
3201 using C<method>.
3202
3203 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3204
3205 Since 1.0.63, use C<guestfs_file> instead which can now
3206 process compressed files.");
3207
3208   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3209    [],
3210    "list extended attributes of a file or directory",
3211    "\
3212 This call lists the extended attributes of the file or directory
3213 C<path>.
3214
3215 At the system call level, this is a combination of the
3216 L<listxattr(2)> and L<getxattr(2)> calls.
3217
3218 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3219
3220   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3221    [],
3222    "list extended attributes of a file or directory",
3223    "\
3224 This is the same as C<guestfs_getxattrs>, but if C<path>
3225 is a symbolic link, then it returns the extended attributes
3226 of the link itself.");
3227
3228   ("setxattr", (RErr, [String "xattr";
3229                        String "val"; Int "vallen"; (* will be BufferIn *)
3230                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3231    [],
3232    "set extended attribute of a file or directory",
3233    "\
3234 This call sets the extended attribute named C<xattr>
3235 of the file C<path> to the value C<val> (of length C<vallen>).
3236 The value is arbitrary 8 bit data.
3237
3238 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3239
3240   ("lsetxattr", (RErr, [String "xattr";
3241                         String "val"; Int "vallen"; (* will be BufferIn *)
3242                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3243    [],
3244    "set extended attribute of a file or directory",
3245    "\
3246 This is the same as C<guestfs_setxattr>, but if C<path>
3247 is a symbolic link, then it sets an extended attribute
3248 of the link itself.");
3249
3250   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3251    [],
3252    "remove extended attribute of a file or directory",
3253    "\
3254 This call removes the extended attribute named C<xattr>
3255 of the file C<path>.
3256
3257 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3258
3259   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3260    [],
3261    "remove extended attribute of a file or directory",
3262    "\
3263 This is the same as C<guestfs_removexattr>, but if C<path>
3264 is a symbolic link, then it removes an extended attribute
3265 of the link itself.");
3266
3267   ("mountpoints", (RHashtable "mps", []), 147, [],
3268    [],
3269    "show mountpoints",
3270    "\
3271 This call is similar to C<guestfs_mounts>.  That call returns
3272 a list of devices.  This one returns a hash table (map) of
3273 device name to directory where the device is mounted.");
3274
3275   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3276    (* This is a special case: while you would expect a parameter
3277     * of type "Pathname", that doesn't work, because it implies
3278     * NEED_ROOT in the generated calling code in stubs.c, and
3279     * this function cannot use NEED_ROOT.
3280     *)
3281    [],
3282    "create a mountpoint",
3283    "\
3284 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3285 specialized calls that can be used to create extra mountpoints
3286 before mounting the first filesystem.
3287
3288 These calls are I<only> necessary in some very limited circumstances,
3289 mainly the case where you want to mount a mix of unrelated and/or
3290 read-only filesystems together.
3291
3292 For example, live CDs often contain a \"Russian doll\" nest of
3293 filesystems, an ISO outer layer, with a squashfs image inside, with
3294 an ext2/3 image inside that.  You can unpack this as follows
3295 in guestfish:
3296
3297  add-ro Fedora-11-i686-Live.iso
3298  run
3299  mkmountpoint /cd
3300  mkmountpoint /squash
3301  mkmountpoint /ext3
3302  mount /dev/sda /cd
3303  mount-loop /cd/LiveOS/squashfs.img /squash
3304  mount-loop /squash/LiveOS/ext3fs.img /ext3
3305
3306 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3307
3308   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3309    [],
3310    "remove a mountpoint",
3311    "\
3312 This calls removes a mountpoint that was previously created
3313 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3314 for full details.");
3315
3316   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3317    [InitISOFS, Always, TestOutputBuffer (
3318       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3319     (* Test various near large, large and too large files (RHBZ#589039). *)
3320     InitBasicFS, Always, TestLastFail (
3321       [["touch"; "/a"];
3322        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3323        ["read_file"; "/a"]]);
3324     InitBasicFS, Always, TestLastFail (
3325       [["touch"; "/a"];
3326        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3327        ["read_file"; "/a"]]);
3328     InitBasicFS, Always, TestLastFail (
3329       [["touch"; "/a"];
3330        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3331        ["read_file"; "/a"]])],
3332    "read a file",
3333    "\
3334 This calls returns the contents of the file C<path> as a
3335 buffer.
3336
3337 Unlike C<guestfs_cat>, this function can correctly
3338 handle files that contain embedded ASCII NUL characters.
3339 However unlike C<guestfs_download>, this function is limited
3340 in the total size of file that can be handled.");
3341
3342   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3343    [InitISOFS, Always, TestOutputList (
3344       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3345     InitISOFS, Always, TestOutputList (
3346       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3347     (* Test for RHBZ#579608, absolute symbolic links. *)
3348     InitISOFS, Always, TestOutputList (
3349       [["grep"; "nomatch"; "/abssymlink"]], [])],
3350    "return lines matching a pattern",
3351    "\
3352 This calls the external C<grep> program and returns the
3353 matching lines.");
3354
3355   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3356    [InitISOFS, Always, TestOutputList (
3357       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3358    "return lines matching a pattern",
3359    "\
3360 This calls the external C<egrep> program and returns the
3361 matching lines.");
3362
3363   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3364    [InitISOFS, Always, TestOutputList (
3365       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3366    "return lines matching a pattern",
3367    "\
3368 This calls the external C<fgrep> program and returns the
3369 matching lines.");
3370
3371   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3372    [InitISOFS, Always, TestOutputList (
3373       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3374    "return lines matching a pattern",
3375    "\
3376 This calls the external C<grep -i> program and returns the
3377 matching lines.");
3378
3379   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3380    [InitISOFS, Always, TestOutputList (
3381       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3382    "return lines matching a pattern",
3383    "\
3384 This calls the external C<egrep -i> program and returns the
3385 matching lines.");
3386
3387   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3388    [InitISOFS, Always, TestOutputList (
3389       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3390    "return lines matching a pattern",
3391    "\
3392 This calls the external C<fgrep -i> program and returns the
3393 matching lines.");
3394
3395   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3396    [InitISOFS, Always, TestOutputList (
3397       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3398    "return lines matching a pattern",
3399    "\
3400 This calls the external C<zgrep> program and returns the
3401 matching lines.");
3402
3403   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3404    [InitISOFS, Always, TestOutputList (
3405       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3406    "return lines matching a pattern",
3407    "\
3408 This calls the external C<zegrep> program and returns the
3409 matching lines.");
3410
3411   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3412    [InitISOFS, Always, TestOutputList (
3413       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3414    "return lines matching a pattern",
3415    "\
3416 This calls the external C<zfgrep> program and returns the
3417 matching lines.");
3418
3419   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3420    [InitISOFS, Always, TestOutputList (
3421       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3422    "return lines matching a pattern",
3423    "\
3424 This calls the external C<zgrep -i> program and returns the
3425 matching lines.");
3426
3427   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3428    [InitISOFS, Always, TestOutputList (
3429       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3430    "return lines matching a pattern",
3431    "\
3432 This calls the external C<zegrep -i> program and returns the
3433 matching lines.");
3434
3435   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3436    [InitISOFS, Always, TestOutputList (
3437       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3438    "return lines matching a pattern",
3439    "\
3440 This calls the external C<zfgrep -i> program and returns the
3441 matching lines.");
3442
3443   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3444    [InitISOFS, Always, TestOutput (
3445       [["realpath"; "/../directory"]], "/directory")],
3446    "canonicalized absolute pathname",
3447    "\
3448 Return the canonicalized absolute pathname of C<path>.  The
3449 returned path has no C<.>, C<..> or symbolic link path elements.");
3450
3451   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3452    [InitBasicFS, Always, TestOutputStruct (
3453       [["touch"; "/a"];
3454        ["ln"; "/a"; "/b"];
3455        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3456    "create a hard link",
3457    "\
3458 This command creates a hard link using the C<ln> command.");
3459
3460   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3461    [InitBasicFS, Always, TestOutputStruct (
3462       [["touch"; "/a"];
3463        ["touch"; "/b"];
3464        ["ln_f"; "/a"; "/b"];
3465        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3466    "create a hard link",
3467    "\
3468 This command creates a hard link using the C<ln -f> command.
3469 The C<-f> option removes the link (C<linkname>) if it exists already.");
3470
3471   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3472    [InitBasicFS, Always, TestOutputStruct (
3473       [["touch"; "/a"];
3474        ["ln_s"; "a"; "/b"];
3475        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3476    "create a symbolic link",
3477    "\
3478 This command creates a symbolic link using the C<ln -s> command.");
3479
3480   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3481    [InitBasicFS, Always, TestOutput (
3482       [["mkdir_p"; "/a/b"];
3483        ["touch"; "/a/b/c"];
3484        ["ln_sf"; "../d"; "/a/b/c"];
3485        ["readlink"; "/a/b/c"]], "../d")],
3486    "create a symbolic link",
3487    "\
3488 This command creates a symbolic link using the C<ln -sf> command,
3489 The C<-f> option removes the link (C<linkname>) if it exists already.");
3490
3491   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3492    [] (* XXX tested above *),
3493    "read the target of a symbolic link",
3494    "\
3495 This command reads the target of a symbolic link.");
3496
3497   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3498    [InitBasicFS, Always, TestOutputStruct (
3499       [["fallocate"; "/a"; "1000000"];
3500        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3501    "preallocate a file in the guest filesystem",
3502    "\
3503 This command preallocates a file (containing zero bytes) named
3504 C<path> of size C<len> bytes.  If the file exists already, it
3505 is overwritten.
3506
3507 Do not confuse this with the guestfish-specific
3508 C<alloc> command which allocates a file in the host and
3509 attaches it as a device.");
3510
3511   ("swapon_device", (RErr, [Device "device"]), 170, [],
3512    [InitPartition, Always, TestRun (
3513       [["mkswap"; "/dev/sda1"];
3514        ["swapon_device"; "/dev/sda1"];
3515        ["swapoff_device"; "/dev/sda1"]])],
3516    "enable swap on device",
3517    "\
3518 This command enables the libguestfs appliance to use the
3519 swap device or partition named C<device>.  The increased
3520 memory is made available for all commands, for example
3521 those run using C<guestfs_command> or C<guestfs_sh>.
3522
3523 Note that you should not swap to existing guest swap
3524 partitions unless you know what you are doing.  They may
3525 contain hibernation information, or other information that
3526 the guest doesn't want you to trash.  You also risk leaking
3527 information about the host to the guest this way.  Instead,
3528 attach a new host device to the guest and swap on that.");
3529
3530   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3531    [], (* XXX tested by swapon_device *)
3532    "disable swap on device",
3533    "\
3534 This command disables the libguestfs appliance swap
3535 device or partition named C<device>.
3536 See C<guestfs_swapon_device>.");
3537
3538   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3539    [InitBasicFS, Always, TestRun (
3540       [["fallocate"; "/swap"; "8388608"];
3541        ["mkswap_file"; "/swap"];
3542        ["swapon_file"; "/swap"];
3543        ["swapoff_file"; "/swap"]])],
3544    "enable swap on file",
3545    "\
3546 This command enables swap to a file.
3547 See C<guestfs_swapon_device> for other notes.");
3548
3549   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3550    [], (* XXX tested by swapon_file *)
3551    "disable swap on file",
3552    "\
3553 This command disables the libguestfs appliance swap on file.");
3554
3555   ("swapon_label", (RErr, [String "label"]), 174, [],
3556    [InitEmpty, Always, TestRun (
3557       [["part_disk"; "/dev/sdb"; "mbr"];
3558        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3559        ["swapon_label"; "swapit"];
3560        ["swapoff_label"; "swapit"];
3561        ["zero"; "/dev/sdb"];
3562        ["blockdev_rereadpt"; "/dev/sdb"]])],
3563    "enable swap on labeled swap partition",
3564    "\
3565 This command enables swap to a labeled swap partition.
3566 See C<guestfs_swapon_device> for other notes.");
3567
3568   ("swapoff_label", (RErr, [String "label"]), 175, [],
3569    [], (* XXX tested by swapon_label *)
3570    "disable swap on labeled swap partition",
3571    "\
3572 This command disables the libguestfs appliance swap on
3573 labeled swap partition.");
3574
3575   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3576    (let uuid = uuidgen () in
3577     [InitEmpty, Always, TestRun (
3578        [["mkswap_U"; uuid; "/dev/sdb"];
3579         ["swapon_uuid"; uuid];
3580         ["swapoff_uuid"; uuid]])]),
3581    "enable swap on swap partition by UUID",
3582    "\
3583 This command enables swap to a swap partition with the given UUID.
3584 See C<guestfs_swapon_device> for other notes.");
3585
3586   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3587    [], (* XXX tested by swapon_uuid *)
3588    "disable swap on swap partition by UUID",
3589    "\
3590 This command disables the libguestfs appliance swap partition
3591 with the given UUID.");
3592
3593   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3594    [InitBasicFS, Always, TestRun (
3595       [["fallocate"; "/swap"; "8388608"];
3596        ["mkswap_file"; "/swap"]])],
3597    "create a swap file",
3598    "\
3599 Create a swap file.
3600
3601 This command just writes a swap file signature to an existing
3602 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3603
3604   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3605    [InitISOFS, Always, TestRun (
3606       [["inotify_init"; "0"]])],
3607    "create an inotify handle",
3608    "\
3609 This command creates a new inotify handle.
3610 The inotify subsystem can be used to notify events which happen to
3611 objects in the guest filesystem.
3612
3613 C<maxevents> is the maximum number of events which will be
3614 queued up between calls to C<guestfs_inotify_read> or
3615 C<guestfs_inotify_files>.
3616 If this is passed as C<0>, then the kernel (or previously set)
3617 default is used.  For Linux 2.6.29 the default was 16384 events.
3618 Beyond this limit, the kernel throws away events, but records
3619 the fact that it threw them away by setting a flag
3620 C<IN_Q_OVERFLOW> in the returned structure list (see
3621 C<guestfs_inotify_read>).
3622
3623 Before any events are generated, you have to add some
3624 watches to the internal watch list.  See:
3625 C<guestfs_inotify_add_watch>,
3626 C<guestfs_inotify_rm_watch> and
3627 C<guestfs_inotify_watch_all>.
3628
3629 Queued up events should be read periodically by calling
3630 C<guestfs_inotify_read>
3631 (or C<guestfs_inotify_files> which is just a helpful
3632 wrapper around C<guestfs_inotify_read>).  If you don't
3633 read the events out often enough then you risk the internal
3634 queue overflowing.
3635
3636 The handle should be closed after use by calling
3637 C<guestfs_inotify_close>.  This also removes any
3638 watches automatically.
3639
3640 See also L<inotify(7)> for an overview of the inotify interface
3641 as exposed by the Linux kernel, which is roughly what we expose
3642 via libguestfs.  Note that there is one global inotify handle
3643 per libguestfs instance.");
3644
3645   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3646    [InitBasicFS, Always, TestOutputList (
3647       [["inotify_init"; "0"];
3648        ["inotify_add_watch"; "/"; "1073741823"];
3649        ["touch"; "/a"];
3650        ["touch"; "/b"];
3651        ["inotify_files"]], ["a"; "b"])],
3652    "add an inotify watch",
3653    "\
3654 Watch C<path> for the events listed in C<mask>.
3655
3656 Note that if C<path> is a directory then events within that
3657 directory are watched, but this does I<not> happen recursively
3658 (in subdirectories).
3659
3660 Note for non-C or non-Linux callers: the inotify events are
3661 defined by the Linux kernel ABI and are listed in
3662 C</usr/include/sys/inotify.h>.");
3663
3664   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3665    [],
3666    "remove an inotify watch",
3667    "\
3668 Remove a previously defined inotify watch.
3669 See C<guestfs_inotify_add_watch>.");
3670
3671   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3672    [],
3673    "return list of inotify events",
3674    "\
3675 Return the complete queue of events that have happened
3676 since the previous read call.
3677
3678 If no events have happened, this returns an empty list.
3679
3680 I<Note>: In order to make sure that all events have been
3681 read, you must call this function repeatedly until it
3682 returns an empty list.  The reason is that the call will
3683 read events up to the maximum appliance-to-host message
3684 size and leave remaining events in the queue.");
3685
3686   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3687    [],
3688    "return list of watched files that had events",
3689    "\
3690 This function is a helpful wrapper around C<guestfs_inotify_read>
3691 which just returns a list of pathnames of objects that were
3692 touched.  The returned pathnames are sorted and deduplicated.");
3693
3694   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3695    [],
3696    "close the inotify handle",
3697    "\
3698 This closes the inotify handle which was previously
3699 opened by inotify_init.  It removes all watches, throws
3700 away any pending events, and deallocates all resources.");
3701
3702   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3703    [],
3704    "set SELinux security context",
3705    "\
3706 This sets the SELinux security context of the daemon
3707 to the string C<context>.
3708
3709 See the documentation about SELINUX in L<guestfs(3)>.");
3710
3711   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3712    [],
3713    "get SELinux security context",
3714    "\
3715 This gets the SELinux security context of the daemon.
3716
3717 See the documentation about SELINUX in L<guestfs(3)>,
3718 and C<guestfs_setcon>");
3719
3720   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3721    [InitEmpty, Always, TestOutput (
3722       [["part_disk"; "/dev/sda"; "mbr"];
3723        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3724        ["mount_options"; ""; "/dev/sda1"; "/"];
3725        ["write_file"; "/new"; "new file contents"; "0"];
3726        ["cat"; "/new"]], "new file contents")],
3727    "make a filesystem with block size",
3728    "\
3729 This call is similar to C<guestfs_mkfs>, but it allows you to
3730 control the block size of the resulting filesystem.  Supported
3731 block sizes depend on the filesystem type, but typically they
3732 are C<1024>, C<2048> or C<4096> only.");
3733
3734   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3735    [InitEmpty, Always, TestOutput (
3736       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3737        ["mke2journal"; "4096"; "/dev/sda1"];
3738        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3739        ["mount_options"; ""; "/dev/sda2"; "/"];
3740        ["write_file"; "/new"; "new file contents"; "0"];
3741        ["cat"; "/new"]], "new file contents")],
3742    "make ext2/3/4 external journal",
3743    "\
3744 This creates an ext2 external journal on C<device>.  It is equivalent
3745 to the command:
3746
3747  mke2fs -O journal_dev -b blocksize device");
3748
3749   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3750    [InitEmpty, Always, TestOutput (
3751       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3752        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3753        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3754        ["mount_options"; ""; "/dev/sda2"; "/"];
3755        ["write_file"; "/new"; "new file contents"; "0"];
3756        ["cat"; "/new"]], "new file contents")],
3757    "make ext2/3/4 external journal with label",
3758    "\
3759 This creates an ext2 external journal on C<device> with label C<label>.");
3760
3761   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3762    (let uuid = uuidgen () in
3763     [InitEmpty, Always, TestOutput (
3764        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3765         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3766         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3767         ["mount_options"; ""; "/dev/sda2"; "/"];
3768         ["write_file"; "/new"; "new file contents"; "0"];
3769         ["cat"; "/new"]], "new file contents")]),
3770    "make ext2/3/4 external journal with UUID",
3771    "\
3772 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3773
3774   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3775    [],
3776    "make ext2/3/4 filesystem with external journal",
3777    "\
3778 This creates an ext2/3/4 filesystem on C<device> with
3779 an external journal on C<journal>.  It is equivalent
3780 to the command:
3781
3782  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3783
3784 See also C<guestfs_mke2journal>.");
3785
3786   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3787    [],
3788    "make ext2/3/4 filesystem with external journal",
3789    "\
3790 This creates an ext2/3/4 filesystem on C<device> with
3791 an external journal on the journal labeled C<label>.
3792
3793 See also C<guestfs_mke2journal_L>.");
3794
3795   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3796    [],
3797    "make ext2/3/4 filesystem with external journal",
3798    "\
3799 This creates an ext2/3/4 filesystem on C<device> with
3800 an external journal on the journal with UUID C<uuid>.
3801
3802 See also C<guestfs_mke2journal_U>.");
3803
3804   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3805    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3806    "load a kernel module",
3807    "\
3808 This loads a kernel module in the appliance.
3809
3810 The kernel module must have been whitelisted when libguestfs
3811 was built (see C<appliance/kmod.whitelist.in> in the source).");
3812
3813   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3814    [InitNone, Always, TestOutput (
3815       [["echo_daemon"; "This is a test"]], "This is a test"
3816     )],
3817    "echo arguments back to the client",
3818    "\
3819 This command concatenate the list of C<words> passed with single spaces between
3820 them and returns the resulting string.
3821
3822 You can use this command to test the connection through to the daemon.
3823
3824 See also C<guestfs_ping_daemon>.");
3825
3826   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3827    [], (* There is a regression test for this. *)
3828    "find all files and directories, returning NUL-separated list",
3829    "\
3830 This command lists out all files and directories, recursively,
3831 starting at C<directory>, placing the resulting list in the
3832 external file called C<files>.
3833
3834 This command works the same way as C<guestfs_find> with the
3835 following exceptions:
3836
3837 =over 4
3838
3839 =item *
3840
3841 The resulting list is written to an external file.
3842
3843 =item *
3844
3845 Items (filenames) in the result are separated
3846 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3847
3848 =item *
3849
3850 This command is not limited in the number of names that it
3851 can return.
3852
3853 =item *
3854
3855 The result list is not sorted.
3856
3857 =back");
3858
3859   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3860    [InitISOFS, Always, TestOutput (
3861       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3862     InitISOFS, Always, TestOutput (
3863       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3864     InitISOFS, Always, TestOutput (
3865       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3866     InitISOFS, Always, TestLastFail (
3867       [["case_sensitive_path"; "/Known-1/"]]);
3868     InitBasicFS, Always, TestOutput (
3869       [["mkdir"; "/a"];
3870        ["mkdir"; "/a/bbb"];
3871        ["touch"; "/a/bbb/c"];
3872        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3873     InitBasicFS, Always, TestOutput (
3874       [["mkdir"; "/a"];
3875        ["mkdir"; "/a/bbb"];
3876        ["touch"; "/a/bbb/c"];
3877        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3878     InitBasicFS, Always, TestLastFail (
3879       [["mkdir"; "/a"];
3880        ["mkdir"; "/a/bbb"];
3881        ["touch"; "/a/bbb/c"];
3882        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3883    "return true path on case-insensitive filesystem",
3884    "\
3885 This can be used to resolve case insensitive paths on
3886 a filesystem which is case sensitive.  The use case is
3887 to resolve paths which you have read from Windows configuration
3888 files or the Windows Registry, to the true path.
3889
3890 The command handles a peculiarity of the Linux ntfs-3g
3891 filesystem driver (and probably others), which is that although
3892 the underlying filesystem is case-insensitive, the driver
3893 exports the filesystem to Linux as case-sensitive.
3894
3895 One consequence of this is that special directories such
3896 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3897 (or other things) depending on the precise details of how
3898 they were created.  In Windows itself this would not be
3899 a problem.
3900
3901 Bug or feature?  You decide:
3902 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3903
3904 This function resolves the true case of each element in the
3905 path and returns the case-sensitive path.
3906
3907 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3908 might return C<\"/WINDOWS/system32\"> (the exact return value
3909 would depend on details of how the directories were originally
3910 created under Windows).
3911
3912 I<Note>:
3913 This function does not handle drive names, backslashes etc.
3914
3915 See also C<guestfs_realpath>.");
3916
3917   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3918    [InitBasicFS, Always, TestOutput (
3919       [["vfs_type"; "/dev/sda1"]], "ext2")],
3920    "get the Linux VFS type corresponding to a mounted device",
3921    "\
3922 This command gets the block device type corresponding to
3923 a mounted device called C<device>.
3924
3925 Usually the result is the name of the Linux VFS module that
3926 is used to mount this device (probably determined automatically
3927 if you used the C<guestfs_mount> call).");
3928
3929   ("truncate", (RErr, [Pathname "path"]), 199, [],
3930    [InitBasicFS, Always, TestOutputStruct (
3931       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3932        ["truncate"; "/test"];
3933        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3934    "truncate a file to zero size",
3935    "\
3936 This command truncates C<path> to a zero-length file.  The
3937 file must exist already.");
3938
3939   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3940    [InitBasicFS, Always, TestOutputStruct (
3941       [["touch"; "/test"];
3942        ["truncate_size"; "/test"; "1000"];
3943        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3944    "truncate a file to a particular size",
3945    "\
3946 This command truncates C<path> to size C<size> bytes.  The file
3947 must exist already.  If the file is smaller than C<size> then
3948 the file is extended to the required size with null bytes.");
3949
3950   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3951    [InitBasicFS, Always, TestOutputStruct (
3952       [["touch"; "/test"];
3953        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3954        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3955    "set timestamp of a file with nanosecond precision",
3956    "\
3957 This command sets the timestamps of a file with nanosecond
3958 precision.
3959
3960 C<atsecs, atnsecs> are the last access time (atime) in secs and
3961 nanoseconds from the epoch.
3962
3963 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3964 secs and nanoseconds from the epoch.
3965
3966 If the C<*nsecs> field contains the special value C<-1> then
3967 the corresponding timestamp is set to the current time.  (The
3968 C<*secs> field is ignored in this case).
3969
3970 If the C<*nsecs> field contains the special value C<-2> then
3971 the corresponding timestamp is left unchanged.  (The
3972 C<*secs> field is ignored in this case).");
3973
3974   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3975    [InitBasicFS, Always, TestOutputStruct (
3976       [["mkdir_mode"; "/test"; "0o111"];
3977        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3978    "create a directory with a particular mode",
3979    "\
3980 This command creates a directory, setting the initial permissions
3981 of the directory to C<mode>.
3982
3983 For common Linux filesystems, the actual mode which is set will
3984 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3985 interpret the mode in other ways.
3986
3987 See also C<guestfs_mkdir>, C<guestfs_umask>");
3988
3989   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3990    [], (* XXX *)
3991    "change file owner and group",
3992    "\
3993 Change the file owner to C<owner> and group to C<group>.
3994 This is like C<guestfs_chown> but if C<path> is a symlink then
3995 the link itself is changed, not the target.
3996
3997 Only numeric uid and gid are supported.  If you want to use
3998 names, you will need to locate and parse the password file
3999 yourself (Augeas support makes this relatively easy).");
4000
4001   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4002    [], (* XXX *)
4003    "lstat on multiple files",
4004    "\
4005 This call allows you to perform the C<guestfs_lstat> operation
4006 on multiple files, where all files are in the directory C<path>.
4007 C<names> is the list of files from this directory.
4008
4009 On return you get a list of stat structs, with a one-to-one
4010 correspondence to the C<names> list.  If any name did not exist
4011 or could not be lstat'd, then the C<ino> field of that structure
4012 is set to C<-1>.
4013
4014 This call is intended for programs that want to efficiently
4015 list a directory contents without making many round-trips.
4016 See also C<guestfs_lxattrlist> for a similarly efficient call
4017 for getting extended attributes.  Very long directory listings
4018 might cause the protocol message size to be exceeded, causing
4019 this call to fail.  The caller must split up such requests
4020 into smaller groups of names.");
4021
4022   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4023    [], (* XXX *)
4024    "lgetxattr on multiple files",
4025    "\
4026 This call allows you to get the extended attributes
4027 of multiple files, where all files are in the directory C<path>.
4028 C<names> is the list of files from this directory.
4029
4030 On return you get a flat list of xattr structs which must be
4031 interpreted sequentially.  The first xattr struct always has a zero-length
4032 C<attrname>.  C<attrval> in this struct is zero-length
4033 to indicate there was an error doing C<lgetxattr> for this
4034 file, I<or> is a C string which is a decimal number
4035 (the number of following attributes for this file, which could
4036 be C<\"0\">).  Then after the first xattr struct are the
4037 zero or more attributes for the first named file.
4038 This repeats for the second and subsequent files.
4039
4040 This call is intended for programs that want to efficiently
4041 list a directory contents without making many round-trips.
4042 See also C<guestfs_lstatlist> for a similarly efficient call
4043 for getting standard stats.  Very long directory listings
4044 might cause the protocol message size to be exceeded, causing
4045 this call to fail.  The caller must split up such requests
4046 into smaller groups of names.");
4047
4048   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4049    [], (* XXX *)
4050    "readlink on multiple files",
4051    "\
4052 This call allows you to do a C<readlink> operation
4053 on multiple files, where all files are in the directory C<path>.
4054 C<names> is the list of files from this directory.
4055
4056 On return you get a list of strings, with a one-to-one
4057 correspondence to the C<names> list.  Each string is the
4058 value of the symbol link.
4059
4060 If the C<readlink(2)> operation fails on any name, then
4061 the corresponding result string is the empty string C<\"\">.
4062 However the whole operation is completed even if there
4063 were C<readlink(2)> errors, and so you can call this
4064 function with names where you don't know if they are
4065 symbolic links already (albeit slightly less efficient).
4066
4067 This call is intended for programs that want to efficiently
4068 list a directory contents without making many round-trips.
4069 Very long directory listings might cause the protocol
4070 message size to be exceeded, causing
4071 this call to fail.  The caller must split up such requests
4072 into smaller groups of names.");
4073
4074   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4075    [InitISOFS, Always, TestOutputBuffer (
4076       [["pread"; "/known-4"; "1"; "3"]], "\n");
4077     InitISOFS, Always, TestOutputBuffer (
4078       [["pread"; "/empty"; "0"; "100"]], "")],
4079    "read part of a file",
4080    "\
4081 This command lets you read part of a file.  It reads C<count>
4082 bytes of the file, starting at C<offset>, from file C<path>.
4083
4084 This may read fewer bytes than requested.  For further details
4085 see the L<pread(2)> system call.");
4086
4087   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4088    [InitEmpty, Always, TestRun (
4089       [["part_init"; "/dev/sda"; "gpt"]])],
4090    "create an empty partition table",
4091    "\
4092 This creates an empty partition table on C<device> of one of the
4093 partition types listed below.  Usually C<parttype> should be
4094 either C<msdos> or C<gpt> (for large disks).
4095
4096 Initially there are no partitions.  Following this, you should
4097 call C<guestfs_part_add> for each partition required.
4098
4099 Possible values for C<parttype> are:
4100
4101 =over 4
4102
4103 =item B<efi> | B<gpt>
4104
4105 Intel EFI / GPT partition table.
4106
4107 This is recommended for >= 2 TB partitions that will be accessed
4108 from Linux and Intel-based Mac OS X.  It also has limited backwards
4109 compatibility with the C<mbr> format.
4110
4111 =item B<mbr> | B<msdos>
4112
4113 The standard PC \"Master Boot Record\" (MBR) format used
4114 by MS-DOS and Windows.  This partition type will B<only> work
4115 for device sizes up to 2 TB.  For large disks we recommend
4116 using C<gpt>.
4117
4118 =back
4119
4120 Other partition table types that may work but are not
4121 supported include:
4122
4123 =over 4
4124
4125 =item B<aix>
4126
4127 AIX disk labels.
4128
4129 =item B<amiga> | B<rdb>
4130
4131 Amiga \"Rigid Disk Block\" format.
4132
4133 =item B<bsd>
4134
4135 BSD disk labels.
4136
4137 =item B<dasd>
4138
4139 DASD, used on IBM mainframes.
4140
4141 =item B<dvh>
4142
4143 MIPS/SGI volumes.
4144
4145 =item B<mac>
4146
4147 Old Mac partition format.  Modern Macs use C<gpt>.
4148
4149 =item B<pc98>
4150
4151 NEC PC-98 format, common in Japan apparently.
4152
4153 =item B<sun>
4154
4155 Sun disk labels.
4156
4157 =back");
4158
4159   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4160    [InitEmpty, Always, TestRun (
4161       [["part_init"; "/dev/sda"; "mbr"];
4162        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4163     InitEmpty, Always, TestRun (
4164       [["part_init"; "/dev/sda"; "gpt"];
4165        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4166        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4167     InitEmpty, Always, TestRun (
4168       [["part_init"; "/dev/sda"; "mbr"];
4169        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4170        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4171        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4172        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4173    "add a partition to the device",
4174    "\
4175 This command adds a partition to C<device>.  If there is no partition
4176 table on the device, call C<guestfs_part_init> first.
4177
4178 The C<prlogex> parameter is the type of partition.  Normally you
4179 should pass C<p> or C<primary> here, but MBR partition tables also
4180 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4181 types.
4182
4183 C<startsect> and C<endsect> are the start and end of the partition
4184 in I<sectors>.  C<endsect> may be negative, which means it counts
4185 backwards from the end of the disk (C<-1> is the last sector).
4186
4187 Creating a partition which covers the whole disk is not so easy.
4188 Use C<guestfs_part_disk> to do that.");
4189
4190   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4191    [InitEmpty, Always, TestRun (
4192       [["part_disk"; "/dev/sda"; "mbr"]]);
4193     InitEmpty, Always, TestRun (
4194       [["part_disk"; "/dev/sda"; "gpt"]])],
4195    "partition whole disk with a single primary partition",
4196    "\
4197 This command is simply a combination of C<guestfs_part_init>
4198 followed by C<guestfs_part_add> to create a single primary partition
4199 covering the whole disk.
4200
4201 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4202 but other possible values are described in C<guestfs_part_init>.");
4203
4204   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4205    [InitEmpty, Always, TestRun (
4206       [["part_disk"; "/dev/sda"; "mbr"];
4207        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4208    "make a partition bootable",
4209    "\
4210 This sets the bootable flag on partition numbered C<partnum> on
4211 device C<device>.  Note that partitions are numbered from 1.
4212
4213 The bootable flag is used by some operating systems (notably
4214 Windows) to determine which partition to boot from.  It is by
4215 no means universally recognized.");
4216
4217   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4218    [InitEmpty, Always, TestRun (
4219       [["part_disk"; "/dev/sda"; "gpt"];
4220        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4221    "set partition name",
4222    "\
4223 This sets the partition name on partition numbered C<partnum> on
4224 device C<device>.  Note that partitions are numbered from 1.
4225
4226 The partition name can only be set on certain types of partition
4227 table.  This works on C<gpt> but not on C<mbr> partitions.");
4228
4229   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4230    [], (* XXX Add a regression test for this. *)
4231    "list partitions on a device",
4232    "\
4233 This command parses the partition table on C<device> and
4234 returns the list of partitions found.
4235
4236 The fields in the returned structure are:
4237
4238 =over 4
4239
4240 =item B<part_num>
4241
4242 Partition number, counting from 1.
4243
4244 =item B<part_start>
4245
4246 Start of the partition I<in bytes>.  To get sectors you have to
4247 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4248
4249 =item B<part_end>
4250
4251 End of the partition in bytes.
4252
4253 =item B<part_size>
4254
4255 Size of the partition in bytes.
4256
4257 =back");
4258
4259   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4260    [InitEmpty, Always, TestOutput (
4261       [["part_disk"; "/dev/sda"; "gpt"];
4262        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4263    "get the partition table type",
4264    "\
4265 This command examines the partition table on C<device> and
4266 returns the partition table type (format) being used.
4267
4268 Common return values include: C<msdos> (a DOS/Windows style MBR
4269 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4270 values are possible, although unusual.  See C<guestfs_part_init>
4271 for a full list.");
4272
4273   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4274    [InitBasicFS, Always, TestOutputBuffer (
4275       [["fill"; "0x63"; "10"; "/test"];
4276        ["read_file"; "/test"]], "cccccccccc")],
4277    "fill a file with octets",
4278    "\
4279 This command creates a new file called C<path>.  The initial
4280 content of the file is C<len> octets of C<c>, where C<c>
4281 must be a number in the range C<[0..255]>.
4282
4283 To fill a file with zero bytes (sparsely), it is
4284 much more efficient to use C<guestfs_truncate_size>.
4285 To create a file with a pattern of repeating bytes
4286 use C<guestfs_fill_pattern>.");
4287
4288   ("available", (RErr, [StringList "groups"]), 216, [],
4289    [InitNone, Always, TestRun [["available"; ""]]],
4290    "test availability of some parts of the API",
4291    "\
4292 This command is used to check the availability of some
4293 groups of functionality in the appliance, which not all builds of
4294 the libguestfs appliance will be able to provide.
4295
4296 The libguestfs groups, and the functions that those
4297 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4298
4299 The argument C<groups> is a list of group names, eg:
4300 C<[\"inotify\", \"augeas\"]> would check for the availability of
4301 the Linux inotify functions and Augeas (configuration file
4302 editing) functions.
4303
4304 The command returns no error if I<all> requested groups are available.
4305
4306 It fails with an error if one or more of the requested
4307 groups is unavailable in the appliance.
4308
4309 If an unknown group name is included in the
4310 list of groups then an error is always returned.
4311
4312 I<Notes:>
4313
4314 =over 4
4315
4316 =item *
4317
4318 You must call C<guestfs_launch> before calling this function.
4319
4320 The reason is because we don't know what groups are
4321 supported by the appliance/daemon until it is running and can
4322 be queried.
4323
4324 =item *
4325
4326 If a group of functions is available, this does not necessarily
4327 mean that they will work.  You still have to check for errors
4328 when calling individual API functions even if they are
4329 available.
4330
4331 =item *
4332
4333 It is usually the job of distro packagers to build
4334 complete functionality into the libguestfs appliance.
4335 Upstream libguestfs, if built from source with all
4336 requirements satisfied, will support everything.
4337
4338 =item *
4339
4340 This call was added in version C<1.0.80>.  In previous
4341 versions of libguestfs all you could do would be to speculatively
4342 execute a command to find out if the daemon implemented it.
4343 See also C<guestfs_version>.
4344
4345 =back");
4346
4347   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4348    [InitBasicFS, Always, TestOutputBuffer (
4349       [["write_file"; "/src"; "hello, world"; "0"];
4350        ["dd"; "/src"; "/dest"];
4351        ["read_file"; "/dest"]], "hello, world")],
4352    "copy from source to destination using dd",
4353    "\
4354 This command copies from one source device or file C<src>
4355 to another destination device or file C<dest>.  Normally you
4356 would use this to copy to or from a device or partition, for
4357 example to duplicate a filesystem.
4358
4359 If the destination is a device, it must be as large or larger
4360 than the source file or device, otherwise the copy will fail.
4361 This command cannot do partial copies (see C<guestfs_copy_size>).");
4362
4363   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4364    [InitBasicFS, Always, TestOutputInt (
4365       [["write_file"; "/file"; "hello, world"; "0"];
4366        ["filesize"; "/file"]], 12)],
4367    "return the size of the file in bytes",
4368    "\
4369 This command returns the size of C<file> in bytes.
4370
4371 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4372 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4373 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4374
4375   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4376    [InitBasicFSonLVM, Always, TestOutputList (
4377       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4378        ["lvs"]], ["/dev/VG/LV2"])],
4379    "rename an LVM logical volume",
4380    "\
4381 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4382
4383   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4384    [InitBasicFSonLVM, Always, TestOutputList (
4385       [["umount"; "/"];
4386        ["vg_activate"; "false"; "VG"];
4387        ["vgrename"; "VG"; "VG2"];
4388        ["vg_activate"; "true"; "VG2"];
4389        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4390        ["vgs"]], ["VG2"])],
4391    "rename an LVM volume group",
4392    "\
4393 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4394
4395   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4396    [InitISOFS, Always, TestOutputBuffer (
4397       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4398    "list the contents of a single file in an initrd",
4399    "\
4400 This command unpacks the file C<filename> from the initrd file
4401 called C<initrdpath>.  The filename must be given I<without> the
4402 initial C</> character.
4403
4404 For example, in guestfish you could use the following command
4405 to examine the boot script (usually called C</init>)
4406 contained in a Linux initrd or initramfs image:
4407
4408  initrd-cat /boot/initrd-<version>.img init
4409
4410 See also C<guestfs_initrd_list>.");
4411
4412   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4413    [],
4414    "get the UUID of a physical volume",
4415    "\
4416 This command returns the UUID of the LVM PV C<device>.");
4417
4418   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4419    [],
4420    "get the UUID of a volume group",
4421    "\
4422 This command returns the UUID of the LVM VG named C<vgname>.");
4423
4424   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4425    [],
4426    "get the UUID of a logical volume",
4427    "\
4428 This command returns the UUID of the LVM LV C<device>.");
4429
4430   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4431    [],
4432    "get the PV UUIDs containing the volume group",
4433    "\
4434 Given a VG called C<vgname>, this returns the UUIDs of all
4435 the physical volumes that this volume group resides on.
4436
4437 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4438 calls to associate physical volumes and volume groups.
4439
4440 See also C<guestfs_vglvuuids>.");
4441
4442   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4443    [],
4444    "get the LV UUIDs of all LVs in the volume group",
4445    "\
4446 Given a VG called C<vgname>, this returns the UUIDs of all
4447 the logical volumes created in this volume group.
4448
4449 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4450 calls to associate logical volumes and volume groups.
4451
4452 See also C<guestfs_vgpvuuids>.");
4453
4454   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4455    [InitBasicFS, Always, TestOutputBuffer (
4456       [["write_file"; "/src"; "hello, world"; "0"];
4457        ["copy_size"; "/src"; "/dest"; "5"];
4458        ["read_file"; "/dest"]], "hello")],
4459    "copy size bytes from source to destination using dd",
4460    "\
4461 This command copies exactly C<size> bytes from one source device
4462 or file C<src> to another destination device or file C<dest>.
4463
4464 Note this will fail if the source is too short or if the destination
4465 is not large enough.");
4466
4467   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4468    [InitBasicFSonLVM, Always, TestRun (
4469       [["zero_device"; "/dev/VG/LV"]])],
4470    "write zeroes to an entire device",
4471    "\
4472 This command writes zeroes over the entire C<device>.  Compare
4473 with C<guestfs_zero> which just zeroes the first few blocks of
4474 a device.");
4475
4476   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4477    [InitBasicFS, Always, TestOutput (
4478       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4479        ["cat"; "/hello"]], "hello\n")],
4480    "unpack compressed tarball to directory",
4481    "\
4482 This command uploads and unpacks local file C<tarball> (an
4483 I<xz compressed> tar file) into C<directory>.");
4484
4485   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4486    [],
4487    "pack directory into compressed tarball",
4488    "\
4489 This command packs the contents of C<directory> and downloads
4490 it to local file C<tarball> (as an xz compressed tar archive).");
4491
4492   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4493    [],
4494    "resize an NTFS filesystem",
4495    "\
4496 This command resizes an NTFS filesystem, expanding or
4497 shrinking it to the size of the underlying device.
4498 See also L<ntfsresize(8)>.");
4499
4500   ("vgscan", (RErr, []), 232, [],
4501    [InitEmpty, Always, TestRun (
4502       [["vgscan"]])],
4503    "rescan for LVM physical volumes, volume groups and logical volumes",
4504    "\
4505 This rescans all block devices and rebuilds the list of LVM
4506 physical volumes, volume groups and logical volumes.");
4507
4508   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4509    [InitEmpty, Always, TestRun (
4510       [["part_init"; "/dev/sda"; "mbr"];
4511        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4512        ["part_del"; "/dev/sda"; "1"]])],
4513    "delete a partition",
4514    "\
4515 This command deletes the partition numbered C<partnum> on C<device>.
4516
4517 Note that in the case of MBR partitioning, deleting an
4518 extended partition also deletes any logical partitions
4519 it contains.");
4520
4521   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4522    [InitEmpty, Always, TestOutputTrue (
4523       [["part_init"; "/dev/sda"; "mbr"];
4524        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4525        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4526        ["part_get_bootable"; "/dev/sda"; "1"]])],
4527    "return true if a partition is bootable",
4528    "\
4529 This command returns true if the partition C<partnum> on
4530 C<device> has the bootable flag set.
4531
4532 See also C<guestfs_part_set_bootable>.");
4533
4534   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4535    [InitEmpty, Always, TestOutputInt (
4536       [["part_init"; "/dev/sda"; "mbr"];
4537        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4538        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4539        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4540    "get the MBR type byte (ID byte) from a partition",
4541    "\
4542 Returns the MBR type byte (also known as the ID byte) from
4543 the numbered partition C<partnum>.
4544
4545 Note that only MBR (old DOS-style) partitions have type bytes.
4546 You will get undefined results for other partition table
4547 types (see C<guestfs_part_get_parttype>).");
4548
4549   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4550    [], (* tested by part_get_mbr_id *)
4551    "set the MBR type byte (ID byte) of a partition",
4552    "\
4553 Sets the MBR type byte (also known as the ID byte) of
4554 the numbered partition C<partnum> to C<idbyte>.  Note
4555 that the type bytes quoted in most documentation are
4556 in fact hexadecimal numbers, but usually documented
4557 without any leading \"0x\" which might be confusing.
4558
4559 Note that only MBR (old DOS-style) partitions have type bytes.
4560 You will get undefined results for other partition table
4561 types (see C<guestfs_part_get_parttype>).");
4562
4563   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4564    [InitISOFS, Always, TestOutput (
4565       [["checksum_device"; "md5"; "/dev/sdd"]],
4566       (Digest.to_hex (Digest.file "images/test.iso")))],
4567    "compute MD5, SHAx or CRC checksum of the contents of a device",
4568    "\
4569 This call computes the MD5, SHAx or CRC checksum of the
4570 contents of the device named C<device>.  For the types of
4571 checksums supported see the C<guestfs_checksum> command.");
4572
4573   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4574    [InitNone, Always, TestRun (
4575       [["part_disk"; "/dev/sda"; "mbr"];
4576        ["pvcreate"; "/dev/sda1"];
4577        ["vgcreate"; "VG"; "/dev/sda1"];
4578        ["lvcreate"; "LV"; "VG"; "10"];
4579        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4580    "expand an LV to fill free space",
4581    "\
4582 This expands an existing logical volume C<lv> so that it fills
4583 C<pc>% of the remaining free space in the volume group.  Commonly
4584 you would call this with pc = 100 which expands the logical volume
4585 as much as possible, using all remaining free space in the volume
4586 group.");
4587
4588   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4589    [], (* XXX Augeas code needs tests. *)
4590    "clear Augeas path",
4591    "\
4592 Set the value associated with C<path> to C<NULL>.  This
4593 is the same as the L<augtool(1)> C<clear> command.");
4594
4595   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4596    [InitEmpty, Always, TestOutputInt (
4597       [["get_umask"]], 0o22)],
4598    "get the current umask",
4599    "\
4600 Return the current umask.  By default the umask is C<022>
4601 unless it has been set by calling C<guestfs_umask>.");
4602
4603   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4604    [],
4605    "upload a file to the appliance (internal use only)",
4606    "\
4607 The C<guestfs_debug_upload> command uploads a file to
4608 the libguestfs appliance.
4609
4610 There is no comprehensive help for this command.  You have
4611 to look at the file C<daemon/debug.c> in the libguestfs source
4612 to find out what it is for.");
4613
4614   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4615    [InitBasicFS, Always, TestOutput (
4616       [["base64_in"; "../images/hello.b64"; "/hello"];
4617        ["cat"; "/hello"]], "hello\n")],
4618    "upload base64-encoded data to file",
4619    "\
4620 This command uploads base64-encoded data from C<base64file>
4621 to C<filename>.");
4622
4623   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4624    [],
4625    "download file and encode as base64",
4626    "\
4627 This command downloads the contents of C<filename>, writing
4628 it out to local file C<base64file> encoded as base64.");
4629
4630   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4631    [],
4632    "compute MD5, SHAx or CRC checksum of files in a directory",
4633    "\
4634 This command computes the checksums of all regular files in
4635 C<directory> and then emits a list of those checksums to
4636 the local output file C<sumsfile>.
4637
4638 This can be used for verifying the integrity of a virtual
4639 machine.  However to be properly secure you should pay
4640 attention to the output of the checksum command (it uses
4641 the ones from GNU coreutils).  In particular when the
4642 filename is not printable, coreutils uses a special
4643 backslash syntax.  For more information, see the GNU
4644 coreutils info file.");
4645
4646   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4647    [InitBasicFS, Always, TestOutputBuffer (
4648       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4649        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4650    "fill a file with a repeating pattern of bytes",
4651    "\
4652 This function is like C<guestfs_fill> except that it creates
4653 a new file of length C<len> containing the repeating pattern
4654 of bytes in C<pattern>.  The pattern is truncated if necessary
4655 to ensure the length of the file is exactly C<len> bytes.");
4656
4657 ]
4658
4659 let all_functions = non_daemon_functions @ daemon_functions
4660
4661 (* In some places we want the functions to be displayed sorted
4662  * alphabetically, so this is useful:
4663  *)
4664 let all_functions_sorted =
4665   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4666                compare n1 n2) all_functions
4667
4668 (* This is used to generate the src/MAX_PROC_NR file which
4669  * contains the maximum procedure number, a surrogate for the
4670  * ABI version number.  See src/Makefile.am for the details.
4671  *)
4672 let max_proc_nr =
4673   let proc_nrs = List.map (
4674     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4675   ) daemon_functions in
4676   List.fold_left max 0 proc_nrs
4677
4678 (* Field types for structures. *)
4679 type field =
4680   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4681   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4682   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4683   | FUInt32
4684   | FInt32
4685   | FUInt64
4686   | FInt64
4687   | FBytes                      (* Any int measure that counts bytes. *)
4688   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4689   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4690
4691 (* Because we generate extra parsing code for LVM command line tools,
4692  * we have to pull out the LVM columns separately here.
4693  *)
4694 let lvm_pv_cols = [
4695   "pv_name", FString;
4696   "pv_uuid", FUUID;
4697   "pv_fmt", FString;
4698   "pv_size", FBytes;
4699   "dev_size", FBytes;
4700   "pv_free", FBytes;
4701   "pv_used", FBytes;
4702   "pv_attr", FString (* XXX *);
4703   "pv_pe_count", FInt64;
4704   "pv_pe_alloc_count", FInt64;
4705   "pv_tags", FString;
4706   "pe_start", FBytes;
4707   "pv_mda_count", FInt64;
4708   "pv_mda_free", FBytes;
4709   (* Not in Fedora 10:
4710      "pv_mda_size", FBytes;
4711   *)
4712 ]
4713 let lvm_vg_cols = [
4714   "vg_name", FString;
4715   "vg_uuid", FUUID;
4716   "vg_fmt", FString;
4717   "vg_attr", FString (* XXX *);
4718   "vg_size", FBytes;
4719   "vg_free", FBytes;
4720   "vg_sysid", FString;
4721   "vg_extent_size", FBytes;
4722   "vg_extent_count", FInt64;
4723   "vg_free_count", FInt64;
4724   "max_lv", FInt64;
4725   "max_pv", FInt64;
4726   "pv_count", FInt64;
4727   "lv_count", FInt64;
4728   "snap_count", FInt64;
4729   "vg_seqno", FInt64;
4730   "vg_tags", FString;
4731   "vg_mda_count", FInt64;
4732   "vg_mda_free", FBytes;
4733   (* Not in Fedora 10:
4734      "vg_mda_size", FBytes;
4735   *)
4736 ]
4737 let lvm_lv_cols = [
4738   "lv_name", FString;
4739   "lv_uuid", FUUID;
4740   "lv_attr", FString (* XXX *);
4741   "lv_major", FInt64;
4742   "lv_minor", FInt64;
4743   "lv_kernel_major", FInt64;
4744   "lv_kernel_minor", FInt64;
4745   "lv_size", FBytes;
4746   "seg_count", FInt64;
4747   "origin", FString;
4748   "snap_percent", FOptPercent;
4749   "copy_percent", FOptPercent;
4750   "move_pv", FString;
4751   "lv_tags", FString;
4752   "mirror_log", FString;
4753   "modules", FString;
4754 ]
4755
4756 (* Names and fields in all structures (in RStruct and RStructList)
4757  * that we support.
4758  *)
4759 let structs = [
4760   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4761    * not use this struct in any new code.
4762    *)
4763   "int_bool", [
4764     "i", FInt32;                (* for historical compatibility *)
4765     "b", FInt32;                (* for historical compatibility *)
4766   ];
4767
4768   (* LVM PVs, VGs, LVs. *)
4769   "lvm_pv", lvm_pv_cols;
4770   "lvm_vg", lvm_vg_cols;
4771   "lvm_lv", lvm_lv_cols;
4772
4773   (* Column names and types from stat structures.
4774    * NB. Can't use things like 'st_atime' because glibc header files
4775    * define some of these as macros.  Ugh.
4776    *)
4777   "stat", [
4778     "dev", FInt64;
4779     "ino", FInt64;
4780     "mode", FInt64;
4781     "nlink", FInt64;
4782     "uid", FInt64;
4783     "gid", FInt64;
4784     "rdev", FInt64;
4785     "size", FInt64;
4786     "blksize", FInt64;
4787     "blocks", FInt64;
4788     "atime", FInt64;
4789     "mtime", FInt64;
4790     "ctime", FInt64;
4791   ];
4792   "statvfs", [
4793     "bsize", FInt64;
4794     "frsize", FInt64;
4795     "blocks", FInt64;
4796     "bfree", FInt64;
4797     "bavail", FInt64;
4798     "files", FInt64;
4799     "ffree", FInt64;
4800     "favail", FInt64;
4801     "fsid", FInt64;
4802     "flag", FInt64;
4803     "namemax", FInt64;
4804   ];
4805
4806   (* Column names in dirent structure. *)
4807   "dirent", [
4808     "ino", FInt64;
4809     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4810     "ftyp", FChar;
4811     "name", FString;
4812   ];
4813
4814   (* Version numbers. *)
4815   "version", [
4816     "major", FInt64;
4817     "minor", FInt64;
4818     "release", FInt64;
4819     "extra", FString;
4820   ];
4821
4822   (* Extended attribute. *)
4823   "xattr", [
4824     "attrname", FString;
4825     "attrval", FBuffer;
4826   ];
4827
4828   (* Inotify events. *)
4829   "inotify_event", [
4830     "in_wd", FInt64;
4831     "in_mask", FUInt32;
4832     "in_cookie", FUInt32;
4833     "in_name", FString;
4834   ];
4835
4836   (* Partition table entry. *)
4837   "partition", [
4838     "part_num", FInt32;
4839     "part_start", FBytes;
4840     "part_end", FBytes;
4841     "part_size", FBytes;
4842   ];
4843 ] (* end of structs *)
4844
4845 (* Ugh, Java has to be different ..
4846  * These names are also used by the Haskell bindings.
4847  *)
4848 let java_structs = [
4849   "int_bool", "IntBool";
4850   "lvm_pv", "PV";
4851   "lvm_vg", "VG";
4852   "lvm_lv", "LV";
4853   "stat", "Stat";
4854   "statvfs", "StatVFS";
4855   "dirent", "Dirent";
4856   "version", "Version";
4857   "xattr", "XAttr";
4858   "inotify_event", "INotifyEvent";
4859   "partition", "Partition";
4860 ]
4861
4862 (* What structs are actually returned. *)
4863 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4864
4865 (* Returns a list of RStruct/RStructList structs that are returned
4866  * by any function.  Each element of returned list is a pair:
4867  *
4868  * (structname, RStructOnly)
4869  *    == there exists function which returns RStruct (_, structname)
4870  * (structname, RStructListOnly)
4871  *    == there exists function which returns RStructList (_, structname)
4872  * (structname, RStructAndList)
4873  *    == there are functions returning both RStruct (_, structname)
4874  *                                      and RStructList (_, structname)
4875  *)
4876 let rstructs_used_by functions =
4877   (* ||| is a "logical OR" for rstructs_used_t *)
4878   let (|||) a b =
4879     match a, b with
4880     | RStructAndList, _
4881     | _, RStructAndList -> RStructAndList
4882     | RStructOnly, RStructListOnly
4883     | RStructListOnly, RStructOnly -> RStructAndList
4884     | RStructOnly, RStructOnly -> RStructOnly
4885     | RStructListOnly, RStructListOnly -> RStructListOnly
4886   in
4887
4888   let h = Hashtbl.create 13 in
4889
4890   (* if elem->oldv exists, update entry using ||| operator,
4891    * else just add elem->newv to the hash
4892    *)
4893   let update elem newv =
4894     try  let oldv = Hashtbl.find h elem in
4895          Hashtbl.replace h elem (newv ||| oldv)
4896     with Not_found -> Hashtbl.add h elem newv
4897   in
4898
4899   List.iter (
4900     fun (_, style, _, _, _, _, _) ->
4901       match fst style with
4902       | RStruct (_, structname) -> update structname RStructOnly
4903       | RStructList (_, structname) -> update structname RStructListOnly
4904       | _ -> ()
4905   ) functions;
4906
4907   (* return key->values as a list of (key,value) *)
4908   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4909
4910 (* Used for testing language bindings. *)
4911 type callt =
4912   | CallString of string
4913   | CallOptString of string option
4914   | CallStringList of string list
4915   | CallInt of int
4916   | CallInt64 of int64
4917   | CallBool of bool
4918
4919 (* Used to memoize the result of pod2text. *)
4920 let pod2text_memo_filename = "src/.pod2text.data"
4921 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4922   try
4923     let chan = open_in pod2text_memo_filename in
4924     let v = input_value chan in
4925     close_in chan;
4926     v
4927   with
4928     _ -> Hashtbl.create 13
4929 let pod2text_memo_updated () =
4930   let chan = open_out pod2text_memo_filename in
4931   output_value chan pod2text_memo;
4932   close_out chan
4933
4934 (* Useful functions.
4935  * Note we don't want to use any external OCaml libraries which
4936  * makes this a bit harder than it should be.
4937  *)
4938 module StringMap = Map.Make (String)
4939
4940 let failwithf fs = ksprintf failwith fs
4941
4942 let unique = let i = ref 0 in fun () -> incr i; !i
4943
4944 let replace_char s c1 c2 =
4945   let s2 = String.copy s in
4946   let r = ref false in
4947   for i = 0 to String.length s2 - 1 do
4948     if String.unsafe_get s2 i = c1 then (
4949       String.unsafe_set s2 i c2;
4950       r := true
4951     )
4952   done;
4953   if not !r then s else s2
4954
4955 let isspace c =
4956   c = ' '
4957   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4958
4959 let triml ?(test = isspace) str =
4960   let i = ref 0 in
4961   let n = ref (String.length str) in
4962   while !n > 0 && test str.[!i]; do
4963     decr n;
4964     incr i
4965   done;
4966   if !i = 0 then str
4967   else String.sub str !i !n
4968
4969 let trimr ?(test = isspace) str =
4970   let n = ref (String.length str) in
4971   while !n > 0 && test str.[!n-1]; do
4972     decr n
4973   done;
4974   if !n = String.length str then str
4975   else String.sub str 0 !n
4976
4977 let trim ?(test = isspace) str =
4978   trimr ~test (triml ~test str)
4979
4980 let rec find s sub =
4981   let len = String.length s in
4982   let sublen = String.length sub in
4983   let rec loop i =
4984     if i <= len-sublen then (
4985       let rec loop2 j =
4986         if j < sublen then (
4987           if s.[i+j] = sub.[j] then loop2 (j+1)
4988           else -1
4989         ) else
4990           i (* found *)
4991       in
4992       let r = loop2 0 in
4993       if r = -1 then loop (i+1) else r
4994     ) else
4995       -1 (* not found *)
4996   in
4997   loop 0
4998
4999 let rec replace_str s s1 s2 =
5000   let len = String.length s in
5001   let sublen = String.length s1 in
5002   let i = find s s1 in
5003   if i = -1 then s
5004   else (
5005     let s' = String.sub s 0 i in
5006     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5007     s' ^ s2 ^ replace_str s'' s1 s2
5008   )
5009
5010 let rec string_split sep str =
5011   let len = String.length str in
5012   let seplen = String.length sep in
5013   let i = find str sep in
5014   if i = -1 then [str]
5015   else (
5016     let s' = String.sub str 0 i in
5017     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5018     s' :: string_split sep s''
5019   )
5020
5021 let files_equal n1 n2 =
5022   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5023   match Sys.command cmd with
5024   | 0 -> true
5025   | 1 -> false
5026   | i -> failwithf "%s: failed with error code %d" cmd i
5027
5028 let rec filter_map f = function
5029   | [] -> []
5030   | x :: xs ->
5031       match f x with
5032       | Some y -> y :: filter_map f xs
5033       | None -> filter_map f xs
5034
5035 let rec find_map f = function
5036   | [] -> raise Not_found
5037   | x :: xs ->
5038       match f x with
5039       | Some y -> y
5040       | None -> find_map f xs
5041
5042 let iteri f xs =
5043   let rec loop i = function
5044     | [] -> ()
5045     | x :: xs -> f i x; loop (i+1) xs
5046   in
5047   loop 0 xs
5048
5049 let mapi f xs =
5050   let rec loop i = function
5051     | [] -> []
5052     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5053   in
5054   loop 0 xs
5055
5056 let count_chars c str =
5057   let count = ref 0 in
5058   for i = 0 to String.length str - 1 do
5059     if c = String.unsafe_get str i then incr count
5060   done;
5061   !count
5062
5063 let name_of_argt = function
5064   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5065   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5066   | FileIn n | FileOut n -> n
5067
5068 let java_name_of_struct typ =
5069   try List.assoc typ java_structs
5070   with Not_found ->
5071     failwithf
5072       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5073
5074 let cols_of_struct typ =
5075   try List.assoc typ structs
5076   with Not_found ->
5077     failwithf "cols_of_struct: unknown struct %s" typ
5078
5079 let seq_of_test = function
5080   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5081   | TestOutputListOfDevices (s, _)
5082   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5083   | TestOutputTrue s | TestOutputFalse s
5084   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5085   | TestOutputStruct (s, _)
5086   | TestLastFail s -> s
5087
5088 (* Handling for function flags. *)
5089 let protocol_limit_warning =
5090   "Because of the message protocol, there is a transfer limit
5091 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5092
5093 let danger_will_robinson =
5094   "B<This command is dangerous.  Without careful use you
5095 can easily destroy all your data>."
5096
5097 let deprecation_notice flags =
5098   try
5099     let alt =
5100       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5101     let txt =
5102       sprintf "This function is deprecated.
5103 In new code, use the C<%s> call instead.
5104
5105 Deprecated functions will not be removed from the API, but the
5106 fact that they are deprecated indicates that there are problems
5107 with correct use of these functions." alt in
5108     Some txt
5109   with
5110     Not_found -> None
5111
5112 (* Create list of optional groups. *)
5113 let optgroups =
5114   let h = Hashtbl.create 13 in
5115   List.iter (
5116     fun (name, _, _, flags, _, _, _) ->
5117       List.iter (
5118         function
5119         | Optional group ->
5120             let names = try Hashtbl.find h group with Not_found -> [] in
5121             Hashtbl.replace h group (name :: names)
5122         | _ -> ()
5123       ) flags
5124   ) daemon_functions;
5125   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5126   let groups =
5127     List.map (
5128       fun group -> group, List.sort compare (Hashtbl.find h group)
5129     ) groups in
5130   List.sort (fun x y -> compare (fst x) (fst y)) groups
5131
5132 (* Check function names etc. for consistency. *)
5133 let check_functions () =
5134   let contains_uppercase str =
5135     let len = String.length str in
5136     let rec loop i =
5137       if i >= len then false
5138       else (
5139         let c = str.[i] in
5140         if c >= 'A' && c <= 'Z' then true
5141         else loop (i+1)
5142       )
5143     in
5144     loop 0
5145   in
5146
5147   (* Check function names. *)
5148   List.iter (
5149     fun (name, _, _, _, _, _, _) ->
5150       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5151         failwithf "function name %s does not need 'guestfs' prefix" name;
5152       if name = "" then
5153         failwithf "function name is empty";
5154       if name.[0] < 'a' || name.[0] > 'z' then
5155         failwithf "function name %s must start with lowercase a-z" name;
5156       if String.contains name '-' then
5157         failwithf "function name %s should not contain '-', use '_' instead."
5158           name
5159   ) all_functions;
5160
5161   (* Check function parameter/return names. *)
5162   List.iter (
5163     fun (name, style, _, _, _, _, _) ->
5164       let check_arg_ret_name n =
5165         if contains_uppercase n then
5166           failwithf "%s param/ret %s should not contain uppercase chars"
5167             name n;
5168         if String.contains n '-' || String.contains n '_' then
5169           failwithf "%s param/ret %s should not contain '-' or '_'"
5170             name n;
5171         if n = "value" then
5172           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;
5173         if n = "int" || n = "char" || n = "short" || n = "long" then
5174           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5175         if n = "i" || n = "n" then
5176           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5177         if n = "argv" || n = "args" then
5178           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5179
5180         (* List Haskell, OCaml and C keywords here.
5181          * http://www.haskell.org/haskellwiki/Keywords
5182          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5183          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5184          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5185          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5186          * Omitting _-containing words, since they're handled above.
5187          * Omitting the OCaml reserved word, "val", is ok,
5188          * and saves us from renaming several parameters.
5189          *)
5190         let reserved = [
5191           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5192           "char"; "class"; "const"; "constraint"; "continue"; "data";
5193           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5194           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5195           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5196           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5197           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5198           "interface";
5199           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5200           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5201           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5202           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5203           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5204           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5205           "volatile"; "when"; "where"; "while";
5206           ] in
5207         if List.mem n reserved then
5208           failwithf "%s has param/ret using reserved word %s" name n;
5209       in
5210
5211       (match fst style with
5212        | RErr -> ()
5213        | RInt n | RInt64 n | RBool n
5214        | RConstString n | RConstOptString n | RString n
5215        | RStringList n | RStruct (n, _) | RStructList (n, _)
5216        | RHashtable n | RBufferOut n ->
5217            check_arg_ret_name n
5218       );
5219       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5220   ) all_functions;
5221
5222   (* Check short descriptions. *)
5223   List.iter (
5224     fun (name, _, _, _, _, shortdesc, _) ->
5225       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5226         failwithf "short description of %s should begin with lowercase." name;
5227       let c = shortdesc.[String.length shortdesc-1] in
5228       if c = '\n' || c = '.' then
5229         failwithf "short description of %s should not end with . or \\n." name
5230   ) all_functions;
5231
5232   (* Check long descriptions. *)
5233   List.iter (
5234     fun (name, _, _, _, _, _, longdesc) ->
5235       if longdesc.[String.length longdesc-1] = '\n' then
5236         failwithf "long description of %s should not end with \\n." name
5237   ) all_functions;
5238
5239   (* Check proc_nrs. *)
5240   List.iter (
5241     fun (name, _, proc_nr, _, _, _, _) ->
5242       if proc_nr <= 0 then
5243         failwithf "daemon function %s should have proc_nr > 0" name
5244   ) daemon_functions;
5245
5246   List.iter (
5247     fun (name, _, proc_nr, _, _, _, _) ->
5248       if proc_nr <> -1 then
5249         failwithf "non-daemon function %s should have proc_nr -1" name
5250   ) non_daemon_functions;
5251
5252   let proc_nrs =
5253     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5254       daemon_functions in
5255   let proc_nrs =
5256     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5257   let rec loop = function
5258     | [] -> ()
5259     | [_] -> ()
5260     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5261         loop rest
5262     | (name1,nr1) :: (name2,nr2) :: _ ->
5263         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5264           name1 name2 nr1 nr2
5265   in
5266   loop proc_nrs;
5267
5268   (* Check tests. *)
5269   List.iter (
5270     function
5271       (* Ignore functions that have no tests.  We generate a
5272        * warning when the user does 'make check' instead.
5273        *)
5274     | name, _, _, _, [], _, _ -> ()
5275     | name, _, _, _, tests, _, _ ->
5276         let funcs =
5277           List.map (
5278             fun (_, _, test) ->
5279               match seq_of_test test with
5280               | [] ->
5281                   failwithf "%s has a test containing an empty sequence" name
5282               | cmds -> List.map List.hd cmds
5283           ) tests in
5284         let funcs = List.flatten funcs in
5285
5286         let tested = List.mem name funcs in
5287
5288         if not tested then
5289           failwithf "function %s has tests but does not test itself" name
5290   ) all_functions
5291
5292 (* 'pr' prints to the current output file. *)
5293 let chan = ref Pervasives.stdout
5294 let lines = ref 0
5295 let pr fs =
5296   ksprintf
5297     (fun str ->
5298        let i = count_chars '\n' str in
5299        lines := !lines + i;
5300        output_string !chan str
5301     ) fs
5302
5303 let copyright_years =
5304   let this_year = 1900 + (localtime (time ())).tm_year in
5305   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5306
5307 (* Generate a header block in a number of standard styles. *)
5308 type comment_style =
5309     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5310 type license = GPLv2plus | LGPLv2plus
5311
5312 let generate_header ?(extra_inputs = []) comment license =
5313   let inputs = "src/generator.ml" :: extra_inputs in
5314   let c = match comment with
5315     | CStyle ->         pr "/* "; " *"
5316     | CPlusPlusStyle -> pr "// "; "//"
5317     | HashStyle ->      pr "# ";  "#"
5318     | OCamlStyle ->     pr "(* "; " *"
5319     | HaskellStyle ->   pr "{- "; "  " in
5320   pr "libguestfs generated file\n";
5321   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5322   List.iter (pr "%s   %s\n" c) inputs;
5323   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5324   pr "%s\n" c;
5325   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5326   pr "%s\n" c;
5327   (match license with
5328    | GPLv2plus ->
5329        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5330        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5331        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5332        pr "%s (at your option) any later version.\n" c;
5333        pr "%s\n" c;
5334        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5335        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5336        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5337        pr "%s GNU General Public License for more details.\n" c;
5338        pr "%s\n" c;
5339        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5340        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5341        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5342
5343    | LGPLv2plus ->
5344        pr "%s This library is free software; you can redistribute it and/or\n" c;
5345        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5346        pr "%s License as published by the Free Software Foundation; either\n" c;
5347        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5348        pr "%s\n" c;
5349        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5350        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5351        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5352        pr "%s Lesser General Public License for more details.\n" c;
5353        pr "%s\n" c;
5354        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5355        pr "%s License along with this library; if not, write to the Free Software\n" c;
5356        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5357   );
5358   (match comment with
5359    | CStyle -> pr " */\n"
5360    | CPlusPlusStyle
5361    | HashStyle -> ()
5362    | OCamlStyle -> pr " *)\n"
5363    | HaskellStyle -> pr "-}\n"
5364   );
5365   pr "\n"
5366
5367 (* Start of main code generation functions below this line. *)
5368
5369 (* Generate the pod documentation for the C API. *)
5370 let rec generate_actions_pod () =
5371   List.iter (
5372     fun (shortname, style, _, flags, _, _, longdesc) ->
5373       if not (List.mem NotInDocs flags) then (
5374         let name = "guestfs_" ^ shortname in
5375         pr "=head2 %s\n\n" name;
5376         pr " ";
5377         generate_prototype ~extern:false ~handle:"g" name style;
5378         pr "\n\n";
5379         pr "%s\n\n" longdesc;
5380         (match fst style with
5381          | RErr ->
5382              pr "This function returns 0 on success or -1 on error.\n\n"
5383          | RInt _ ->
5384              pr "On error this function returns -1.\n\n"
5385          | RInt64 _ ->
5386              pr "On error this function returns -1.\n\n"
5387          | RBool _ ->
5388              pr "This function returns a C truth value on success or -1 on error.\n\n"
5389          | RConstString _ ->
5390              pr "This function returns a string, or NULL on error.
5391 The string is owned by the guest handle and must I<not> be freed.\n\n"
5392          | RConstOptString _ ->
5393              pr "This function returns a string which may be NULL.
5394 There is way to return an error from this function.
5395 The string is owned by the guest handle and must I<not> be freed.\n\n"
5396          | RString _ ->
5397              pr "This function returns a string, or NULL on error.
5398 I<The caller must free the returned string after use>.\n\n"
5399          | RStringList _ ->
5400              pr "This function returns a NULL-terminated array of strings
5401 (like L<environ(3)>), or NULL if there was an error.
5402 I<The caller must free the strings and the array after use>.\n\n"
5403          | RStruct (_, typ) ->
5404              pr "This function returns a C<struct guestfs_%s *>,
5405 or NULL if there was an error.
5406 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5407          | RStructList (_, typ) ->
5408              pr "This function returns a C<struct guestfs_%s_list *>
5409 (see E<lt>guestfs-structs.hE<gt>),
5410 or NULL if there was an error.
5411 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5412          | RHashtable _ ->
5413              pr "This function returns a NULL-terminated array of
5414 strings, or NULL if there was an error.
5415 The array of strings will always have length C<2n+1>, where
5416 C<n> keys and values alternate, followed by the trailing NULL entry.
5417 I<The caller must free the strings and the array after use>.\n\n"
5418          | RBufferOut _ ->
5419              pr "This function returns a buffer, or NULL on error.
5420 The size of the returned buffer is written to C<*size_r>.
5421 I<The caller must free the returned buffer after use>.\n\n"
5422         );
5423         if List.mem ProtocolLimitWarning flags then
5424           pr "%s\n\n" protocol_limit_warning;
5425         if List.mem DangerWillRobinson flags then
5426           pr "%s\n\n" danger_will_robinson;
5427         match deprecation_notice flags with
5428         | None -> ()
5429         | Some txt -> pr "%s\n\n" txt
5430       )
5431   ) all_functions_sorted
5432
5433 and generate_structs_pod () =
5434   (* Structs documentation. *)
5435   List.iter (
5436     fun (typ, cols) ->
5437       pr "=head2 guestfs_%s\n" typ;
5438       pr "\n";
5439       pr " struct guestfs_%s {\n" typ;
5440       List.iter (
5441         function
5442         | name, FChar -> pr "   char %s;\n" name
5443         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5444         | name, FInt32 -> pr "   int32_t %s;\n" name
5445         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5446         | name, FInt64 -> pr "   int64_t %s;\n" name
5447         | name, FString -> pr "   char *%s;\n" name
5448         | name, FBuffer ->
5449             pr "   /* The next two fields describe a byte array. */\n";
5450             pr "   uint32_t %s_len;\n" name;
5451             pr "   char *%s;\n" name
5452         | name, FUUID ->
5453             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5454             pr "   char %s[32];\n" name
5455         | name, FOptPercent ->
5456             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5457             pr "   float %s;\n" name
5458       ) cols;
5459       pr " };\n";
5460       pr " \n";
5461       pr " struct guestfs_%s_list {\n" typ;
5462       pr "   uint32_t len; /* Number of elements in list. */\n";
5463       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5464       pr " };\n";
5465       pr " \n";
5466       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5467       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5468         typ typ;
5469       pr "\n"
5470   ) structs
5471
5472 and generate_availability_pod () =
5473   (* Availability documentation. *)
5474   pr "=over 4\n";
5475   pr "\n";
5476   List.iter (
5477     fun (group, functions) ->
5478       pr "=item B<%s>\n" group;
5479       pr "\n";
5480       pr "The following functions:\n";
5481       List.iter (pr "L</guestfs_%s>\n") functions;
5482       pr "\n"
5483   ) optgroups;
5484   pr "=back\n";
5485   pr "\n"
5486
5487 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5488  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5489  *
5490  * We have to use an underscore instead of a dash because otherwise
5491  * rpcgen generates incorrect code.
5492  *
5493  * This header is NOT exported to clients, but see also generate_structs_h.
5494  *)
5495 and generate_xdr () =
5496   generate_header CStyle LGPLv2plus;
5497
5498   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5499   pr "typedef string str<>;\n";
5500   pr "\n";
5501
5502   (* Internal structures. *)
5503   List.iter (
5504     function
5505     | typ, cols ->
5506         pr "struct guestfs_int_%s {\n" typ;
5507         List.iter (function
5508                    | name, FChar -> pr "  char %s;\n" name
5509                    | name, FString -> pr "  string %s<>;\n" name
5510                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5511                    | name, FUUID -> pr "  opaque %s[32];\n" name
5512                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5513                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5514                    | name, FOptPercent -> pr "  float %s;\n" name
5515                   ) cols;
5516         pr "};\n";
5517         pr "\n";
5518         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5519         pr "\n";
5520   ) structs;
5521
5522   List.iter (
5523     fun (shortname, style, _, _, _, _, _) ->
5524       let name = "guestfs_" ^ shortname in
5525
5526       (match snd style with
5527        | [] -> ()
5528        | args ->
5529            pr "struct %s_args {\n" name;
5530            List.iter (
5531              function
5532              | Pathname n | Device n | Dev_or_Path n | String n ->
5533                  pr "  string %s<>;\n" n
5534              | OptString n -> pr "  str *%s;\n" n
5535              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5536              | Bool n -> pr "  bool %s;\n" n
5537              | Int n -> pr "  int %s;\n" n
5538              | Int64 n -> pr "  hyper %s;\n" n
5539              | FileIn _ | FileOut _ -> ()
5540            ) args;
5541            pr "};\n\n"
5542       );
5543       (match fst style with
5544        | RErr -> ()
5545        | RInt n ->
5546            pr "struct %s_ret {\n" name;
5547            pr "  int %s;\n" n;
5548            pr "};\n\n"
5549        | RInt64 n ->
5550            pr "struct %s_ret {\n" name;
5551            pr "  hyper %s;\n" n;
5552            pr "};\n\n"
5553        | RBool n ->
5554            pr "struct %s_ret {\n" name;
5555            pr "  bool %s;\n" n;
5556            pr "};\n\n"
5557        | RConstString _ | RConstOptString _ ->
5558            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5559        | RString n ->
5560            pr "struct %s_ret {\n" name;
5561            pr "  string %s<>;\n" n;
5562            pr "};\n\n"
5563        | RStringList n ->
5564            pr "struct %s_ret {\n" name;
5565            pr "  str %s<>;\n" n;
5566            pr "};\n\n"
5567        | RStruct (n, typ) ->
5568            pr "struct %s_ret {\n" name;
5569            pr "  guestfs_int_%s %s;\n" typ n;
5570            pr "};\n\n"
5571        | RStructList (n, typ) ->
5572            pr "struct %s_ret {\n" name;
5573            pr "  guestfs_int_%s_list %s;\n" typ n;
5574            pr "};\n\n"
5575        | RHashtable n ->
5576            pr "struct %s_ret {\n" name;
5577            pr "  str %s<>;\n" n;
5578            pr "};\n\n"
5579        | RBufferOut n ->
5580            pr "struct %s_ret {\n" name;
5581            pr "  opaque %s<>;\n" n;
5582            pr "};\n\n"
5583       );
5584   ) daemon_functions;
5585
5586   (* Table of procedure numbers. *)
5587   pr "enum guestfs_procedure {\n";
5588   List.iter (
5589     fun (shortname, _, proc_nr, _, _, _, _) ->
5590       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5591   ) daemon_functions;
5592   pr "  GUESTFS_PROC_NR_PROCS\n";
5593   pr "};\n";
5594   pr "\n";
5595
5596   (* Having to choose a maximum message size is annoying for several
5597    * reasons (it limits what we can do in the API), but it (a) makes
5598    * the protocol a lot simpler, and (b) provides a bound on the size
5599    * of the daemon which operates in limited memory space.
5600    *)
5601   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5602   pr "\n";
5603
5604   (* Message header, etc. *)
5605   pr "\
5606 /* The communication protocol is now documented in the guestfs(3)
5607  * manpage.
5608  */
5609
5610 const GUESTFS_PROGRAM = 0x2000F5F5;
5611 const GUESTFS_PROTOCOL_VERSION = 1;
5612
5613 /* These constants must be larger than any possible message length. */
5614 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5615 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5616
5617 enum guestfs_message_direction {
5618   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5619   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5620 };
5621
5622 enum guestfs_message_status {
5623   GUESTFS_STATUS_OK = 0,
5624   GUESTFS_STATUS_ERROR = 1
5625 };
5626
5627 const GUESTFS_ERROR_LEN = 256;
5628
5629 struct guestfs_message_error {
5630   string error_message<GUESTFS_ERROR_LEN>;
5631 };
5632
5633 struct guestfs_message_header {
5634   unsigned prog;                     /* GUESTFS_PROGRAM */
5635   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5636   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5637   guestfs_message_direction direction;
5638   unsigned serial;                   /* message serial number */
5639   guestfs_message_status status;
5640 };
5641
5642 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5643
5644 struct guestfs_chunk {
5645   int cancel;                        /* if non-zero, transfer is cancelled */
5646   /* data size is 0 bytes if the transfer has finished successfully */
5647   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5648 };
5649 "
5650
5651 (* Generate the guestfs-structs.h file. *)
5652 and generate_structs_h () =
5653   generate_header CStyle LGPLv2plus;
5654
5655   (* This is a public exported header file containing various
5656    * structures.  The structures are carefully written to have
5657    * exactly the same in-memory format as the XDR structures that
5658    * we use on the wire to the daemon.  The reason for creating
5659    * copies of these structures here is just so we don't have to
5660    * export the whole of guestfs_protocol.h (which includes much
5661    * unrelated and XDR-dependent stuff that we don't want to be
5662    * public, or required by clients).
5663    *
5664    * To reiterate, we will pass these structures to and from the
5665    * client with a simple assignment or memcpy, so the format
5666    * must be identical to what rpcgen / the RFC defines.
5667    *)
5668
5669   (* Public structures. *)
5670   List.iter (
5671     fun (typ, cols) ->
5672       pr "struct guestfs_%s {\n" typ;
5673       List.iter (
5674         function
5675         | name, FChar -> pr "  char %s;\n" name
5676         | name, FString -> pr "  char *%s;\n" name
5677         | name, FBuffer ->
5678             pr "  uint32_t %s_len;\n" name;
5679             pr "  char *%s;\n" name
5680         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5681         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5682         | name, FInt32 -> pr "  int32_t %s;\n" name
5683         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5684         | name, FInt64 -> pr "  int64_t %s;\n" name
5685         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5686       ) cols;
5687       pr "};\n";
5688       pr "\n";
5689       pr "struct guestfs_%s_list {\n" typ;
5690       pr "  uint32_t len;\n";
5691       pr "  struct guestfs_%s *val;\n" typ;
5692       pr "};\n";
5693       pr "\n";
5694       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5695       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5696       pr "\n"
5697   ) structs
5698
5699 (* Generate the guestfs-actions.h file. *)
5700 and generate_actions_h () =
5701   generate_header CStyle LGPLv2plus;
5702   List.iter (
5703     fun (shortname, style, _, _, _, _, _) ->
5704       let name = "guestfs_" ^ shortname in
5705       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5706         name style
5707   ) all_functions
5708
5709 (* Generate the guestfs-internal-actions.h file. *)
5710 and generate_internal_actions_h () =
5711   generate_header CStyle LGPLv2plus;
5712   List.iter (
5713     fun (shortname, style, _, _, _, _, _) ->
5714       let name = "guestfs__" ^ shortname in
5715       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5716         name style
5717   ) non_daemon_functions
5718
5719 (* Generate the client-side dispatch stubs. *)
5720 and generate_client_actions () =
5721   generate_header CStyle LGPLv2plus;
5722
5723   pr "\
5724 #include <stdio.h>
5725 #include <stdlib.h>
5726 #include <stdint.h>
5727 #include <string.h>
5728 #include <inttypes.h>
5729
5730 #include \"guestfs.h\"
5731 #include \"guestfs-internal.h\"
5732 #include \"guestfs-internal-actions.h\"
5733 #include \"guestfs_protocol.h\"
5734
5735 #define error guestfs_error
5736 //#define perrorf guestfs_perrorf
5737 #define safe_malloc guestfs_safe_malloc
5738 #define safe_realloc guestfs_safe_realloc
5739 //#define safe_strdup guestfs_safe_strdup
5740 #define safe_memdup guestfs_safe_memdup
5741
5742 /* Check the return message from a call for validity. */
5743 static int
5744 check_reply_header (guestfs_h *g,
5745                     const struct guestfs_message_header *hdr,
5746                     unsigned int proc_nr, unsigned int serial)
5747 {
5748   if (hdr->prog != GUESTFS_PROGRAM) {
5749     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5750     return -1;
5751   }
5752   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5753     error (g, \"wrong protocol version (%%d/%%d)\",
5754            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5755     return -1;
5756   }
5757   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5758     error (g, \"unexpected message direction (%%d/%%d)\",
5759            hdr->direction, GUESTFS_DIRECTION_REPLY);
5760     return -1;
5761   }
5762   if (hdr->proc != proc_nr) {
5763     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5764     return -1;
5765   }
5766   if (hdr->serial != serial) {
5767     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5768     return -1;
5769   }
5770
5771   return 0;
5772 }
5773
5774 /* Check we are in the right state to run a high-level action. */
5775 static int
5776 check_state (guestfs_h *g, const char *caller)
5777 {
5778   if (!guestfs__is_ready (g)) {
5779     if (guestfs__is_config (g) || guestfs__is_launching (g))
5780       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5781         caller);
5782     else
5783       error (g, \"%%s called from the wrong state, %%d != READY\",
5784         caller, guestfs__get_state (g));
5785     return -1;
5786   }
5787   return 0;
5788 }
5789
5790 ";
5791
5792   (* Generate code to generate guestfish call traces. *)
5793   let trace_call shortname style =
5794     pr "  if (guestfs__get_trace (g)) {\n";
5795
5796     let needs_i =
5797       List.exists (function
5798                    | StringList _ | DeviceList _ -> true
5799                    | _ -> false) (snd style) in
5800     if needs_i then (
5801       pr "    int i;\n";
5802       pr "\n"
5803     );
5804
5805     pr "    printf (\"%s\");\n" shortname;
5806     List.iter (
5807       function
5808       | String n                        (* strings *)
5809       | Device n
5810       | Pathname n
5811       | Dev_or_Path n
5812       | FileIn n
5813       | FileOut n ->
5814           (* guestfish doesn't support string escaping, so neither do we *)
5815           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5816       | OptString n ->                  (* string option *)
5817           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5818           pr "    else printf (\" null\");\n"
5819       | StringList n
5820       | DeviceList n ->                 (* string list *)
5821           pr "    putchar (' ');\n";
5822           pr "    putchar ('\"');\n";
5823           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5824           pr "      if (i > 0) putchar (' ');\n";
5825           pr "      fputs (%s[i], stdout);\n" n;
5826           pr "    }\n";
5827           pr "    putchar ('\"');\n";
5828       | Bool n ->                       (* boolean *)
5829           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5830       | Int n ->                        (* int *)
5831           pr "    printf (\" %%d\", %s);\n" n
5832       | Int64 n ->
5833           pr "    printf (\" %%\" PRIi64, %s);\n" n
5834     ) (snd style);
5835     pr "    putchar ('\\n');\n";
5836     pr "  }\n";
5837     pr "\n";
5838   in
5839
5840   (* For non-daemon functions, generate a wrapper around each function. *)
5841   List.iter (
5842     fun (shortname, style, _, _, _, _, _) ->
5843       let name = "guestfs_" ^ shortname in
5844
5845       generate_prototype ~extern:false ~semicolon:false ~newline:true
5846         ~handle:"g" name style;
5847       pr "{\n";
5848       trace_call shortname style;
5849       pr "  return guestfs__%s " shortname;
5850       generate_c_call_args ~handle:"g" style;
5851       pr ";\n";
5852       pr "}\n";
5853       pr "\n"
5854   ) non_daemon_functions;
5855
5856   (* Client-side stubs for each function. *)
5857   List.iter (
5858     fun (shortname, style, _, _, _, _, _) ->
5859       let name = "guestfs_" ^ shortname in
5860
5861       (* Generate the action stub. *)
5862       generate_prototype ~extern:false ~semicolon:false ~newline:true
5863         ~handle:"g" name style;
5864
5865       let error_code =
5866         match fst style with
5867         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5868         | RConstString _ | RConstOptString _ ->
5869             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5870         | RString _ | RStringList _
5871         | RStruct _ | RStructList _
5872         | RHashtable _ | RBufferOut _ ->
5873             "NULL" in
5874
5875       pr "{\n";
5876
5877       (match snd style with
5878        | [] -> ()
5879        | _ -> pr "  struct %s_args args;\n" name
5880       );
5881
5882       pr "  guestfs_message_header hdr;\n";
5883       pr "  guestfs_message_error err;\n";
5884       let has_ret =
5885         match fst style with
5886         | RErr -> false
5887         | RConstString _ | RConstOptString _ ->
5888             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5889         | RInt _ | RInt64 _
5890         | RBool _ | RString _ | RStringList _
5891         | RStruct _ | RStructList _
5892         | RHashtable _ | RBufferOut _ ->
5893             pr "  struct %s_ret ret;\n" name;
5894             true in
5895
5896       pr "  int serial;\n";
5897       pr "  int r;\n";
5898       pr "\n";
5899       trace_call shortname style;
5900       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5901         shortname error_code;
5902       pr "  guestfs___set_busy (g);\n";
5903       pr "\n";
5904
5905       (* Send the main header and arguments. *)
5906       (match snd style with
5907        | [] ->
5908            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5909              (String.uppercase shortname)
5910        | args ->
5911            List.iter (
5912              function
5913              | Pathname n | Device n | Dev_or_Path n | String n ->
5914                  pr "  args.%s = (char *) %s;\n" n n
5915              | OptString n ->
5916                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5917              | StringList n | DeviceList n ->
5918                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5919                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5920              | Bool n ->
5921                  pr "  args.%s = %s;\n" n n
5922              | Int n ->
5923                  pr "  args.%s = %s;\n" n n
5924              | Int64 n ->
5925                  pr "  args.%s = %s;\n" n n
5926              | FileIn _ | FileOut _ -> ()
5927            ) args;
5928            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5929              (String.uppercase shortname);
5930            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5931              name;
5932       );
5933       pr "  if (serial == -1) {\n";
5934       pr "    guestfs___end_busy (g);\n";
5935       pr "    return %s;\n" error_code;
5936       pr "  }\n";
5937       pr "\n";
5938
5939       (* Send any additional files (FileIn) requested. *)
5940       let need_read_reply_label = ref false in
5941       List.iter (
5942         function
5943         | FileIn n ->
5944             pr "  r = guestfs___send_file (g, %s);\n" n;
5945             pr "  if (r == -1) {\n";
5946             pr "    guestfs___end_busy (g);\n";
5947             pr "    return %s;\n" error_code;
5948             pr "  }\n";
5949             pr "  if (r == -2) /* daemon cancelled */\n";
5950             pr "    goto read_reply;\n";
5951             need_read_reply_label := true;
5952             pr "\n";
5953         | _ -> ()
5954       ) (snd style);
5955
5956       (* Wait for the reply from the remote end. *)
5957       if !need_read_reply_label then pr " read_reply:\n";
5958       pr "  memset (&hdr, 0, sizeof hdr);\n";
5959       pr "  memset (&err, 0, sizeof err);\n";
5960       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5961       pr "\n";
5962       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5963       if not has_ret then
5964         pr "NULL, NULL"
5965       else
5966         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5967       pr ");\n";
5968
5969       pr "  if (r == -1) {\n";
5970       pr "    guestfs___end_busy (g);\n";
5971       pr "    return %s;\n" error_code;
5972       pr "  }\n";
5973       pr "\n";
5974
5975       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5976         (String.uppercase shortname);
5977       pr "    guestfs___end_busy (g);\n";
5978       pr "    return %s;\n" error_code;
5979       pr "  }\n";
5980       pr "\n";
5981
5982       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5983       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5984       pr "    free (err.error_message);\n";
5985       pr "    guestfs___end_busy (g);\n";
5986       pr "    return %s;\n" error_code;
5987       pr "  }\n";
5988       pr "\n";
5989
5990       (* Expecting to receive further files (FileOut)? *)
5991       List.iter (
5992         function
5993         | FileOut n ->
5994             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5995             pr "    guestfs___end_busy (g);\n";
5996             pr "    return %s;\n" error_code;
5997             pr "  }\n";
5998             pr "\n";
5999         | _ -> ()
6000       ) (snd style);
6001
6002       pr "  guestfs___end_busy (g);\n";
6003
6004       (match fst style with
6005        | RErr -> pr "  return 0;\n"
6006        | RInt n | RInt64 n | RBool n ->
6007            pr "  return ret.%s;\n" n
6008        | RConstString _ | RConstOptString _ ->
6009            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6010        | RString n ->
6011            pr "  return ret.%s; /* caller will free */\n" n
6012        | RStringList n | RHashtable n ->
6013            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6014            pr "  ret.%s.%s_val =\n" n n;
6015            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6016            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6017              n n;
6018            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6019            pr "  return ret.%s.%s_val;\n" n n
6020        | RStruct (n, _) ->
6021            pr "  /* caller will free this */\n";
6022            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6023        | RStructList (n, _) ->
6024            pr "  /* caller will free this */\n";
6025            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6026        | RBufferOut n ->
6027            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6028            pr "   * _val might be NULL here.  To make the API saner for\n";
6029            pr "   * callers, we turn this case into a unique pointer (using\n";
6030            pr "   * malloc(1)).\n";
6031            pr "   */\n";
6032            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6033            pr "    *size_r = ret.%s.%s_len;\n" n n;
6034            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6035            pr "  } else {\n";
6036            pr "    free (ret.%s.%s_val);\n" n n;
6037            pr "    char *p = safe_malloc (g, 1);\n";
6038            pr "    *size_r = ret.%s.%s_len;\n" n n;
6039            pr "    return p;\n";
6040            pr "  }\n";
6041       );
6042
6043       pr "}\n\n"
6044   ) daemon_functions;
6045
6046   (* Functions to free structures. *)
6047   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6048   pr " * structure format is identical to the XDR format.  See note in\n";
6049   pr " * generator.ml.\n";
6050   pr " */\n";
6051   pr "\n";
6052
6053   List.iter (
6054     fun (typ, _) ->
6055       pr "void\n";
6056       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6057       pr "{\n";
6058       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6059       pr "  free (x);\n";
6060       pr "}\n";
6061       pr "\n";
6062
6063       pr "void\n";
6064       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6065       pr "{\n";
6066       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6067       pr "  free (x);\n";
6068       pr "}\n";
6069       pr "\n";
6070
6071   ) structs;
6072
6073 (* Generate daemon/actions.h. *)
6074 and generate_daemon_actions_h () =
6075   generate_header CStyle GPLv2plus;
6076
6077   pr "#include \"../src/guestfs_protocol.h\"\n";
6078   pr "\n";
6079
6080   List.iter (
6081     fun (name, style, _, _, _, _, _) ->
6082       generate_prototype
6083         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6084         name style;
6085   ) daemon_functions
6086
6087 (* Generate the linker script which controls the visibility of
6088  * symbols in the public ABI and ensures no other symbols get
6089  * exported accidentally.
6090  *)
6091 and generate_linker_script () =
6092   generate_header HashStyle GPLv2plus;
6093
6094   let globals = [
6095     "guestfs_create";
6096     "guestfs_close";
6097     "guestfs_get_error_handler";
6098     "guestfs_get_out_of_memory_handler";
6099     "guestfs_last_error";
6100     "guestfs_set_error_handler";
6101     "guestfs_set_launch_done_callback";
6102     "guestfs_set_log_message_callback";
6103     "guestfs_set_out_of_memory_handler";
6104     "guestfs_set_subprocess_quit_callback";
6105
6106     (* Unofficial parts of the API: the bindings code use these
6107      * functions, so it is useful to export them.
6108      *)
6109     "guestfs_safe_calloc";
6110     "guestfs_safe_malloc";
6111   ] in
6112   let functions =
6113     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6114       all_functions in
6115   let structs =
6116     List.concat (
6117       List.map (fun (typ, _) ->
6118                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6119         structs
6120     ) in
6121   let globals = List.sort compare (globals @ functions @ structs) in
6122
6123   pr "{\n";
6124   pr "    global:\n";
6125   List.iter (pr "        %s;\n") globals;
6126   pr "\n";
6127
6128   pr "    local:\n";
6129   pr "        *;\n";
6130   pr "};\n"
6131
6132 (* Generate the server-side stubs. *)
6133 and generate_daemon_actions () =
6134   generate_header CStyle GPLv2plus;
6135
6136   pr "#include <config.h>\n";
6137   pr "\n";
6138   pr "#include <stdio.h>\n";
6139   pr "#include <stdlib.h>\n";
6140   pr "#include <string.h>\n";
6141   pr "#include <inttypes.h>\n";
6142   pr "#include <rpc/types.h>\n";
6143   pr "#include <rpc/xdr.h>\n";
6144   pr "\n";
6145   pr "#include \"daemon.h\"\n";
6146   pr "#include \"c-ctype.h\"\n";
6147   pr "#include \"../src/guestfs_protocol.h\"\n";
6148   pr "#include \"actions.h\"\n";
6149   pr "\n";
6150
6151   List.iter (
6152     fun (name, style, _, _, _, _, _) ->
6153       (* Generate server-side stubs. *)
6154       pr "static void %s_stub (XDR *xdr_in)\n" name;
6155       pr "{\n";
6156       let error_code =
6157         match fst style with
6158         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6159         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6160         | RBool _ -> pr "  int r;\n"; "-1"
6161         | RConstString _ | RConstOptString _ ->
6162             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6163         | RString _ -> pr "  char *r;\n"; "NULL"
6164         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6165         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6166         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6167         | RBufferOut _ ->
6168             pr "  size_t size = 1;\n";
6169             pr "  char *r;\n";
6170             "NULL" in
6171
6172       (match snd style with
6173        | [] -> ()
6174        | args ->
6175            pr "  struct guestfs_%s_args args;\n" name;
6176            List.iter (
6177              function
6178              | Device n | Dev_or_Path n
6179              | Pathname n
6180              | String n -> ()
6181              | OptString n -> pr "  char *%s;\n" n
6182              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6183              | Bool n -> pr "  int %s;\n" n
6184              | Int n -> pr "  int %s;\n" n
6185              | Int64 n -> pr "  int64_t %s;\n" n
6186              | FileIn _ | FileOut _ -> ()
6187            ) args
6188       );
6189       pr "\n";
6190
6191       let is_filein =
6192         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6193
6194       (match snd style with
6195        | [] -> ()
6196        | args ->
6197            pr "  memset (&args, 0, sizeof args);\n";
6198            pr "\n";
6199            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6200            if is_filein then
6201              pr "    if (cancel_receive () != -2)\n";
6202            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6203            pr "    goto done;\n";
6204            pr "  }\n";
6205            let pr_args n =
6206              pr "  char *%s = args.%s;\n" n n
6207            in
6208            let pr_list_handling_code n =
6209              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6210              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6211              pr "  if (%s == NULL) {\n" n;
6212              if is_filein then
6213                pr "    if (cancel_receive () != -2)\n";
6214              pr "      reply_with_perror (\"realloc\");\n";
6215              pr "    goto done;\n";
6216              pr "  }\n";
6217              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6218              pr "  args.%s.%s_val = %s;\n" n n n;
6219            in
6220            List.iter (
6221              function
6222              | Pathname n ->
6223                  pr_args n;
6224                  pr "  ABS_PATH (%s, %s, goto done);\n"
6225                    n (if is_filein then "cancel_receive ()" else "0");
6226              | Device n ->
6227                  pr_args n;
6228                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6229                    n (if is_filein then "cancel_receive ()" else "0");
6230              | Dev_or_Path n ->
6231                  pr_args n;
6232                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6233                    n (if is_filein then "cancel_receive ()" else "0");
6234              | String n -> pr_args n
6235              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6236              | StringList n ->
6237                  pr_list_handling_code n;
6238              | DeviceList n ->
6239                  pr_list_handling_code n;
6240                  pr "  /* Ensure that each is a device,\n";
6241                  pr "   * and perform device name translation. */\n";
6242                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6243                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6244                    (if is_filein then "cancel_receive ()" else "0");
6245                  pr "  }\n";
6246              | Bool n -> pr "  %s = args.%s;\n" n n
6247              | Int n -> pr "  %s = args.%s;\n" n n
6248              | Int64 n -> pr "  %s = args.%s;\n" n n
6249              | FileIn _ | FileOut _ -> ()
6250            ) args;
6251            pr "\n"
6252       );
6253
6254
6255       (* this is used at least for do_equal *)
6256       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6257         (* Emit NEED_ROOT just once, even when there are two or
6258            more Pathname args *)
6259         pr "  NEED_ROOT (%s, goto done);\n"
6260           (if is_filein then "cancel_receive ()" else "0");
6261       );
6262
6263       (* Don't want to call the impl with any FileIn or FileOut
6264        * parameters, since these go "outside" the RPC protocol.
6265        *)
6266       let args' =
6267         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6268           (snd style) in
6269       pr "  r = do_%s " name;
6270       generate_c_call_args (fst style, args');
6271       pr ";\n";
6272
6273       (match fst style with
6274        | RErr | RInt _ | RInt64 _ | RBool _
6275        | RConstString _ | RConstOptString _
6276        | RString _ | RStringList _ | RHashtable _
6277        | RStruct (_, _) | RStructList (_, _) ->
6278            pr "  if (r == %s)\n" error_code;
6279            pr "    /* do_%s has already called reply_with_error */\n" name;
6280            pr "    goto done;\n";
6281            pr "\n"
6282        | RBufferOut _ ->
6283            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6284            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6285            pr "   */\n";
6286            pr "  if (size == 1 && r == %s)\n" error_code;
6287            pr "    /* do_%s has already called reply_with_error */\n" name;
6288            pr "    goto done;\n";
6289            pr "\n"
6290       );
6291
6292       (* If there are any FileOut parameters, then the impl must
6293        * send its own reply.
6294        *)
6295       let no_reply =
6296         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6297       if no_reply then
6298         pr "  /* do_%s has already sent a reply */\n" name
6299       else (
6300         match fst style with
6301         | RErr -> pr "  reply (NULL, NULL);\n"
6302         | RInt n | RInt64 n | RBool n ->
6303             pr "  struct guestfs_%s_ret ret;\n" name;
6304             pr "  ret.%s = r;\n" n;
6305             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6306               name
6307         | RConstString _ | RConstOptString _ ->
6308             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6309         | RString n ->
6310             pr "  struct guestfs_%s_ret ret;\n" name;
6311             pr "  ret.%s = r;\n" n;
6312             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6313               name;
6314             pr "  free (r);\n"
6315         | RStringList n | RHashtable n ->
6316             pr "  struct guestfs_%s_ret ret;\n" name;
6317             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6318             pr "  ret.%s.%s_val = r;\n" n n;
6319             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6320               name;
6321             pr "  free_strings (r);\n"
6322         | RStruct (n, _) ->
6323             pr "  struct guestfs_%s_ret ret;\n" name;
6324             pr "  ret.%s = *r;\n" n;
6325             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6326               name;
6327             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6328               name
6329         | RStructList (n, _) ->
6330             pr "  struct guestfs_%s_ret ret;\n" name;
6331             pr "  ret.%s = *r;\n" n;
6332             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6333               name;
6334             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6335               name
6336         | RBufferOut n ->
6337             pr "  struct guestfs_%s_ret ret;\n" name;
6338             pr "  ret.%s.%s_val = r;\n" n n;
6339             pr "  ret.%s.%s_len = size;\n" n n;
6340             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6341               name;
6342             pr "  free (r);\n"
6343       );
6344
6345       (* Free the args. *)
6346       pr "done:\n";
6347       (match snd style with
6348        | [] -> ()
6349        | _ ->
6350            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6351              name
6352       );
6353       pr "  return;\n";
6354       pr "}\n\n";
6355   ) daemon_functions;
6356
6357   (* Dispatch function. *)
6358   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6359   pr "{\n";
6360   pr "  switch (proc_nr) {\n";
6361
6362   List.iter (
6363     fun (name, style, _, _, _, _, _) ->
6364       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6365       pr "      %s_stub (xdr_in);\n" name;
6366       pr "      break;\n"
6367   ) daemon_functions;
6368
6369   pr "    default:\n";
6370   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";
6371   pr "  }\n";
6372   pr "}\n";
6373   pr "\n";
6374
6375   (* LVM columns and tokenization functions. *)
6376   (* XXX This generates crap code.  We should rethink how we
6377    * do this parsing.
6378    *)
6379   List.iter (
6380     function
6381     | typ, cols ->
6382         pr "static const char *lvm_%s_cols = \"%s\";\n"
6383           typ (String.concat "," (List.map fst cols));
6384         pr "\n";
6385
6386         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6387         pr "{\n";
6388         pr "  char *tok, *p, *next;\n";
6389         pr "  int i, j;\n";
6390         pr "\n";
6391         (*
6392           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6393           pr "\n";
6394         *)
6395         pr "  if (!str) {\n";
6396         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6397         pr "    return -1;\n";
6398         pr "  }\n";
6399         pr "  if (!*str || c_isspace (*str)) {\n";
6400         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6401         pr "    return -1;\n";
6402         pr "  }\n";
6403         pr "  tok = str;\n";
6404         List.iter (
6405           fun (name, coltype) ->
6406             pr "  if (!tok) {\n";
6407             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6408             pr "    return -1;\n";
6409             pr "  }\n";
6410             pr "  p = strchrnul (tok, ',');\n";
6411             pr "  if (*p) next = p+1; else next = NULL;\n";
6412             pr "  *p = '\\0';\n";
6413             (match coltype with
6414              | FString ->
6415                  pr "  r->%s = strdup (tok);\n" name;
6416                  pr "  if (r->%s == NULL) {\n" name;
6417                  pr "    perror (\"strdup\");\n";
6418                  pr "    return -1;\n";
6419                  pr "  }\n"
6420              | FUUID ->
6421                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6422                  pr "    if (tok[j] == '\\0') {\n";
6423                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6424                  pr "      return -1;\n";
6425                  pr "    } else if (tok[j] != '-')\n";
6426                  pr "      r->%s[i++] = tok[j];\n" name;
6427                  pr "  }\n";
6428              | FBytes ->
6429                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6430                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6431                  pr "    return -1;\n";
6432                  pr "  }\n";
6433              | FInt64 ->
6434                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6435                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6436                  pr "    return -1;\n";
6437                  pr "  }\n";
6438              | FOptPercent ->
6439                  pr "  if (tok[0] == '\\0')\n";
6440                  pr "    r->%s = -1;\n" name;
6441                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6442                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6443                  pr "    return -1;\n";
6444                  pr "  }\n";
6445              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6446                  assert false (* can never be an LVM column *)
6447             );
6448             pr "  tok = next;\n";
6449         ) cols;
6450
6451         pr "  if (tok != NULL) {\n";
6452         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6453         pr "    return -1;\n";
6454         pr "  }\n";
6455         pr "  return 0;\n";
6456         pr "}\n";
6457         pr "\n";
6458
6459         pr "guestfs_int_lvm_%s_list *\n" typ;
6460         pr "parse_command_line_%ss (void)\n" typ;
6461         pr "{\n";
6462         pr "  char *out, *err;\n";
6463         pr "  char *p, *pend;\n";
6464         pr "  int r, i;\n";
6465         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6466         pr "  void *newp;\n";
6467         pr "\n";
6468         pr "  ret = malloc (sizeof *ret);\n";
6469         pr "  if (!ret) {\n";
6470         pr "    reply_with_perror (\"malloc\");\n";
6471         pr "    return NULL;\n";
6472         pr "  }\n";
6473         pr "\n";
6474         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6475         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6476         pr "\n";
6477         pr "  r = command (&out, &err,\n";
6478         pr "           \"lvm\", \"%ss\",\n" typ;
6479         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6480         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6481         pr "  if (r == -1) {\n";
6482         pr "    reply_with_error (\"%%s\", err);\n";
6483         pr "    free (out);\n";
6484         pr "    free (err);\n";
6485         pr "    free (ret);\n";
6486         pr "    return NULL;\n";
6487         pr "  }\n";
6488         pr "\n";
6489         pr "  free (err);\n";
6490         pr "\n";
6491         pr "  /* Tokenize each line of the output. */\n";
6492         pr "  p = out;\n";
6493         pr "  i = 0;\n";
6494         pr "  while (p) {\n";
6495         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6496         pr "    if (pend) {\n";
6497         pr "      *pend = '\\0';\n";
6498         pr "      pend++;\n";
6499         pr "    }\n";
6500         pr "\n";
6501         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6502         pr "      p++;\n";
6503         pr "\n";
6504         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6505         pr "      p = pend;\n";
6506         pr "      continue;\n";
6507         pr "    }\n";
6508         pr "\n";
6509         pr "    /* Allocate some space to store this next entry. */\n";
6510         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6511         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6512         pr "    if (newp == NULL) {\n";
6513         pr "      reply_with_perror (\"realloc\");\n";
6514         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6515         pr "      free (ret);\n";
6516         pr "      free (out);\n";
6517         pr "      return NULL;\n";
6518         pr "    }\n";
6519         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6520         pr "\n";
6521         pr "    /* Tokenize the next entry. */\n";
6522         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6523         pr "    if (r == -1) {\n";
6524         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6525         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6526         pr "      free (ret);\n";
6527         pr "      free (out);\n";
6528         pr "      return NULL;\n";
6529         pr "    }\n";
6530         pr "\n";
6531         pr "    ++i;\n";
6532         pr "    p = pend;\n";
6533         pr "  }\n";
6534         pr "\n";
6535         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6536         pr "\n";
6537         pr "  free (out);\n";
6538         pr "  return ret;\n";
6539         pr "}\n"
6540
6541   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6542
6543 (* Generate a list of function names, for debugging in the daemon.. *)
6544 and generate_daemon_names () =
6545   generate_header CStyle GPLv2plus;
6546
6547   pr "#include <config.h>\n";
6548   pr "\n";
6549   pr "#include \"daemon.h\"\n";
6550   pr "\n";
6551
6552   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6553   pr "const char *function_names[] = {\n";
6554   List.iter (
6555     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6556   ) daemon_functions;
6557   pr "};\n";
6558
6559 (* Generate the optional groups for the daemon to implement
6560  * guestfs_available.
6561  *)
6562 and generate_daemon_optgroups_c () =
6563   generate_header CStyle GPLv2plus;
6564
6565   pr "#include <config.h>\n";
6566   pr "\n";
6567   pr "#include \"daemon.h\"\n";
6568   pr "#include \"optgroups.h\"\n";
6569   pr "\n";
6570
6571   pr "struct optgroup optgroups[] = {\n";
6572   List.iter (
6573     fun (group, _) ->
6574       pr "  { \"%s\", optgroup_%s_available },\n" group group
6575   ) optgroups;
6576   pr "  { NULL, NULL }\n";
6577   pr "};\n"
6578
6579 and generate_daemon_optgroups_h () =
6580   generate_header CStyle GPLv2plus;
6581
6582   List.iter (
6583     fun (group, _) ->
6584       pr "extern int optgroup_%s_available (void);\n" group
6585   ) optgroups
6586
6587 (* Generate the tests. *)
6588 and generate_tests () =
6589   generate_header CStyle GPLv2plus;
6590
6591   pr "\
6592 #include <stdio.h>
6593 #include <stdlib.h>
6594 #include <string.h>
6595 #include <unistd.h>
6596 #include <sys/types.h>
6597 #include <fcntl.h>
6598
6599 #include \"guestfs.h\"
6600 #include \"guestfs-internal.h\"
6601
6602 static guestfs_h *g;
6603 static int suppress_error = 0;
6604
6605 static void print_error (guestfs_h *g, void *data, const char *msg)
6606 {
6607   if (!suppress_error)
6608     fprintf (stderr, \"%%s\\n\", msg);
6609 }
6610
6611 /* FIXME: nearly identical code appears in fish.c */
6612 static void print_strings (char *const *argv)
6613 {
6614   int argc;
6615
6616   for (argc = 0; argv[argc] != NULL; ++argc)
6617     printf (\"\\t%%s\\n\", argv[argc]);
6618 }
6619
6620 /*
6621 static void print_table (char const *const *argv)
6622 {
6623   int i;
6624
6625   for (i = 0; argv[i] != NULL; i += 2)
6626     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6627 }
6628 */
6629
6630 ";
6631
6632   (* Generate a list of commands which are not tested anywhere. *)
6633   pr "static void no_test_warnings (void)\n";
6634   pr "{\n";
6635
6636   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6637   List.iter (
6638     fun (_, _, _, _, tests, _, _) ->
6639       let tests = filter_map (
6640         function
6641         | (_, (Always|If _|Unless _), test) -> Some test
6642         | (_, Disabled, _) -> None
6643       ) tests in
6644       let seq = List.concat (List.map seq_of_test tests) in
6645       let cmds_tested = List.map List.hd seq in
6646       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6647   ) all_functions;
6648
6649   List.iter (
6650     fun (name, _, _, _, _, _, _) ->
6651       if not (Hashtbl.mem hash name) then
6652         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6653   ) all_functions;
6654
6655   pr "}\n";
6656   pr "\n";
6657
6658   (* Generate the actual tests.  Note that we generate the tests
6659    * in reverse order, deliberately, so that (in general) the
6660    * newest tests run first.  This makes it quicker and easier to
6661    * debug them.
6662    *)
6663   let test_names =
6664     List.map (
6665       fun (name, _, _, flags, tests, _, _) ->
6666         mapi (generate_one_test name flags) tests
6667     ) (List.rev all_functions) in
6668   let test_names = List.concat test_names in
6669   let nr_tests = List.length test_names in
6670
6671   pr "\
6672 int main (int argc, char *argv[])
6673 {
6674   char c = 0;
6675   unsigned long int n_failed = 0;
6676   const char *filename;
6677   int fd;
6678   int nr_tests, test_num = 0;
6679
6680   setbuf (stdout, NULL);
6681
6682   no_test_warnings ();
6683
6684   g = guestfs_create ();
6685   if (g == NULL) {
6686     printf (\"guestfs_create FAILED\\n\");
6687     exit (EXIT_FAILURE);
6688   }
6689
6690   guestfs_set_error_handler (g, print_error, NULL);
6691
6692   guestfs_set_path (g, \"../appliance\");
6693
6694   filename = \"test1.img\";
6695   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6696   if (fd == -1) {
6697     perror (filename);
6698     exit (EXIT_FAILURE);
6699   }
6700   if (lseek (fd, %d, SEEK_SET) == -1) {
6701     perror (\"lseek\");
6702     close (fd);
6703     unlink (filename);
6704     exit (EXIT_FAILURE);
6705   }
6706   if (write (fd, &c, 1) == -1) {
6707     perror (\"write\");
6708     close (fd);
6709     unlink (filename);
6710     exit (EXIT_FAILURE);
6711   }
6712   if (close (fd) == -1) {
6713     perror (filename);
6714     unlink (filename);
6715     exit (EXIT_FAILURE);
6716   }
6717   if (guestfs_add_drive (g, filename) == -1) {
6718     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6719     exit (EXIT_FAILURE);
6720   }
6721
6722   filename = \"test2.img\";
6723   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6724   if (fd == -1) {
6725     perror (filename);
6726     exit (EXIT_FAILURE);
6727   }
6728   if (lseek (fd, %d, SEEK_SET) == -1) {
6729     perror (\"lseek\");
6730     close (fd);
6731     unlink (filename);
6732     exit (EXIT_FAILURE);
6733   }
6734   if (write (fd, &c, 1) == -1) {
6735     perror (\"write\");
6736     close (fd);
6737     unlink (filename);
6738     exit (EXIT_FAILURE);
6739   }
6740   if (close (fd) == -1) {
6741     perror (filename);
6742     unlink (filename);
6743     exit (EXIT_FAILURE);
6744   }
6745   if (guestfs_add_drive (g, filename) == -1) {
6746     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6747     exit (EXIT_FAILURE);
6748   }
6749
6750   filename = \"test3.img\";
6751   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6752   if (fd == -1) {
6753     perror (filename);
6754     exit (EXIT_FAILURE);
6755   }
6756   if (lseek (fd, %d, SEEK_SET) == -1) {
6757     perror (\"lseek\");
6758     close (fd);
6759     unlink (filename);
6760     exit (EXIT_FAILURE);
6761   }
6762   if (write (fd, &c, 1) == -1) {
6763     perror (\"write\");
6764     close (fd);
6765     unlink (filename);
6766     exit (EXIT_FAILURE);
6767   }
6768   if (close (fd) == -1) {
6769     perror (filename);
6770     unlink (filename);
6771     exit (EXIT_FAILURE);
6772   }
6773   if (guestfs_add_drive (g, filename) == -1) {
6774     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6775     exit (EXIT_FAILURE);
6776   }
6777
6778   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6779     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6780     exit (EXIT_FAILURE);
6781   }
6782
6783   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6784   alarm (600);
6785
6786   if (guestfs_launch (g) == -1) {
6787     printf (\"guestfs_launch FAILED\\n\");
6788     exit (EXIT_FAILURE);
6789   }
6790
6791   /* Cancel previous alarm. */
6792   alarm (0);
6793
6794   nr_tests = %d;
6795
6796 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6797
6798   iteri (
6799     fun i test_name ->
6800       pr "  test_num++;\n";
6801       pr "  if (guestfs_get_verbose (g))\n";
6802       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6803       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6804       pr "  if (%s () == -1) {\n" test_name;
6805       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6806       pr "    n_failed++;\n";
6807       pr "  }\n";
6808   ) test_names;
6809   pr "\n";
6810
6811   pr "  guestfs_close (g);\n";
6812   pr "  unlink (\"test1.img\");\n";
6813   pr "  unlink (\"test2.img\");\n";
6814   pr "  unlink (\"test3.img\");\n";
6815   pr "\n";
6816
6817   pr "  if (n_failed > 0) {\n";
6818   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6819   pr "    exit (EXIT_FAILURE);\n";
6820   pr "  }\n";
6821   pr "\n";
6822
6823   pr "  exit (EXIT_SUCCESS);\n";
6824   pr "}\n"
6825
6826 and generate_one_test name flags i (init, prereq, test) =
6827   let test_name = sprintf "test_%s_%d" name i in
6828
6829   pr "\
6830 static int %s_skip (void)
6831 {
6832   const char *str;
6833
6834   str = getenv (\"TEST_ONLY\");
6835   if (str)
6836     return strstr (str, \"%s\") == NULL;
6837   str = getenv (\"SKIP_%s\");
6838   if (str && STREQ (str, \"1\")) return 1;
6839   str = getenv (\"SKIP_TEST_%s\");
6840   if (str && STREQ (str, \"1\")) return 1;
6841   return 0;
6842 }
6843
6844 " test_name name (String.uppercase test_name) (String.uppercase name);
6845
6846   (match prereq with
6847    | Disabled | Always -> ()
6848    | If code | Unless code ->
6849        pr "static int %s_prereq (void)\n" test_name;
6850        pr "{\n";
6851        pr "  %s\n" code;
6852        pr "}\n";
6853        pr "\n";
6854   );
6855
6856   pr "\
6857 static int %s (void)
6858 {
6859   if (%s_skip ()) {
6860     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6861     return 0;
6862   }
6863
6864 " test_name test_name test_name;
6865
6866   (* Optional functions should only be tested if the relevant
6867    * support is available in the daemon.
6868    *)
6869   List.iter (
6870     function
6871     | Optional group ->
6872         pr "  {\n";
6873         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6874         pr "    int r;\n";
6875         pr "    suppress_error = 1;\n";
6876         pr "    r = guestfs_available (g, (char **) groups);\n";
6877         pr "    suppress_error = 0;\n";
6878         pr "    if (r == -1) {\n";
6879         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6880         pr "      return 0;\n";
6881         pr "    }\n";
6882         pr "  }\n";
6883     | _ -> ()
6884   ) flags;
6885
6886   (match prereq with
6887    | Disabled ->
6888        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6889    | If _ ->
6890        pr "  if (! %s_prereq ()) {\n" test_name;
6891        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6892        pr "    return 0;\n";
6893        pr "  }\n";
6894        pr "\n";
6895        generate_one_test_body name i test_name init test;
6896    | Unless _ ->
6897        pr "  if (%s_prereq ()) {\n" test_name;
6898        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6899        pr "    return 0;\n";
6900        pr "  }\n";
6901        pr "\n";
6902        generate_one_test_body name i test_name init test;
6903    | Always ->
6904        generate_one_test_body name i test_name init test
6905   );
6906
6907   pr "  return 0;\n";
6908   pr "}\n";
6909   pr "\n";
6910   test_name
6911
6912 and generate_one_test_body name i test_name init test =
6913   (match init with
6914    | InitNone (* XXX at some point, InitNone and InitEmpty became
6915                * folded together as the same thing.  Really we should
6916                * make InitNone do nothing at all, but the tests may
6917                * need to be checked to make sure this is OK.
6918                *)
6919    | InitEmpty ->
6920        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6921        List.iter (generate_test_command_call test_name)
6922          [["blockdev_setrw"; "/dev/sda"];
6923           ["umount_all"];
6924           ["lvm_remove_all"]]
6925    | InitPartition ->
6926        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6927        List.iter (generate_test_command_call test_name)
6928          [["blockdev_setrw"; "/dev/sda"];
6929           ["umount_all"];
6930           ["lvm_remove_all"];
6931           ["part_disk"; "/dev/sda"; "mbr"]]
6932    | InitBasicFS ->
6933        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6934        List.iter (generate_test_command_call test_name)
6935          [["blockdev_setrw"; "/dev/sda"];
6936           ["umount_all"];
6937           ["lvm_remove_all"];
6938           ["part_disk"; "/dev/sda"; "mbr"];
6939           ["mkfs"; "ext2"; "/dev/sda1"];
6940           ["mount_options"; ""; "/dev/sda1"; "/"]]
6941    | InitBasicFSonLVM ->
6942        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6943          test_name;
6944        List.iter (generate_test_command_call test_name)
6945          [["blockdev_setrw"; "/dev/sda"];
6946           ["umount_all"];
6947           ["lvm_remove_all"];
6948           ["part_disk"; "/dev/sda"; "mbr"];
6949           ["pvcreate"; "/dev/sda1"];
6950           ["vgcreate"; "VG"; "/dev/sda1"];
6951           ["lvcreate"; "LV"; "VG"; "8"];
6952           ["mkfs"; "ext2"; "/dev/VG/LV"];
6953           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6954    | InitISOFS ->
6955        pr "  /* InitISOFS for %s */\n" test_name;
6956        List.iter (generate_test_command_call test_name)
6957          [["blockdev_setrw"; "/dev/sda"];
6958           ["umount_all"];
6959           ["lvm_remove_all"];
6960           ["mount_ro"; "/dev/sdd"; "/"]]
6961   );
6962
6963   let get_seq_last = function
6964     | [] ->
6965         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6966           test_name
6967     | seq ->
6968         let seq = List.rev seq in
6969         List.rev (List.tl seq), List.hd seq
6970   in
6971
6972   match test with
6973   | TestRun seq ->
6974       pr "  /* TestRun for %s (%d) */\n" name i;
6975       List.iter (generate_test_command_call test_name) seq
6976   | TestOutput (seq, expected) ->
6977       pr "  /* TestOutput for %s (%d) */\n" name i;
6978       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6979       let seq, last = get_seq_last seq in
6980       let test () =
6981         pr "    if (STRNEQ (r, expected)) {\n";
6982         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6983         pr "      return -1;\n";
6984         pr "    }\n"
6985       in
6986       List.iter (generate_test_command_call test_name) seq;
6987       generate_test_command_call ~test test_name last
6988   | TestOutputList (seq, expected) ->
6989       pr "  /* TestOutputList for %s (%d) */\n" name i;
6990       let seq, last = get_seq_last seq in
6991       let test () =
6992         iteri (
6993           fun i str ->
6994             pr "    if (!r[%d]) {\n" i;
6995             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6996             pr "      print_strings (r);\n";
6997             pr "      return -1;\n";
6998             pr "    }\n";
6999             pr "    {\n";
7000             pr "      const char *expected = \"%s\";\n" (c_quote str);
7001             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7002             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7003             pr "        return -1;\n";
7004             pr "      }\n";
7005             pr "    }\n"
7006         ) expected;
7007         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7008         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7009           test_name;
7010         pr "      print_strings (r);\n";
7011         pr "      return -1;\n";
7012         pr "    }\n"
7013       in
7014       List.iter (generate_test_command_call test_name) seq;
7015       generate_test_command_call ~test test_name last
7016   | TestOutputListOfDevices (seq, expected) ->
7017       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7018       let seq, last = get_seq_last seq in
7019       let test () =
7020         iteri (
7021           fun i str ->
7022             pr "    if (!r[%d]) {\n" i;
7023             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7024             pr "      print_strings (r);\n";
7025             pr "      return -1;\n";
7026             pr "    }\n";
7027             pr "    {\n";
7028             pr "      const char *expected = \"%s\";\n" (c_quote str);
7029             pr "      r[%d][5] = 's';\n" i;
7030             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7031             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7032             pr "        return -1;\n";
7033             pr "      }\n";
7034             pr "    }\n"
7035         ) expected;
7036         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7037         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7038           test_name;
7039         pr "      print_strings (r);\n";
7040         pr "      return -1;\n";
7041         pr "    }\n"
7042       in
7043       List.iter (generate_test_command_call test_name) seq;
7044       generate_test_command_call ~test test_name last
7045   | TestOutputInt (seq, expected) ->
7046       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7047       let seq, last = get_seq_last seq in
7048       let test () =
7049         pr "    if (r != %d) {\n" expected;
7050         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7051           test_name expected;
7052         pr "               (int) r);\n";
7053         pr "      return -1;\n";
7054         pr "    }\n"
7055       in
7056       List.iter (generate_test_command_call test_name) seq;
7057       generate_test_command_call ~test test_name last
7058   | TestOutputIntOp (seq, op, expected) ->
7059       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7060       let seq, last = get_seq_last seq in
7061       let test () =
7062         pr "    if (! (r %s %d)) {\n" op expected;
7063         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7064           test_name op expected;
7065         pr "               (int) r);\n";
7066         pr "      return -1;\n";
7067         pr "    }\n"
7068       in
7069       List.iter (generate_test_command_call test_name) seq;
7070       generate_test_command_call ~test test_name last
7071   | TestOutputTrue seq ->
7072       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7073       let seq, last = get_seq_last seq in
7074       let test () =
7075         pr "    if (!r) {\n";
7076         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7077           test_name;
7078         pr "      return -1;\n";
7079         pr "    }\n"
7080       in
7081       List.iter (generate_test_command_call test_name) seq;
7082       generate_test_command_call ~test test_name last
7083   | TestOutputFalse seq ->
7084       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7085       let seq, last = get_seq_last seq in
7086       let test () =
7087         pr "    if (r) {\n";
7088         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7089           test_name;
7090         pr "      return -1;\n";
7091         pr "    }\n"
7092       in
7093       List.iter (generate_test_command_call test_name) seq;
7094       generate_test_command_call ~test test_name last
7095   | TestOutputLength (seq, expected) ->
7096       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7097       let seq, last = get_seq_last seq in
7098       let test () =
7099         pr "    int j;\n";
7100         pr "    for (j = 0; j < %d; ++j)\n" expected;
7101         pr "      if (r[j] == NULL) {\n";
7102         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7103           test_name;
7104         pr "        print_strings (r);\n";
7105         pr "        return -1;\n";
7106         pr "      }\n";
7107         pr "    if (r[j] != NULL) {\n";
7108         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7109           test_name;
7110         pr "      print_strings (r);\n";
7111         pr "      return -1;\n";
7112         pr "    }\n"
7113       in
7114       List.iter (generate_test_command_call test_name) seq;
7115       generate_test_command_call ~test test_name last
7116   | TestOutputBuffer (seq, expected) ->
7117       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7118       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7119       let seq, last = get_seq_last seq in
7120       let len = String.length expected in
7121       let test () =
7122         pr "    if (size != %d) {\n" len;
7123         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7124         pr "      return -1;\n";
7125         pr "    }\n";
7126         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7127         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7128         pr "      return -1;\n";
7129         pr "    }\n"
7130       in
7131       List.iter (generate_test_command_call test_name) seq;
7132       generate_test_command_call ~test test_name last
7133   | TestOutputStruct (seq, checks) ->
7134       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7135       let seq, last = get_seq_last seq in
7136       let test () =
7137         List.iter (
7138           function
7139           | CompareWithInt (field, expected) ->
7140               pr "    if (r->%s != %d) {\n" field expected;
7141               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7142                 test_name field expected;
7143               pr "               (int) r->%s);\n" field;
7144               pr "      return -1;\n";
7145               pr "    }\n"
7146           | CompareWithIntOp (field, op, expected) ->
7147               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7148               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7149                 test_name field op expected;
7150               pr "               (int) r->%s);\n" field;
7151               pr "      return -1;\n";
7152               pr "    }\n"
7153           | CompareWithString (field, expected) ->
7154               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7155               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7156                 test_name field expected;
7157               pr "               r->%s);\n" field;
7158               pr "      return -1;\n";
7159               pr "    }\n"
7160           | CompareFieldsIntEq (field1, field2) ->
7161               pr "    if (r->%s != r->%s) {\n" field1 field2;
7162               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7163                 test_name field1 field2;
7164               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7165               pr "      return -1;\n";
7166               pr "    }\n"
7167           | CompareFieldsStrEq (field1, field2) ->
7168               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7169               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7170                 test_name field1 field2;
7171               pr "               r->%s, r->%s);\n" field1 field2;
7172               pr "      return -1;\n";
7173               pr "    }\n"
7174         ) checks
7175       in
7176       List.iter (generate_test_command_call test_name) seq;
7177       generate_test_command_call ~test test_name last
7178   | TestLastFail seq ->
7179       pr "  /* TestLastFail for %s (%d) */\n" name i;
7180       let seq, last = get_seq_last seq in
7181       List.iter (generate_test_command_call test_name) seq;
7182       generate_test_command_call test_name ~expect_error:true last
7183
7184 (* Generate the code to run a command, leaving the result in 'r'.
7185  * If you expect to get an error then you should set expect_error:true.
7186  *)
7187 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7188   match cmd with
7189   | [] -> assert false
7190   | name :: args ->
7191       (* Look up the command to find out what args/ret it has. *)
7192       let style =
7193         try
7194           let _, style, _, _, _, _, _ =
7195             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7196           style
7197         with Not_found ->
7198           failwithf "%s: in test, command %s was not found" test_name name in
7199
7200       if List.length (snd style) <> List.length args then
7201         failwithf "%s: in test, wrong number of args given to %s"
7202           test_name name;
7203
7204       pr "  {\n";
7205
7206       List.iter (
7207         function
7208         | OptString n, "NULL" -> ()
7209         | Pathname n, arg
7210         | Device n, arg
7211         | Dev_or_Path n, arg
7212         | String n, arg
7213         | OptString n, arg ->
7214             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7215         | Int _, _
7216         | Int64 _, _
7217         | Bool _, _
7218         | FileIn _, _ | FileOut _, _ -> ()
7219         | StringList n, "" | DeviceList n, "" ->
7220             pr "    const char *const %s[1] = { NULL };\n" n
7221         | StringList n, arg | DeviceList n, arg ->
7222             let strs = string_split " " arg in
7223             iteri (
7224               fun i str ->
7225                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7226             ) strs;
7227             pr "    const char *const %s[] = {\n" n;
7228             iteri (
7229               fun i _ -> pr "      %s_%d,\n" n i
7230             ) strs;
7231             pr "      NULL\n";
7232             pr "    };\n";
7233       ) (List.combine (snd style) args);
7234
7235       let error_code =
7236         match fst style with
7237         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7238         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7239         | RConstString _ | RConstOptString _ ->
7240             pr "    const char *r;\n"; "NULL"
7241         | RString _ -> pr "    char *r;\n"; "NULL"
7242         | RStringList _ | RHashtable _ ->
7243             pr "    char **r;\n";
7244             pr "    int i;\n";
7245             "NULL"
7246         | RStruct (_, typ) ->
7247             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7248         | RStructList (_, typ) ->
7249             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7250         | RBufferOut _ ->
7251             pr "    char *r;\n";
7252             pr "    size_t size;\n";
7253             "NULL" in
7254
7255       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7256       pr "    r = guestfs_%s (g" name;
7257
7258       (* Generate the parameters. *)
7259       List.iter (
7260         function
7261         | OptString _, "NULL" -> pr ", NULL"
7262         | Pathname n, _
7263         | Device n, _ | Dev_or_Path n, _
7264         | String n, _
7265         | OptString n, _ ->
7266             pr ", %s" n
7267         | FileIn _, arg | FileOut _, arg ->
7268             pr ", \"%s\"" (c_quote arg)
7269         | StringList n, _ | DeviceList n, _ ->
7270             pr ", (char **) %s" n
7271         | Int _, arg ->
7272             let i =
7273               try int_of_string arg
7274               with Failure "int_of_string" ->
7275                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7276             pr ", %d" i
7277         | Int64 _, arg ->
7278             let i =
7279               try Int64.of_string arg
7280               with Failure "int_of_string" ->
7281                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7282             pr ", %Ld" i
7283         | Bool _, arg ->
7284             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7285       ) (List.combine (snd style) args);
7286
7287       (match fst style with
7288        | RBufferOut _ -> pr ", &size"
7289        | _ -> ()
7290       );
7291
7292       pr ");\n";
7293
7294       if not expect_error then
7295         pr "    if (r == %s)\n" error_code
7296       else
7297         pr "    if (r != %s)\n" error_code;
7298       pr "      return -1;\n";
7299
7300       (* Insert the test code. *)
7301       (match test with
7302        | None -> ()
7303        | Some f -> f ()
7304       );
7305
7306       (match fst style with
7307        | RErr | RInt _ | RInt64 _ | RBool _
7308        | RConstString _ | RConstOptString _ -> ()
7309        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7310        | RStringList _ | RHashtable _ ->
7311            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7312            pr "      free (r[i]);\n";
7313            pr "    free (r);\n"
7314        | RStruct (_, typ) ->
7315            pr "    guestfs_free_%s (r);\n" typ
7316        | RStructList (_, typ) ->
7317            pr "    guestfs_free_%s_list (r);\n" typ
7318       );
7319
7320       pr "  }\n"
7321
7322 and c_quote str =
7323   let str = replace_str str "\r" "\\r" in
7324   let str = replace_str str "\n" "\\n" in
7325   let str = replace_str str "\t" "\\t" in
7326   let str = replace_str str "\000" "\\0" in
7327   str
7328
7329 (* Generate a lot of different functions for guestfish. *)
7330 and generate_fish_cmds () =
7331   generate_header CStyle GPLv2plus;
7332
7333   let all_functions =
7334     List.filter (
7335       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7336     ) all_functions in
7337   let all_functions_sorted =
7338     List.filter (
7339       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7340     ) all_functions_sorted in
7341
7342   pr "#include <config.h>\n";
7343   pr "\n";
7344   pr "#include <stdio.h>\n";
7345   pr "#include <stdlib.h>\n";
7346   pr "#include <string.h>\n";
7347   pr "#include <inttypes.h>\n";
7348   pr "\n";
7349   pr "#include <guestfs.h>\n";
7350   pr "#include \"c-ctype.h\"\n";
7351   pr "#include \"full-write.h\"\n";
7352   pr "#include \"xstrtol.h\"\n";
7353   pr "#include \"fish.h\"\n";
7354   pr "\n";
7355
7356   (* list_commands function, which implements guestfish -h *)
7357   pr "void list_commands (void)\n";
7358   pr "{\n";
7359   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7360   pr "  list_builtin_commands ();\n";
7361   List.iter (
7362     fun (name, _, _, flags, _, shortdesc, _) ->
7363       let name = replace_char name '_' '-' in
7364       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7365         name shortdesc
7366   ) all_functions_sorted;
7367   pr "  printf (\"    %%s\\n\",";
7368   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7369   pr "}\n";
7370   pr "\n";
7371
7372   (* display_command function, which implements guestfish -h cmd *)
7373   pr "void display_command (const char *cmd)\n";
7374   pr "{\n";
7375   List.iter (
7376     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7377       let name2 = replace_char name '_' '-' in
7378       let alias =
7379         try find_map (function FishAlias n -> Some n | _ -> None) flags
7380         with Not_found -> name in
7381       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7382       let synopsis =
7383         match snd style with
7384         | [] -> name2
7385         | args ->
7386             sprintf "%s %s"
7387               name2 (String.concat " " (List.map name_of_argt args)) in
7388
7389       let warnings =
7390         if List.mem ProtocolLimitWarning flags then
7391           ("\n\n" ^ protocol_limit_warning)
7392         else "" in
7393
7394       (* For DangerWillRobinson commands, we should probably have
7395        * guestfish prompt before allowing you to use them (especially
7396        * in interactive mode). XXX
7397        *)
7398       let warnings =
7399         warnings ^
7400           if List.mem DangerWillRobinson flags then
7401             ("\n\n" ^ danger_will_robinson)
7402           else "" in
7403
7404       let warnings =
7405         warnings ^
7406           match deprecation_notice flags with
7407           | None -> ""
7408           | Some txt -> "\n\n" ^ txt in
7409
7410       let describe_alias =
7411         if name <> alias then
7412           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7413         else "" in
7414
7415       pr "  if (";
7416       pr "STRCASEEQ (cmd, \"%s\")" name;
7417       if name <> name2 then
7418         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7419       if name <> alias then
7420         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7421       pr ")\n";
7422       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7423         name2 shortdesc
7424         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7425          "=head1 DESCRIPTION\n\n" ^
7426          longdesc ^ warnings ^ describe_alias);
7427       pr "  else\n"
7428   ) all_functions;
7429   pr "    display_builtin_command (cmd);\n";
7430   pr "}\n";
7431   pr "\n";
7432
7433   let emit_print_list_function typ =
7434     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7435       typ typ typ;
7436     pr "{\n";
7437     pr "  unsigned int i;\n";
7438     pr "\n";
7439     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7440     pr "    printf (\"[%%d] = {\\n\", i);\n";
7441     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7442     pr "    printf (\"}\\n\");\n";
7443     pr "  }\n";
7444     pr "}\n";
7445     pr "\n";
7446   in
7447
7448   (* print_* functions *)
7449   List.iter (
7450     fun (typ, cols) ->
7451       let needs_i =
7452         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7453
7454       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7455       pr "{\n";
7456       if needs_i then (
7457         pr "  unsigned int i;\n";
7458         pr "\n"
7459       );
7460       List.iter (
7461         function
7462         | name, FString ->
7463             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7464         | name, FUUID ->
7465             pr "  printf (\"%%s%s: \", indent);\n" name;
7466             pr "  for (i = 0; i < 32; ++i)\n";
7467             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7468             pr "  printf (\"\\n\");\n"
7469         | name, FBuffer ->
7470             pr "  printf (\"%%s%s: \", indent);\n" name;
7471             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7472             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7473             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7474             pr "    else\n";
7475             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7476             pr "  printf (\"\\n\");\n"
7477         | name, (FUInt64|FBytes) ->
7478             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7479               name typ name
7480         | name, FInt64 ->
7481             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7482               name typ name
7483         | name, FUInt32 ->
7484             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7485               name typ name
7486         | name, FInt32 ->
7487             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7488               name typ name
7489         | name, FChar ->
7490             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7491               name typ name
7492         | name, FOptPercent ->
7493             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7494               typ name name typ name;
7495             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7496       ) cols;
7497       pr "}\n";
7498       pr "\n";
7499   ) structs;
7500
7501   (* Emit a print_TYPE_list function definition only if that function is used. *)
7502   List.iter (
7503     function
7504     | typ, (RStructListOnly | RStructAndList) ->
7505         (* generate the function for typ *)
7506         emit_print_list_function typ
7507     | typ, _ -> () (* empty *)
7508   ) (rstructs_used_by all_functions);
7509
7510   (* Emit a print_TYPE function definition only if that function is used. *)
7511   List.iter (
7512     function
7513     | typ, (RStructOnly | RStructAndList) ->
7514         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7515         pr "{\n";
7516         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7517         pr "}\n";
7518         pr "\n";
7519     | typ, _ -> () (* empty *)
7520   ) (rstructs_used_by all_functions);
7521
7522   (* run_<action> actions *)
7523   List.iter (
7524     fun (name, style, _, flags, _, _, _) ->
7525       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7526       pr "{\n";
7527       (match fst style with
7528        | RErr
7529        | RInt _
7530        | RBool _ -> pr "  int r;\n"
7531        | RInt64 _ -> pr "  int64_t r;\n"
7532        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7533        | RString _ -> pr "  char *r;\n"
7534        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7535        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7536        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7537        | RBufferOut _ ->
7538            pr "  char *r;\n";
7539            pr "  size_t size;\n";
7540       );
7541       List.iter (
7542         function
7543         | Device n
7544         | String n
7545         | OptString n -> pr "  const char *%s;\n" n
7546         | Pathname n
7547         | Dev_or_Path n
7548         | FileIn n
7549         | FileOut n -> pr "  char *%s;\n" n
7550         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7551         | Bool n -> pr "  int %s;\n" n
7552         | Int n -> pr "  int %s;\n" n
7553         | Int64 n -> pr "  int64_t %s;\n" n
7554       ) (snd style);
7555
7556       (* Check and convert parameters. *)
7557       let argc_expected = List.length (snd style) in
7558       pr "  if (argc != %d) {\n" argc_expected;
7559       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7560         argc_expected;
7561       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7562       pr "    return -1;\n";
7563       pr "  }\n";
7564
7565       let parse_integer fn fntyp rtyp range name i =
7566         pr "  {\n";
7567         pr "    strtol_error xerr;\n";
7568         pr "    %s r;\n" fntyp;
7569         pr "\n";
7570         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7571         pr "    if (xerr != LONGINT_OK) {\n";
7572         pr "      fprintf (stderr,\n";
7573         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7574         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7575         pr "      return -1;\n";
7576         pr "    }\n";
7577         (match range with
7578          | None -> ()
7579          | Some (min, max, comment) ->
7580              pr "    /* %s */\n" comment;
7581              pr "    if (r < %s || r > %s) {\n" min max;
7582              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7583                name;
7584              pr "      return -1;\n";
7585              pr "    }\n";
7586              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7587         );
7588         pr "    %s = r;\n" name;
7589         pr "  }\n";
7590       in
7591
7592       iteri (
7593         fun i ->
7594           function
7595           | Device name
7596           | String name ->
7597               pr "  %s = argv[%d];\n" name i
7598           | Pathname name
7599           | Dev_or_Path name ->
7600               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7601               pr "  if (%s == NULL) return -1;\n" name
7602           | OptString name ->
7603               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7604                 name i i
7605           | FileIn name ->
7606               pr "  %s = file_in (argv[%d]);\n" name i;
7607               pr "  if (%s == NULL) return -1;\n" name
7608           | FileOut name ->
7609               pr "  %s = file_out (argv[%d]);\n" name i;
7610               pr "  if (%s == NULL) return -1;\n" name
7611           | StringList name | DeviceList name ->
7612               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7613               pr "  if (%s == NULL) return -1;\n" name;
7614           | Bool name ->
7615               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7616           | Int name ->
7617               let range =
7618                 let min = "(-(2LL<<30))"
7619                 and max = "((2LL<<30)-1)"
7620                 and comment =
7621                   "The Int type in the generator is a signed 31 bit int." in
7622                 Some (min, max, comment) in
7623               parse_integer "xstrtoll" "long long" "int" range name i
7624           | Int64 name ->
7625               parse_integer "xstrtoll" "long long" "int64_t" None name i
7626       ) (snd style);
7627
7628       (* Call C API function. *)
7629       pr "  r = guestfs_%s " name;
7630       generate_c_call_args ~handle:"g" style;
7631       pr ";\n";
7632
7633       List.iter (
7634         function
7635         | Device name | String name
7636         | OptString name | Bool name
7637         | Int name | Int64 name -> ()
7638         | Pathname name | Dev_or_Path name | FileOut name ->
7639             pr "  free (%s);\n" name
7640         | FileIn name ->
7641             pr "  free_file_in (%s);\n" name
7642         | StringList name | DeviceList name ->
7643             pr "  free_strings (%s);\n" name
7644       ) (snd style);
7645
7646       (* Any output flags? *)
7647       let fish_output =
7648         let flags = filter_map (
7649           function FishOutput flag -> Some flag | _ -> None
7650         ) flags in
7651         match flags with
7652         | [] -> None
7653         | [f] -> Some f
7654         | _ ->
7655             failwithf "%s: more than one FishOutput flag is not allowed" name in
7656
7657       (* Check return value for errors and display command results. *)
7658       (match fst style with
7659        | RErr -> pr "  return r;\n"
7660        | RInt _ ->
7661            pr "  if (r == -1) return -1;\n";
7662            (match fish_output with
7663             | None ->
7664                 pr "  printf (\"%%d\\n\", r);\n";
7665             | Some FishOutputOctal ->
7666                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7667             | Some FishOutputHexadecimal ->
7668                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7669            pr "  return 0;\n"
7670        | RInt64 _ ->
7671            pr "  if (r == -1) return -1;\n";
7672            (match fish_output with
7673             | None ->
7674                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7675             | Some FishOutputOctal ->
7676                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7677             | Some FishOutputHexadecimal ->
7678                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7679            pr "  return 0;\n"
7680        | RBool _ ->
7681            pr "  if (r == -1) return -1;\n";
7682            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7683            pr "  return 0;\n"
7684        | RConstString _ ->
7685            pr "  if (r == NULL) return -1;\n";
7686            pr "  printf (\"%%s\\n\", r);\n";
7687            pr "  return 0;\n"
7688        | RConstOptString _ ->
7689            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7690            pr "  return 0;\n"
7691        | RString _ ->
7692            pr "  if (r == NULL) return -1;\n";
7693            pr "  printf (\"%%s\\n\", r);\n";
7694            pr "  free (r);\n";
7695            pr "  return 0;\n"
7696        | RStringList _ ->
7697            pr "  if (r == NULL) return -1;\n";
7698            pr "  print_strings (r);\n";
7699            pr "  free_strings (r);\n";
7700            pr "  return 0;\n"
7701        | RStruct (_, typ) ->
7702            pr "  if (r == NULL) return -1;\n";
7703            pr "  print_%s (r);\n" typ;
7704            pr "  guestfs_free_%s (r);\n" typ;
7705            pr "  return 0;\n"
7706        | RStructList (_, typ) ->
7707            pr "  if (r == NULL) return -1;\n";
7708            pr "  print_%s_list (r);\n" typ;
7709            pr "  guestfs_free_%s_list (r);\n" typ;
7710            pr "  return 0;\n"
7711        | RHashtable _ ->
7712            pr "  if (r == NULL) return -1;\n";
7713            pr "  print_table (r);\n";
7714            pr "  free_strings (r);\n";
7715            pr "  return 0;\n"
7716        | RBufferOut _ ->
7717            pr "  if (r == NULL) return -1;\n";
7718            pr "  if (full_write (1, r, size) != size) {\n";
7719            pr "    perror (\"write\");\n";
7720            pr "    free (r);\n";
7721            pr "    return -1;\n";
7722            pr "  }\n";
7723            pr "  free (r);\n";
7724            pr "  return 0;\n"
7725       );
7726       pr "}\n";
7727       pr "\n"
7728   ) all_functions;
7729
7730   (* run_action function *)
7731   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7732   pr "{\n";
7733   List.iter (
7734     fun (name, _, _, flags, _, _, _) ->
7735       let name2 = replace_char name '_' '-' in
7736       let alias =
7737         try find_map (function FishAlias n -> Some n | _ -> None) flags
7738         with Not_found -> name in
7739       pr "  if (";
7740       pr "STRCASEEQ (cmd, \"%s\")" name;
7741       if name <> name2 then
7742         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7743       if name <> alias then
7744         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7745       pr ")\n";
7746       pr "    return run_%s (cmd, argc, argv);\n" name;
7747       pr "  else\n";
7748   ) all_functions;
7749   pr "    {\n";
7750   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7751   pr "      if (command_num == 1)\n";
7752   pr "        extended_help_message ();\n";
7753   pr "      return -1;\n";
7754   pr "    }\n";
7755   pr "  return 0;\n";
7756   pr "}\n";
7757   pr "\n"
7758
7759 (* Readline completion for guestfish. *)
7760 and generate_fish_completion () =
7761   generate_header CStyle GPLv2plus;
7762
7763   let all_functions =
7764     List.filter (
7765       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7766     ) all_functions in
7767
7768   pr "\
7769 #include <config.h>
7770
7771 #include <stdio.h>
7772 #include <stdlib.h>
7773 #include <string.h>
7774
7775 #ifdef HAVE_LIBREADLINE
7776 #include <readline/readline.h>
7777 #endif
7778
7779 #include \"fish.h\"
7780
7781 #ifdef HAVE_LIBREADLINE
7782
7783 static const char *const commands[] = {
7784   BUILTIN_COMMANDS_FOR_COMPLETION,
7785 ";
7786
7787   (* Get the commands, including the aliases.  They don't need to be
7788    * sorted - the generator() function just does a dumb linear search.
7789    *)
7790   let commands =
7791     List.map (
7792       fun (name, _, _, flags, _, _, _) ->
7793         let name2 = replace_char name '_' '-' in
7794         let alias =
7795           try find_map (function FishAlias n -> Some n | _ -> None) flags
7796           with Not_found -> name in
7797
7798         if name <> alias then [name2; alias] else [name2]
7799     ) all_functions in
7800   let commands = List.flatten commands in
7801
7802   List.iter (pr "  \"%s\",\n") commands;
7803
7804   pr "  NULL
7805 };
7806
7807 static char *
7808 generator (const char *text, int state)
7809 {
7810   static int index, len;
7811   const char *name;
7812
7813   if (!state) {
7814     index = 0;
7815     len = strlen (text);
7816   }
7817
7818   rl_attempted_completion_over = 1;
7819
7820   while ((name = commands[index]) != NULL) {
7821     index++;
7822     if (STRCASEEQLEN (name, text, len))
7823       return strdup (name);
7824   }
7825
7826   return NULL;
7827 }
7828
7829 #endif /* HAVE_LIBREADLINE */
7830
7831 #ifdef HAVE_RL_COMPLETION_MATCHES
7832 #define RL_COMPLETION_MATCHES rl_completion_matches
7833 #else
7834 #ifdef HAVE_COMPLETION_MATCHES
7835 #define RL_COMPLETION_MATCHES completion_matches
7836 #endif
7837 #endif /* else just fail if we don't have either symbol */
7838
7839 char **
7840 do_completion (const char *text, int start, int end)
7841 {
7842   char **matches = NULL;
7843
7844 #ifdef HAVE_LIBREADLINE
7845   rl_completion_append_character = ' ';
7846
7847   if (start == 0)
7848     matches = RL_COMPLETION_MATCHES (text, generator);
7849   else if (complete_dest_paths)
7850     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7851 #endif
7852
7853   return matches;
7854 }
7855 ";
7856
7857 (* Generate the POD documentation for guestfish. *)
7858 and generate_fish_actions_pod () =
7859   let all_functions_sorted =
7860     List.filter (
7861       fun (_, _, _, flags, _, _, _) ->
7862         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7863     ) all_functions_sorted in
7864
7865   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7866
7867   List.iter (
7868     fun (name, style, _, flags, _, _, longdesc) ->
7869       let longdesc =
7870         Str.global_substitute rex (
7871           fun s ->
7872             let sub =
7873               try Str.matched_group 1 s
7874               with Not_found ->
7875                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7876             "C<" ^ replace_char sub '_' '-' ^ ">"
7877         ) longdesc in
7878       let name = replace_char name '_' '-' in
7879       let alias =
7880         try find_map (function FishAlias n -> Some n | _ -> None) flags
7881         with Not_found -> name in
7882
7883       pr "=head2 %s" name;
7884       if name <> alias then
7885         pr " | %s" alias;
7886       pr "\n";
7887       pr "\n";
7888       pr " %s" name;
7889       List.iter (
7890         function
7891         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7892         | OptString n -> pr " %s" n
7893         | StringList n | DeviceList n -> pr " '%s ...'" n
7894         | Bool _ -> pr " true|false"
7895         | Int n -> pr " %s" n
7896         | Int64 n -> pr " %s" n
7897         | FileIn n | FileOut n -> pr " (%s|-)" n
7898       ) (snd style);
7899       pr "\n";
7900       pr "\n";
7901       pr "%s\n\n" longdesc;
7902
7903       if List.exists (function FileIn _ | FileOut _ -> true
7904                       | _ -> false) (snd style) then
7905         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7906
7907       if List.mem ProtocolLimitWarning flags then
7908         pr "%s\n\n" protocol_limit_warning;
7909
7910       if List.mem DangerWillRobinson flags then
7911         pr "%s\n\n" danger_will_robinson;
7912
7913       match deprecation_notice flags with
7914       | None -> ()
7915       | Some txt -> pr "%s\n\n" txt
7916   ) all_functions_sorted
7917
7918 (* Generate a C function prototype. *)
7919 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7920     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7921     ?(prefix = "")
7922     ?handle name style =
7923   if extern then pr "extern ";
7924   if static then pr "static ";
7925   (match fst style with
7926    | RErr -> pr "int "
7927    | RInt _ -> pr "int "
7928    | RInt64 _ -> pr "int64_t "
7929    | RBool _ -> pr "int "
7930    | RConstString _ | RConstOptString _ -> pr "const char *"
7931    | RString _ | RBufferOut _ -> pr "char *"
7932    | RStringList _ | RHashtable _ -> pr "char **"
7933    | RStruct (_, typ) ->
7934        if not in_daemon then pr "struct guestfs_%s *" typ
7935        else pr "guestfs_int_%s *" typ
7936    | RStructList (_, typ) ->
7937        if not in_daemon then pr "struct guestfs_%s_list *" typ
7938        else pr "guestfs_int_%s_list *" typ
7939   );
7940   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7941   pr "%s%s (" prefix name;
7942   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7943     pr "void"
7944   else (
7945     let comma = ref false in
7946     (match handle with
7947      | None -> ()
7948      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7949     );
7950     let next () =
7951       if !comma then (
7952         if single_line then pr ", " else pr ",\n\t\t"
7953       );
7954       comma := true
7955     in
7956     List.iter (
7957       function
7958       | Pathname n
7959       | Device n | Dev_or_Path n
7960       | String n
7961       | OptString n ->
7962           next ();
7963           pr "const char *%s" n
7964       | StringList n | DeviceList n ->
7965           next ();
7966           pr "char *const *%s" n
7967       | Bool n -> next (); pr "int %s" n
7968       | Int n -> next (); pr "int %s" n
7969       | Int64 n -> next (); pr "int64_t %s" n
7970       | FileIn n
7971       | FileOut n ->
7972           if not in_daemon then (next (); pr "const char *%s" n)
7973     ) (snd style);
7974     if is_RBufferOut then (next (); pr "size_t *size_r");
7975   );
7976   pr ")";
7977   if semicolon then pr ";";
7978   if newline then pr "\n"
7979
7980 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7981 and generate_c_call_args ?handle ?(decl = false) style =
7982   pr "(";
7983   let comma = ref false in
7984   let next () =
7985     if !comma then pr ", ";
7986     comma := true
7987   in
7988   (match handle with
7989    | None -> ()
7990    | Some handle -> pr "%s" handle; comma := true
7991   );
7992   List.iter (
7993     fun arg ->
7994       next ();
7995       pr "%s" (name_of_argt arg)
7996   ) (snd style);
7997   (* For RBufferOut calls, add implicit &size parameter. *)
7998   if not decl then (
7999     match fst style with
8000     | RBufferOut _ ->
8001         next ();
8002         pr "&size"
8003     | _ -> ()
8004   );
8005   pr ")"
8006
8007 (* Generate the OCaml bindings interface. *)
8008 and generate_ocaml_mli () =
8009   generate_header OCamlStyle LGPLv2plus;
8010
8011   pr "\
8012 (** For API documentation you should refer to the C API
8013     in the guestfs(3) manual page.  The OCaml API uses almost
8014     exactly the same calls. *)
8015
8016 type t
8017 (** A [guestfs_h] handle. *)
8018
8019 exception Error of string
8020 (** This exception is raised when there is an error. *)
8021
8022 exception Handle_closed of string
8023 (** This exception is raised if you use a {!Guestfs.t} handle
8024     after calling {!close} on it.  The string is the name of
8025     the function. *)
8026
8027 val create : unit -> t
8028 (** Create a {!Guestfs.t} handle. *)
8029
8030 val close : t -> unit
8031 (** Close the {!Guestfs.t} handle and free up all resources used
8032     by it immediately.
8033
8034     Handles are closed by the garbage collector when they become
8035     unreferenced, but callers can call this in order to provide
8036     predictable cleanup. *)
8037
8038 ";
8039   generate_ocaml_structure_decls ();
8040
8041   (* The actions. *)
8042   List.iter (
8043     fun (name, style, _, _, _, shortdesc, _) ->
8044       generate_ocaml_prototype name style;
8045       pr "(** %s *)\n" shortdesc;
8046       pr "\n"
8047   ) all_functions_sorted
8048
8049 (* Generate the OCaml bindings implementation. *)
8050 and generate_ocaml_ml () =
8051   generate_header OCamlStyle LGPLv2plus;
8052
8053   pr "\
8054 type t
8055
8056 exception Error of string
8057 exception Handle_closed of string
8058
8059 external create : unit -> t = \"ocaml_guestfs_create\"
8060 external close : t -> unit = \"ocaml_guestfs_close\"
8061
8062 (* Give the exceptions names, so they can be raised from the C code. *)
8063 let () =
8064   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8065   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8066
8067 ";
8068
8069   generate_ocaml_structure_decls ();
8070
8071   (* The actions. *)
8072   List.iter (
8073     fun (name, style, _, _, _, shortdesc, _) ->
8074       generate_ocaml_prototype ~is_external:true name style;
8075   ) all_functions_sorted
8076
8077 (* Generate the OCaml bindings C implementation. *)
8078 and generate_ocaml_c () =
8079   generate_header CStyle LGPLv2plus;
8080
8081   pr "\
8082 #include <stdio.h>
8083 #include <stdlib.h>
8084 #include <string.h>
8085
8086 #include <caml/config.h>
8087 #include <caml/alloc.h>
8088 #include <caml/callback.h>
8089 #include <caml/fail.h>
8090 #include <caml/memory.h>
8091 #include <caml/mlvalues.h>
8092 #include <caml/signals.h>
8093
8094 #include <guestfs.h>
8095
8096 #include \"guestfs_c.h\"
8097
8098 /* Copy a hashtable of string pairs into an assoc-list.  We return
8099  * the list in reverse order, but hashtables aren't supposed to be
8100  * ordered anyway.
8101  */
8102 static CAMLprim value
8103 copy_table (char * const * argv)
8104 {
8105   CAMLparam0 ();
8106   CAMLlocal5 (rv, pairv, kv, vv, cons);
8107   int i;
8108
8109   rv = Val_int (0);
8110   for (i = 0; argv[i] != NULL; i += 2) {
8111     kv = caml_copy_string (argv[i]);
8112     vv = caml_copy_string (argv[i+1]);
8113     pairv = caml_alloc (2, 0);
8114     Store_field (pairv, 0, kv);
8115     Store_field (pairv, 1, vv);
8116     cons = caml_alloc (2, 0);
8117     Store_field (cons, 1, rv);
8118     rv = cons;
8119     Store_field (cons, 0, pairv);
8120   }
8121
8122   CAMLreturn (rv);
8123 }
8124
8125 ";
8126
8127   (* Struct copy functions. *)
8128
8129   let emit_ocaml_copy_list_function typ =
8130     pr "static CAMLprim value\n";
8131     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8132     pr "{\n";
8133     pr "  CAMLparam0 ();\n";
8134     pr "  CAMLlocal2 (rv, v);\n";
8135     pr "  unsigned int i;\n";
8136     pr "\n";
8137     pr "  if (%ss->len == 0)\n" typ;
8138     pr "    CAMLreturn (Atom (0));\n";
8139     pr "  else {\n";
8140     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8141     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8142     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8143     pr "      caml_modify (&Field (rv, i), v);\n";
8144     pr "    }\n";
8145     pr "    CAMLreturn (rv);\n";
8146     pr "  }\n";
8147     pr "}\n";
8148     pr "\n";
8149   in
8150
8151   List.iter (
8152     fun (typ, cols) ->
8153       let has_optpercent_col =
8154         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8155
8156       pr "static CAMLprim value\n";
8157       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8158       pr "{\n";
8159       pr "  CAMLparam0 ();\n";
8160       if has_optpercent_col then
8161         pr "  CAMLlocal3 (rv, v, v2);\n"
8162       else
8163         pr "  CAMLlocal2 (rv, v);\n";
8164       pr "\n";
8165       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8166       iteri (
8167         fun i col ->
8168           (match col with
8169            | name, FString ->
8170                pr "  v = caml_copy_string (%s->%s);\n" typ name
8171            | name, FBuffer ->
8172                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8173                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8174                  typ name typ name
8175            | name, FUUID ->
8176                pr "  v = caml_alloc_string (32);\n";
8177                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8178            | name, (FBytes|FInt64|FUInt64) ->
8179                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8180            | name, (FInt32|FUInt32) ->
8181                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8182            | name, FOptPercent ->
8183                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8184                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8185                pr "    v = caml_alloc (1, 0);\n";
8186                pr "    Store_field (v, 0, v2);\n";
8187                pr "  } else /* None */\n";
8188                pr "    v = Val_int (0);\n";
8189            | name, FChar ->
8190                pr "  v = Val_int (%s->%s);\n" typ name
8191           );
8192           pr "  Store_field (rv, %d, v);\n" i
8193       ) cols;
8194       pr "  CAMLreturn (rv);\n";
8195       pr "}\n";
8196       pr "\n";
8197   ) structs;
8198
8199   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8200   List.iter (
8201     function
8202     | typ, (RStructListOnly | RStructAndList) ->
8203         (* generate the function for typ *)
8204         emit_ocaml_copy_list_function typ
8205     | typ, _ -> () (* empty *)
8206   ) (rstructs_used_by all_functions);
8207
8208   (* The wrappers. *)
8209   List.iter (
8210     fun (name, style, _, _, _, _, _) ->
8211       pr "/* Automatically generated wrapper for function\n";
8212       pr " * ";
8213       generate_ocaml_prototype name style;
8214       pr " */\n";
8215       pr "\n";
8216
8217       let params =
8218         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8219
8220       let needs_extra_vs =
8221         match fst style with RConstOptString _ -> true | _ -> false in
8222
8223       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8224       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8225       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8226       pr "\n";
8227
8228       pr "CAMLprim value\n";
8229       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8230       List.iter (pr ", value %s") (List.tl params);
8231       pr ")\n";
8232       pr "{\n";
8233
8234       (match params with
8235        | [p1; p2; p3; p4; p5] ->
8236            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8237        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8238            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8239            pr "  CAMLxparam%d (%s);\n"
8240              (List.length rest) (String.concat ", " rest)
8241        | ps ->
8242            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8243       );
8244       if not needs_extra_vs then
8245         pr "  CAMLlocal1 (rv);\n"
8246       else
8247         pr "  CAMLlocal3 (rv, v, v2);\n";
8248       pr "\n";
8249
8250       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8251       pr "  if (g == NULL)\n";
8252       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8253       pr "\n";
8254
8255       List.iter (
8256         function
8257         | Pathname n
8258         | Device n | Dev_or_Path n
8259         | String n
8260         | FileIn n
8261         | FileOut n ->
8262             pr "  const char *%s = String_val (%sv);\n" n n
8263         | OptString n ->
8264             pr "  const char *%s =\n" n;
8265             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8266               n n
8267         | StringList n | DeviceList n ->
8268             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8269         | Bool n ->
8270             pr "  int %s = Bool_val (%sv);\n" n n
8271         | Int n ->
8272             pr "  int %s = Int_val (%sv);\n" n n
8273         | Int64 n ->
8274             pr "  int64_t %s = Int64_val (%sv);\n" n n
8275       ) (snd style);
8276       let error_code =
8277         match fst style with
8278         | RErr -> pr "  int r;\n"; "-1"
8279         | RInt _ -> pr "  int r;\n"; "-1"
8280         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8281         | RBool _ -> pr "  int r;\n"; "-1"
8282         | RConstString _ | RConstOptString _ ->
8283             pr "  const char *r;\n"; "NULL"
8284         | RString _ -> pr "  char *r;\n"; "NULL"
8285         | RStringList _ ->
8286             pr "  int i;\n";
8287             pr "  char **r;\n";
8288             "NULL"
8289         | RStruct (_, typ) ->
8290             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8291         | RStructList (_, typ) ->
8292             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8293         | RHashtable _ ->
8294             pr "  int i;\n";
8295             pr "  char **r;\n";
8296             "NULL"
8297         | RBufferOut _ ->
8298             pr "  char *r;\n";
8299             pr "  size_t size;\n";
8300             "NULL" in
8301       pr "\n";
8302
8303       pr "  caml_enter_blocking_section ();\n";
8304       pr "  r = guestfs_%s " name;
8305       generate_c_call_args ~handle:"g" style;
8306       pr ";\n";
8307       pr "  caml_leave_blocking_section ();\n";
8308
8309       List.iter (
8310         function
8311         | StringList n | DeviceList n ->
8312             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8313         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8314         | Bool _ | Int _ | Int64 _
8315         | FileIn _ | FileOut _ -> ()
8316       ) (snd style);
8317
8318       pr "  if (r == %s)\n" error_code;
8319       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8320       pr "\n";
8321
8322       (match fst style with
8323        | RErr -> pr "  rv = Val_unit;\n"
8324        | RInt _ -> pr "  rv = Val_int (r);\n"
8325        | RInt64 _ ->
8326            pr "  rv = caml_copy_int64 (r);\n"
8327        | RBool _ -> pr "  rv = Val_bool (r);\n"
8328        | RConstString _ ->
8329            pr "  rv = caml_copy_string (r);\n"
8330        | RConstOptString _ ->
8331            pr "  if (r) { /* Some string */\n";
8332            pr "    v = caml_alloc (1, 0);\n";
8333            pr "    v2 = caml_copy_string (r);\n";
8334            pr "    Store_field (v, 0, v2);\n";
8335            pr "  } else /* None */\n";
8336            pr "    v = Val_int (0);\n";
8337        | RString _ ->
8338            pr "  rv = caml_copy_string (r);\n";
8339            pr "  free (r);\n"
8340        | RStringList _ ->
8341            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8342            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8343            pr "  free (r);\n"
8344        | RStruct (_, typ) ->
8345            pr "  rv = copy_%s (r);\n" typ;
8346            pr "  guestfs_free_%s (r);\n" typ;
8347        | RStructList (_, typ) ->
8348            pr "  rv = copy_%s_list (r);\n" typ;
8349            pr "  guestfs_free_%s_list (r);\n" typ;
8350        | RHashtable _ ->
8351            pr "  rv = copy_table (r);\n";
8352            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8353            pr "  free (r);\n";
8354        | RBufferOut _ ->
8355            pr "  rv = caml_alloc_string (size);\n";
8356            pr "  memcpy (String_val (rv), r, size);\n";
8357       );
8358
8359       pr "  CAMLreturn (rv);\n";
8360       pr "}\n";
8361       pr "\n";
8362
8363       if List.length params > 5 then (
8364         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8365         pr "CAMLprim value ";
8366         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8367         pr "CAMLprim value\n";
8368         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8369         pr "{\n";
8370         pr "  return ocaml_guestfs_%s (argv[0]" name;
8371         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8372         pr ");\n";
8373         pr "}\n";
8374         pr "\n"
8375       )
8376   ) all_functions_sorted
8377
8378 and generate_ocaml_structure_decls () =
8379   List.iter (
8380     fun (typ, cols) ->
8381       pr "type %s = {\n" typ;
8382       List.iter (
8383         function
8384         | name, FString -> pr "  %s : string;\n" name
8385         | name, FBuffer -> pr "  %s : string;\n" name
8386         | name, FUUID -> pr "  %s : string;\n" name
8387         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8388         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8389         | name, FChar -> pr "  %s : char;\n" name
8390         | name, FOptPercent -> pr "  %s : float option;\n" name
8391       ) cols;
8392       pr "}\n";
8393       pr "\n"
8394   ) structs
8395
8396 and generate_ocaml_prototype ?(is_external = false) name style =
8397   if is_external then pr "external " else pr "val ";
8398   pr "%s : t -> " name;
8399   List.iter (
8400     function
8401     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8402     | OptString _ -> pr "string option -> "
8403     | StringList _ | DeviceList _ -> pr "string array -> "
8404     | Bool _ -> pr "bool -> "
8405     | Int _ -> pr "int -> "
8406     | Int64 _ -> pr "int64 -> "
8407   ) (snd style);
8408   (match fst style with
8409    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8410    | RInt _ -> pr "int"
8411    | RInt64 _ -> pr "int64"
8412    | RBool _ -> pr "bool"
8413    | RConstString _ -> pr "string"
8414    | RConstOptString _ -> pr "string option"
8415    | RString _ | RBufferOut _ -> pr "string"
8416    | RStringList _ -> pr "string array"
8417    | RStruct (_, typ) -> pr "%s" typ
8418    | RStructList (_, typ) -> pr "%s array" typ
8419    | RHashtable _ -> pr "(string * string) list"
8420   );
8421   if is_external then (
8422     pr " = ";
8423     if List.length (snd style) + 1 > 5 then
8424       pr "\"ocaml_guestfs_%s_byte\" " name;
8425     pr "\"ocaml_guestfs_%s\"" name
8426   );
8427   pr "\n"
8428
8429 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8430 and generate_perl_xs () =
8431   generate_header CStyle LGPLv2plus;
8432
8433   pr "\
8434 #include \"EXTERN.h\"
8435 #include \"perl.h\"
8436 #include \"XSUB.h\"
8437
8438 #include <guestfs.h>
8439
8440 #ifndef PRId64
8441 #define PRId64 \"lld\"
8442 #endif
8443
8444 static SV *
8445 my_newSVll(long long val) {
8446 #ifdef USE_64_BIT_ALL
8447   return newSViv(val);
8448 #else
8449   char buf[100];
8450   int len;
8451   len = snprintf(buf, 100, \"%%\" PRId64, val);
8452   return newSVpv(buf, len);
8453 #endif
8454 }
8455
8456 #ifndef PRIu64
8457 #define PRIu64 \"llu\"
8458 #endif
8459
8460 static SV *
8461 my_newSVull(unsigned long long val) {
8462 #ifdef USE_64_BIT_ALL
8463   return newSVuv(val);
8464 #else
8465   char buf[100];
8466   int len;
8467   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8468   return newSVpv(buf, len);
8469 #endif
8470 }
8471
8472 /* http://www.perlmonks.org/?node_id=680842 */
8473 static char **
8474 XS_unpack_charPtrPtr (SV *arg) {
8475   char **ret;
8476   AV *av;
8477   I32 i;
8478
8479   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8480     croak (\"array reference expected\");
8481
8482   av = (AV *)SvRV (arg);
8483   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8484   if (!ret)
8485     croak (\"malloc failed\");
8486
8487   for (i = 0; i <= av_len (av); i++) {
8488     SV **elem = av_fetch (av, i, 0);
8489
8490     if (!elem || !*elem)
8491       croak (\"missing element in list\");
8492
8493     ret[i] = SvPV_nolen (*elem);
8494   }
8495
8496   ret[i] = NULL;
8497
8498   return ret;
8499 }
8500
8501 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8502
8503 PROTOTYPES: ENABLE
8504
8505 guestfs_h *
8506 _create ()
8507    CODE:
8508       RETVAL = guestfs_create ();
8509       if (!RETVAL)
8510         croak (\"could not create guestfs handle\");
8511       guestfs_set_error_handler (RETVAL, NULL, NULL);
8512  OUTPUT:
8513       RETVAL
8514
8515 void
8516 DESTROY (g)
8517       guestfs_h *g;
8518  PPCODE:
8519       guestfs_close (g);
8520
8521 ";
8522
8523   List.iter (
8524     fun (name, style, _, _, _, _, _) ->
8525       (match fst style with
8526        | RErr -> pr "void\n"
8527        | RInt _ -> pr "SV *\n"
8528        | RInt64 _ -> pr "SV *\n"
8529        | RBool _ -> pr "SV *\n"
8530        | RConstString _ -> pr "SV *\n"
8531        | RConstOptString _ -> pr "SV *\n"
8532        | RString _ -> pr "SV *\n"
8533        | RBufferOut _ -> pr "SV *\n"
8534        | RStringList _
8535        | RStruct _ | RStructList _
8536        | RHashtable _ ->
8537            pr "void\n" (* all lists returned implictly on the stack *)
8538       );
8539       (* Call and arguments. *)
8540       pr "%s " name;
8541       generate_c_call_args ~handle:"g" ~decl:true style;
8542       pr "\n";
8543       pr "      guestfs_h *g;\n";
8544       iteri (
8545         fun i ->
8546           function
8547           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8548               pr "      char *%s;\n" n
8549           | OptString n ->
8550               (* http://www.perlmonks.org/?node_id=554277
8551                * Note that the implicit handle argument means we have
8552                * to add 1 to the ST(x) operator.
8553                *)
8554               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8555           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8556           | Bool n -> pr "      int %s;\n" n
8557           | Int n -> pr "      int %s;\n" n
8558           | Int64 n -> pr "      int64_t %s;\n" n
8559       ) (snd style);
8560
8561       let do_cleanups () =
8562         List.iter (
8563           function
8564           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8565           | Bool _ | Int _ | Int64 _
8566           | FileIn _ | FileOut _ -> ()
8567           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8568         ) (snd style)
8569       in
8570
8571       (* Code. *)
8572       (match fst style with
8573        | RErr ->
8574            pr "PREINIT:\n";
8575            pr "      int r;\n";
8576            pr " PPCODE:\n";
8577            pr "      r = guestfs_%s " name;
8578            generate_c_call_args ~handle:"g" style;
8579            pr ";\n";
8580            do_cleanups ();
8581            pr "      if (r == -1)\n";
8582            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8583        | RInt n
8584        | RBool n ->
8585            pr "PREINIT:\n";
8586            pr "      int %s;\n" n;
8587            pr "   CODE:\n";
8588            pr "      %s = guestfs_%s " n name;
8589            generate_c_call_args ~handle:"g" style;
8590            pr ";\n";
8591            do_cleanups ();
8592            pr "      if (%s == -1)\n" n;
8593            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8594            pr "      RETVAL = newSViv (%s);\n" n;
8595            pr " OUTPUT:\n";
8596            pr "      RETVAL\n"
8597        | RInt64 n ->
8598            pr "PREINIT:\n";
8599            pr "      int64_t %s;\n" n;
8600            pr "   CODE:\n";
8601            pr "      %s = guestfs_%s " n name;
8602            generate_c_call_args ~handle:"g" style;
8603            pr ";\n";
8604            do_cleanups ();
8605            pr "      if (%s == -1)\n" n;
8606            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8607            pr "      RETVAL = my_newSVll (%s);\n" n;
8608            pr " OUTPUT:\n";
8609            pr "      RETVAL\n"
8610        | RConstString n ->
8611            pr "PREINIT:\n";
8612            pr "      const char *%s;\n" n;
8613            pr "   CODE:\n";
8614            pr "      %s = guestfs_%s " n name;
8615            generate_c_call_args ~handle:"g" style;
8616            pr ";\n";
8617            do_cleanups ();
8618            pr "      if (%s == NULL)\n" n;
8619            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8620            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8621            pr " OUTPUT:\n";
8622            pr "      RETVAL\n"
8623        | RConstOptString n ->
8624            pr "PREINIT:\n";
8625            pr "      const char *%s;\n" n;
8626            pr "   CODE:\n";
8627            pr "      %s = guestfs_%s " n name;
8628            generate_c_call_args ~handle:"g" style;
8629            pr ";\n";
8630            do_cleanups ();
8631            pr "      if (%s == NULL)\n" n;
8632            pr "        RETVAL = &PL_sv_undef;\n";
8633            pr "      else\n";
8634            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8635            pr " OUTPUT:\n";
8636            pr "      RETVAL\n"
8637        | RString n ->
8638            pr "PREINIT:\n";
8639            pr "      char *%s;\n" n;
8640            pr "   CODE:\n";
8641            pr "      %s = guestfs_%s " n name;
8642            generate_c_call_args ~handle:"g" style;
8643            pr ";\n";
8644            do_cleanups ();
8645            pr "      if (%s == NULL)\n" n;
8646            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8647            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8648            pr "      free (%s);\n" n;
8649            pr " OUTPUT:\n";
8650            pr "      RETVAL\n"
8651        | RStringList n | RHashtable n ->
8652            pr "PREINIT:\n";
8653            pr "      char **%s;\n" n;
8654            pr "      int i, n;\n";
8655            pr " PPCODE:\n";
8656            pr "      %s = guestfs_%s " n name;
8657            generate_c_call_args ~handle:"g" style;
8658            pr ";\n";
8659            do_cleanups ();
8660            pr "      if (%s == NULL)\n" n;
8661            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8662            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8663            pr "      EXTEND (SP, n);\n";
8664            pr "      for (i = 0; i < n; ++i) {\n";
8665            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8666            pr "        free (%s[i]);\n" n;
8667            pr "      }\n";
8668            pr "      free (%s);\n" n;
8669        | RStruct (n, typ) ->
8670            let cols = cols_of_struct typ in
8671            generate_perl_struct_code typ cols name style n do_cleanups
8672        | RStructList (n, typ) ->
8673            let cols = cols_of_struct typ in
8674            generate_perl_struct_list_code typ cols name style n do_cleanups
8675        | RBufferOut n ->
8676            pr "PREINIT:\n";
8677            pr "      char *%s;\n" n;
8678            pr "      size_t size;\n";
8679            pr "   CODE:\n";
8680            pr "      %s = guestfs_%s " n name;
8681            generate_c_call_args ~handle:"g" style;
8682            pr ";\n";
8683            do_cleanups ();
8684            pr "      if (%s == NULL)\n" n;
8685            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8686            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8687            pr "      free (%s);\n" n;
8688            pr " OUTPUT:\n";
8689            pr "      RETVAL\n"
8690       );
8691
8692       pr "\n"
8693   ) all_functions
8694
8695 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8696   pr "PREINIT:\n";
8697   pr "      struct guestfs_%s_list *%s;\n" typ n;
8698   pr "      int i;\n";
8699   pr "      HV *hv;\n";
8700   pr " PPCODE:\n";
8701   pr "      %s = guestfs_%s " n name;
8702   generate_c_call_args ~handle:"g" style;
8703   pr ";\n";
8704   do_cleanups ();
8705   pr "      if (%s == NULL)\n" n;
8706   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8707   pr "      EXTEND (SP, %s->len);\n" n;
8708   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8709   pr "        hv = newHV ();\n";
8710   List.iter (
8711     function
8712     | name, FString ->
8713         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8714           name (String.length name) n name
8715     | name, FUUID ->
8716         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8717           name (String.length name) n name
8718     | name, FBuffer ->
8719         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8720           name (String.length name) n name n name
8721     | name, (FBytes|FUInt64) ->
8722         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8723           name (String.length name) n name
8724     | name, FInt64 ->
8725         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8726           name (String.length name) n name
8727     | name, (FInt32|FUInt32) ->
8728         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8729           name (String.length name) n name
8730     | name, FChar ->
8731         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8732           name (String.length name) n name
8733     | name, FOptPercent ->
8734         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8735           name (String.length name) n name
8736   ) cols;
8737   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8738   pr "      }\n";
8739   pr "      guestfs_free_%s_list (%s);\n" typ n
8740
8741 and generate_perl_struct_code typ cols name style n do_cleanups =
8742   pr "PREINIT:\n";
8743   pr "      struct guestfs_%s *%s;\n" typ n;
8744   pr " PPCODE:\n";
8745   pr "      %s = guestfs_%s " n name;
8746   generate_c_call_args ~handle:"g" style;
8747   pr ";\n";
8748   do_cleanups ();
8749   pr "      if (%s == NULL)\n" n;
8750   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8751   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8752   List.iter (
8753     fun ((name, _) as col) ->
8754       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8755
8756       match col with
8757       | name, FString ->
8758           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8759             n name
8760       | name, FBuffer ->
8761           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8762             n name n name
8763       | name, FUUID ->
8764           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8765             n name
8766       | name, (FBytes|FUInt64) ->
8767           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8768             n name
8769       | name, FInt64 ->
8770           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8771             n name
8772       | name, (FInt32|FUInt32) ->
8773           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8774             n name
8775       | name, FChar ->
8776           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8777             n name
8778       | name, FOptPercent ->
8779           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8780             n name
8781   ) cols;
8782   pr "      free (%s);\n" n
8783
8784 (* Generate Sys/Guestfs.pm. *)
8785 and generate_perl_pm () =
8786   generate_header HashStyle LGPLv2plus;
8787
8788   pr "\
8789 =pod
8790
8791 =head1 NAME
8792
8793 Sys::Guestfs - Perl bindings for libguestfs
8794
8795 =head1 SYNOPSIS
8796
8797  use Sys::Guestfs;
8798
8799  my $h = Sys::Guestfs->new ();
8800  $h->add_drive ('guest.img');
8801  $h->launch ();
8802  $h->mount ('/dev/sda1', '/');
8803  $h->touch ('/hello');
8804  $h->sync ();
8805
8806 =head1 DESCRIPTION
8807
8808 The C<Sys::Guestfs> module provides a Perl XS binding to the
8809 libguestfs API for examining and modifying virtual machine
8810 disk images.
8811
8812 Amongst the things this is good for: making batch configuration
8813 changes to guests, getting disk used/free statistics (see also:
8814 virt-df), migrating between virtualization systems (see also:
8815 virt-p2v), performing partial backups, performing partial guest
8816 clones, cloning guests and changing registry/UUID/hostname info, and
8817 much else besides.
8818
8819 Libguestfs uses Linux kernel and qemu code, and can access any type of
8820 guest filesystem that Linux and qemu can, including but not limited
8821 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8822 schemes, qcow, qcow2, vmdk.
8823
8824 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8825 LVs, what filesystem is in each LV, etc.).  It can also run commands
8826 in the context of the guest.  Also you can access filesystems over
8827 FUSE.
8828
8829 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8830 functions for using libguestfs from Perl, including integration
8831 with libvirt.
8832
8833 =head1 ERRORS
8834
8835 All errors turn into calls to C<croak> (see L<Carp(3)>).
8836
8837 =head1 METHODS
8838
8839 =over 4
8840
8841 =cut
8842
8843 package Sys::Guestfs;
8844
8845 use strict;
8846 use warnings;
8847
8848 # This version number changes whenever a new function
8849 # is added to the libguestfs API.  It is not directly
8850 # related to the libguestfs version number.
8851 use vars qw($VERSION);
8852 $VERSION = '0.%d';
8853
8854 require XSLoader;
8855 XSLoader::load ('Sys::Guestfs');
8856
8857 =item $h = Sys::Guestfs->new ();
8858
8859 Create a new guestfs handle.
8860
8861 =cut
8862
8863 sub new {
8864   my $proto = shift;
8865   my $class = ref ($proto) || $proto;
8866
8867   my $self = Sys::Guestfs::_create ();
8868   bless $self, $class;
8869   return $self;
8870 }
8871
8872 " max_proc_nr;
8873
8874   (* Actions.  We only need to print documentation for these as
8875    * they are pulled in from the XS code automatically.
8876    *)
8877   List.iter (
8878     fun (name, style, _, flags, _, _, longdesc) ->
8879       if not (List.mem NotInDocs flags) then (
8880         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8881         pr "=item ";
8882         generate_perl_prototype name style;
8883         pr "\n\n";
8884         pr "%s\n\n" longdesc;
8885         if List.mem ProtocolLimitWarning flags then
8886           pr "%s\n\n" protocol_limit_warning;
8887         if List.mem DangerWillRobinson flags then
8888           pr "%s\n\n" danger_will_robinson;
8889         match deprecation_notice flags with
8890         | None -> ()
8891         | Some txt -> pr "%s\n\n" txt
8892       )
8893   ) all_functions_sorted;
8894
8895   (* End of file. *)
8896   pr "\
8897 =cut
8898
8899 1;
8900
8901 =back
8902
8903 =head1 COPYRIGHT
8904
8905 Copyright (C) %s Red Hat Inc.
8906
8907 =head1 LICENSE
8908
8909 Please see the file COPYING.LIB for the full license.
8910
8911 =head1 SEE ALSO
8912
8913 L<guestfs(3)>,
8914 L<guestfish(1)>,
8915 L<http://libguestfs.org>,
8916 L<Sys::Guestfs::Lib(3)>.
8917
8918 =cut
8919 " copyright_years
8920
8921 and generate_perl_prototype name style =
8922   (match fst style with
8923    | RErr -> ()
8924    | RBool n
8925    | RInt n
8926    | RInt64 n
8927    | RConstString n
8928    | RConstOptString n
8929    | RString n
8930    | RBufferOut n -> pr "$%s = " n
8931    | RStruct (n,_)
8932    | RHashtable n -> pr "%%%s = " n
8933    | RStringList n
8934    | RStructList (n,_) -> pr "@%s = " n
8935   );
8936   pr "$h->%s (" name;
8937   let comma = ref false in
8938   List.iter (
8939     fun arg ->
8940       if !comma then pr ", ";
8941       comma := true;
8942       match arg with
8943       | Pathname n | Device n | Dev_or_Path n | String n
8944       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8945           pr "$%s" n
8946       | StringList n | DeviceList n ->
8947           pr "\\@%s" n
8948   ) (snd style);
8949   pr ");"
8950
8951 (* Generate Python C module. *)
8952 and generate_python_c () =
8953   generate_header CStyle LGPLv2plus;
8954
8955   pr "\
8956 #include <Python.h>
8957
8958 #include <stdio.h>
8959 #include <stdlib.h>
8960 #include <assert.h>
8961
8962 #include \"guestfs.h\"
8963
8964 typedef struct {
8965   PyObject_HEAD
8966   guestfs_h *g;
8967 } Pyguestfs_Object;
8968
8969 static guestfs_h *
8970 get_handle (PyObject *obj)
8971 {
8972   assert (obj);
8973   assert (obj != Py_None);
8974   return ((Pyguestfs_Object *) obj)->g;
8975 }
8976
8977 static PyObject *
8978 put_handle (guestfs_h *g)
8979 {
8980   assert (g);
8981   return
8982     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8983 }
8984
8985 /* This list should be freed (but not the strings) after use. */
8986 static char **
8987 get_string_list (PyObject *obj)
8988 {
8989   int i, len;
8990   char **r;
8991
8992   assert (obj);
8993
8994   if (!PyList_Check (obj)) {
8995     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8996     return NULL;
8997   }
8998
8999   len = PyList_Size (obj);
9000   r = malloc (sizeof (char *) * (len+1));
9001   if (r == NULL) {
9002     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9003     return NULL;
9004   }
9005
9006   for (i = 0; i < len; ++i)
9007     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9008   r[len] = NULL;
9009
9010   return r;
9011 }
9012
9013 static PyObject *
9014 put_string_list (char * const * const argv)
9015 {
9016   PyObject *list;
9017   int argc, i;
9018
9019   for (argc = 0; argv[argc] != NULL; ++argc)
9020     ;
9021
9022   list = PyList_New (argc);
9023   for (i = 0; i < argc; ++i)
9024     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9025
9026   return list;
9027 }
9028
9029 static PyObject *
9030 put_table (char * const * const argv)
9031 {
9032   PyObject *list, *item;
9033   int argc, i;
9034
9035   for (argc = 0; argv[argc] != NULL; ++argc)
9036     ;
9037
9038   list = PyList_New (argc >> 1);
9039   for (i = 0; i < argc; i += 2) {
9040     item = PyTuple_New (2);
9041     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9042     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9043     PyList_SetItem (list, i >> 1, item);
9044   }
9045
9046   return list;
9047 }
9048
9049 static void
9050 free_strings (char **argv)
9051 {
9052   int argc;
9053
9054   for (argc = 0; argv[argc] != NULL; ++argc)
9055     free (argv[argc]);
9056   free (argv);
9057 }
9058
9059 static PyObject *
9060 py_guestfs_create (PyObject *self, PyObject *args)
9061 {
9062   guestfs_h *g;
9063
9064   g = guestfs_create ();
9065   if (g == NULL) {
9066     PyErr_SetString (PyExc_RuntimeError,
9067                      \"guestfs.create: failed to allocate handle\");
9068     return NULL;
9069   }
9070   guestfs_set_error_handler (g, NULL, NULL);
9071   return put_handle (g);
9072 }
9073
9074 static PyObject *
9075 py_guestfs_close (PyObject *self, PyObject *args)
9076 {
9077   PyObject *py_g;
9078   guestfs_h *g;
9079
9080   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9081     return NULL;
9082   g = get_handle (py_g);
9083
9084   guestfs_close (g);
9085
9086   Py_INCREF (Py_None);
9087   return Py_None;
9088 }
9089
9090 ";
9091
9092   let emit_put_list_function typ =
9093     pr "static PyObject *\n";
9094     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9095     pr "{\n";
9096     pr "  PyObject *list;\n";
9097     pr "  int i;\n";
9098     pr "\n";
9099     pr "  list = PyList_New (%ss->len);\n" typ;
9100     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9101     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9102     pr "  return list;\n";
9103     pr "};\n";
9104     pr "\n"
9105   in
9106
9107   (* Structures, turned into Python dictionaries. *)
9108   List.iter (
9109     fun (typ, cols) ->
9110       pr "static PyObject *\n";
9111       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9112       pr "{\n";
9113       pr "  PyObject *dict;\n";
9114       pr "\n";
9115       pr "  dict = PyDict_New ();\n";
9116       List.iter (
9117         function
9118         | name, FString ->
9119             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9120             pr "                        PyString_FromString (%s->%s));\n"
9121               typ name
9122         | name, FBuffer ->
9123             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9124             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9125               typ name typ name
9126         | name, FUUID ->
9127             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9128             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9129               typ name
9130         | name, (FBytes|FUInt64) ->
9131             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9132             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9133               typ name
9134         | name, FInt64 ->
9135             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9136             pr "                        PyLong_FromLongLong (%s->%s));\n"
9137               typ name
9138         | name, FUInt32 ->
9139             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9140             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9141               typ name
9142         | name, FInt32 ->
9143             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9144             pr "                        PyLong_FromLong (%s->%s));\n"
9145               typ name
9146         | name, FOptPercent ->
9147             pr "  if (%s->%s >= 0)\n" typ name;
9148             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9149             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9150               typ name;
9151             pr "  else {\n";
9152             pr "    Py_INCREF (Py_None);\n";
9153             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9154             pr "  }\n"
9155         | name, FChar ->
9156             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9157             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9158       ) cols;
9159       pr "  return dict;\n";
9160       pr "};\n";
9161       pr "\n";
9162
9163   ) structs;
9164
9165   (* Emit a put_TYPE_list function definition only if that function is used. *)
9166   List.iter (
9167     function
9168     | typ, (RStructListOnly | RStructAndList) ->
9169         (* generate the function for typ *)
9170         emit_put_list_function typ
9171     | typ, _ -> () (* empty *)
9172   ) (rstructs_used_by all_functions);
9173
9174   (* Python wrapper functions. *)
9175   List.iter (
9176     fun (name, style, _, _, _, _, _) ->
9177       pr "static PyObject *\n";
9178       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9179       pr "{\n";
9180
9181       pr "  PyObject *py_g;\n";
9182       pr "  guestfs_h *g;\n";
9183       pr "  PyObject *py_r;\n";
9184
9185       let error_code =
9186         match fst style with
9187         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9188         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9189         | RConstString _ | RConstOptString _ ->
9190             pr "  const char *r;\n"; "NULL"
9191         | RString _ -> pr "  char *r;\n"; "NULL"
9192         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9193         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9194         | RStructList (_, typ) ->
9195             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9196         | RBufferOut _ ->
9197             pr "  char *r;\n";
9198             pr "  size_t size;\n";
9199             "NULL" in
9200
9201       List.iter (
9202         function
9203         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9204             pr "  const char *%s;\n" n
9205         | OptString n -> pr "  const char *%s;\n" n
9206         | StringList n | DeviceList n ->
9207             pr "  PyObject *py_%s;\n" n;
9208             pr "  char **%s;\n" n
9209         | Bool n -> pr "  int %s;\n" n
9210         | Int n -> pr "  int %s;\n" n
9211         | Int64 n -> pr "  long long %s;\n" n
9212       ) (snd style);
9213
9214       pr "\n";
9215
9216       (* Convert the parameters. *)
9217       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9218       List.iter (
9219         function
9220         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9221         | OptString _ -> pr "z"
9222         | StringList _ | DeviceList _ -> pr "O"
9223         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9224         | Int _ -> pr "i"
9225         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9226                              * emulate C's int/long/long long in Python?
9227                              *)
9228       ) (snd style);
9229       pr ":guestfs_%s\",\n" name;
9230       pr "                         &py_g";
9231       List.iter (
9232         function
9233         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9234         | OptString n -> pr ", &%s" n
9235         | StringList n | DeviceList n -> pr ", &py_%s" n
9236         | Bool n -> pr ", &%s" n
9237         | Int n -> pr ", &%s" n
9238         | Int64 n -> pr ", &%s" n
9239       ) (snd style);
9240
9241       pr "))\n";
9242       pr "    return NULL;\n";
9243
9244       pr "  g = get_handle (py_g);\n";
9245       List.iter (
9246         function
9247         | Pathname _ | Device _ | Dev_or_Path _ | String _
9248         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9249         | StringList n | DeviceList n ->
9250             pr "  %s = get_string_list (py_%s);\n" n n;
9251             pr "  if (!%s) return NULL;\n" n
9252       ) (snd style);
9253
9254       pr "\n";
9255
9256       pr "  r = guestfs_%s " name;
9257       generate_c_call_args ~handle:"g" style;
9258       pr ";\n";
9259
9260       List.iter (
9261         function
9262         | Pathname _ | Device _ | Dev_or_Path _ | String _
9263         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9264         | StringList n | DeviceList n ->
9265             pr "  free (%s);\n" n
9266       ) (snd style);
9267
9268       pr "  if (r == %s) {\n" error_code;
9269       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9270       pr "    return NULL;\n";
9271       pr "  }\n";
9272       pr "\n";
9273
9274       (match fst style with
9275        | RErr ->
9276            pr "  Py_INCREF (Py_None);\n";
9277            pr "  py_r = Py_None;\n"
9278        | RInt _
9279        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9280        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9281        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9282        | RConstOptString _ ->
9283            pr "  if (r)\n";
9284            pr "    py_r = PyString_FromString (r);\n";
9285            pr "  else {\n";
9286            pr "    Py_INCREF (Py_None);\n";
9287            pr "    py_r = Py_None;\n";
9288            pr "  }\n"
9289        | RString _ ->
9290            pr "  py_r = PyString_FromString (r);\n";
9291            pr "  free (r);\n"
9292        | RStringList _ ->
9293            pr "  py_r = put_string_list (r);\n";
9294            pr "  free_strings (r);\n"
9295        | RStruct (_, typ) ->
9296            pr "  py_r = put_%s (r);\n" typ;
9297            pr "  guestfs_free_%s (r);\n" typ
9298        | RStructList (_, typ) ->
9299            pr "  py_r = put_%s_list (r);\n" typ;
9300            pr "  guestfs_free_%s_list (r);\n" typ
9301        | RHashtable n ->
9302            pr "  py_r = put_table (r);\n";
9303            pr "  free_strings (r);\n"
9304        | RBufferOut _ ->
9305            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9306            pr "  free (r);\n"
9307       );
9308
9309       pr "  return py_r;\n";
9310       pr "}\n";
9311       pr "\n"
9312   ) all_functions;
9313
9314   (* Table of functions. *)
9315   pr "static PyMethodDef methods[] = {\n";
9316   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9317   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9318   List.iter (
9319     fun (name, _, _, _, _, _, _) ->
9320       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9321         name name
9322   ) all_functions;
9323   pr "  { NULL, NULL, 0, NULL }\n";
9324   pr "};\n";
9325   pr "\n";
9326
9327   (* Init function. *)
9328   pr "\
9329 void
9330 initlibguestfsmod (void)
9331 {
9332   static int initialized = 0;
9333
9334   if (initialized) return;
9335   Py_InitModule ((char *) \"libguestfsmod\", methods);
9336   initialized = 1;
9337 }
9338 "
9339
9340 (* Generate Python module. *)
9341 and generate_python_py () =
9342   generate_header HashStyle LGPLv2plus;
9343
9344   pr "\
9345 u\"\"\"Python bindings for libguestfs
9346
9347 import guestfs
9348 g = guestfs.GuestFS ()
9349 g.add_drive (\"guest.img\")
9350 g.launch ()
9351 parts = g.list_partitions ()
9352
9353 The guestfs module provides a Python binding to the libguestfs API
9354 for examining and modifying virtual machine disk images.
9355
9356 Amongst the things this is good for: making batch configuration
9357 changes to guests, getting disk used/free statistics (see also:
9358 virt-df), migrating between virtualization systems (see also:
9359 virt-p2v), performing partial backups, performing partial guest
9360 clones, cloning guests and changing registry/UUID/hostname info, and
9361 much else besides.
9362
9363 Libguestfs uses Linux kernel and qemu code, and can access any type of
9364 guest filesystem that Linux and qemu can, including but not limited
9365 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9366 schemes, qcow, qcow2, vmdk.
9367
9368 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9369 LVs, what filesystem is in each LV, etc.).  It can also run commands
9370 in the context of the guest.  Also you can access filesystems over
9371 FUSE.
9372
9373 Errors which happen while using the API are turned into Python
9374 RuntimeError exceptions.
9375
9376 To create a guestfs handle you usually have to perform the following
9377 sequence of calls:
9378
9379 # Create the handle, call add_drive at least once, and possibly
9380 # several times if the guest has multiple block devices:
9381 g = guestfs.GuestFS ()
9382 g.add_drive (\"guest.img\")
9383
9384 # Launch the qemu subprocess and wait for it to become ready:
9385 g.launch ()
9386
9387 # Now you can issue commands, for example:
9388 logvols = g.lvs ()
9389
9390 \"\"\"
9391
9392 import libguestfsmod
9393
9394 class GuestFS:
9395     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9396
9397     def __init__ (self):
9398         \"\"\"Create a new libguestfs handle.\"\"\"
9399         self._o = libguestfsmod.create ()
9400
9401     def __del__ (self):
9402         libguestfsmod.close (self._o)
9403
9404 ";
9405
9406   List.iter (
9407     fun (name, style, _, flags, _, _, longdesc) ->
9408       pr "    def %s " name;
9409       generate_py_call_args ~handle:"self" (snd style);
9410       pr ":\n";
9411
9412       if not (List.mem NotInDocs flags) then (
9413         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9414         let doc =
9415           match fst style with
9416           | RErr | RInt _ | RInt64 _ | RBool _
9417           | RConstOptString _ | RConstString _
9418           | RString _ | RBufferOut _ -> doc
9419           | RStringList _ ->
9420               doc ^ "\n\nThis function returns a list of strings."
9421           | RStruct (_, typ) ->
9422               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9423           | RStructList (_, typ) ->
9424               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9425           | RHashtable _ ->
9426               doc ^ "\n\nThis function returns a dictionary." in
9427         let doc =
9428           if List.mem ProtocolLimitWarning flags then
9429             doc ^ "\n\n" ^ protocol_limit_warning
9430           else doc in
9431         let doc =
9432           if List.mem DangerWillRobinson flags then
9433             doc ^ "\n\n" ^ danger_will_robinson
9434           else doc in
9435         let doc =
9436           match deprecation_notice flags with
9437           | None -> doc
9438           | Some txt -> doc ^ "\n\n" ^ txt in
9439         let doc = pod2text ~width:60 name doc in
9440         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9441         let doc = String.concat "\n        " doc in
9442         pr "        u\"\"\"%s\"\"\"\n" doc;
9443       );
9444       pr "        return libguestfsmod.%s " name;
9445       generate_py_call_args ~handle:"self._o" (snd style);
9446       pr "\n";
9447       pr "\n";
9448   ) all_functions
9449
9450 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9451 and generate_py_call_args ~handle args =
9452   pr "(%s" handle;
9453   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9454   pr ")"
9455
9456 (* Useful if you need the longdesc POD text as plain text.  Returns a
9457  * list of lines.
9458  *
9459  * Because this is very slow (the slowest part of autogeneration),
9460  * we memoize the results.
9461  *)
9462 and pod2text ~width name longdesc =
9463   let key = width, name, longdesc in
9464   try Hashtbl.find pod2text_memo key
9465   with Not_found ->
9466     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9467     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9468     close_out chan;
9469     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9470     let chan = open_process_in cmd in
9471     let lines = ref [] in
9472     let rec loop i =
9473       let line = input_line chan in
9474       if i = 1 then             (* discard the first line of output *)
9475         loop (i+1)
9476       else (
9477         let line = triml line in
9478         lines := line :: !lines;
9479         loop (i+1)
9480       ) in
9481     let lines = try loop 1 with End_of_file -> List.rev !lines in
9482     unlink filename;
9483     (match close_process_in chan with
9484      | WEXITED 0 -> ()
9485      | WEXITED i ->
9486          failwithf "pod2text: process exited with non-zero status (%d)" i
9487      | WSIGNALED i | WSTOPPED i ->
9488          failwithf "pod2text: process signalled or stopped by signal %d" i
9489     );
9490     Hashtbl.add pod2text_memo key lines;
9491     pod2text_memo_updated ();
9492     lines
9493
9494 (* Generate ruby bindings. *)
9495 and generate_ruby_c () =
9496   generate_header CStyle LGPLv2plus;
9497
9498   pr "\
9499 #include <stdio.h>
9500 #include <stdlib.h>
9501
9502 #include <ruby.h>
9503
9504 #include \"guestfs.h\"
9505
9506 #include \"extconf.h\"
9507
9508 /* For Ruby < 1.9 */
9509 #ifndef RARRAY_LEN
9510 #define RARRAY_LEN(r) (RARRAY((r))->len)
9511 #endif
9512
9513 static VALUE m_guestfs;                 /* guestfs module */
9514 static VALUE c_guestfs;                 /* guestfs_h handle */
9515 static VALUE e_Error;                   /* used for all errors */
9516
9517 static void ruby_guestfs_free (void *p)
9518 {
9519   if (!p) return;
9520   guestfs_close ((guestfs_h *) p);
9521 }
9522
9523 static VALUE ruby_guestfs_create (VALUE m)
9524 {
9525   guestfs_h *g;
9526
9527   g = guestfs_create ();
9528   if (!g)
9529     rb_raise (e_Error, \"failed to create guestfs handle\");
9530
9531   /* Don't print error messages to stderr by default. */
9532   guestfs_set_error_handler (g, NULL, NULL);
9533
9534   /* Wrap it, and make sure the close function is called when the
9535    * handle goes away.
9536    */
9537   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9538 }
9539
9540 static VALUE ruby_guestfs_close (VALUE gv)
9541 {
9542   guestfs_h *g;
9543   Data_Get_Struct (gv, guestfs_h, g);
9544
9545   ruby_guestfs_free (g);
9546   DATA_PTR (gv) = NULL;
9547
9548   return Qnil;
9549 }
9550
9551 ";
9552
9553   List.iter (
9554     fun (name, style, _, _, _, _, _) ->
9555       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9556       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9557       pr ")\n";
9558       pr "{\n";
9559       pr "  guestfs_h *g;\n";
9560       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9561       pr "  if (!g)\n";
9562       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9563         name;
9564       pr "\n";
9565
9566       List.iter (
9567         function
9568         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9569             pr "  Check_Type (%sv, T_STRING);\n" n;
9570             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9571             pr "  if (!%s)\n" n;
9572             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9573             pr "              \"%s\", \"%s\");\n" n name
9574         | OptString n ->
9575             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9576         | StringList n | DeviceList n ->
9577             pr "  char **%s;\n" n;
9578             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9579             pr "  {\n";
9580             pr "    int i, len;\n";
9581             pr "    len = RARRAY_LEN (%sv);\n" n;
9582             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9583               n;
9584             pr "    for (i = 0; i < len; ++i) {\n";
9585             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9586             pr "      %s[i] = StringValueCStr (v);\n" n;
9587             pr "    }\n";
9588             pr "    %s[len] = NULL;\n" n;
9589             pr "  }\n";
9590         | Bool n ->
9591             pr "  int %s = RTEST (%sv);\n" n n
9592         | Int n ->
9593             pr "  int %s = NUM2INT (%sv);\n" n n
9594         | Int64 n ->
9595             pr "  long long %s = NUM2LL (%sv);\n" n n
9596       ) (snd style);
9597       pr "\n";
9598
9599       let error_code =
9600         match fst style with
9601         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9602         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9603         | RConstString _ | RConstOptString _ ->
9604             pr "  const char *r;\n"; "NULL"
9605         | RString _ -> pr "  char *r;\n"; "NULL"
9606         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9607         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9608         | RStructList (_, typ) ->
9609             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9610         | RBufferOut _ ->
9611             pr "  char *r;\n";
9612             pr "  size_t size;\n";
9613             "NULL" in
9614       pr "\n";
9615
9616       pr "  r = guestfs_%s " name;
9617       generate_c_call_args ~handle:"g" style;
9618       pr ";\n";
9619
9620       List.iter (
9621         function
9622         | Pathname _ | Device _ | Dev_or_Path _ | String _
9623         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9624         | StringList n | DeviceList n ->
9625             pr "  free (%s);\n" n
9626       ) (snd style);
9627
9628       pr "  if (r == %s)\n" error_code;
9629       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9630       pr "\n";
9631
9632       (match fst style with
9633        | RErr ->
9634            pr "  return Qnil;\n"
9635        | RInt _ | RBool _ ->
9636            pr "  return INT2NUM (r);\n"
9637        | RInt64 _ ->
9638            pr "  return ULL2NUM (r);\n"
9639        | RConstString _ ->
9640            pr "  return rb_str_new2 (r);\n";
9641        | RConstOptString _ ->
9642            pr "  if (r)\n";
9643            pr "    return rb_str_new2 (r);\n";
9644            pr "  else\n";
9645            pr "    return Qnil;\n";
9646        | RString _ ->
9647            pr "  VALUE rv = rb_str_new2 (r);\n";
9648            pr "  free (r);\n";
9649            pr "  return rv;\n";
9650        | RStringList _ ->
9651            pr "  int i, len = 0;\n";
9652            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9653            pr "  VALUE rv = rb_ary_new2 (len);\n";
9654            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9655            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9656            pr "    free (r[i]);\n";
9657            pr "  }\n";
9658            pr "  free (r);\n";
9659            pr "  return rv;\n"
9660        | RStruct (_, typ) ->
9661            let cols = cols_of_struct typ in
9662            generate_ruby_struct_code typ cols
9663        | RStructList (_, typ) ->
9664            let cols = cols_of_struct typ in
9665            generate_ruby_struct_list_code typ cols
9666        | RHashtable _ ->
9667            pr "  VALUE rv = rb_hash_new ();\n";
9668            pr "  int i;\n";
9669            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9670            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9671            pr "    free (r[i]);\n";
9672            pr "    free (r[i+1]);\n";
9673            pr "  }\n";
9674            pr "  free (r);\n";
9675            pr "  return rv;\n"
9676        | RBufferOut _ ->
9677            pr "  VALUE rv = rb_str_new (r, size);\n";
9678            pr "  free (r);\n";
9679            pr "  return rv;\n";
9680       );
9681
9682       pr "}\n";
9683       pr "\n"
9684   ) all_functions;
9685
9686   pr "\
9687 /* Initialize the module. */
9688 void Init__guestfs ()
9689 {
9690   m_guestfs = rb_define_module (\"Guestfs\");
9691   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9692   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9693
9694   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9695   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9696
9697 ";
9698   (* Define the rest of the methods. *)
9699   List.iter (
9700     fun (name, style, _, _, _, _, _) ->
9701       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9702       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9703   ) all_functions;
9704
9705   pr "}\n"
9706
9707 (* Ruby code to return a struct. *)
9708 and generate_ruby_struct_code typ cols =
9709   pr "  VALUE rv = rb_hash_new ();\n";
9710   List.iter (
9711     function
9712     | name, FString ->
9713         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9714     | name, FBuffer ->
9715         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9716     | name, FUUID ->
9717         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9718     | name, (FBytes|FUInt64) ->
9719         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9720     | name, FInt64 ->
9721         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9722     | name, FUInt32 ->
9723         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9724     | name, FInt32 ->
9725         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9726     | name, FOptPercent ->
9727         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9728     | name, FChar -> (* XXX wrong? *)
9729         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9730   ) cols;
9731   pr "  guestfs_free_%s (r);\n" typ;
9732   pr "  return rv;\n"
9733
9734 (* Ruby code to return a struct list. *)
9735 and generate_ruby_struct_list_code typ cols =
9736   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9737   pr "  int i;\n";
9738   pr "  for (i = 0; i < r->len; ++i) {\n";
9739   pr "    VALUE hv = rb_hash_new ();\n";
9740   List.iter (
9741     function
9742     | name, FString ->
9743         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9744     | name, FBuffer ->
9745         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
9746     | name, FUUID ->
9747         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9748     | name, (FBytes|FUInt64) ->
9749         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9750     | name, FInt64 ->
9751         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9752     | name, FUInt32 ->
9753         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9754     | name, FInt32 ->
9755         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9756     | name, FOptPercent ->
9757         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9758     | name, FChar -> (* XXX wrong? *)
9759         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9760   ) cols;
9761   pr "    rb_ary_push (rv, hv);\n";
9762   pr "  }\n";
9763   pr "  guestfs_free_%s_list (r);\n" typ;
9764   pr "  return rv;\n"
9765
9766 (* Generate Java bindings GuestFS.java file. *)
9767 and generate_java_java () =
9768   generate_header CStyle LGPLv2plus;
9769
9770   pr "\
9771 package com.redhat.et.libguestfs;
9772
9773 import java.util.HashMap;
9774 import com.redhat.et.libguestfs.LibGuestFSException;
9775 import com.redhat.et.libguestfs.PV;
9776 import com.redhat.et.libguestfs.VG;
9777 import com.redhat.et.libguestfs.LV;
9778 import com.redhat.et.libguestfs.Stat;
9779 import com.redhat.et.libguestfs.StatVFS;
9780 import com.redhat.et.libguestfs.IntBool;
9781 import com.redhat.et.libguestfs.Dirent;
9782
9783 /**
9784  * The GuestFS object is a libguestfs handle.
9785  *
9786  * @author rjones
9787  */
9788 public class GuestFS {
9789   // Load the native code.
9790   static {
9791     System.loadLibrary (\"guestfs_jni\");
9792   }
9793
9794   /**
9795    * The native guestfs_h pointer.
9796    */
9797   long g;
9798
9799   /**
9800    * Create a libguestfs handle.
9801    *
9802    * @throws LibGuestFSException
9803    */
9804   public GuestFS () throws LibGuestFSException
9805   {
9806     g = _create ();
9807   }
9808   private native long _create () throws LibGuestFSException;
9809
9810   /**
9811    * Close a libguestfs handle.
9812    *
9813    * You can also leave handles to be collected by the garbage
9814    * collector, but this method ensures that the resources used
9815    * by the handle are freed up immediately.  If you call any
9816    * other methods after closing the handle, you will get an
9817    * exception.
9818    *
9819    * @throws LibGuestFSException
9820    */
9821   public void close () throws LibGuestFSException
9822   {
9823     if (g != 0)
9824       _close (g);
9825     g = 0;
9826   }
9827   private native void _close (long g) throws LibGuestFSException;
9828
9829   public void finalize () throws LibGuestFSException
9830   {
9831     close ();
9832   }
9833
9834 ";
9835
9836   List.iter (
9837     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9838       if not (List.mem NotInDocs flags); then (
9839         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9840         let doc =
9841           if List.mem ProtocolLimitWarning flags then
9842             doc ^ "\n\n" ^ protocol_limit_warning
9843           else doc in
9844         let doc =
9845           if List.mem DangerWillRobinson flags then
9846             doc ^ "\n\n" ^ danger_will_robinson
9847           else doc in
9848         let doc =
9849           match deprecation_notice flags with
9850           | None -> doc
9851           | Some txt -> doc ^ "\n\n" ^ txt in
9852         let doc = pod2text ~width:60 name doc in
9853         let doc = List.map (            (* RHBZ#501883 *)
9854           function
9855           | "" -> "<p>"
9856           | nonempty -> nonempty
9857         ) doc in
9858         let doc = String.concat "\n   * " doc in
9859
9860         pr "  /**\n";
9861         pr "   * %s\n" shortdesc;
9862         pr "   * <p>\n";
9863         pr "   * %s\n" doc;
9864         pr "   * @throws LibGuestFSException\n";
9865         pr "   */\n";
9866         pr "  ";
9867       );
9868       generate_java_prototype ~public:true ~semicolon:false name style;
9869       pr "\n";
9870       pr "  {\n";
9871       pr "    if (g == 0)\n";
9872       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9873         name;
9874       pr "    ";
9875       if fst style <> RErr then pr "return ";
9876       pr "_%s " name;
9877       generate_java_call_args ~handle:"g" (snd style);
9878       pr ";\n";
9879       pr "  }\n";
9880       pr "  ";
9881       generate_java_prototype ~privat:true ~native:true name style;
9882       pr "\n";
9883       pr "\n";
9884   ) all_functions;
9885
9886   pr "}\n"
9887
9888 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9889 and generate_java_call_args ~handle args =
9890   pr "(%s" handle;
9891   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9892   pr ")"
9893
9894 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9895     ?(semicolon=true) name style =
9896   if privat then pr "private ";
9897   if public then pr "public ";
9898   if native then pr "native ";
9899
9900   (* return type *)
9901   (match fst style with
9902    | RErr -> pr "void ";
9903    | RInt _ -> pr "int ";
9904    | RInt64 _ -> pr "long ";
9905    | RBool _ -> pr "boolean ";
9906    | RConstString _ | RConstOptString _ | RString _
9907    | RBufferOut _ -> pr "String ";
9908    | RStringList _ -> pr "String[] ";
9909    | RStruct (_, typ) ->
9910        let name = java_name_of_struct typ in
9911        pr "%s " name;
9912    | RStructList (_, typ) ->
9913        let name = java_name_of_struct typ in
9914        pr "%s[] " name;
9915    | RHashtable _ -> pr "HashMap<String,String> ";
9916   );
9917
9918   if native then pr "_%s " name else pr "%s " name;
9919   pr "(";
9920   let needs_comma = ref false in
9921   if native then (
9922     pr "long g";
9923     needs_comma := true
9924   );
9925
9926   (* args *)
9927   List.iter (
9928     fun arg ->
9929       if !needs_comma then pr ", ";
9930       needs_comma := true;
9931
9932       match arg with
9933       | Pathname n
9934       | Device n | Dev_or_Path n
9935       | String n
9936       | OptString n
9937       | FileIn n
9938       | FileOut n ->
9939           pr "String %s" n
9940       | StringList n | DeviceList n ->
9941           pr "String[] %s" n
9942       | Bool n ->
9943           pr "boolean %s" n
9944       | Int n ->
9945           pr "int %s" n
9946       | Int64 n ->
9947           pr "long %s" n
9948   ) (snd style);
9949
9950   pr ")\n";
9951   pr "    throws LibGuestFSException";
9952   if semicolon then pr ";"
9953
9954 and generate_java_struct jtyp cols () =
9955   generate_header CStyle LGPLv2plus;
9956
9957   pr "\
9958 package com.redhat.et.libguestfs;
9959
9960 /**
9961  * Libguestfs %s structure.
9962  *
9963  * @author rjones
9964  * @see GuestFS
9965  */
9966 public class %s {
9967 " jtyp jtyp;
9968
9969   List.iter (
9970     function
9971     | name, FString
9972     | name, FUUID
9973     | name, FBuffer -> pr "  public String %s;\n" name
9974     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9975     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9976     | name, FChar -> pr "  public char %s;\n" name
9977     | name, FOptPercent ->
9978         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9979         pr "  public float %s;\n" name
9980   ) cols;
9981
9982   pr "}\n"
9983
9984 and generate_java_c () =
9985   generate_header CStyle LGPLv2plus;
9986
9987   pr "\
9988 #include <stdio.h>
9989 #include <stdlib.h>
9990 #include <string.h>
9991
9992 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9993 #include \"guestfs.h\"
9994
9995 /* Note that this function returns.  The exception is not thrown
9996  * until after the wrapper function returns.
9997  */
9998 static void
9999 throw_exception (JNIEnv *env, const char *msg)
10000 {
10001   jclass cl;
10002   cl = (*env)->FindClass (env,
10003                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10004   (*env)->ThrowNew (env, cl, msg);
10005 }
10006
10007 JNIEXPORT jlong JNICALL
10008 Java_com_redhat_et_libguestfs_GuestFS__1create
10009   (JNIEnv *env, jobject obj)
10010 {
10011   guestfs_h *g;
10012
10013   g = guestfs_create ();
10014   if (g == NULL) {
10015     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10016     return 0;
10017   }
10018   guestfs_set_error_handler (g, NULL, NULL);
10019   return (jlong) (long) g;
10020 }
10021
10022 JNIEXPORT void JNICALL
10023 Java_com_redhat_et_libguestfs_GuestFS__1close
10024   (JNIEnv *env, jobject obj, jlong jg)
10025 {
10026   guestfs_h *g = (guestfs_h *) (long) jg;
10027   guestfs_close (g);
10028 }
10029
10030 ";
10031
10032   List.iter (
10033     fun (name, style, _, _, _, _, _) ->
10034       pr "JNIEXPORT ";
10035       (match fst style with
10036        | RErr -> pr "void ";
10037        | RInt _ -> pr "jint ";
10038        | RInt64 _ -> pr "jlong ";
10039        | RBool _ -> pr "jboolean ";
10040        | RConstString _ | RConstOptString _ | RString _
10041        | RBufferOut _ -> pr "jstring ";
10042        | RStruct _ | RHashtable _ ->
10043            pr "jobject ";
10044        | RStringList _ | RStructList _ ->
10045            pr "jobjectArray ";
10046       );
10047       pr "JNICALL\n";
10048       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10049       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10050       pr "\n";
10051       pr "  (JNIEnv *env, jobject obj, jlong jg";
10052       List.iter (
10053         function
10054         | Pathname n
10055         | Device n | Dev_or_Path n
10056         | String n
10057         | OptString n
10058         | FileIn n
10059         | FileOut n ->
10060             pr ", jstring j%s" n
10061         | StringList n | DeviceList n ->
10062             pr ", jobjectArray j%s" n
10063         | Bool n ->
10064             pr ", jboolean j%s" n
10065         | Int n ->
10066             pr ", jint j%s" n
10067         | Int64 n ->
10068             pr ", jlong j%s" n
10069       ) (snd style);
10070       pr ")\n";
10071       pr "{\n";
10072       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10073       let error_code, no_ret =
10074         match fst style with
10075         | RErr -> pr "  int r;\n"; "-1", ""
10076         | RBool _
10077         | RInt _ -> pr "  int r;\n"; "-1", "0"
10078         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10079         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10080         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10081         | RString _ ->
10082             pr "  jstring jr;\n";
10083             pr "  char *r;\n"; "NULL", "NULL"
10084         | RStringList _ ->
10085             pr "  jobjectArray jr;\n";
10086             pr "  int r_len;\n";
10087             pr "  jclass cl;\n";
10088             pr "  jstring jstr;\n";
10089             pr "  char **r;\n"; "NULL", "NULL"
10090         | RStruct (_, typ) ->
10091             pr "  jobject jr;\n";
10092             pr "  jclass cl;\n";
10093             pr "  jfieldID fl;\n";
10094             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10095         | RStructList (_, typ) ->
10096             pr "  jobjectArray jr;\n";
10097             pr "  jclass cl;\n";
10098             pr "  jfieldID fl;\n";
10099             pr "  jobject jfl;\n";
10100             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10101         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10102         | RBufferOut _ ->
10103             pr "  jstring jr;\n";
10104             pr "  char *r;\n";
10105             pr "  size_t size;\n";
10106             "NULL", "NULL" in
10107       List.iter (
10108         function
10109         | Pathname n
10110         | Device n | Dev_or_Path n
10111         | String n
10112         | OptString n
10113         | FileIn n
10114         | FileOut n ->
10115             pr "  const char *%s;\n" n
10116         | StringList n | DeviceList n ->
10117             pr "  int %s_len;\n" n;
10118             pr "  const char **%s;\n" n
10119         | Bool n
10120         | Int n ->
10121             pr "  int %s;\n" n
10122         | Int64 n ->
10123             pr "  int64_t %s;\n" n
10124       ) (snd style);
10125
10126       let needs_i =
10127         (match fst style with
10128          | RStringList _ | RStructList _ -> true
10129          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10130          | RConstOptString _
10131          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10132           List.exists (function
10133                        | StringList _ -> true
10134                        | DeviceList _ -> true
10135                        | _ -> false) (snd style) in
10136       if needs_i then
10137         pr "  int i;\n";
10138
10139       pr "\n";
10140
10141       (* Get the parameters. *)
10142       List.iter (
10143         function
10144         | Pathname n
10145         | Device n | Dev_or_Path n
10146         | String n
10147         | FileIn n
10148         | FileOut n ->
10149             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10150         | OptString n ->
10151             (* This is completely undocumented, but Java null becomes
10152              * a NULL parameter.
10153              *)
10154             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10155         | StringList n | DeviceList n ->
10156             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10157             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10158             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10159             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10160               n;
10161             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10162             pr "  }\n";
10163             pr "  %s[%s_len] = NULL;\n" n n;
10164         | Bool n
10165         | Int n
10166         | Int64 n ->
10167             pr "  %s = j%s;\n" n n
10168       ) (snd style);
10169
10170       (* Make the call. *)
10171       pr "  r = guestfs_%s " name;
10172       generate_c_call_args ~handle:"g" style;
10173       pr ";\n";
10174
10175       (* Release the parameters. *)
10176       List.iter (
10177         function
10178         | Pathname n
10179         | Device n | Dev_or_Path n
10180         | String n
10181         | FileIn n
10182         | FileOut n ->
10183             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10184         | OptString n ->
10185             pr "  if (j%s)\n" n;
10186             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10187         | StringList n | DeviceList n ->
10188             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10189             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10190               n;
10191             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10192             pr "  }\n";
10193             pr "  free (%s);\n" n
10194         | Bool n
10195         | Int n
10196         | Int64 n -> ()
10197       ) (snd style);
10198
10199       (* Check for errors. *)
10200       pr "  if (r == %s) {\n" error_code;
10201       pr "    throw_exception (env, guestfs_last_error (g));\n";
10202       pr "    return %s;\n" no_ret;
10203       pr "  }\n";
10204
10205       (* Return value. *)
10206       (match fst style with
10207        | RErr -> ()
10208        | RInt _ -> pr "  return (jint) r;\n"
10209        | RBool _ -> pr "  return (jboolean) r;\n"
10210        | RInt64 _ -> pr "  return (jlong) r;\n"
10211        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10212        | RConstOptString _ ->
10213            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10214        | RString _ ->
10215            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10216            pr "  free (r);\n";
10217            pr "  return jr;\n"
10218        | RStringList _ ->
10219            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10220            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10221            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10222            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10223            pr "  for (i = 0; i < r_len; ++i) {\n";
10224            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10225            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10226            pr "    free (r[i]);\n";
10227            pr "  }\n";
10228            pr "  free (r);\n";
10229            pr "  return jr;\n"
10230        | RStruct (_, typ) ->
10231            let jtyp = java_name_of_struct typ in
10232            let cols = cols_of_struct typ in
10233            generate_java_struct_return typ jtyp cols
10234        | RStructList (_, typ) ->
10235            let jtyp = java_name_of_struct typ in
10236            let cols = cols_of_struct typ in
10237            generate_java_struct_list_return typ jtyp cols
10238        | RHashtable _ ->
10239            (* XXX *)
10240            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10241            pr "  return NULL;\n"
10242        | RBufferOut _ ->
10243            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10244            pr "  free (r);\n";
10245            pr "  return jr;\n"
10246       );
10247
10248       pr "}\n";
10249       pr "\n"
10250   ) all_functions
10251
10252 and generate_java_struct_return typ jtyp cols =
10253   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10254   pr "  jr = (*env)->AllocObject (env, cl);\n";
10255   List.iter (
10256     function
10257     | name, FString ->
10258         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10259         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10260     | name, FUUID ->
10261         pr "  {\n";
10262         pr "    char s[33];\n";
10263         pr "    memcpy (s, r->%s, 32);\n" name;
10264         pr "    s[32] = 0;\n";
10265         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10266         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10267         pr "  }\n";
10268     | name, FBuffer ->
10269         pr "  {\n";
10270         pr "    int len = r->%s_len;\n" name;
10271         pr "    char s[len+1];\n";
10272         pr "    memcpy (s, r->%s, len);\n" name;
10273         pr "    s[len] = 0;\n";
10274         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10275         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10276         pr "  }\n";
10277     | name, (FBytes|FUInt64|FInt64) ->
10278         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10279         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10280     | name, (FUInt32|FInt32) ->
10281         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10282         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10283     | name, FOptPercent ->
10284         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10285         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10286     | name, FChar ->
10287         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10288         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10289   ) cols;
10290   pr "  free (r);\n";
10291   pr "  return jr;\n"
10292
10293 and generate_java_struct_list_return typ jtyp cols =
10294   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10295   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10296   pr "  for (i = 0; i < r->len; ++i) {\n";
10297   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10298   List.iter (
10299     function
10300     | name, FString ->
10301         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10302         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10303     | name, FUUID ->
10304         pr "    {\n";
10305         pr "      char s[33];\n";
10306         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10307         pr "      s[32] = 0;\n";
10308         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10309         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10310         pr "    }\n";
10311     | name, FBuffer ->
10312         pr "    {\n";
10313         pr "      int len = r->val[i].%s_len;\n" name;
10314         pr "      char s[len+1];\n";
10315         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10316         pr "      s[len] = 0;\n";
10317         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10318         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10319         pr "    }\n";
10320     | name, (FBytes|FUInt64|FInt64) ->
10321         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10322         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10323     | name, (FUInt32|FInt32) ->
10324         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10325         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10326     | name, FOptPercent ->
10327         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10328         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10329     | name, FChar ->
10330         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10331         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10332   ) cols;
10333   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10334   pr "  }\n";
10335   pr "  guestfs_free_%s_list (r);\n" typ;
10336   pr "  return jr;\n"
10337
10338 and generate_java_makefile_inc () =
10339   generate_header HashStyle GPLv2plus;
10340
10341   pr "java_built_sources = \\\n";
10342   List.iter (
10343     fun (typ, jtyp) ->
10344         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10345   ) java_structs;
10346   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10347
10348 and generate_haskell_hs () =
10349   generate_header HaskellStyle LGPLv2plus;
10350
10351   (* XXX We only know how to generate partial FFI for Haskell
10352    * at the moment.  Please help out!
10353    *)
10354   let can_generate style =
10355     match style with
10356     | RErr, _
10357     | RInt _, _
10358     | RInt64 _, _ -> true
10359     | RBool _, _
10360     | RConstString _, _
10361     | RConstOptString _, _
10362     | RString _, _
10363     | RStringList _, _
10364     | RStruct _, _
10365     | RStructList _, _
10366     | RHashtable _, _
10367     | RBufferOut _, _ -> false in
10368
10369   pr "\
10370 {-# INCLUDE <guestfs.h> #-}
10371 {-# LANGUAGE ForeignFunctionInterface #-}
10372
10373 module Guestfs (
10374   create";
10375
10376   (* List out the names of the actions we want to export. *)
10377   List.iter (
10378     fun (name, style, _, _, _, _, _) ->
10379       if can_generate style then pr ",\n  %s" name
10380   ) all_functions;
10381
10382   pr "
10383   ) where
10384
10385 -- Unfortunately some symbols duplicate ones already present
10386 -- in Prelude.  We don't know which, so we hard-code a list
10387 -- here.
10388 import Prelude hiding (truncate)
10389
10390 import Foreign
10391 import Foreign.C
10392 import Foreign.C.Types
10393 import IO
10394 import Control.Exception
10395 import Data.Typeable
10396
10397 data GuestfsS = GuestfsS            -- represents the opaque C struct
10398 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10399 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10400
10401 -- XXX define properly later XXX
10402 data PV = PV
10403 data VG = VG
10404 data LV = LV
10405 data IntBool = IntBool
10406 data Stat = Stat
10407 data StatVFS = StatVFS
10408 data Hashtable = Hashtable
10409
10410 foreign import ccall unsafe \"guestfs_create\" c_create
10411   :: IO GuestfsP
10412 foreign import ccall unsafe \"&guestfs_close\" c_close
10413   :: FunPtr (GuestfsP -> IO ())
10414 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10415   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10416
10417 create :: IO GuestfsH
10418 create = do
10419   p <- c_create
10420   c_set_error_handler p nullPtr nullPtr
10421   h <- newForeignPtr c_close p
10422   return h
10423
10424 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10425   :: GuestfsP -> IO CString
10426
10427 -- last_error :: GuestfsH -> IO (Maybe String)
10428 -- last_error h = do
10429 --   str <- withForeignPtr h (\\p -> c_last_error p)
10430 --   maybePeek peekCString str
10431
10432 last_error :: GuestfsH -> IO (String)
10433 last_error h = do
10434   str <- withForeignPtr h (\\p -> c_last_error p)
10435   if (str == nullPtr)
10436     then return \"no error\"
10437     else peekCString str
10438
10439 ";
10440
10441   (* Generate wrappers for each foreign function. *)
10442   List.iter (
10443     fun (name, style, _, _, _, _, _) ->
10444       if can_generate style then (
10445         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10446         pr "  :: ";
10447         generate_haskell_prototype ~handle:"GuestfsP" style;
10448         pr "\n";
10449         pr "\n";
10450         pr "%s :: " name;
10451         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10452         pr "\n";
10453         pr "%s %s = do\n" name
10454           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10455         pr "  r <- ";
10456         (* Convert pointer arguments using with* functions. *)
10457         List.iter (
10458           function
10459           | FileIn n
10460           | FileOut n
10461           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10462           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10463           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10464           | Bool _ | Int _ | Int64 _ -> ()
10465         ) (snd style);
10466         (* Convert integer arguments. *)
10467         let args =
10468           List.map (
10469             function
10470             | Bool n -> sprintf "(fromBool %s)" n
10471             | Int n -> sprintf "(fromIntegral %s)" n
10472             | Int64 n -> sprintf "(fromIntegral %s)" n
10473             | FileIn n | FileOut n
10474             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10475           ) (snd style) in
10476         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10477           (String.concat " " ("p" :: args));
10478         (match fst style with
10479          | RErr | RInt _ | RInt64 _ | RBool _ ->
10480              pr "  if (r == -1)\n";
10481              pr "    then do\n";
10482              pr "      err <- last_error h\n";
10483              pr "      fail err\n";
10484          | RConstString _ | RConstOptString _ | RString _
10485          | RStringList _ | RStruct _
10486          | RStructList _ | RHashtable _ | RBufferOut _ ->
10487              pr "  if (r == nullPtr)\n";
10488              pr "    then do\n";
10489              pr "      err <- last_error h\n";
10490              pr "      fail err\n";
10491         );
10492         (match fst style with
10493          | RErr ->
10494              pr "    else return ()\n"
10495          | RInt _ ->
10496              pr "    else return (fromIntegral r)\n"
10497          | RInt64 _ ->
10498              pr "    else return (fromIntegral r)\n"
10499          | RBool _ ->
10500              pr "    else return (toBool r)\n"
10501          | RConstString _
10502          | RConstOptString _
10503          | RString _
10504          | RStringList _
10505          | RStruct _
10506          | RStructList _
10507          | RHashtable _
10508          | RBufferOut _ ->
10509              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10510         );
10511         pr "\n";
10512       )
10513   ) all_functions
10514
10515 and generate_haskell_prototype ~handle ?(hs = false) style =
10516   pr "%s -> " handle;
10517   let string = if hs then "String" else "CString" in
10518   let int = if hs then "Int" else "CInt" in
10519   let bool = if hs then "Bool" else "CInt" in
10520   let int64 = if hs then "Integer" else "Int64" in
10521   List.iter (
10522     fun arg ->
10523       (match arg with
10524        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10525        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10526        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10527        | Bool _ -> pr "%s" bool
10528        | Int _ -> pr "%s" int
10529        | Int64 _ -> pr "%s" int
10530        | FileIn _ -> pr "%s" string
10531        | FileOut _ -> pr "%s" string
10532       );
10533       pr " -> ";
10534   ) (snd style);
10535   pr "IO (";
10536   (match fst style with
10537    | RErr -> if not hs then pr "CInt"
10538    | RInt _ -> pr "%s" int
10539    | RInt64 _ -> pr "%s" int64
10540    | RBool _ -> pr "%s" bool
10541    | RConstString _ -> pr "%s" string
10542    | RConstOptString _ -> pr "Maybe %s" string
10543    | RString _ -> pr "%s" string
10544    | RStringList _ -> pr "[%s]" string
10545    | RStruct (_, typ) ->
10546        let name = java_name_of_struct typ in
10547        pr "%s" name
10548    | RStructList (_, typ) ->
10549        let name = java_name_of_struct typ in
10550        pr "[%s]" name
10551    | RHashtable _ -> pr "Hashtable"
10552    | RBufferOut _ -> pr "%s" string
10553   );
10554   pr ")"
10555
10556 and generate_csharp () =
10557   generate_header CPlusPlusStyle LGPLv2plus;
10558
10559   (* XXX Make this configurable by the C# assembly users. *)
10560   let library = "libguestfs.so.0" in
10561
10562   pr "\
10563 // These C# bindings are highly experimental at present.
10564 //
10565 // Firstly they only work on Linux (ie. Mono).  In order to get them
10566 // to work on Windows (ie. .Net) you would need to port the library
10567 // itself to Windows first.
10568 //
10569 // The second issue is that some calls are known to be incorrect and
10570 // can cause Mono to segfault.  Particularly: calls which pass or
10571 // return string[], or return any structure value.  This is because
10572 // we haven't worked out the correct way to do this from C#.
10573 //
10574 // The third issue is that when compiling you get a lot of warnings.
10575 // We are not sure whether the warnings are important or not.
10576 //
10577 // Fourthly we do not routinely build or test these bindings as part
10578 // of the make && make check cycle, which means that regressions might
10579 // go unnoticed.
10580 //
10581 // Suggestions and patches are welcome.
10582
10583 // To compile:
10584 //
10585 // gmcs Libguestfs.cs
10586 // mono Libguestfs.exe
10587 //
10588 // (You'll probably want to add a Test class / static main function
10589 // otherwise this won't do anything useful).
10590
10591 using System;
10592 using System.IO;
10593 using System.Runtime.InteropServices;
10594 using System.Runtime.Serialization;
10595 using System.Collections;
10596
10597 namespace Guestfs
10598 {
10599   class Error : System.ApplicationException
10600   {
10601     public Error (string message) : base (message) {}
10602     protected Error (SerializationInfo info, StreamingContext context) {}
10603   }
10604
10605   class Guestfs
10606   {
10607     IntPtr _handle;
10608
10609     [DllImport (\"%s\")]
10610     static extern IntPtr guestfs_create ();
10611
10612     public Guestfs ()
10613     {
10614       _handle = guestfs_create ();
10615       if (_handle == IntPtr.Zero)
10616         throw new Error (\"could not create guestfs handle\");
10617     }
10618
10619     [DllImport (\"%s\")]
10620     static extern void guestfs_close (IntPtr h);
10621
10622     ~Guestfs ()
10623     {
10624       guestfs_close (_handle);
10625     }
10626
10627     [DllImport (\"%s\")]
10628     static extern string guestfs_last_error (IntPtr h);
10629
10630 " library library library;
10631
10632   (* Generate C# structure bindings.  We prefix struct names with
10633    * underscore because C# cannot have conflicting struct names and
10634    * method names (eg. "class stat" and "stat").
10635    *)
10636   List.iter (
10637     fun (typ, cols) ->
10638       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10639       pr "    public class _%s {\n" typ;
10640       List.iter (
10641         function
10642         | name, FChar -> pr "      char %s;\n" name
10643         | name, FString -> pr "      string %s;\n" name
10644         | name, FBuffer ->
10645             pr "      uint %s_len;\n" name;
10646             pr "      string %s;\n" name
10647         | name, FUUID ->
10648             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10649             pr "      string %s;\n" name
10650         | name, FUInt32 -> pr "      uint %s;\n" name
10651         | name, FInt32 -> pr "      int %s;\n" name
10652         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10653         | name, FInt64 -> pr "      long %s;\n" name
10654         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10655       ) cols;
10656       pr "    }\n";
10657       pr "\n"
10658   ) structs;
10659
10660   (* Generate C# function bindings. *)
10661   List.iter (
10662     fun (name, style, _, _, _, shortdesc, _) ->
10663       let rec csharp_return_type () =
10664         match fst style with
10665         | RErr -> "void"
10666         | RBool n -> "bool"
10667         | RInt n -> "int"
10668         | RInt64 n -> "long"
10669         | RConstString n
10670         | RConstOptString n
10671         | RString n
10672         | RBufferOut n -> "string"
10673         | RStruct (_,n) -> "_" ^ n
10674         | RHashtable n -> "Hashtable"
10675         | RStringList n -> "string[]"
10676         | RStructList (_,n) -> sprintf "_%s[]" n
10677
10678       and c_return_type () =
10679         match fst style with
10680         | RErr
10681         | RBool _
10682         | RInt _ -> "int"
10683         | RInt64 _ -> "long"
10684         | RConstString _
10685         | RConstOptString _
10686         | RString _
10687         | RBufferOut _ -> "string"
10688         | RStruct (_,n) -> "_" ^ n
10689         | RHashtable _
10690         | RStringList _ -> "string[]"
10691         | RStructList (_,n) -> sprintf "_%s[]" n
10692
10693       and c_error_comparison () =
10694         match fst style with
10695         | RErr
10696         | RBool _
10697         | RInt _
10698         | RInt64 _ -> "== -1"
10699         | RConstString _
10700         | RConstOptString _
10701         | RString _
10702         | RBufferOut _
10703         | RStruct (_,_)
10704         | RHashtable _
10705         | RStringList _
10706         | RStructList (_,_) -> "== null"
10707
10708       and generate_extern_prototype () =
10709         pr "    static extern %s guestfs_%s (IntPtr h"
10710           (c_return_type ()) name;
10711         List.iter (
10712           function
10713           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10714           | FileIn n | FileOut n ->
10715               pr ", [In] string %s" n
10716           | StringList n | DeviceList n ->
10717               pr ", [In] string[] %s" n
10718           | Bool n ->
10719               pr ", bool %s" n
10720           | Int n ->
10721               pr ", int %s" n
10722           | Int64 n ->
10723               pr ", long %s" n
10724         ) (snd style);
10725         pr ");\n"
10726
10727       and generate_public_prototype () =
10728         pr "    public %s %s (" (csharp_return_type ()) name;
10729         let comma = ref false in
10730         let next () =
10731           if !comma then pr ", ";
10732           comma := true
10733         in
10734         List.iter (
10735           function
10736           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10737           | FileIn n | FileOut n ->
10738               next (); pr "string %s" n
10739           | StringList n | DeviceList n ->
10740               next (); pr "string[] %s" n
10741           | Bool n ->
10742               next (); pr "bool %s" n
10743           | Int n ->
10744               next (); pr "int %s" n
10745           | Int64 n ->
10746               next (); pr "long %s" n
10747         ) (snd style);
10748         pr ")\n"
10749
10750       and generate_call () =
10751         pr "guestfs_%s (_handle" name;
10752         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10753         pr ");\n";
10754       in
10755
10756       pr "    [DllImport (\"%s\")]\n" library;
10757       generate_extern_prototype ();
10758       pr "\n";
10759       pr "    /// <summary>\n";
10760       pr "    /// %s\n" shortdesc;
10761       pr "    /// </summary>\n";
10762       generate_public_prototype ();
10763       pr "    {\n";
10764       pr "      %s r;\n" (c_return_type ());
10765       pr "      r = ";
10766       generate_call ();
10767       pr "      if (r %s)\n" (c_error_comparison ());
10768       pr "        throw new Error (guestfs_last_error (_handle));\n";
10769       (match fst style with
10770        | RErr -> ()
10771        | RBool _ ->
10772            pr "      return r != 0 ? true : false;\n"
10773        | RHashtable _ ->
10774            pr "      Hashtable rr = new Hashtable ();\n";
10775            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10776            pr "        rr.Add (r[i], r[i+1]);\n";
10777            pr "      return rr;\n"
10778        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10779        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10780        | RStructList _ ->
10781            pr "      return r;\n"
10782       );
10783       pr "    }\n";
10784       pr "\n";
10785   ) all_functions_sorted;
10786
10787   pr "  }
10788 }
10789 "
10790
10791 and generate_bindtests () =
10792   generate_header CStyle LGPLv2plus;
10793
10794   pr "\
10795 #include <stdio.h>
10796 #include <stdlib.h>
10797 #include <inttypes.h>
10798 #include <string.h>
10799
10800 #include \"guestfs.h\"
10801 #include \"guestfs-internal.h\"
10802 #include \"guestfs-internal-actions.h\"
10803 #include \"guestfs_protocol.h\"
10804
10805 #define error guestfs_error
10806 #define safe_calloc guestfs_safe_calloc
10807 #define safe_malloc guestfs_safe_malloc
10808
10809 static void
10810 print_strings (char *const *argv)
10811 {
10812   int argc;
10813
10814   printf (\"[\");
10815   for (argc = 0; argv[argc] != NULL; ++argc) {
10816     if (argc > 0) printf (\", \");
10817     printf (\"\\\"%%s\\\"\", argv[argc]);
10818   }
10819   printf (\"]\\n\");
10820 }
10821
10822 /* The test0 function prints its parameters to stdout. */
10823 ";
10824
10825   let test0, tests =
10826     match test_functions with
10827     | [] -> assert false
10828     | test0 :: tests -> test0, tests in
10829
10830   let () =
10831     let (name, style, _, _, _, _, _) = test0 in
10832     generate_prototype ~extern:false ~semicolon:false ~newline:true
10833       ~handle:"g" ~prefix:"guestfs__" name style;
10834     pr "{\n";
10835     List.iter (
10836       function
10837       | Pathname n
10838       | Device n | Dev_or_Path n
10839       | String n
10840       | FileIn n
10841       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10842       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10843       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10844       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10845       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10846       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10847     ) (snd style);
10848     pr "  /* Java changes stdout line buffering so we need this: */\n";
10849     pr "  fflush (stdout);\n";
10850     pr "  return 0;\n";
10851     pr "}\n";
10852     pr "\n" in
10853
10854   List.iter (
10855     fun (name, style, _, _, _, _, _) ->
10856       if String.sub name (String.length name - 3) 3 <> "err" then (
10857         pr "/* Test normal return. */\n";
10858         generate_prototype ~extern:false ~semicolon:false ~newline:true
10859           ~handle:"g" ~prefix:"guestfs__" name style;
10860         pr "{\n";
10861         (match fst style with
10862          | RErr ->
10863              pr "  return 0;\n"
10864          | RInt _ ->
10865              pr "  int r;\n";
10866              pr "  sscanf (val, \"%%d\", &r);\n";
10867              pr "  return r;\n"
10868          | RInt64 _ ->
10869              pr "  int64_t r;\n";
10870              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10871              pr "  return r;\n"
10872          | RBool _ ->
10873              pr "  return STREQ (val, \"true\");\n"
10874          | RConstString _
10875          | RConstOptString _ ->
10876              (* Can't return the input string here.  Return a static
10877               * string so we ensure we get a segfault if the caller
10878               * tries to free it.
10879               *)
10880              pr "  return \"static string\";\n"
10881          | RString _ ->
10882              pr "  return strdup (val);\n"
10883          | RStringList _ ->
10884              pr "  char **strs;\n";
10885              pr "  int n, i;\n";
10886              pr "  sscanf (val, \"%%d\", &n);\n";
10887              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10888              pr "  for (i = 0; i < n; ++i) {\n";
10889              pr "    strs[i] = safe_malloc (g, 16);\n";
10890              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10891              pr "  }\n";
10892              pr "  strs[n] = NULL;\n";
10893              pr "  return strs;\n"
10894          | RStruct (_, typ) ->
10895              pr "  struct guestfs_%s *r;\n" typ;
10896              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10897              pr "  return r;\n"
10898          | RStructList (_, typ) ->
10899              pr "  struct guestfs_%s_list *r;\n" typ;
10900              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10901              pr "  sscanf (val, \"%%d\", &r->len);\n";
10902              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10903              pr "  return r;\n"
10904          | RHashtable _ ->
10905              pr "  char **strs;\n";
10906              pr "  int n, i;\n";
10907              pr "  sscanf (val, \"%%d\", &n);\n";
10908              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10909              pr "  for (i = 0; i < n; ++i) {\n";
10910              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10911              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10912              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10913              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10914              pr "  }\n";
10915              pr "  strs[n*2] = NULL;\n";
10916              pr "  return strs;\n"
10917          | RBufferOut _ ->
10918              pr "  return strdup (val);\n"
10919         );
10920         pr "}\n";
10921         pr "\n"
10922       ) else (
10923         pr "/* Test error return. */\n";
10924         generate_prototype ~extern:false ~semicolon:false ~newline:true
10925           ~handle:"g" ~prefix:"guestfs__" name style;
10926         pr "{\n";
10927         pr "  error (g, \"error\");\n";
10928         (match fst style with
10929          | RErr | RInt _ | RInt64 _ | RBool _ ->
10930              pr "  return -1;\n"
10931          | RConstString _ | RConstOptString _
10932          | RString _ | RStringList _ | RStruct _
10933          | RStructList _
10934          | RHashtable _
10935          | RBufferOut _ ->
10936              pr "  return NULL;\n"
10937         );
10938         pr "}\n";
10939         pr "\n"
10940       )
10941   ) tests
10942
10943 and generate_ocaml_bindtests () =
10944   generate_header OCamlStyle GPLv2plus;
10945
10946   pr "\
10947 let () =
10948   let g = Guestfs.create () in
10949 ";
10950
10951   let mkargs args =
10952     String.concat " " (
10953       List.map (
10954         function
10955         | CallString s -> "\"" ^ s ^ "\""
10956         | CallOptString None -> "None"
10957         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10958         | CallStringList xs ->
10959             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10960         | CallInt i when i >= 0 -> string_of_int i
10961         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10962         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10963         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10964         | CallBool b -> string_of_bool b
10965       ) args
10966     )
10967   in
10968
10969   generate_lang_bindtests (
10970     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10971   );
10972
10973   pr "print_endline \"EOF\"\n"
10974
10975 and generate_perl_bindtests () =
10976   pr "#!/usr/bin/perl -w\n";
10977   generate_header HashStyle GPLv2plus;
10978
10979   pr "\
10980 use strict;
10981
10982 use Sys::Guestfs;
10983
10984 my $g = Sys::Guestfs->new ();
10985 ";
10986
10987   let mkargs args =
10988     String.concat ", " (
10989       List.map (
10990         function
10991         | CallString s -> "\"" ^ s ^ "\""
10992         | CallOptString None -> "undef"
10993         | CallOptString (Some s) -> sprintf "\"%s\"" s
10994         | CallStringList xs ->
10995             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10996         | CallInt i -> string_of_int i
10997         | CallInt64 i -> Int64.to_string i
10998         | CallBool b -> if b then "1" else "0"
10999       ) args
11000     )
11001   in
11002
11003   generate_lang_bindtests (
11004     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11005   );
11006
11007   pr "print \"EOF\\n\"\n"
11008
11009 and generate_python_bindtests () =
11010   generate_header HashStyle GPLv2plus;
11011
11012   pr "\
11013 import guestfs
11014
11015 g = guestfs.GuestFS ()
11016 ";
11017
11018   let mkargs args =
11019     String.concat ", " (
11020       List.map (
11021         function
11022         | CallString s -> "\"" ^ s ^ "\""
11023         | CallOptString None -> "None"
11024         | CallOptString (Some s) -> sprintf "\"%s\"" s
11025         | CallStringList xs ->
11026             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11027         | CallInt i -> string_of_int i
11028         | CallInt64 i -> Int64.to_string i
11029         | CallBool b -> if b then "1" else "0"
11030       ) args
11031     )
11032   in
11033
11034   generate_lang_bindtests (
11035     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11036   );
11037
11038   pr "print \"EOF\"\n"
11039
11040 and generate_ruby_bindtests () =
11041   generate_header HashStyle GPLv2plus;
11042
11043   pr "\
11044 require 'guestfs'
11045
11046 g = Guestfs::create()
11047 ";
11048
11049   let mkargs args =
11050     String.concat ", " (
11051       List.map (
11052         function
11053         | CallString s -> "\"" ^ s ^ "\""
11054         | CallOptString None -> "nil"
11055         | CallOptString (Some s) -> sprintf "\"%s\"" s
11056         | CallStringList xs ->
11057             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11058         | CallInt i -> string_of_int i
11059         | CallInt64 i -> Int64.to_string i
11060         | CallBool b -> string_of_bool b
11061       ) args
11062     )
11063   in
11064
11065   generate_lang_bindtests (
11066     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11067   );
11068
11069   pr "print \"EOF\\n\"\n"
11070
11071 and generate_java_bindtests () =
11072   generate_header CStyle GPLv2plus;
11073
11074   pr "\
11075 import com.redhat.et.libguestfs.*;
11076
11077 public class Bindtests {
11078     public static void main (String[] argv)
11079     {
11080         try {
11081             GuestFS g = new GuestFS ();
11082 ";
11083
11084   let mkargs args =
11085     String.concat ", " (
11086       List.map (
11087         function
11088         | CallString s -> "\"" ^ s ^ "\""
11089         | CallOptString None -> "null"
11090         | CallOptString (Some s) -> sprintf "\"%s\"" s
11091         | CallStringList xs ->
11092             "new String[]{" ^
11093               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11094         | CallInt i -> string_of_int i
11095         | CallInt64 i -> Int64.to_string i
11096         | CallBool b -> string_of_bool b
11097       ) args
11098     )
11099   in
11100
11101   generate_lang_bindtests (
11102     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11103   );
11104
11105   pr "
11106             System.out.println (\"EOF\");
11107         }
11108         catch (Exception exn) {
11109             System.err.println (exn);
11110             System.exit (1);
11111         }
11112     }
11113 }
11114 "
11115
11116 and generate_haskell_bindtests () =
11117   generate_header HaskellStyle GPLv2plus;
11118
11119   pr "\
11120 module Bindtests where
11121 import qualified Guestfs
11122
11123 main = do
11124   g <- Guestfs.create
11125 ";
11126
11127   let mkargs args =
11128     String.concat " " (
11129       List.map (
11130         function
11131         | CallString s -> "\"" ^ s ^ "\""
11132         | CallOptString None -> "Nothing"
11133         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11134         | CallStringList xs ->
11135             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11136         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11137         | CallInt i -> string_of_int i
11138         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11139         | CallInt64 i -> Int64.to_string i
11140         | CallBool true -> "True"
11141         | CallBool false -> "False"
11142       ) args
11143     )
11144   in
11145
11146   generate_lang_bindtests (
11147     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11148   );
11149
11150   pr "  putStrLn \"EOF\"\n"
11151
11152 (* Language-independent bindings tests - we do it this way to
11153  * ensure there is parity in testing bindings across all languages.
11154  *)
11155 and generate_lang_bindtests call =
11156   call "test0" [CallString "abc"; CallOptString (Some "def");
11157                 CallStringList []; CallBool false;
11158                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11159   call "test0" [CallString "abc"; CallOptString None;
11160                 CallStringList []; CallBool false;
11161                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11162   call "test0" [CallString ""; CallOptString (Some "def");
11163                 CallStringList []; CallBool false;
11164                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11165   call "test0" [CallString ""; CallOptString (Some "");
11166                 CallStringList []; CallBool false;
11167                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11168   call "test0" [CallString "abc"; CallOptString (Some "def");
11169                 CallStringList ["1"]; CallBool false;
11170                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11171   call "test0" [CallString "abc"; CallOptString (Some "def");
11172                 CallStringList ["1"; "2"]; CallBool false;
11173                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11174   call "test0" [CallString "abc"; CallOptString (Some "def");
11175                 CallStringList ["1"]; CallBool true;
11176                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11177   call "test0" [CallString "abc"; CallOptString (Some "def");
11178                 CallStringList ["1"]; CallBool false;
11179                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11180   call "test0" [CallString "abc"; CallOptString (Some "def");
11181                 CallStringList ["1"]; CallBool false;
11182                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11183   call "test0" [CallString "abc"; CallOptString (Some "def");
11184                 CallStringList ["1"]; CallBool false;
11185                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11186   call "test0" [CallString "abc"; CallOptString (Some "def");
11187                 CallStringList ["1"]; CallBool false;
11188                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11189   call "test0" [CallString "abc"; CallOptString (Some "def");
11190                 CallStringList ["1"]; CallBool false;
11191                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11192   call "test0" [CallString "abc"; CallOptString (Some "def");
11193                 CallStringList ["1"]; CallBool false;
11194                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11195
11196 (* XXX Add here tests of the return and error functions. *)
11197
11198 (* Code to generator bindings for virt-inspector.  Currently only
11199  * implemented for OCaml code (for virt-p2v 2.0).
11200  *)
11201 let rng_input = "inspector/virt-inspector.rng"
11202
11203 (* Read the input file and parse it into internal structures.  This is
11204  * by no means a complete RELAX NG parser, but is just enough to be
11205  * able to parse the specific input file.
11206  *)
11207 type rng =
11208   | Element of string * rng list        (* <element name=name/> *)
11209   | Attribute of string * rng list        (* <attribute name=name/> *)
11210   | Interleave of rng list                (* <interleave/> *)
11211   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11212   | OneOrMore of rng                        (* <oneOrMore/> *)
11213   | Optional of rng                        (* <optional/> *)
11214   | Choice of string list                (* <choice><value/>*</choice> *)
11215   | Value of string                        (* <value>str</value> *)
11216   | Text                                (* <text/> *)
11217
11218 let rec string_of_rng = function
11219   | Element (name, xs) ->
11220       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11221   | Attribute (name, xs) ->
11222       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11223   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11224   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11225   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11226   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11227   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11228   | Value value -> "Value \"" ^ value ^ "\""
11229   | Text -> "Text"
11230
11231 and string_of_rng_list xs =
11232   String.concat ", " (List.map string_of_rng xs)
11233
11234 let rec parse_rng ?defines context = function
11235   | [] -> []
11236   | Xml.Element ("element", ["name", name], children) :: rest ->
11237       Element (name, parse_rng ?defines context children)
11238       :: parse_rng ?defines context rest
11239   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11240       Attribute (name, parse_rng ?defines context children)
11241       :: parse_rng ?defines context rest
11242   | Xml.Element ("interleave", [], children) :: rest ->
11243       Interleave (parse_rng ?defines context children)
11244       :: parse_rng ?defines context rest
11245   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11246       let rng = parse_rng ?defines context [child] in
11247       (match rng with
11248        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11249        | _ ->
11250            failwithf "%s: <zeroOrMore> contains more than one child element"
11251              context
11252       )
11253   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11254       let rng = parse_rng ?defines context [child] in
11255       (match rng with
11256        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11257        | _ ->
11258            failwithf "%s: <oneOrMore> contains more than one child element"
11259              context
11260       )
11261   | Xml.Element ("optional", [], [child]) :: rest ->
11262       let rng = parse_rng ?defines context [child] in
11263       (match rng with
11264        | [child] -> Optional child :: parse_rng ?defines context rest
11265        | _ ->
11266            failwithf "%s: <optional> contains more than one child element"
11267              context
11268       )
11269   | Xml.Element ("choice", [], children) :: rest ->
11270       let values = List.map (
11271         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11272         | _ ->
11273             failwithf "%s: can't handle anything except <value> in <choice>"
11274               context
11275       ) children in
11276       Choice values
11277       :: parse_rng ?defines context rest
11278   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11279       Value value :: parse_rng ?defines context rest
11280   | Xml.Element ("text", [], []) :: rest ->
11281       Text :: parse_rng ?defines context rest
11282   | Xml.Element ("ref", ["name", name], []) :: rest ->
11283       (* Look up the reference.  Because of limitations in this parser,
11284        * we can't handle arbitrarily nested <ref> yet.  You can only
11285        * use <ref> from inside <start>.
11286        *)
11287       (match defines with
11288        | None ->
11289            failwithf "%s: contains <ref>, but no refs are defined yet" context
11290        | Some map ->
11291            let rng = StringMap.find name map in
11292            rng @ parse_rng ?defines context rest
11293       )
11294   | x :: _ ->
11295       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11296
11297 let grammar =
11298   let xml = Xml.parse_file rng_input in
11299   match xml with
11300   | Xml.Element ("grammar", _,
11301                  Xml.Element ("start", _, gram) :: defines) ->
11302       (* The <define/> elements are referenced in the <start> section,
11303        * so build a map of those first.
11304        *)
11305       let defines = List.fold_left (
11306         fun map ->
11307           function Xml.Element ("define", ["name", name], defn) ->
11308             StringMap.add name defn map
11309           | _ ->
11310               failwithf "%s: expected <define name=name/>" rng_input
11311       ) StringMap.empty defines in
11312       let defines = StringMap.mapi parse_rng defines in
11313
11314       (* Parse the <start> clause, passing the defines. *)
11315       parse_rng ~defines "<start>" gram
11316   | _ ->
11317       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11318         rng_input
11319
11320 let name_of_field = function
11321   | Element (name, _) | Attribute (name, _)
11322   | ZeroOrMore (Element (name, _))
11323   | OneOrMore (Element (name, _))
11324   | Optional (Element (name, _)) -> name
11325   | Optional (Attribute (name, _)) -> name
11326   | Text -> (* an unnamed field in an element *)
11327       "data"
11328   | rng ->
11329       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11330
11331 (* At the moment this function only generates OCaml types.  However we
11332  * should parameterize it later so it can generate types/structs in a
11333  * variety of languages.
11334  *)
11335 let generate_types xs =
11336   (* A simple type is one that can be printed out directly, eg.
11337    * "string option".  A complex type is one which has a name and has
11338    * to be defined via another toplevel definition, eg. a struct.
11339    *
11340    * generate_type generates code for either simple or complex types.
11341    * In the simple case, it returns the string ("string option").  In
11342    * the complex case, it returns the name ("mountpoint").  In the
11343    * complex case it has to print out the definition before returning,
11344    * so it should only be called when we are at the beginning of a
11345    * new line (BOL context).
11346    *)
11347   let rec generate_type = function
11348     | Text ->                                (* string *)
11349         "string", true
11350     | Choice values ->                        (* [`val1|`val2|...] *)
11351         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11352     | ZeroOrMore rng ->                        (* <rng> list *)
11353         let t, is_simple = generate_type rng in
11354         t ^ " list (* 0 or more *)", is_simple
11355     | OneOrMore rng ->                        (* <rng> list *)
11356         let t, is_simple = generate_type rng in
11357         t ^ " list (* 1 or more *)", is_simple
11358                                         (* virt-inspector hack: bool *)
11359     | Optional (Attribute (name, [Value "1"])) ->
11360         "bool", true
11361     | Optional rng ->                        (* <rng> list *)
11362         let t, is_simple = generate_type rng in
11363         t ^ " option", is_simple
11364                                         (* type name = { fields ... } *)
11365     | Element (name, fields) when is_attrs_interleave fields ->
11366         generate_type_struct name (get_attrs_interleave fields)
11367     | Element (name, [field])                (* type name = field *)
11368     | Attribute (name, [field]) ->
11369         let t, is_simple = generate_type field in
11370         if is_simple then (t, true)
11371         else (
11372           pr "type %s = %s\n" name t;
11373           name, false
11374         )
11375     | Element (name, fields) ->              (* type name = { fields ... } *)
11376         generate_type_struct name fields
11377     | rng ->
11378         failwithf "generate_type failed at: %s" (string_of_rng rng)
11379
11380   and is_attrs_interleave = function
11381     | [Interleave _] -> true
11382     | Attribute _ :: fields -> is_attrs_interleave fields
11383     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11384     | _ -> false
11385
11386   and get_attrs_interleave = function
11387     | [Interleave fields] -> fields
11388     | ((Attribute _) as field) :: fields
11389     | ((Optional (Attribute _)) as field) :: fields ->
11390         field :: get_attrs_interleave fields
11391     | _ -> assert false
11392
11393   and generate_types xs =
11394     List.iter (fun x -> ignore (generate_type x)) xs
11395
11396   and generate_type_struct name fields =
11397     (* Calculate the types of the fields first.  We have to do this
11398      * before printing anything so we are still in BOL context.
11399      *)
11400     let types = List.map fst (List.map generate_type fields) in
11401
11402     (* Special case of a struct containing just a string and another
11403      * field.  Turn it into an assoc list.
11404      *)
11405     match types with
11406     | ["string"; other] ->
11407         let fname1, fname2 =
11408           match fields with
11409           | [f1; f2] -> name_of_field f1, name_of_field f2
11410           | _ -> assert false in
11411         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11412         name, false
11413
11414     | types ->
11415         pr "type %s = {\n" name;
11416         List.iter (
11417           fun (field, ftype) ->
11418             let fname = name_of_field field in
11419             pr "  %s_%s : %s;\n" name fname ftype
11420         ) (List.combine fields types);
11421         pr "}\n";
11422         (* Return the name of this type, and
11423          * false because it's not a simple type.
11424          *)
11425         name, false
11426   in
11427
11428   generate_types xs
11429
11430 let generate_parsers xs =
11431   (* As for generate_type above, generate_parser makes a parser for
11432    * some type, and returns the name of the parser it has generated.
11433    * Because it (may) need to print something, it should always be
11434    * called in BOL context.
11435    *)
11436   let rec generate_parser = function
11437     | Text ->                                (* string *)
11438         "string_child_or_empty"
11439     | Choice values ->                        (* [`val1|`val2|...] *)
11440         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11441           (String.concat "|"
11442              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11443     | ZeroOrMore rng ->                        (* <rng> list *)
11444         let pa = generate_parser rng in
11445         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11446     | OneOrMore rng ->                        (* <rng> list *)
11447         let pa = generate_parser rng in
11448         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11449                                         (* virt-inspector hack: bool *)
11450     | Optional (Attribute (name, [Value "1"])) ->
11451         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11452     | Optional rng ->                        (* <rng> list *)
11453         let pa = generate_parser rng in
11454         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11455                                         (* type name = { fields ... } *)
11456     | Element (name, fields) when is_attrs_interleave fields ->
11457         generate_parser_struct name (get_attrs_interleave fields)
11458     | Element (name, [field]) ->        (* type name = field *)
11459         let pa = generate_parser field in
11460         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11461         pr "let %s =\n" parser_name;
11462         pr "  %s\n" pa;
11463         pr "let parse_%s = %s\n" name parser_name;
11464         parser_name
11465     | Attribute (name, [field]) ->
11466         let pa = generate_parser field in
11467         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11468         pr "let %s =\n" parser_name;
11469         pr "  %s\n" pa;
11470         pr "let parse_%s = %s\n" name parser_name;
11471         parser_name
11472     | Element (name, fields) ->              (* type name = { fields ... } *)
11473         generate_parser_struct name ([], fields)
11474     | rng ->
11475         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11476
11477   and is_attrs_interleave = function
11478     | [Interleave _] -> true
11479     | Attribute _ :: fields -> is_attrs_interleave fields
11480     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11481     | _ -> false
11482
11483   and get_attrs_interleave = function
11484     | [Interleave fields] -> [], fields
11485     | ((Attribute _) as field) :: fields
11486     | ((Optional (Attribute _)) as field) :: fields ->
11487         let attrs, interleaves = get_attrs_interleave fields in
11488         (field :: attrs), interleaves
11489     | _ -> assert false
11490
11491   and generate_parsers xs =
11492     List.iter (fun x -> ignore (generate_parser x)) xs
11493
11494   and generate_parser_struct name (attrs, interleaves) =
11495     (* Generate parsers for the fields first.  We have to do this
11496      * before printing anything so we are still in BOL context.
11497      *)
11498     let fields = attrs @ interleaves in
11499     let pas = List.map generate_parser fields in
11500
11501     (* Generate an intermediate tuple from all the fields first.
11502      * If the type is just a string + another field, then we will
11503      * return this directly, otherwise it is turned into a record.
11504      *
11505      * RELAX NG note: This code treats <interleave> and plain lists of
11506      * fields the same.  In other words, it doesn't bother enforcing
11507      * any ordering of fields in the XML.
11508      *)
11509     pr "let parse_%s x =\n" name;
11510     pr "  let t = (\n    ";
11511     let comma = ref false in
11512     List.iter (
11513       fun x ->
11514         if !comma then pr ",\n    ";
11515         comma := true;
11516         match x with
11517         | Optional (Attribute (fname, [field])), pa ->
11518             pr "%s x" pa
11519         | Optional (Element (fname, [field])), pa ->
11520             pr "%s (optional_child %S x)" pa fname
11521         | Attribute (fname, [Text]), _ ->
11522             pr "attribute %S x" fname
11523         | (ZeroOrMore _ | OneOrMore _), pa ->
11524             pr "%s x" pa
11525         | Text, pa ->
11526             pr "%s x" pa
11527         | (field, pa) ->
11528             let fname = name_of_field field in
11529             pr "%s (child %S x)" pa fname
11530     ) (List.combine fields pas);
11531     pr "\n  ) in\n";
11532
11533     (match fields with
11534      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11535          pr "  t\n"
11536
11537      | _ ->
11538          pr "  (Obj.magic t : %s)\n" name
11539 (*
11540          List.iter (
11541            function
11542            | (Optional (Attribute (fname, [field])), pa) ->
11543                pr "  %s_%s =\n" name fname;
11544                pr "    %s x;\n" pa
11545            | (Optional (Element (fname, [field])), pa) ->
11546                pr "  %s_%s =\n" name fname;
11547                pr "    (let x = optional_child %S x in\n" fname;
11548                pr "     %s x);\n" pa
11549            | (field, pa) ->
11550                let fname = name_of_field field in
11551                pr "  %s_%s =\n" name fname;
11552                pr "    (let x = child %S x in\n" fname;
11553                pr "     %s x);\n" pa
11554          ) (List.combine fields pas);
11555          pr "}\n"
11556 *)
11557     );
11558     sprintf "parse_%s" name
11559   in
11560
11561   generate_parsers xs
11562
11563 (* Generate ocaml/guestfs_inspector.mli. *)
11564 let generate_ocaml_inspector_mli () =
11565   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11566
11567   pr "\
11568 (** This is an OCaml language binding to the external [virt-inspector]
11569     program.
11570
11571     For more information, please read the man page [virt-inspector(1)].
11572 *)
11573
11574 ";
11575
11576   generate_types grammar;
11577   pr "(** The nested information returned from the {!inspect} function. *)\n";
11578   pr "\n";
11579
11580   pr "\
11581 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11582 (** To inspect a libvirt domain called [name], pass a singleton
11583     list: [inspect [name]].  When using libvirt only, you may
11584     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11585
11586     To inspect a disk image or images, pass a list of the filenames
11587     of the disk images: [inspect filenames]
11588
11589     This function inspects the given guest or disk images and
11590     returns a list of operating system(s) found and a large amount
11591     of information about them.  In the vast majority of cases,
11592     a virtual machine only contains a single operating system.
11593
11594     If the optional [~xml] parameter is given, then this function
11595     skips running the external virt-inspector program and just
11596     parses the given XML directly (which is expected to be XML
11597     produced from a previous run of virt-inspector).  The list of
11598     names and connect URI are ignored in this case.
11599
11600     This function can throw a wide variety of exceptions, for example
11601     if the external virt-inspector program cannot be found, or if
11602     it doesn't generate valid XML.
11603 *)
11604 "
11605
11606 (* Generate ocaml/guestfs_inspector.ml. *)
11607 let generate_ocaml_inspector_ml () =
11608   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11609
11610   pr "open Unix\n";
11611   pr "\n";
11612
11613   generate_types grammar;
11614   pr "\n";
11615
11616   pr "\
11617 (* Misc functions which are used by the parser code below. *)
11618 let first_child = function
11619   | Xml.Element (_, _, c::_) -> c
11620   | Xml.Element (name, _, []) ->
11621       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11622   | Xml.PCData str ->
11623       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11624
11625 let string_child_or_empty = function
11626   | Xml.Element (_, _, [Xml.PCData s]) -> s
11627   | Xml.Element (_, _, []) -> \"\"
11628   | Xml.Element (x, _, _) ->
11629       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11630                 x ^ \" instead\")
11631   | Xml.PCData str ->
11632       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11633
11634 let optional_child name xml =
11635   let children = Xml.children xml in
11636   try
11637     Some (List.find (function
11638                      | Xml.Element (n, _, _) when n = name -> true
11639                      | _ -> false) children)
11640   with
11641     Not_found -> None
11642
11643 let child name xml =
11644   match optional_child name xml with
11645   | Some c -> c
11646   | None ->
11647       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11648
11649 let attribute name xml =
11650   try Xml.attrib xml name
11651   with Xml.No_attribute _ ->
11652     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11653
11654 ";
11655
11656   generate_parsers grammar;
11657   pr "\n";
11658
11659   pr "\
11660 (* Run external virt-inspector, then use parser to parse the XML. *)
11661 let inspect ?connect ?xml names =
11662   let xml =
11663     match xml with
11664     | None ->
11665         if names = [] then invalid_arg \"inspect: no names given\";
11666         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11667           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11668           names in
11669         let cmd = List.map Filename.quote cmd in
11670         let cmd = String.concat \" \" cmd in
11671         let chan = open_process_in cmd in
11672         let xml = Xml.parse_in chan in
11673         (match close_process_in chan with
11674          | WEXITED 0 -> ()
11675          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11676          | WSIGNALED i | WSTOPPED i ->
11677              failwith (\"external virt-inspector command died or stopped on sig \" ^
11678                        string_of_int i)
11679         );
11680         xml
11681     | Some doc ->
11682         Xml.parse_string doc in
11683   parse_operatingsystems xml
11684 "
11685
11686 and generate_max_proc_nr () =
11687   pr "%d\n" max_proc_nr
11688
11689 let output_to filename k =
11690   let filename_new = filename ^ ".new" in
11691   chan := open_out filename_new;
11692   k ();
11693   close_out !chan;
11694   chan := Pervasives.stdout;
11695
11696   (* Is the new file different from the current file? *)
11697   if Sys.file_exists filename && files_equal filename filename_new then
11698     unlink filename_new                 (* same, so skip it *)
11699   else (
11700     (* different, overwrite old one *)
11701     (try chmod filename 0o644 with Unix_error _ -> ());
11702     rename filename_new filename;
11703     chmod filename 0o444;
11704     printf "written %s\n%!" filename;
11705   )
11706
11707 let perror msg = function
11708   | Unix_error (err, _, _) ->
11709       eprintf "%s: %s\n" msg (error_message err)
11710   | exn ->
11711       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11712
11713 (* Main program. *)
11714 let () =
11715   let lock_fd =
11716     try openfile "HACKING" [O_RDWR] 0
11717     with
11718     | Unix_error (ENOENT, _, _) ->
11719         eprintf "\
11720 You are probably running this from the wrong directory.
11721 Run it from the top source directory using the command
11722   src/generator.ml
11723 ";
11724         exit 1
11725     | exn ->
11726         perror "open: HACKING" exn;
11727         exit 1 in
11728
11729   (* Acquire a lock so parallel builds won't try to run the generator
11730    * twice at the same time.  Subsequent builds will wait for the first
11731    * one to finish.  Note the lock is released implicitly when the
11732    * program exits.
11733    *)
11734   (try lockf lock_fd F_LOCK 1
11735    with exn ->
11736      perror "lock: HACKING" exn;
11737      exit 1);
11738
11739   check_functions ();
11740
11741   output_to "src/guestfs_protocol.x" generate_xdr;
11742   output_to "src/guestfs-structs.h" generate_structs_h;
11743   output_to "src/guestfs-actions.h" generate_actions_h;
11744   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11745   output_to "src/guestfs-actions.c" generate_client_actions;
11746   output_to "src/guestfs-bindtests.c" generate_bindtests;
11747   output_to "src/guestfs-structs.pod" generate_structs_pod;
11748   output_to "src/guestfs-actions.pod" generate_actions_pod;
11749   output_to "src/guestfs-availability.pod" generate_availability_pod;
11750   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11751   output_to "src/libguestfs.syms" generate_linker_script;
11752   output_to "daemon/actions.h" generate_daemon_actions_h;
11753   output_to "daemon/stubs.c" generate_daemon_actions;
11754   output_to "daemon/names.c" generate_daemon_names;
11755   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11756   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11757   output_to "capitests/tests.c" generate_tests;
11758   output_to "fish/cmds.c" generate_fish_cmds;
11759   output_to "fish/completion.c" generate_fish_completion;
11760   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11761   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11762   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11763   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11764   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11765   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11766   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11767   output_to "perl/Guestfs.xs" generate_perl_xs;
11768   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11769   output_to "perl/bindtests.pl" generate_perl_bindtests;
11770   output_to "python/guestfs-py.c" generate_python_c;
11771   output_to "python/guestfs.py" generate_python_py;
11772   output_to "python/bindtests.py" generate_python_bindtests;
11773   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11774   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11775   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11776
11777   List.iter (
11778     fun (typ, jtyp) ->
11779       let cols = cols_of_struct typ in
11780       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11781       output_to filename (generate_java_struct jtyp cols);
11782   ) java_structs;
11783
11784   output_to "java/Makefile.inc" generate_java_makefile_inc;
11785   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11786   output_to "java/Bindtests.java" generate_java_bindtests;
11787   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11788   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11789   output_to "csharp/Libguestfs.cs" generate_csharp;
11790
11791   (* Always generate this file last, and unconditionally.  It's used
11792    * by the Makefile to know when we must re-run the generator.
11793    *)
11794   let chan = open_out "src/stamp-generator" in
11795   fprintf chan "1\n";
11796   close_out chan;
11797
11798   printf "generated %d lines of code\n" !lines