generator: Comment and whitespace changes only.
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009 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
45 open Unix
46 open Printf
47
48 type style = ret * args
49 and ret =
50     (* "RErr" as a return value means an int used as a simple error
51      * indication, ie. 0 or -1.
52      *)
53   | RErr
54
55     (* "RInt" as a return value means an int which is -1 for error
56      * or any value >= 0 on success.  Only use this for smallish
57      * positive ints (0 <= i < 2^30).
58      *)
59   | RInt of string
60
61     (* "RInt64" is the same as RInt, but is guaranteed to be able
62      * to return a full 64 bit value, _except_ that -1 means error
63      * (so -1 cannot be a valid, non-error return value).
64      *)
65   | RInt64 of string
66
67     (* "RBool" is a bool return value which can be true/false or
68      * -1 for error.
69      *)
70   | RBool of string
71
72     (* "RConstString" is a string that refers to a constant value.
73      * The return value must NOT be NULL (since NULL indicates
74      * an error).
75      *
76      * Try to avoid using this.  In particular you cannot use this
77      * for values returned from the daemon, because there is no
78      * thread-safe way to return them in the C API.
79      *)
80   | RConstString of string
81
82     (* "RConstOptString" is an even more broken version of
83      * "RConstString".  The returned string may be NULL and there
84      * is no way to return an error indication.  Avoid using this!
85      *)
86   | RConstOptString of string
87
88     (* "RString" is a returned string.  It must NOT be NULL, since
89      * a NULL return indicates an error.  The caller frees this.
90      *)
91   | RString of string
92
93     (* "RStringList" is a list of strings.  No string in the list
94      * can be NULL.  The caller frees the strings and the array.
95      *)
96   | RStringList of string
97
98     (* "RStruct" is a function which returns a single named structure
99      * or an error indication (in C, a struct, and in other languages
100      * with varying representations, but usually very efficient).  See
101      * after the function list below for the structures.
102      *)
103   | RStruct of string * string          (* name of retval, name of struct *)
104
105     (* "RStructList" is a function which returns either a list/array
106      * of structures (could be zero-length), or an error indication.
107      *)
108   | RStructList of string * string      (* name of retval, name of struct *)
109
110     (* Key-value pairs of untyped strings.  Turns into a hashtable or
111      * dictionary in languages which support it.  DON'T use this as a
112      * general "bucket" for results.  Prefer a stronger typed return
113      * value if one is available, or write a custom struct.  Don't use
114      * this if the list could potentially be very long, since it is
115      * inefficient.  Keys should be unique.  NULLs are not permitted.
116      *)
117   | RHashtable of string
118
119     (* "RBufferOut" is handled almost exactly like RString, but
120      * it allows the string to contain arbitrary 8 bit data including
121      * ASCII NUL.  In the C API this causes an implicit extra parameter
122      * to be added of type <size_t *size_r>.  The extra parameter
123      * returns the actual size of the return buffer in bytes.
124      *
125      * Other programming languages support strings with arbitrary 8 bit
126      * data.
127      *
128      * At the RPC layer we have to use the opaque<> type instead of
129      * string<>.  Returned data is still limited to the max message
130      * size (ie. ~ 2 MB).
131      *)
132   | RBufferOut of string
133
134 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
135
136     (* Note in future we should allow a "variable args" parameter as
137      * the final parameter, to allow commands like
138      *   chmod mode file [file(s)...]
139      * This is not implemented yet, but many commands (such as chmod)
140      * are currently defined with the argument order keeping this future
141      * possibility in mind.
142      *)
143 and argt =
144   | String of string    (* const char *name, cannot be NULL *)
145   | Device of string    (* /dev device name, cannot be NULL *)
146   | Pathname of string  (* file name, cannot be NULL *)
147   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
148   | OptString of string (* const char *name, may be NULL *)
149   | StringList of string(* list of strings (each string cannot be NULL) *)
150   | DeviceList of string(* list of Device names (each cannot be NULL) *)
151   | Bool of string      (* boolean *)
152   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
153   | Int64 of string     (* any 64 bit int *)
154     (* These are treated as filenames (simple string parameters) in
155      * the C API and bindings.  But in the RPC protocol, we transfer
156      * the actual file content up to or down from the daemon.
157      * FileIn: local machine -> daemon (in request)
158      * FileOut: daemon -> local machine (in reply)
159      * In guestfish (only), the special name "-" means read from
160      * stdin or write to stdout.
161      *)
162   | FileIn of string
163   | FileOut of string
164 (* Not implemented:
165     (* Opaque buffer which can contain arbitrary 8 bit data.
166      * In the C API, this is expressed as <char *, int> pair.
167      * Most other languages have a string type which can contain
168      * ASCII NUL.  We use whatever type is appropriate for each
169      * language.
170      * Buffers are limited by the total message size.  To transfer
171      * large blocks of data, use FileIn/FileOut parameters instead.
172      * To return an arbitrary buffer, use RBufferOut.
173      *)
174   | BufferIn of string
175 *)
176
177 type flags =
178   | ProtocolLimitWarning  (* display warning about protocol size limits *)
179   | DangerWillRobinson    (* flags particularly dangerous commands *)
180   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
181   | FishAction of string  (* call this function in guestfish *)
182   | NotInFish             (* do not export via guestfish *)
183   | NotInDocs             (* do not add this function to documentation *)
184   | DeprecatedBy of string (* function is deprecated, use .. instead *)
185   | Optional of string    (* function is part of an optional group *)
186
187 (* You can supply zero or as many tests as you want per API call.
188  *
189  * Note that the test environment has 3 block devices, of size 500MB,
190  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
191  * a fourth ISO block device with some known files on it (/dev/sdd).
192  *
193  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
194  * Number of cylinders was 63 for IDE emulated disks with precisely
195  * the same size.  How exactly this is calculated is a mystery.
196  *
197  * The ISO block device (/dev/sdd) comes from images/test.iso.
198  *
199  * To be able to run the tests in a reasonable amount of time,
200  * the virtual machine and block devices are reused between tests.
201  * So don't try testing kill_subprocess :-x
202  *
203  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
204  *
205  * Don't assume anything about the previous contents of the block
206  * devices.  Use 'Init*' to create some initial scenarios.
207  *
208  * You can add a prerequisite clause to any individual test.  This
209  * is a run-time check, which, if it fails, causes the test to be
210  * skipped.  Useful if testing a command which might not work on
211  * all variations of libguestfs builds.  A test that has prerequisite
212  * of 'Always' is run unconditionally.
213  *
214  * In addition, packagers can skip individual tests by setting the
215  * environment variables:     eg:
216  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
217  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
218  *)
219 type tests = (test_init * test_prereq * test) list
220 and test =
221     (* Run the command sequence and just expect nothing to fail. *)
222   | TestRun of seq
223
224     (* Run the command sequence and expect the output of the final
225      * command to be the string.
226      *)
227   | TestOutput of seq * string
228
229     (* Run the command sequence and expect the output of the final
230      * command to be the list of strings.
231      *)
232   | TestOutputList of seq * string list
233
234     (* Run the command sequence and expect the output of the final
235      * command to be the list of block devices (could be either
236      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
237      * character of each string).
238      *)
239   | TestOutputListOfDevices of seq * string list
240
241     (* Run the command sequence and expect the output of the final
242      * command to be the integer.
243      *)
244   | TestOutputInt of seq * int
245
246     (* Run the command sequence and expect the output of the final
247      * command to be <op> <int>, eg. ">=", "1".
248      *)
249   | TestOutputIntOp of seq * string * int
250
251     (* Run the command sequence and expect the output of the final
252      * command to be a true value (!= 0 or != NULL).
253      *)
254   | TestOutputTrue of seq
255
256     (* Run the command sequence and expect the output of the final
257      * command to be a false value (== 0 or == NULL, but not an error).
258      *)
259   | TestOutputFalse of seq
260
261     (* Run the command sequence and expect the output of the final
262      * command to be a list of the given length (but don't care about
263      * content).
264      *)
265   | TestOutputLength of seq * int
266
267     (* Run the command sequence and expect the output of the final
268      * command to be a buffer (RBufferOut), ie. string + size.
269      *)
270   | TestOutputBuffer of seq * string
271
272     (* Run the command sequence and expect the output of the final
273      * command to be a structure.
274      *)
275   | TestOutputStruct of seq * test_field_compare list
276
277     (* Run the command sequence and expect the final command (only)
278      * to fail.
279      *)
280   | TestLastFail of seq
281
282 and test_field_compare =
283   | CompareWithInt of string * int
284   | CompareWithIntOp of string * string * int
285   | CompareWithString of string * string
286   | CompareFieldsIntEq of string * string
287   | CompareFieldsStrEq of string * string
288
289 (* Test prerequisites. *)
290 and test_prereq =
291     (* Test always runs. *)
292   | Always
293
294     (* Test is currently disabled - eg. it fails, or it tests some
295      * unimplemented feature.
296      *)
297   | Disabled
298
299     (* 'string' is some C code (a function body) that should return
300      * true or false.  The test will run if the code returns true.
301      *)
302   | If of string
303
304     (* As for 'If' but the test runs _unless_ the code returns true. *)
305   | Unless of string
306
307 (* Some initial scenarios for testing. *)
308 and test_init =
309     (* Do nothing, block devices could contain random stuff including
310      * LVM PVs, and some filesystems might be mounted.  This is usually
311      * a bad idea.
312      *)
313   | InitNone
314
315     (* Block devices are empty and no filesystems are mounted. *)
316   | InitEmpty
317
318     (* /dev/sda contains a single partition /dev/sda1, with random
319      * content.  /dev/sdb and /dev/sdc may have random content.
320      * No LVM.
321      *)
322   | InitPartition
323
324     (* /dev/sda contains a single partition /dev/sda1, which is formatted
325      * as ext2, empty [except for lost+found] and mounted on /.
326      * /dev/sdb and /dev/sdc may have random content.
327      * No LVM.
328      *)
329   | InitBasicFS
330
331     (* /dev/sda:
332      *   /dev/sda1 (is a PV):
333      *     /dev/VG/LV (size 8MB):
334      *       formatted as ext2, empty [except for lost+found], mounted on /
335      * /dev/sdb and /dev/sdc may have random content.
336      *)
337   | InitBasicFSonLVM
338
339     (* /dev/sdd (the ISO, see images/ directory in source)
340      * is mounted on /
341      *)
342   | InitISOFS
343
344 (* Sequence of commands for testing. *)
345 and seq = cmd list
346 and cmd = string list
347
348 (* Note about long descriptions: When referring to another
349  * action, use the format C<guestfs_other> (ie. the full name of
350  * the C function).  This will be replaced as appropriate in other
351  * language bindings.
352  *
353  * Apart from that, long descriptions are just perldoc paragraphs.
354  *)
355
356 (* Generate a random UUID (used in tests). *)
357 let uuidgen () =
358   let chan = open_process_in "uuidgen" in
359   let uuid = input_line chan in
360   (match close_process_in chan with
361    | WEXITED 0 -> ()
362    | WEXITED _ ->
363        failwith "uuidgen: process exited with non-zero status"
364    | WSIGNALED _ | WSTOPPED _ ->
365        failwith "uuidgen: process signalled or stopped by signal"
366   );
367   uuid
368
369 (* These test functions are used in the language binding tests. *)
370
371 let test_all_args = [
372   String "str";
373   OptString "optstr";
374   StringList "strlist";
375   Bool "b";
376   Int "integer";
377   Int64 "integer64";
378   FileIn "filein";
379   FileOut "fileout";
380 ]
381
382 let test_all_rets = [
383   (* except for RErr, which is tested thoroughly elsewhere *)
384   "test0rint",         RInt "valout";
385   "test0rint64",       RInt64 "valout";
386   "test0rbool",        RBool "valout";
387   "test0rconststring", RConstString "valout";
388   "test0rconstoptstring", RConstOptString "valout";
389   "test0rstring",      RString "valout";
390   "test0rstringlist",  RStringList "valout";
391   "test0rstruct",      RStruct ("valout", "lvm_pv");
392   "test0rstructlist",  RStructList ("valout", "lvm_pv");
393   "test0rhashtable",   RHashtable "valout";
394 ]
395
396 let test_functions = [
397   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
398    [],
399    "internal test function - do not use",
400    "\
401 This is an internal test function which is used to test whether
402 the automatically generated bindings can handle every possible
403 parameter type correctly.
404
405 It echos the contents of each parameter to stdout.
406
407 You probably don't want to call this function.");
408 ] @ List.flatten (
409   List.map (
410     fun (name, ret) ->
411       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
412         [],
413         "internal test function - do not use",
414         "\
415 This is an internal test function which is used to test whether
416 the automatically generated bindings can handle every possible
417 return type correctly.
418
419 It converts string C<val> to the return type.
420
421 You probably don't want to call this function.");
422        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
423         [],
424         "internal test function - do not use",
425         "\
426 This is an internal test function which is used to test whether
427 the automatically generated bindings can handle every possible
428 return type correctly.
429
430 This function always returns an error.
431
432 You probably don't want to call this function.")]
433   ) test_all_rets
434 )
435
436 (* non_daemon_functions are any functions which don't get processed
437  * in the daemon, eg. functions for setting and getting local
438  * configuration values.
439  *)
440
441 let non_daemon_functions = test_functions @ [
442   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
443    [],
444    "launch the qemu subprocess",
445    "\
446 Internally libguestfs is implemented by running a virtual machine
447 using L<qemu(1)>.
448
449 You should call this after configuring the handle
450 (eg. adding drives) but before performing any actions.");
451
452   ("wait_ready", (RErr, []), -1, [NotInFish],
453    [],
454    "wait until the qemu subprocess launches (no op)",
455    "\
456 This function is a no op.
457
458 In versions of the API E<lt> 1.0.71 you had to call this function
459 just after calling C<guestfs_launch> to wait for the launch
460 to complete.  However this is no longer necessary because
461 C<guestfs_launch> now does the waiting.
462
463 If you see any calls to this function in code then you can just
464 remove them, unless you want to retain compatibility with older
465 versions of the API.");
466
467   ("kill_subprocess", (RErr, []), -1, [],
468    [],
469    "kill the qemu subprocess",
470    "\
471 This kills the qemu subprocess.  You should never need to call this.");
472
473   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
474    [],
475    "add an image to examine or modify",
476    "\
477 This function adds a virtual machine disk image C<filename> to the
478 guest.  The first time you call this function, the disk appears as IDE
479 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
480 so on.
481
482 You don't necessarily need to be root when using libguestfs.  However
483 you obviously do need sufficient permissions to access the filename
484 for whatever operations you want to perform (ie. read access if you
485 just want to read the image or write access if you want to modify the
486 image).
487
488 This is equivalent to the qemu parameter
489 C<-drive file=filename,cache=off,if=...>.
490 C<cache=off> is omitted in cases where it is not supported by
491 the underlying filesystem.
492
493 Note that this call checks for the existence of C<filename>.  This
494 stops you from specifying other types of drive which are supported
495 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
496 the general C<guestfs_config> call instead.");
497
498   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
499    [],
500    "add a CD-ROM disk image to examine",
501    "\
502 This function adds a virtual CD-ROM disk image to the guest.
503
504 This is equivalent to the qemu parameter C<-cdrom filename>.
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_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
512    [],
513    "add a drive in snapshot mode (read-only)",
514    "\
515 This adds a drive in snapshot mode, making it effectively
516 read-only.
517
518 Note that writes to the device are allowed, and will be seen for
519 the duration of the guestfs handle, but they are written
520 to a temporary file which is discarded as soon as the guestfs
521 handle is closed.  We don't currently have any method to enable
522 changes to be committed, although qemu can support this.
523
524 This is equivalent to the qemu parameter
525 C<-drive file=filename,snapshot=on,if=...>.
526
527 Note that this call checks for the existence of C<filename>.  This
528 stops you from specifying other types of drive which are supported
529 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
530 the general C<guestfs_config> call instead.");
531
532   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
533    [],
534    "add qemu parameters",
535    "\
536 This can be used to add arbitrary qemu command line parameters
537 of the form C<-param value>.  Actually it's not quite arbitrary - we
538 prevent you from setting some parameters which would interfere with
539 parameters that we use.
540
541 The first character of C<param> string must be a C<-> (dash).
542
543 C<value> can be NULL.");
544
545   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
546    [],
547    "set the qemu binary",
548    "\
549 Set the qemu binary that we will use.
550
551 The default is chosen when the library was compiled by the
552 configure script.
553
554 You can also override this by setting the C<LIBGUESTFS_QEMU>
555 environment variable.
556
557 Setting C<qemu> to C<NULL> restores the default qemu binary.");
558
559   ("get_qemu", (RConstString "qemu", []), -1, [],
560    [InitNone, Always, TestRun (
561       [["get_qemu"]])],
562    "get the qemu binary",
563    "\
564 Return the current qemu binary.
565
566 This is always non-NULL.  If it wasn't set already, then this will
567 return the default qemu binary name.");
568
569   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
570    [],
571    "set the search path",
572    "\
573 Set the path that libguestfs searches for kernel and initrd.img.
574
575 The default is C<$libdir/guestfs> unless overridden by setting
576 C<LIBGUESTFS_PATH> environment variable.
577
578 Setting C<path> to C<NULL> restores the default path.");
579
580   ("get_path", (RConstString "path", []), -1, [],
581    [InitNone, Always, TestRun (
582       [["get_path"]])],
583    "get the search path",
584    "\
585 Return the current search path.
586
587 This is always non-NULL.  If it wasn't set already, then this will
588 return the default path.");
589
590   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
591    [],
592    "add options to kernel command line",
593    "\
594 This function is used to add additional options to the
595 guest kernel command line.
596
597 The default is C<NULL> unless overridden by setting
598 C<LIBGUESTFS_APPEND> environment variable.
599
600 Setting C<append> to C<NULL> means I<no> additional options
601 are passed (libguestfs always adds a few of its own).");
602
603   ("get_append", (RConstOptString "append", []), -1, [],
604    (* This cannot be tested with the current framework.  The
605     * function can return NULL in normal operations, which the
606     * test framework interprets as an error.
607     *)
608    [],
609    "get the additional kernel options",
610    "\
611 Return the additional kernel options which are added to the
612 guest kernel command line.
613
614 If C<NULL> then no options are added.");
615
616   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
617    [],
618    "set autosync mode",
619    "\
620 If C<autosync> is true, this enables autosync.  Libguestfs will make a
621 best effort attempt to run C<guestfs_umount_all> followed by
622 C<guestfs_sync> when the handle is closed
623 (also if the program exits without closing handles).
624
625 This is disabled by default (except in guestfish where it is
626 enabled by default).");
627
628   ("get_autosync", (RBool "autosync", []), -1, [],
629    [InitNone, Always, TestRun (
630       [["get_autosync"]])],
631    "get autosync mode",
632    "\
633 Get the autosync flag.");
634
635   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
636    [],
637    "set verbose mode",
638    "\
639 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
640
641 Verbose messages are disabled unless the environment variable
642 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
643
644   ("get_verbose", (RBool "verbose", []), -1, [],
645    [],
646    "get verbose mode",
647    "\
648 This returns the verbose messages flag.");
649
650   ("is_ready", (RBool "ready", []), -1, [],
651    [InitNone, Always, TestOutputTrue (
652       [["is_ready"]])],
653    "is ready to accept commands",
654    "\
655 This returns true iff this handle is ready to accept commands
656 (in the C<READY> state).
657
658 For more information on states, see L<guestfs(3)>.");
659
660   ("is_config", (RBool "config", []), -1, [],
661    [InitNone, Always, TestOutputFalse (
662       [["is_config"]])],
663    "is in configuration state",
664    "\
665 This returns true iff this handle is being configured
666 (in the C<CONFIG> state).
667
668 For more information on states, see L<guestfs(3)>.");
669
670   ("is_launching", (RBool "launching", []), -1, [],
671    [InitNone, Always, TestOutputFalse (
672       [["is_launching"]])],
673    "is launching subprocess",
674    "\
675 This returns true iff this handle is launching the subprocess
676 (in the C<LAUNCHING> state).
677
678 For more information on states, see L<guestfs(3)>.");
679
680   ("is_busy", (RBool "busy", []), -1, [],
681    [InitNone, Always, TestOutputFalse (
682       [["is_busy"]])],
683    "is busy processing a command",
684    "\
685 This returns true iff this handle is busy processing a command
686 (in the C<BUSY> state).
687
688 For more information on states, see L<guestfs(3)>.");
689
690   ("get_state", (RInt "state", []), -1, [],
691    [],
692    "get the current state",
693    "\
694 This returns the current state as an opaque integer.  This is
695 only useful for printing debug and internal error messages.
696
697 For more information on states, see L<guestfs(3)>.");
698
699   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
700    [InitNone, Always, TestOutputInt (
701       [["set_memsize"; "500"];
702        ["get_memsize"]], 500)],
703    "set memory allocated to the qemu subprocess",
704    "\
705 This sets the memory size in megabytes allocated to the
706 qemu subprocess.  This only has any effect if called before
707 C<guestfs_launch>.
708
709 You can also change this by setting the environment
710 variable C<LIBGUESTFS_MEMSIZE> before the handle is
711 created.
712
713 For more information on the architecture of libguestfs,
714 see L<guestfs(3)>.");
715
716   ("get_memsize", (RInt "memsize", []), -1, [],
717    [InitNone, Always, TestOutputIntOp (
718       [["get_memsize"]], ">=", 256)],
719    "get memory allocated to the qemu subprocess",
720    "\
721 This gets the memory size in megabytes allocated to the
722 qemu subprocess.
723
724 If C<guestfs_set_memsize> was not called
725 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
726 then this returns the compiled-in default value for memsize.
727
728 For more information on the architecture of libguestfs,
729 see L<guestfs(3)>.");
730
731   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
732    [InitNone, Always, TestOutputIntOp (
733       [["get_pid"]], ">=", 1)],
734    "get PID of qemu subprocess",
735    "\
736 Return the process ID of the qemu subprocess.  If there is no
737 qemu subprocess, then this will return an error.
738
739 This is an internal call used for debugging and testing.");
740
741   ("version", (RStruct ("version", "version"), []), -1, [],
742    [InitNone, Always, TestOutputStruct (
743       [["version"]], [CompareWithInt ("major", 1)])],
744    "get the library version number",
745    "\
746 Return the libguestfs version number that the program is linked
747 against.
748
749 Note that because of dynamic linking this is not necessarily
750 the version of libguestfs that you compiled against.  You can
751 compile the program, and then at runtime dynamically link
752 against a completely different C<libguestfs.so> library.
753
754 This call was added in version C<1.0.58>.  In previous
755 versions of libguestfs there was no way to get the version
756 number.  From C code you can use ELF weak linking tricks to find out if
757 this symbol exists (if it doesn't, then it's an earlier version).
758
759 The call returns a structure with four elements.  The first
760 three (C<major>, C<minor> and C<release>) are numbers and
761 correspond to the usual version triplet.  The fourth element
762 (C<extra>) is a string and is normally empty, but may be
763 used for distro-specific information.
764
765 To construct the original version string:
766 C<$major.$minor.$release$extra>
767
768 I<Note:> Don't use this call to test for availability
769 of features.  Distro backports makes this unreliable.  Use
770 C<guestfs_available> instead.");
771
772   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
773    [InitNone, Always, TestOutputTrue (
774       [["set_selinux"; "true"];
775        ["get_selinux"]])],
776    "set SELinux enabled or disabled at appliance boot",
777    "\
778 This sets the selinux flag that is passed to the appliance
779 at boot time.  The default is C<selinux=0> (disabled).
780
781 Note that if SELinux is enabled, it is always in
782 Permissive mode (C<enforcing=0>).
783
784 For more information on the architecture of libguestfs,
785 see L<guestfs(3)>.");
786
787   ("get_selinux", (RBool "selinux", []), -1, [],
788    [],
789    "get SELinux enabled flag",
790    "\
791 This returns the current setting of the selinux flag which
792 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
793
794 For more information on the architecture of libguestfs,
795 see L<guestfs(3)>.");
796
797   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
798    [InitNone, Always, TestOutputFalse (
799       [["set_trace"; "false"];
800        ["get_trace"]])],
801    "enable or disable command traces",
802    "\
803 If the command trace flag is set to 1, then commands are
804 printed on stdout before they are executed in a format
805 which is very similar to the one used by guestfish.  In
806 other words, you can run a program with this enabled, and
807 you will get out a script which you can feed to guestfish
808 to perform the same set of actions.
809
810 If you want to trace C API calls into libguestfs (and
811 other libraries) then possibly a better way is to use
812 the external ltrace(1) command.
813
814 Command traces are disabled unless the environment variable
815 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
816
817   ("get_trace", (RBool "trace", []), -1, [],
818    [],
819    "get command trace enabled flag",
820    "\
821 Return the command trace flag.");
822
823   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
824    [InitNone, Always, TestOutputFalse (
825       [["set_direct"; "false"];
826        ["get_direct"]])],
827    "enable or disable direct appliance mode",
828    "\
829 If the direct appliance mode flag is enabled, then stdin and
830 stdout are passed directly through to the appliance once it
831 is launched.
832
833 One consequence of this is that log messages aren't caught
834 by the library and handled by C<guestfs_set_log_message_callback>,
835 but go straight to stdout.
836
837 You probably don't want to use this unless you know what you
838 are doing.
839
840 The default is disabled.");
841
842   ("get_direct", (RBool "direct", []), -1, [],
843    [],
844    "get direct appliance mode flag",
845    "\
846 Return the direct appliance mode flag.");
847
848   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
849    [InitNone, Always, TestOutputTrue (
850       [["set_recovery_proc"; "true"];
851        ["get_recovery_proc"]])],
852    "enable or disable the recovery process",
853    "\
854 If this is called with the parameter C<false> then
855 C<guestfs_launch> does not create a recovery process.  The
856 purpose of the recovery process is to stop runaway qemu
857 processes in the case where the main program aborts abruptly.
858
859 This only has any effect if called before C<guestfs_launch>,
860 and the default is true.
861
862 About the only time when you would want to disable this is
863 if the main process will fork itself into the background
864 (\"daemonize\" itself).  In this case the recovery process
865 thinks that the main program has disappeared and so kills
866 qemu, which is not very helpful.");
867
868   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
869    [],
870    "get recovery process enabled flag",
871    "\
872 Return the recovery process enabled flag.");
873
874 ]
875
876 (* daemon_functions are any functions which cause some action
877  * to take place in the daemon.
878  *)
879
880 let daemon_functions = [
881   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
882    [InitEmpty, Always, TestOutput (
883       [["part_disk"; "/dev/sda"; "mbr"];
884        ["mkfs"; "ext2"; "/dev/sda1"];
885        ["mount"; "/dev/sda1"; "/"];
886        ["write_file"; "/new"; "new file contents"; "0"];
887        ["cat"; "/new"]], "new file contents")],
888    "mount a guest disk at a position in the filesystem",
889    "\
890 Mount a guest disk at a position in the filesystem.  Block devices
891 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
892 the guest.  If those block devices contain partitions, they will have
893 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
894 names can be used.
895
896 The rules are the same as for L<mount(2)>:  A filesystem must
897 first be mounted on C</> before others can be mounted.  Other
898 filesystems can only be mounted on directories which already
899 exist.
900
901 The mounted filesystem is writable, if we have sufficient permissions
902 on the underlying device.
903
904 The filesystem options C<sync> and C<noatime> are set with this
905 call, in order to improve reliability.");
906
907   ("sync", (RErr, []), 2, [],
908    [ InitEmpty, Always, TestRun [["sync"]]],
909    "sync disks, writes are flushed through to the disk image",
910    "\
911 This syncs the disk, so that any writes are flushed through to the
912 underlying disk image.
913
914 You should always call this if you have modified a disk image, before
915 closing the handle.");
916
917   ("touch", (RErr, [Pathname "path"]), 3, [],
918    [InitBasicFS, Always, TestOutputTrue (
919       [["touch"; "/new"];
920        ["exists"; "/new"]])],
921    "update file timestamps or create a new file",
922    "\
923 Touch acts like the L<touch(1)> command.  It can be used to
924 update the timestamps on a file, or, if the file does not exist,
925 to create a new zero-length file.");
926
927   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
928    [InitISOFS, Always, TestOutput (
929       [["cat"; "/known-2"]], "abcdef\n")],
930    "list the contents of a file",
931    "\
932 Return the contents of the file named C<path>.
933
934 Note that this function cannot correctly handle binary files
935 (specifically, files containing C<\\0> character which is treated
936 as end of string).  For those you need to use the C<guestfs_read_file>
937 or C<guestfs_download> functions which have a more complex interface.");
938
939   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
940    [], (* XXX Tricky to test because it depends on the exact format
941         * of the 'ls -l' command, which changes between F10 and F11.
942         *)
943    "list the files in a directory (long format)",
944    "\
945 List the files in C<directory> (relative to the root directory,
946 there is no cwd) in the format of 'ls -la'.
947
948 This command is mostly useful for interactive sessions.  It
949 is I<not> intended that you try to parse the output string.");
950
951   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
952    [InitBasicFS, Always, TestOutputList (
953       [["touch"; "/new"];
954        ["touch"; "/newer"];
955        ["touch"; "/newest"];
956        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
957    "list the files in a directory",
958    "\
959 List the files in C<directory> (relative to the root directory,
960 there is no cwd).  The '.' and '..' entries are not returned, but
961 hidden files are shown.
962
963 This command is mostly useful for interactive sessions.  Programs
964 should probably use C<guestfs_readdir> instead.");
965
966   ("list_devices", (RStringList "devices", []), 7, [],
967    [InitEmpty, Always, TestOutputListOfDevices (
968       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
969    "list the block devices",
970    "\
971 List all the block devices.
972
973 The full block device names are returned, eg. C</dev/sda>");
974
975   ("list_partitions", (RStringList "partitions", []), 8, [],
976    [InitBasicFS, Always, TestOutputListOfDevices (
977       [["list_partitions"]], ["/dev/sda1"]);
978     InitEmpty, Always, TestOutputListOfDevices (
979       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
980        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
981    "list the partitions",
982    "\
983 List all the partitions detected on all block devices.
984
985 The full partition device names are returned, eg. C</dev/sda1>
986
987 This does not return logical volumes.  For that you will need to
988 call C<guestfs_lvs>.");
989
990   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
991    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
992       [["pvs"]], ["/dev/sda1"]);
993     InitEmpty, Always, TestOutputListOfDevices (
994       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
995        ["pvcreate"; "/dev/sda1"];
996        ["pvcreate"; "/dev/sda2"];
997        ["pvcreate"; "/dev/sda3"];
998        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
999    "list the LVM physical volumes (PVs)",
1000    "\
1001 List all the physical volumes detected.  This is the equivalent
1002 of the L<pvs(8)> command.
1003
1004 This returns a list of just the device names that contain
1005 PVs (eg. C</dev/sda2>).
1006
1007 See also C<guestfs_pvs_full>.");
1008
1009   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1010    [InitBasicFSonLVM, Always, TestOutputList (
1011       [["vgs"]], ["VG"]);
1012     InitEmpty, Always, TestOutputList (
1013       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1014        ["pvcreate"; "/dev/sda1"];
1015        ["pvcreate"; "/dev/sda2"];
1016        ["pvcreate"; "/dev/sda3"];
1017        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1018        ["vgcreate"; "VG2"; "/dev/sda3"];
1019        ["vgs"]], ["VG1"; "VG2"])],
1020    "list the LVM volume groups (VGs)",
1021    "\
1022 List all the volumes groups detected.  This is the equivalent
1023 of the L<vgs(8)> command.
1024
1025 This returns a list of just the volume group names that were
1026 detected (eg. C<VolGroup00>).
1027
1028 See also C<guestfs_vgs_full>.");
1029
1030   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1031    [InitBasicFSonLVM, Always, TestOutputList (
1032       [["lvs"]], ["/dev/VG/LV"]);
1033     InitEmpty, Always, TestOutputList (
1034       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1035        ["pvcreate"; "/dev/sda1"];
1036        ["pvcreate"; "/dev/sda2"];
1037        ["pvcreate"; "/dev/sda3"];
1038        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1039        ["vgcreate"; "VG2"; "/dev/sda3"];
1040        ["lvcreate"; "LV1"; "VG1"; "50"];
1041        ["lvcreate"; "LV2"; "VG1"; "50"];
1042        ["lvcreate"; "LV3"; "VG2"; "50"];
1043        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1044    "list the LVM logical volumes (LVs)",
1045    "\
1046 List all the logical volumes detected.  This is the equivalent
1047 of the L<lvs(8)> command.
1048
1049 This returns a list of the logical volume device names
1050 (eg. C</dev/VolGroup00/LogVol00>).
1051
1052 See also C<guestfs_lvs_full>.");
1053
1054   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1055    [], (* XXX how to test? *)
1056    "list the LVM physical volumes (PVs)",
1057    "\
1058 List all the physical volumes detected.  This is the equivalent
1059 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1060
1061   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1062    [], (* XXX how to test? *)
1063    "list the LVM volume groups (VGs)",
1064    "\
1065 List all the volumes groups detected.  This is the equivalent
1066 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1067
1068   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1069    [], (* XXX how to test? *)
1070    "list the LVM logical volumes (LVs)",
1071    "\
1072 List all the logical volumes detected.  This is the equivalent
1073 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1074
1075   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1076    [InitISOFS, Always, TestOutputList (
1077       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1078     InitISOFS, Always, TestOutputList (
1079       [["read_lines"; "/empty"]], [])],
1080    "read file as lines",
1081    "\
1082 Return the contents of the file named C<path>.
1083
1084 The file contents are returned as a list of lines.  Trailing
1085 C<LF> and C<CRLF> character sequences are I<not> returned.
1086
1087 Note that this function cannot correctly handle binary files
1088 (specifically, files containing C<\\0> character which is treated
1089 as end of line).  For those you need to use the C<guestfs_read_file>
1090 function which has a more complex interface.");
1091
1092   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1093    [], (* XXX Augeas code needs tests. *)
1094    "create a new Augeas handle",
1095    "\
1096 Create a new Augeas handle for editing configuration files.
1097 If there was any previous Augeas handle associated with this
1098 guestfs session, then it is closed.
1099
1100 You must call this before using any other C<guestfs_aug_*>
1101 commands.
1102
1103 C<root> is the filesystem root.  C<root> must not be NULL,
1104 use C</> instead.
1105
1106 The flags are the same as the flags defined in
1107 E<lt>augeas.hE<gt>, the logical I<or> of the following
1108 integers:
1109
1110 =over 4
1111
1112 =item C<AUG_SAVE_BACKUP> = 1
1113
1114 Keep the original file with a C<.augsave> extension.
1115
1116 =item C<AUG_SAVE_NEWFILE> = 2
1117
1118 Save changes into a file with extension C<.augnew>, and
1119 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1120
1121 =item C<AUG_TYPE_CHECK> = 4
1122
1123 Typecheck lenses (can be expensive).
1124
1125 =item C<AUG_NO_STDINC> = 8
1126
1127 Do not use standard load path for modules.
1128
1129 =item C<AUG_SAVE_NOOP> = 16
1130
1131 Make save a no-op, just record what would have been changed.
1132
1133 =item C<AUG_NO_LOAD> = 32
1134
1135 Do not load the tree in C<guestfs_aug_init>.
1136
1137 =back
1138
1139 To close the handle, you can call C<guestfs_aug_close>.
1140
1141 To find out more about Augeas, see L<http://augeas.net/>.");
1142
1143   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1144    [], (* XXX Augeas code needs tests. *)
1145    "close the current Augeas handle",
1146    "\
1147 Close the current Augeas handle and free up any resources
1148 used by it.  After calling this, you have to call
1149 C<guestfs_aug_init> again before you can use any other
1150 Augeas functions.");
1151
1152   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1153    [], (* XXX Augeas code needs tests. *)
1154    "define an Augeas variable",
1155    "\
1156 Defines an Augeas variable C<name> whose value is the result
1157 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1158 undefined.
1159
1160 On success this returns the number of nodes in C<expr>, or
1161 C<0> if C<expr> evaluates to something which is not a nodeset.");
1162
1163   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1164    [], (* XXX Augeas code needs tests. *)
1165    "define an Augeas node",
1166    "\
1167 Defines a variable C<name> whose value is the result of
1168 evaluating C<expr>.
1169
1170 If C<expr> evaluates to an empty nodeset, a node is created,
1171 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1172 C<name> will be the nodeset containing that single node.
1173
1174 On success this returns a pair containing the
1175 number of nodes in the nodeset, and a boolean flag
1176 if a node was created.");
1177
1178   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1179    [], (* XXX Augeas code needs tests. *)
1180    "look up the value of an Augeas path",
1181    "\
1182 Look up the value associated with C<path>.  If C<path>
1183 matches exactly one node, the C<value> is returned.");
1184
1185   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1186    [], (* XXX Augeas code needs tests. *)
1187    "set Augeas path to value",
1188    "\
1189 Set the value associated with C<path> to C<value>.");
1190
1191   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1192    [], (* XXX Augeas code needs tests. *)
1193    "insert a sibling Augeas node",
1194    "\
1195 Create a new sibling C<label> for C<path>, inserting it into
1196 the tree before or after C<path> (depending on the boolean
1197 flag C<before>).
1198
1199 C<path> must match exactly one existing node in the tree, and
1200 C<label> must be a label, ie. not contain C</>, C<*> or end
1201 with a bracketed index C<[N]>.");
1202
1203   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1204    [], (* XXX Augeas code needs tests. *)
1205    "remove an Augeas path",
1206    "\
1207 Remove C<path> and all of its children.
1208
1209 On success this returns the number of entries which were removed.");
1210
1211   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1212    [], (* XXX Augeas code needs tests. *)
1213    "move Augeas node",
1214    "\
1215 Move the node C<src> to C<dest>.  C<src> must match exactly
1216 one node.  C<dest> is overwritten if it exists.");
1217
1218   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1219    [], (* XXX Augeas code needs tests. *)
1220    "return Augeas nodes which match augpath",
1221    "\
1222 Returns a list of paths which match the path expression C<path>.
1223 The returned paths are sufficiently qualified so that they match
1224 exactly one node in the current tree.");
1225
1226   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1227    [], (* XXX Augeas code needs tests. *)
1228    "write all pending Augeas changes to disk",
1229    "\
1230 This writes all pending changes to disk.
1231
1232 The flags which were passed to C<guestfs_aug_init> affect exactly
1233 how files are saved.");
1234
1235   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1236    [], (* XXX Augeas code needs tests. *)
1237    "load files into the tree",
1238    "\
1239 Load files into the tree.
1240
1241 See C<aug_load> in the Augeas documentation for the full gory
1242 details.");
1243
1244   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1245    [], (* XXX Augeas code needs tests. *)
1246    "list Augeas nodes under augpath",
1247    "\
1248 This is just a shortcut for listing C<guestfs_aug_match>
1249 C<path/*> and sorting the resulting nodes into alphabetical order.");
1250
1251   ("rm", (RErr, [Pathname "path"]), 29, [],
1252    [InitBasicFS, Always, TestRun
1253       [["touch"; "/new"];
1254        ["rm"; "/new"]];
1255     InitBasicFS, Always, TestLastFail
1256       [["rm"; "/new"]];
1257     InitBasicFS, Always, TestLastFail
1258       [["mkdir"; "/new"];
1259        ["rm"; "/new"]]],
1260    "remove a file",
1261    "\
1262 Remove the single file C<path>.");
1263
1264   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1265    [InitBasicFS, Always, TestRun
1266       [["mkdir"; "/new"];
1267        ["rmdir"; "/new"]];
1268     InitBasicFS, Always, TestLastFail
1269       [["rmdir"; "/new"]];
1270     InitBasicFS, Always, TestLastFail
1271       [["touch"; "/new"];
1272        ["rmdir"; "/new"]]],
1273    "remove a directory",
1274    "\
1275 Remove the single directory C<path>.");
1276
1277   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1278    [InitBasicFS, Always, TestOutputFalse
1279       [["mkdir"; "/new"];
1280        ["mkdir"; "/new/foo"];
1281        ["touch"; "/new/foo/bar"];
1282        ["rm_rf"; "/new"];
1283        ["exists"; "/new"]]],
1284    "remove a file or directory recursively",
1285    "\
1286 Remove the file or directory C<path>, recursively removing the
1287 contents if its a directory.  This is like the C<rm -rf> shell
1288 command.");
1289
1290   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1291    [InitBasicFS, Always, TestOutputTrue
1292       [["mkdir"; "/new"];
1293        ["is_dir"; "/new"]];
1294     InitBasicFS, Always, TestLastFail
1295       [["mkdir"; "/new/foo/bar"]]],
1296    "create a directory",
1297    "\
1298 Create a directory named C<path>.");
1299
1300   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1301    [InitBasicFS, Always, TestOutputTrue
1302       [["mkdir_p"; "/new/foo/bar"];
1303        ["is_dir"; "/new/foo/bar"]];
1304     InitBasicFS, Always, TestOutputTrue
1305       [["mkdir_p"; "/new/foo/bar"];
1306        ["is_dir"; "/new/foo"]];
1307     InitBasicFS, Always, TestOutputTrue
1308       [["mkdir_p"; "/new/foo/bar"];
1309        ["is_dir"; "/new"]];
1310     (* Regression tests for RHBZ#503133: *)
1311     InitBasicFS, Always, TestRun
1312       [["mkdir"; "/new"];
1313        ["mkdir_p"; "/new"]];
1314     InitBasicFS, Always, TestLastFail
1315       [["touch"; "/new"];
1316        ["mkdir_p"; "/new"]]],
1317    "create a directory and parents",
1318    "\
1319 Create a directory named C<path>, creating any parent directories
1320 as necessary.  This is like the C<mkdir -p> shell command.");
1321
1322   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1323    [], (* XXX Need stat command to test *)
1324    "change file mode",
1325    "\
1326 Change the mode (permissions) of C<path> to C<mode>.  Only
1327 numeric modes are supported.");
1328
1329   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1330    [], (* XXX Need stat command to test *)
1331    "change file owner and group",
1332    "\
1333 Change the file owner to C<owner> and group to C<group>.
1334
1335 Only numeric uid and gid are supported.  If you want to use
1336 names, you will need to locate and parse the password file
1337 yourself (Augeas support makes this relatively easy).");
1338
1339   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1340    [InitISOFS, Always, TestOutputTrue (
1341       [["exists"; "/empty"]]);
1342     InitISOFS, Always, TestOutputTrue (
1343       [["exists"; "/directory"]])],
1344    "test if file or directory exists",
1345    "\
1346 This returns C<true> if and only if there is a file, directory
1347 (or anything) with the given C<path> name.
1348
1349 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1350
1351   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1352    [InitISOFS, Always, TestOutputTrue (
1353       [["is_file"; "/known-1"]]);
1354     InitISOFS, Always, TestOutputFalse (
1355       [["is_file"; "/directory"]])],
1356    "test if file exists",
1357    "\
1358 This returns C<true> if and only if there is a file
1359 with the given C<path> name.  Note that it returns false for
1360 other objects like directories.
1361
1362 See also C<guestfs_stat>.");
1363
1364   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1365    [InitISOFS, Always, TestOutputFalse (
1366       [["is_dir"; "/known-3"]]);
1367     InitISOFS, Always, TestOutputTrue (
1368       [["is_dir"; "/directory"]])],
1369    "test if file exists",
1370    "\
1371 This returns C<true> if and only if there is a directory
1372 with the given C<path> name.  Note that it returns false for
1373 other objects like files.
1374
1375 See also C<guestfs_stat>.");
1376
1377   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1378    [InitEmpty, Always, TestOutputListOfDevices (
1379       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1380        ["pvcreate"; "/dev/sda1"];
1381        ["pvcreate"; "/dev/sda2"];
1382        ["pvcreate"; "/dev/sda3"];
1383        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1384    "create an LVM physical volume",
1385    "\
1386 This creates an LVM physical volume on the named C<device>,
1387 where C<device> should usually be a partition name such
1388 as C</dev/sda1>.");
1389
1390   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1391    [InitEmpty, Always, TestOutputList (
1392       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1393        ["pvcreate"; "/dev/sda1"];
1394        ["pvcreate"; "/dev/sda2"];
1395        ["pvcreate"; "/dev/sda3"];
1396        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1397        ["vgcreate"; "VG2"; "/dev/sda3"];
1398        ["vgs"]], ["VG1"; "VG2"])],
1399    "create an LVM volume group",
1400    "\
1401 This creates an LVM volume group called C<volgroup>
1402 from the non-empty list of physical volumes C<physvols>.");
1403
1404   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1405    [InitEmpty, Always, TestOutputList (
1406       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1407        ["pvcreate"; "/dev/sda1"];
1408        ["pvcreate"; "/dev/sda2"];
1409        ["pvcreate"; "/dev/sda3"];
1410        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1411        ["vgcreate"; "VG2"; "/dev/sda3"];
1412        ["lvcreate"; "LV1"; "VG1"; "50"];
1413        ["lvcreate"; "LV2"; "VG1"; "50"];
1414        ["lvcreate"; "LV3"; "VG2"; "50"];
1415        ["lvcreate"; "LV4"; "VG2"; "50"];
1416        ["lvcreate"; "LV5"; "VG2"; "50"];
1417        ["lvs"]],
1418       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1419        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1420    "create an LVM volume group",
1421    "\
1422 This creates an LVM volume group called C<logvol>
1423 on the volume group C<volgroup>, with C<size> megabytes.");
1424
1425   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1426    [InitEmpty, Always, TestOutput (
1427       [["part_disk"; "/dev/sda"; "mbr"];
1428        ["mkfs"; "ext2"; "/dev/sda1"];
1429        ["mount"; "/dev/sda1"; "/"];
1430        ["write_file"; "/new"; "new file contents"; "0"];
1431        ["cat"; "/new"]], "new file contents")],
1432    "make a filesystem",
1433    "\
1434 This creates a filesystem on C<device> (usually a partition
1435 or LVM logical volume).  The filesystem type is C<fstype>, for
1436 example C<ext3>.");
1437
1438   ("sfdisk", (RErr, [Device "device";
1439                      Int "cyls"; Int "heads"; Int "sectors";
1440                      StringList "lines"]), 43, [DangerWillRobinson],
1441    [],
1442    "create partitions on a block device",
1443    "\
1444 This is a direct interface to the L<sfdisk(8)> program for creating
1445 partitions on block devices.
1446
1447 C<device> should be a block device, for example C</dev/sda>.
1448
1449 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1450 and sectors on the device, which are passed directly to sfdisk as
1451 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1452 of these, then the corresponding parameter is omitted.  Usually for
1453 'large' disks, you can just pass C<0> for these, but for small
1454 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1455 out the right geometry and you will need to tell it.
1456
1457 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1458 information refer to the L<sfdisk(8)> manpage.
1459
1460 To create a single partition occupying the whole disk, you would
1461 pass C<lines> as a single element list, when the single element being
1462 the string C<,> (comma).
1463
1464 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1465 C<guestfs_part_init>");
1466
1467   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1468    [InitBasicFS, Always, TestOutput (
1469       [["write_file"; "/new"; "new file contents"; "0"];
1470        ["cat"; "/new"]], "new file contents");
1471     InitBasicFS, Always, TestOutput (
1472       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1473        ["cat"; "/new"]], "\nnew file contents\n");
1474     InitBasicFS, Always, TestOutput (
1475       [["write_file"; "/new"; "\n\n"; "0"];
1476        ["cat"; "/new"]], "\n\n");
1477     InitBasicFS, Always, TestOutput (
1478       [["write_file"; "/new"; ""; "0"];
1479        ["cat"; "/new"]], "");
1480     InitBasicFS, Always, TestOutput (
1481       [["write_file"; "/new"; "\n\n\n"; "0"];
1482        ["cat"; "/new"]], "\n\n\n");
1483     InitBasicFS, Always, TestOutput (
1484       [["write_file"; "/new"; "\n"; "0"];
1485        ["cat"; "/new"]], "\n")],
1486    "create a file",
1487    "\
1488 This call creates a file called C<path>.  The contents of the
1489 file is the string C<content> (which can contain any 8 bit data),
1490 with length C<size>.
1491
1492 As a special case, if C<size> is C<0>
1493 then the length is calculated using C<strlen> (so in this case
1494 the content cannot contain embedded ASCII NULs).
1495
1496 I<NB.> Owing to a bug, writing content containing ASCII NUL
1497 characters does I<not> work, even if the length is specified.
1498 We hope to resolve this bug in a future version.  In the meantime
1499 use C<guestfs_upload>.");
1500
1501   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1502    [InitEmpty, Always, TestOutputListOfDevices (
1503       [["part_disk"; "/dev/sda"; "mbr"];
1504        ["mkfs"; "ext2"; "/dev/sda1"];
1505        ["mount"; "/dev/sda1"; "/"];
1506        ["mounts"]], ["/dev/sda1"]);
1507     InitEmpty, Always, TestOutputList (
1508       [["part_disk"; "/dev/sda"; "mbr"];
1509        ["mkfs"; "ext2"; "/dev/sda1"];
1510        ["mount"; "/dev/sda1"; "/"];
1511        ["umount"; "/"];
1512        ["mounts"]], [])],
1513    "unmount a filesystem",
1514    "\
1515 This unmounts the given filesystem.  The filesystem may be
1516 specified either by its mountpoint (path) or the device which
1517 contains the filesystem.");
1518
1519   ("mounts", (RStringList "devices", []), 46, [],
1520    [InitBasicFS, Always, TestOutputListOfDevices (
1521       [["mounts"]], ["/dev/sda1"])],
1522    "show mounted filesystems",
1523    "\
1524 This returns the list of currently mounted filesystems.  It returns
1525 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1526
1527 Some internal mounts are not shown.
1528
1529 See also: C<guestfs_mountpoints>");
1530
1531   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1532    [InitBasicFS, Always, TestOutputList (
1533       [["umount_all"];
1534        ["mounts"]], []);
1535     (* check that umount_all can unmount nested mounts correctly: *)
1536     InitEmpty, Always, TestOutputList (
1537       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1538        ["mkfs"; "ext2"; "/dev/sda1"];
1539        ["mkfs"; "ext2"; "/dev/sda2"];
1540        ["mkfs"; "ext2"; "/dev/sda3"];
1541        ["mount"; "/dev/sda1"; "/"];
1542        ["mkdir"; "/mp1"];
1543        ["mount"; "/dev/sda2"; "/mp1"];
1544        ["mkdir"; "/mp1/mp2"];
1545        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1546        ["mkdir"; "/mp1/mp2/mp3"];
1547        ["umount_all"];
1548        ["mounts"]], [])],
1549    "unmount all filesystems",
1550    "\
1551 This unmounts all mounted filesystems.
1552
1553 Some internal mounts are not unmounted by this call.");
1554
1555   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1556    [],
1557    "remove all LVM LVs, VGs and PVs",
1558    "\
1559 This command removes all LVM logical volumes, volume groups
1560 and physical volumes.");
1561
1562   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1563    [InitISOFS, Always, TestOutput (
1564       [["file"; "/empty"]], "empty");
1565     InitISOFS, Always, TestOutput (
1566       [["file"; "/known-1"]], "ASCII text");
1567     InitISOFS, Always, TestLastFail (
1568       [["file"; "/notexists"]])],
1569    "determine file type",
1570    "\
1571 This call uses the standard L<file(1)> command to determine
1572 the type or contents of the file.  This also works on devices,
1573 for example to find out whether a partition contains a filesystem.
1574
1575 This call will also transparently look inside various types
1576 of compressed file.
1577
1578 The exact command which runs is C<file -zbsL path>.  Note in
1579 particular that the filename is not prepended to the output
1580 (the C<-b> option).");
1581
1582   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1583    [InitBasicFS, Always, TestOutput (
1584       [["upload"; "test-command"; "/test-command"];
1585        ["chmod"; "0o755"; "/test-command"];
1586        ["command"; "/test-command 1"]], "Result1");
1587     InitBasicFS, Always, TestOutput (
1588       [["upload"; "test-command"; "/test-command"];
1589        ["chmod"; "0o755"; "/test-command"];
1590        ["command"; "/test-command 2"]], "Result2\n");
1591     InitBasicFS, Always, TestOutput (
1592       [["upload"; "test-command"; "/test-command"];
1593        ["chmod"; "0o755"; "/test-command"];
1594        ["command"; "/test-command 3"]], "\nResult3");
1595     InitBasicFS, Always, TestOutput (
1596       [["upload"; "test-command"; "/test-command"];
1597        ["chmod"; "0o755"; "/test-command"];
1598        ["command"; "/test-command 4"]], "\nResult4\n");
1599     InitBasicFS, Always, TestOutput (
1600       [["upload"; "test-command"; "/test-command"];
1601        ["chmod"; "0o755"; "/test-command"];
1602        ["command"; "/test-command 5"]], "\nResult5\n\n");
1603     InitBasicFS, Always, TestOutput (
1604       [["upload"; "test-command"; "/test-command"];
1605        ["chmod"; "0o755"; "/test-command"];
1606        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1607     InitBasicFS, Always, TestOutput (
1608       [["upload"; "test-command"; "/test-command"];
1609        ["chmod"; "0o755"; "/test-command"];
1610        ["command"; "/test-command 7"]], "");
1611     InitBasicFS, Always, TestOutput (
1612       [["upload"; "test-command"; "/test-command"];
1613        ["chmod"; "0o755"; "/test-command"];
1614        ["command"; "/test-command 8"]], "\n");
1615     InitBasicFS, Always, TestOutput (
1616       [["upload"; "test-command"; "/test-command"];
1617        ["chmod"; "0o755"; "/test-command"];
1618        ["command"; "/test-command 9"]], "\n\n");
1619     InitBasicFS, Always, TestOutput (
1620       [["upload"; "test-command"; "/test-command"];
1621        ["chmod"; "0o755"; "/test-command"];
1622        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1623     InitBasicFS, Always, TestOutput (
1624       [["upload"; "test-command"; "/test-command"];
1625        ["chmod"; "0o755"; "/test-command"];
1626        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1627     InitBasicFS, Always, TestLastFail (
1628       [["upload"; "test-command"; "/test-command"];
1629        ["chmod"; "0o755"; "/test-command"];
1630        ["command"; "/test-command"]])],
1631    "run a command from the guest filesystem",
1632    "\
1633 This call runs a command from the guest filesystem.  The
1634 filesystem must be mounted, and must contain a compatible
1635 operating system (ie. something Linux, with the same
1636 or compatible processor architecture).
1637
1638 The single parameter is an argv-style list of arguments.
1639 The first element is the name of the program to run.
1640 Subsequent elements are parameters.  The list must be
1641 non-empty (ie. must contain a program name).  Note that
1642 the command runs directly, and is I<not> invoked via
1643 the shell (see C<guestfs_sh>).
1644
1645 The return value is anything printed to I<stdout> by
1646 the command.
1647
1648 If the command returns a non-zero exit status, then
1649 this function returns an error message.  The error message
1650 string is the content of I<stderr> from the command.
1651
1652 The C<$PATH> environment variable will contain at least
1653 C</usr/bin> and C</bin>.  If you require a program from
1654 another location, you should provide the full path in the
1655 first parameter.
1656
1657 Shared libraries and data files required by the program
1658 must be available on filesystems which are mounted in the
1659 correct places.  It is the caller's responsibility to ensure
1660 all filesystems that are needed are mounted at the right
1661 locations.");
1662
1663   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1664    [InitBasicFS, Always, TestOutputList (
1665       [["upload"; "test-command"; "/test-command"];
1666        ["chmod"; "0o755"; "/test-command"];
1667        ["command_lines"; "/test-command 1"]], ["Result1"]);
1668     InitBasicFS, Always, TestOutputList (
1669       [["upload"; "test-command"; "/test-command"];
1670        ["chmod"; "0o755"; "/test-command"];
1671        ["command_lines"; "/test-command 2"]], ["Result2"]);
1672     InitBasicFS, Always, TestOutputList (
1673       [["upload"; "test-command"; "/test-command"];
1674        ["chmod"; "0o755"; "/test-command"];
1675        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1676     InitBasicFS, Always, TestOutputList (
1677       [["upload"; "test-command"; "/test-command"];
1678        ["chmod"; "0o755"; "/test-command"];
1679        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1680     InitBasicFS, Always, TestOutputList (
1681       [["upload"; "test-command"; "/test-command"];
1682        ["chmod"; "0o755"; "/test-command"];
1683        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1684     InitBasicFS, Always, TestOutputList (
1685       [["upload"; "test-command"; "/test-command"];
1686        ["chmod"; "0o755"; "/test-command"];
1687        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1688     InitBasicFS, Always, TestOutputList (
1689       [["upload"; "test-command"; "/test-command"];
1690        ["chmod"; "0o755"; "/test-command"];
1691        ["command_lines"; "/test-command 7"]], []);
1692     InitBasicFS, Always, TestOutputList (
1693       [["upload"; "test-command"; "/test-command"];
1694        ["chmod"; "0o755"; "/test-command"];
1695        ["command_lines"; "/test-command 8"]], [""]);
1696     InitBasicFS, Always, TestOutputList (
1697       [["upload"; "test-command"; "/test-command"];
1698        ["chmod"; "0o755"; "/test-command"];
1699        ["command_lines"; "/test-command 9"]], ["";""]);
1700     InitBasicFS, Always, TestOutputList (
1701       [["upload"; "test-command"; "/test-command"];
1702        ["chmod"; "0o755"; "/test-command"];
1703        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1704     InitBasicFS, Always, TestOutputList (
1705       [["upload"; "test-command"; "/test-command"];
1706        ["chmod"; "0o755"; "/test-command"];
1707        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1708    "run a command, returning lines",
1709    "\
1710 This is the same as C<guestfs_command>, but splits the
1711 result into a list of lines.
1712
1713 See also: C<guestfs_sh_lines>");
1714
1715   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1716    [InitISOFS, Always, TestOutputStruct (
1717       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1718    "get file information",
1719    "\
1720 Returns file information for the given C<path>.
1721
1722 This is the same as the C<stat(2)> system call.");
1723
1724   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1725    [InitISOFS, Always, TestOutputStruct (
1726       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1727    "get file information for a symbolic link",
1728    "\
1729 Returns file information for the given C<path>.
1730
1731 This is the same as C<guestfs_stat> except that if C<path>
1732 is a symbolic link, then the link is stat-ed, not the file it
1733 refers to.
1734
1735 This is the same as the C<lstat(2)> system call.");
1736
1737   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1738    [InitISOFS, Always, TestOutputStruct (
1739       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1740    "get file system statistics",
1741    "\
1742 Returns file system statistics for any mounted file system.
1743 C<path> should be a file or directory in the mounted file system
1744 (typically it is the mount point itself, but it doesn't need to be).
1745
1746 This is the same as the C<statvfs(2)> system call.");
1747
1748   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1749    [], (* XXX test *)
1750    "get ext2/ext3/ext4 superblock details",
1751    "\
1752 This returns the contents of the ext2, ext3 or ext4 filesystem
1753 superblock on C<device>.
1754
1755 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1756 manpage for more details.  The list of fields returned isn't
1757 clearly defined, and depends on both the version of C<tune2fs>
1758 that libguestfs was built against, and the filesystem itself.");
1759
1760   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1761    [InitEmpty, Always, TestOutputTrue (
1762       [["blockdev_setro"; "/dev/sda"];
1763        ["blockdev_getro"; "/dev/sda"]])],
1764    "set block device to read-only",
1765    "\
1766 Sets the block device named C<device> to read-only.
1767
1768 This uses the L<blockdev(8)> command.");
1769
1770   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1771    [InitEmpty, Always, TestOutputFalse (
1772       [["blockdev_setrw"; "/dev/sda"];
1773        ["blockdev_getro"; "/dev/sda"]])],
1774    "set block device to read-write",
1775    "\
1776 Sets the block device named C<device> to read-write.
1777
1778 This uses the L<blockdev(8)> command.");
1779
1780   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1781    [InitEmpty, Always, TestOutputTrue (
1782       [["blockdev_setro"; "/dev/sda"];
1783        ["blockdev_getro"; "/dev/sda"]])],
1784    "is block device set to read-only",
1785    "\
1786 Returns a boolean indicating if the block device is read-only
1787 (true if read-only, false if not).
1788
1789 This uses the L<blockdev(8)> command.");
1790
1791   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1792    [InitEmpty, Always, TestOutputInt (
1793       [["blockdev_getss"; "/dev/sda"]], 512)],
1794    "get sectorsize of block device",
1795    "\
1796 This returns the size of sectors on a block device.
1797 Usually 512, but can be larger for modern devices.
1798
1799 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1800 for that).
1801
1802 This uses the L<blockdev(8)> command.");
1803
1804   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1805    [InitEmpty, Always, TestOutputInt (
1806       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1807    "get blocksize of block device",
1808    "\
1809 This returns the block size of a device.
1810
1811 (Note this is different from both I<size in blocks> and
1812 I<filesystem block size>).
1813
1814 This uses the L<blockdev(8)> command.");
1815
1816   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1817    [], (* XXX test *)
1818    "set blocksize of block device",
1819    "\
1820 This sets the block size of a device.
1821
1822 (Note this is different from both I<size in blocks> and
1823 I<filesystem block size>).
1824
1825 This uses the L<blockdev(8)> command.");
1826
1827   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1828    [InitEmpty, Always, TestOutputInt (
1829       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1830    "get total size of device in 512-byte sectors",
1831    "\
1832 This returns the size of the device in units of 512-byte sectors
1833 (even if the sectorsize isn't 512 bytes ... weird).
1834
1835 See also C<guestfs_blockdev_getss> for the real sector size of
1836 the device, and C<guestfs_blockdev_getsize64> for the more
1837 useful I<size in bytes>.
1838
1839 This uses the L<blockdev(8)> command.");
1840
1841   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1842    [InitEmpty, Always, TestOutputInt (
1843       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1844    "get total size of device in bytes",
1845    "\
1846 This returns the size of the device in bytes.
1847
1848 See also C<guestfs_blockdev_getsz>.
1849
1850 This uses the L<blockdev(8)> command.");
1851
1852   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1853    [InitEmpty, Always, TestRun
1854       [["blockdev_flushbufs"; "/dev/sda"]]],
1855    "flush device buffers",
1856    "\
1857 This tells the kernel to flush internal buffers associated
1858 with C<device>.
1859
1860 This uses the L<blockdev(8)> command.");
1861
1862   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1863    [InitEmpty, Always, TestRun
1864       [["blockdev_rereadpt"; "/dev/sda"]]],
1865    "reread partition table",
1866    "\
1867 Reread the partition table on C<device>.
1868
1869 This uses the L<blockdev(8)> command.");
1870
1871   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1872    [InitBasicFS, Always, TestOutput (
1873       (* Pick a file from cwd which isn't likely to change. *)
1874       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1875        ["checksum"; "md5"; "/COPYING.LIB"]],
1876       Digest.to_hex (Digest.file "COPYING.LIB"))],
1877    "upload a file from the local machine",
1878    "\
1879 Upload local file C<filename> to C<remotefilename> on the
1880 filesystem.
1881
1882 C<filename> can also be a named pipe.
1883
1884 See also C<guestfs_download>.");
1885
1886   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1887    [InitBasicFS, Always, TestOutput (
1888       (* Pick a file from cwd which isn't likely to change. *)
1889       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1890        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1891        ["upload"; "testdownload.tmp"; "/upload"];
1892        ["checksum"; "md5"; "/upload"]],
1893       Digest.to_hex (Digest.file "COPYING.LIB"))],
1894    "download a file to the local machine",
1895    "\
1896 Download file C<remotefilename> and save it as C<filename>
1897 on the local machine.
1898
1899 C<filename> can also be a named pipe.
1900
1901 See also C<guestfs_upload>, C<guestfs_cat>.");
1902
1903   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1904    [InitISOFS, Always, TestOutput (
1905       [["checksum"; "crc"; "/known-3"]], "2891671662");
1906     InitISOFS, Always, TestLastFail (
1907       [["checksum"; "crc"; "/notexists"]]);
1908     InitISOFS, Always, TestOutput (
1909       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1910     InitISOFS, Always, TestOutput (
1911       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1912     InitISOFS, Always, TestOutput (
1913       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1914     InitISOFS, Always, TestOutput (
1915       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1916     InitISOFS, Always, TestOutput (
1917       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1918     InitISOFS, Always, TestOutput (
1919       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1920    "compute MD5, SHAx or CRC checksum of file",
1921    "\
1922 This call computes the MD5, SHAx or CRC checksum of the
1923 file named C<path>.
1924
1925 The type of checksum to compute is given by the C<csumtype>
1926 parameter which must have one of the following values:
1927
1928 =over 4
1929
1930 =item C<crc>
1931
1932 Compute the cyclic redundancy check (CRC) specified by POSIX
1933 for the C<cksum> command.
1934
1935 =item C<md5>
1936
1937 Compute the MD5 hash (using the C<md5sum> program).
1938
1939 =item C<sha1>
1940
1941 Compute the SHA1 hash (using the C<sha1sum> program).
1942
1943 =item C<sha224>
1944
1945 Compute the SHA224 hash (using the C<sha224sum> program).
1946
1947 =item C<sha256>
1948
1949 Compute the SHA256 hash (using the C<sha256sum> program).
1950
1951 =item C<sha384>
1952
1953 Compute the SHA384 hash (using the C<sha384sum> program).
1954
1955 =item C<sha512>
1956
1957 Compute the SHA512 hash (using the C<sha512sum> program).
1958
1959 =back
1960
1961 The checksum is returned as a printable string.");
1962
1963   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1964    [InitBasicFS, Always, TestOutput (
1965       [["tar_in"; "../images/helloworld.tar"; "/"];
1966        ["cat"; "/hello"]], "hello\n")],
1967    "unpack tarfile to directory",
1968    "\
1969 This command uploads and unpacks local file C<tarfile> (an
1970 I<uncompressed> tar file) into C<directory>.
1971
1972 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1973
1974   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1975    [],
1976    "pack directory into tarfile",
1977    "\
1978 This command packs the contents of C<directory> and downloads
1979 it to local file C<tarfile>.
1980
1981 To download a compressed tarball, use C<guestfs_tgz_out>.");
1982
1983   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1984    [InitBasicFS, Always, TestOutput (
1985       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1986        ["cat"; "/hello"]], "hello\n")],
1987    "unpack compressed tarball to directory",
1988    "\
1989 This command uploads and unpacks local file C<tarball> (a
1990 I<gzip compressed> tar file) into C<directory>.
1991
1992 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1993
1994   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1995    [],
1996    "pack directory into compressed tarball",
1997    "\
1998 This command packs the contents of C<directory> and downloads
1999 it to local file C<tarball>.
2000
2001 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2002
2003   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2004    [InitBasicFS, Always, TestLastFail (
2005       [["umount"; "/"];
2006        ["mount_ro"; "/dev/sda1"; "/"];
2007        ["touch"; "/new"]]);
2008     InitBasicFS, Always, TestOutput (
2009       [["write_file"; "/new"; "data"; "0"];
2010        ["umount"; "/"];
2011        ["mount_ro"; "/dev/sda1"; "/"];
2012        ["cat"; "/new"]], "data")],
2013    "mount a guest disk, read-only",
2014    "\
2015 This is the same as the C<guestfs_mount> command, but it
2016 mounts the filesystem with the read-only (I<-o ro>) flag.");
2017
2018   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2019    [],
2020    "mount a guest disk with mount options",
2021    "\
2022 This is the same as the C<guestfs_mount> command, but it
2023 allows you to set the mount options as for the
2024 L<mount(8)> I<-o> flag.");
2025
2026   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2027    [],
2028    "mount a guest disk with mount options and vfstype",
2029    "\
2030 This is the same as the C<guestfs_mount> command, but it
2031 allows you to set both the mount options and the vfstype
2032 as for the L<mount(8)> I<-o> and I<-t> flags.");
2033
2034   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2035    [],
2036    "debugging and internals",
2037    "\
2038 The C<guestfs_debug> command exposes some internals of
2039 C<guestfsd> (the guestfs daemon) that runs inside the
2040 qemu subprocess.
2041
2042 There is no comprehensive help for this command.  You have
2043 to look at the file C<daemon/debug.c> in the libguestfs source
2044 to find out what you can do.");
2045
2046   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2047    [InitEmpty, Always, TestOutputList (
2048       [["part_disk"; "/dev/sda"; "mbr"];
2049        ["pvcreate"; "/dev/sda1"];
2050        ["vgcreate"; "VG"; "/dev/sda1"];
2051        ["lvcreate"; "LV1"; "VG"; "50"];
2052        ["lvcreate"; "LV2"; "VG"; "50"];
2053        ["lvremove"; "/dev/VG/LV1"];
2054        ["lvs"]], ["/dev/VG/LV2"]);
2055     InitEmpty, Always, TestOutputList (
2056       [["part_disk"; "/dev/sda"; "mbr"];
2057        ["pvcreate"; "/dev/sda1"];
2058        ["vgcreate"; "VG"; "/dev/sda1"];
2059        ["lvcreate"; "LV1"; "VG"; "50"];
2060        ["lvcreate"; "LV2"; "VG"; "50"];
2061        ["lvremove"; "/dev/VG"];
2062        ["lvs"]], []);
2063     InitEmpty, Always, TestOutputList (
2064       [["part_disk"; "/dev/sda"; "mbr"];
2065        ["pvcreate"; "/dev/sda1"];
2066        ["vgcreate"; "VG"; "/dev/sda1"];
2067        ["lvcreate"; "LV1"; "VG"; "50"];
2068        ["lvcreate"; "LV2"; "VG"; "50"];
2069        ["lvremove"; "/dev/VG"];
2070        ["vgs"]], ["VG"])],
2071    "remove an LVM logical volume",
2072    "\
2073 Remove an LVM logical volume C<device>, where C<device> is
2074 the path to the LV, such as C</dev/VG/LV>.
2075
2076 You can also remove all LVs in a volume group by specifying
2077 the VG name, C</dev/VG>.");
2078
2079   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2080    [InitEmpty, Always, TestOutputList (
2081       [["part_disk"; "/dev/sda"; "mbr"];
2082        ["pvcreate"; "/dev/sda1"];
2083        ["vgcreate"; "VG"; "/dev/sda1"];
2084        ["lvcreate"; "LV1"; "VG"; "50"];
2085        ["lvcreate"; "LV2"; "VG"; "50"];
2086        ["vgremove"; "VG"];
2087        ["lvs"]], []);
2088     InitEmpty, Always, TestOutputList (
2089       [["part_disk"; "/dev/sda"; "mbr"];
2090        ["pvcreate"; "/dev/sda1"];
2091        ["vgcreate"; "VG"; "/dev/sda1"];
2092        ["lvcreate"; "LV1"; "VG"; "50"];
2093        ["lvcreate"; "LV2"; "VG"; "50"];
2094        ["vgremove"; "VG"];
2095        ["vgs"]], [])],
2096    "remove an LVM volume group",
2097    "\
2098 Remove an LVM volume group C<vgname>, (for example C<VG>).
2099
2100 This also forcibly removes all logical volumes in the volume
2101 group (if any).");
2102
2103   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2104    [InitEmpty, Always, TestOutputListOfDevices (
2105       [["part_disk"; "/dev/sda"; "mbr"];
2106        ["pvcreate"; "/dev/sda1"];
2107        ["vgcreate"; "VG"; "/dev/sda1"];
2108        ["lvcreate"; "LV1"; "VG"; "50"];
2109        ["lvcreate"; "LV2"; "VG"; "50"];
2110        ["vgremove"; "VG"];
2111        ["pvremove"; "/dev/sda1"];
2112        ["lvs"]], []);
2113     InitEmpty, Always, TestOutputListOfDevices (
2114       [["part_disk"; "/dev/sda"; "mbr"];
2115        ["pvcreate"; "/dev/sda1"];
2116        ["vgcreate"; "VG"; "/dev/sda1"];
2117        ["lvcreate"; "LV1"; "VG"; "50"];
2118        ["lvcreate"; "LV2"; "VG"; "50"];
2119        ["vgremove"; "VG"];
2120        ["pvremove"; "/dev/sda1"];
2121        ["vgs"]], []);
2122     InitEmpty, Always, TestOutputListOfDevices (
2123       [["part_disk"; "/dev/sda"; "mbr"];
2124        ["pvcreate"; "/dev/sda1"];
2125        ["vgcreate"; "VG"; "/dev/sda1"];
2126        ["lvcreate"; "LV1"; "VG"; "50"];
2127        ["lvcreate"; "LV2"; "VG"; "50"];
2128        ["vgremove"; "VG"];
2129        ["pvremove"; "/dev/sda1"];
2130        ["pvs"]], [])],
2131    "remove an LVM physical volume",
2132    "\
2133 This wipes a physical volume C<device> so that LVM will no longer
2134 recognise it.
2135
2136 The implementation uses the C<pvremove> command which refuses to
2137 wipe physical volumes that contain any volume groups, so you have
2138 to remove those first.");
2139
2140   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2141    [InitBasicFS, Always, TestOutput (
2142       [["set_e2label"; "/dev/sda1"; "testlabel"];
2143        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2144    "set the ext2/3/4 filesystem label",
2145    "\
2146 This sets the ext2/3/4 filesystem label of the filesystem on
2147 C<device> to C<label>.  Filesystem labels are limited to
2148 16 characters.
2149
2150 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2151 to return the existing label on a filesystem.");
2152
2153   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2154    [],
2155    "get the ext2/3/4 filesystem label",
2156    "\
2157 This returns the ext2/3/4 filesystem label of the filesystem on
2158 C<device>.");
2159
2160   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2161    (let uuid = uuidgen () in
2162     [InitBasicFS, Always, TestOutput (
2163        [["set_e2uuid"; "/dev/sda1"; uuid];
2164         ["get_e2uuid"; "/dev/sda1"]], uuid);
2165      InitBasicFS, Always, TestOutput (
2166        [["set_e2uuid"; "/dev/sda1"; "clear"];
2167         ["get_e2uuid"; "/dev/sda1"]], "");
2168      (* We can't predict what UUIDs will be, so just check the commands run. *)
2169      InitBasicFS, Always, TestRun (
2170        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2171      InitBasicFS, Always, TestRun (
2172        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2173    "set the ext2/3/4 filesystem UUID",
2174    "\
2175 This sets the ext2/3/4 filesystem UUID of the filesystem on
2176 C<device> to C<uuid>.  The format of the UUID and alternatives
2177 such as C<clear>, C<random> and C<time> are described in the
2178 L<tune2fs(8)> manpage.
2179
2180 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2181 to return the existing UUID of a filesystem.");
2182
2183   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2184    [],
2185    "get the ext2/3/4 filesystem UUID",
2186    "\
2187 This returns the ext2/3/4 filesystem UUID of the filesystem on
2188 C<device>.");
2189
2190   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2191    [InitBasicFS, Always, TestOutputInt (
2192       [["umount"; "/dev/sda1"];
2193        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2194     InitBasicFS, Always, TestOutputInt (
2195       [["umount"; "/dev/sda1"];
2196        ["zero"; "/dev/sda1"];
2197        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2198    "run the filesystem checker",
2199    "\
2200 This runs the filesystem checker (fsck) on C<device> which
2201 should have filesystem type C<fstype>.
2202
2203 The returned integer is the status.  See L<fsck(8)> for the
2204 list of status codes from C<fsck>.
2205
2206 Notes:
2207
2208 =over 4
2209
2210 =item *
2211
2212 Multiple status codes can be summed together.
2213
2214 =item *
2215
2216 A non-zero return code can mean \"success\", for example if
2217 errors have been corrected on the filesystem.
2218
2219 =item *
2220
2221 Checking or repairing NTFS volumes is not supported
2222 (by linux-ntfs).
2223
2224 =back
2225
2226 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2227
2228   ("zero", (RErr, [Device "device"]), 85, [],
2229    [InitBasicFS, Always, TestOutput (
2230       [["umount"; "/dev/sda1"];
2231        ["zero"; "/dev/sda1"];
2232        ["file"; "/dev/sda1"]], "data")],
2233    "write zeroes to the device",
2234    "\
2235 This command writes zeroes over the first few blocks of C<device>.
2236
2237 How many blocks are zeroed isn't specified (but it's I<not> enough
2238 to securely wipe the device).  It should be sufficient to remove
2239 any partition tables, filesystem superblocks and so on.
2240
2241 See also: C<guestfs_scrub_device>.");
2242
2243   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2244    (* Test disabled because grub-install incompatible with virtio-blk driver.
2245     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2246     *)
2247    [InitBasicFS, Disabled, TestOutputTrue (
2248       [["grub_install"; "/"; "/dev/sda1"];
2249        ["is_dir"; "/boot"]])],
2250    "install GRUB",
2251    "\
2252 This command installs GRUB (the Grand Unified Bootloader) on
2253 C<device>, with the root directory being C<root>.");
2254
2255   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2256    [InitBasicFS, Always, TestOutput (
2257       [["write_file"; "/old"; "file content"; "0"];
2258        ["cp"; "/old"; "/new"];
2259        ["cat"; "/new"]], "file content");
2260     InitBasicFS, Always, TestOutputTrue (
2261       [["write_file"; "/old"; "file content"; "0"];
2262        ["cp"; "/old"; "/new"];
2263        ["is_file"; "/old"]]);
2264     InitBasicFS, Always, TestOutput (
2265       [["write_file"; "/old"; "file content"; "0"];
2266        ["mkdir"; "/dir"];
2267        ["cp"; "/old"; "/dir/new"];
2268        ["cat"; "/dir/new"]], "file content")],
2269    "copy a file",
2270    "\
2271 This copies a file from C<src> to C<dest> where C<dest> is
2272 either a destination filename or destination directory.");
2273
2274   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2275    [InitBasicFS, Always, TestOutput (
2276       [["mkdir"; "/olddir"];
2277        ["mkdir"; "/newdir"];
2278        ["write_file"; "/olddir/file"; "file content"; "0"];
2279        ["cp_a"; "/olddir"; "/newdir"];
2280        ["cat"; "/newdir/olddir/file"]], "file content")],
2281    "copy a file or directory recursively",
2282    "\
2283 This copies a file or directory from C<src> to C<dest>
2284 recursively using the C<cp -a> command.");
2285
2286   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2287    [InitBasicFS, Always, TestOutput (
2288       [["write_file"; "/old"; "file content"; "0"];
2289        ["mv"; "/old"; "/new"];
2290        ["cat"; "/new"]], "file content");
2291     InitBasicFS, Always, TestOutputFalse (
2292       [["write_file"; "/old"; "file content"; "0"];
2293        ["mv"; "/old"; "/new"];
2294        ["is_file"; "/old"]])],
2295    "move a file",
2296    "\
2297 This moves a file from C<src> to C<dest> where C<dest> is
2298 either a destination filename or destination directory.");
2299
2300   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2301    [InitEmpty, Always, TestRun (
2302       [["drop_caches"; "3"]])],
2303    "drop kernel page cache, dentries and inodes",
2304    "\
2305 This instructs the guest kernel to drop its page cache,
2306 and/or dentries and inode caches.  The parameter C<whattodrop>
2307 tells the kernel what precisely to drop, see
2308 L<http://linux-mm.org/Drop_Caches>
2309
2310 Setting C<whattodrop> to 3 should drop everything.
2311
2312 This automatically calls L<sync(2)> before the operation,
2313 so that the maximum guest memory is freed.");
2314
2315   ("dmesg", (RString "kmsgs", []), 91, [],
2316    [InitEmpty, Always, TestRun (
2317       [["dmesg"]])],
2318    "return kernel messages",
2319    "\
2320 This returns the kernel messages (C<dmesg> output) from
2321 the guest kernel.  This is sometimes useful for extended
2322 debugging of problems.
2323
2324 Another way to get the same information is to enable
2325 verbose messages with C<guestfs_set_verbose> or by setting
2326 the environment variable C<LIBGUESTFS_DEBUG=1> before
2327 running the program.");
2328
2329   ("ping_daemon", (RErr, []), 92, [],
2330    [InitEmpty, Always, TestRun (
2331       [["ping_daemon"]])],
2332    "ping the guest daemon",
2333    "\
2334 This is a test probe into the guestfs daemon running inside
2335 the qemu subprocess.  Calling this function checks that the
2336 daemon responds to the ping message, without affecting the daemon
2337 or attached block device(s) in any other way.");
2338
2339   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2340    [InitBasicFS, Always, TestOutputTrue (
2341       [["write_file"; "/file1"; "contents of a file"; "0"];
2342        ["cp"; "/file1"; "/file2"];
2343        ["equal"; "/file1"; "/file2"]]);
2344     InitBasicFS, Always, TestOutputFalse (
2345       [["write_file"; "/file1"; "contents of a file"; "0"];
2346        ["write_file"; "/file2"; "contents of another file"; "0"];
2347        ["equal"; "/file1"; "/file2"]]);
2348     InitBasicFS, Always, TestLastFail (
2349       [["equal"; "/file1"; "/file2"]])],
2350    "test if two files have equal contents",
2351    "\
2352 This compares the two files C<file1> and C<file2> and returns
2353 true if their content is exactly equal, or false otherwise.
2354
2355 The external L<cmp(1)> program is used for the comparison.");
2356
2357   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2358    [InitISOFS, Always, TestOutputList (
2359       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2360     InitISOFS, Always, TestOutputList (
2361       [["strings"; "/empty"]], [])],
2362    "print the printable strings in a file",
2363    "\
2364 This runs the L<strings(1)> command on a file and returns
2365 the list of printable strings found.");
2366
2367   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2368    [InitISOFS, Always, TestOutputList (
2369       [["strings_e"; "b"; "/known-5"]], []);
2370     InitBasicFS, Disabled, TestOutputList (
2371       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2372        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2373    "print the printable strings in a file",
2374    "\
2375 This is like the C<guestfs_strings> command, but allows you to
2376 specify the encoding.
2377
2378 See the L<strings(1)> manpage for the full list of encodings.
2379
2380 Commonly useful encodings are C<l> (lower case L) which will
2381 show strings inside Windows/x86 files.
2382
2383 The returned strings are transcoded to UTF-8.");
2384
2385   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2386    [InitISOFS, Always, TestOutput (
2387       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2388     (* Test for RHBZ#501888c2 regression which caused large hexdump
2389      * commands to segfault.
2390      *)
2391     InitISOFS, Always, TestRun (
2392       [["hexdump"; "/100krandom"]])],
2393    "dump a file in hexadecimal",
2394    "\
2395 This runs C<hexdump -C> on the given C<path>.  The result is
2396 the human-readable, canonical hex dump of the file.");
2397
2398   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2399    [InitNone, Always, TestOutput (
2400       [["part_disk"; "/dev/sda"; "mbr"];
2401        ["mkfs"; "ext3"; "/dev/sda1"];
2402        ["mount"; "/dev/sda1"; "/"];
2403        ["write_file"; "/new"; "test file"; "0"];
2404        ["umount"; "/dev/sda1"];
2405        ["zerofree"; "/dev/sda1"];
2406        ["mount"; "/dev/sda1"; "/"];
2407        ["cat"; "/new"]], "test file")],
2408    "zero unused inodes and disk blocks on ext2/3 filesystem",
2409    "\
2410 This runs the I<zerofree> program on C<device>.  This program
2411 claims to zero unused inodes and disk blocks on an ext2/3
2412 filesystem, thus making it possible to compress the filesystem
2413 more effectively.
2414
2415 You should B<not> run this program if the filesystem is
2416 mounted.
2417
2418 It is possible that using this program can damage the filesystem
2419 or data on the filesystem.");
2420
2421   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2422    [],
2423    "resize an LVM physical volume",
2424    "\
2425 This resizes (expands or shrinks) an existing LVM physical
2426 volume to match the new size of the underlying device.");
2427
2428   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2429                        Int "cyls"; Int "heads"; Int "sectors";
2430                        String "line"]), 99, [DangerWillRobinson],
2431    [],
2432    "modify a single partition on a block device",
2433    "\
2434 This runs L<sfdisk(8)> option to modify just the single
2435 partition C<n> (note: C<n> counts from 1).
2436
2437 For other parameters, see C<guestfs_sfdisk>.  You should usually
2438 pass C<0> for the cyls/heads/sectors parameters.
2439
2440 See also: C<guestfs_part_add>");
2441
2442   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2443    [],
2444    "display the partition table",
2445    "\
2446 This displays the partition table on C<device>, in the
2447 human-readable output of the L<sfdisk(8)> command.  It is
2448 not intended to be parsed.
2449
2450 See also: C<guestfs_part_list>");
2451
2452   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2453    [],
2454    "display the kernel geometry",
2455    "\
2456 This displays the kernel's idea of the geometry of C<device>.
2457
2458 The result is in human-readable format, and not designed to
2459 be parsed.");
2460
2461   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2462    [],
2463    "display the disk geometry from the partition table",
2464    "\
2465 This displays the disk geometry of C<device> read from the
2466 partition table.  Especially in the case where the underlying
2467 block device has been resized, this can be different from the
2468 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2469
2470 The result is in human-readable format, and not designed to
2471 be parsed.");
2472
2473   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2474    [],
2475    "activate or deactivate all volume groups",
2476    "\
2477 This command activates or (if C<activate> is false) deactivates
2478 all logical volumes in all volume groups.
2479 If activated, then they are made known to the
2480 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2481 then those devices disappear.
2482
2483 This command is the same as running C<vgchange -a y|n>");
2484
2485   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2486    [],
2487    "activate or deactivate some volume groups",
2488    "\
2489 This command activates or (if C<activate> is false) deactivates
2490 all logical volumes in the listed volume groups C<volgroups>.
2491 If activated, then they are made known to the
2492 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2493 then those devices disappear.
2494
2495 This command is the same as running C<vgchange -a y|n volgroups...>
2496
2497 Note that if C<volgroups> is an empty list then B<all> volume groups
2498 are activated or deactivated.");
2499
2500   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2501    [InitNone, Always, TestOutput (
2502       [["part_disk"; "/dev/sda"; "mbr"];
2503        ["pvcreate"; "/dev/sda1"];
2504        ["vgcreate"; "VG"; "/dev/sda1"];
2505        ["lvcreate"; "LV"; "VG"; "10"];
2506        ["mkfs"; "ext2"; "/dev/VG/LV"];
2507        ["mount"; "/dev/VG/LV"; "/"];
2508        ["write_file"; "/new"; "test content"; "0"];
2509        ["umount"; "/"];
2510        ["lvresize"; "/dev/VG/LV"; "20"];
2511        ["e2fsck_f"; "/dev/VG/LV"];
2512        ["resize2fs"; "/dev/VG/LV"];
2513        ["mount"; "/dev/VG/LV"; "/"];
2514        ["cat"; "/new"]], "test content")],
2515    "resize an LVM logical volume",
2516    "\
2517 This resizes (expands or shrinks) an existing LVM logical
2518 volume to C<mbytes>.  When reducing, data in the reduced part
2519 is lost.");
2520
2521   ("resize2fs", (RErr, [Device "device"]), 106, [],
2522    [], (* lvresize tests this *)
2523    "resize an ext2/ext3 filesystem",
2524    "\
2525 This resizes an ext2 or ext3 filesystem to match the size of
2526 the underlying device.
2527
2528 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2529 on the C<device> before calling this command.  For unknown reasons
2530 C<resize2fs> sometimes gives an error about this and sometimes not.
2531 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2532 calling this function.");
2533
2534   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2535    [InitBasicFS, Always, TestOutputList (
2536       [["find"; "/"]], ["lost+found"]);
2537     InitBasicFS, Always, TestOutputList (
2538       [["touch"; "/a"];
2539        ["mkdir"; "/b"];
2540        ["touch"; "/b/c"];
2541        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2542     InitBasicFS, Always, TestOutputList (
2543       [["mkdir_p"; "/a/b/c"];
2544        ["touch"; "/a/b/c/d"];
2545        ["find"; "/a/b/"]], ["c"; "c/d"])],
2546    "find all files and directories",
2547    "\
2548 This command lists out all files and directories, recursively,
2549 starting at C<directory>.  It is essentially equivalent to
2550 running the shell command C<find directory -print> but some
2551 post-processing happens on the output, described below.
2552
2553 This returns a list of strings I<without any prefix>.  Thus
2554 if the directory structure was:
2555
2556  /tmp/a
2557  /tmp/b
2558  /tmp/c/d
2559
2560 then the returned list from C<guestfs_find> C</tmp> would be
2561 4 elements:
2562
2563  a
2564  b
2565  c
2566  c/d
2567
2568 If C<directory> is not a directory, then this command returns
2569 an error.
2570
2571 The returned list is sorted.
2572
2573 See also C<guestfs_find0>.");
2574
2575   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2576    [], (* lvresize tests this *)
2577    "check an ext2/ext3 filesystem",
2578    "\
2579 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2580 filesystem checker on C<device>, noninteractively (C<-p>),
2581 even if the filesystem appears to be clean (C<-f>).
2582
2583 This command is only needed because of C<guestfs_resize2fs>
2584 (q.v.).  Normally you should use C<guestfs_fsck>.");
2585
2586   ("sleep", (RErr, [Int "secs"]), 109, [],
2587    [InitNone, Always, TestRun (
2588       [["sleep"; "1"]])],
2589    "sleep for some seconds",
2590    "\
2591 Sleep for C<secs> seconds.");
2592
2593   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2594    [InitNone, Always, TestOutputInt (
2595       [["part_disk"; "/dev/sda"; "mbr"];
2596        ["mkfs"; "ntfs"; "/dev/sda1"];
2597        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2598     InitNone, Always, TestOutputInt (
2599       [["part_disk"; "/dev/sda"; "mbr"];
2600        ["mkfs"; "ext2"; "/dev/sda1"];
2601        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2602    "probe NTFS volume",
2603    "\
2604 This command runs the L<ntfs-3g.probe(8)> command which probes
2605 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2606 be mounted read-write, and some cannot be mounted at all).
2607
2608 C<rw> is a boolean flag.  Set it to true if you want to test
2609 if the volume can be mounted read-write.  Set it to false if
2610 you want to test if the volume can be mounted read-only.
2611
2612 The return value is an integer which C<0> if the operation
2613 would succeed, or some non-zero value documented in the
2614 L<ntfs-3g.probe(8)> manual page.");
2615
2616   ("sh", (RString "output", [String "command"]), 111, [],
2617    [], (* XXX needs tests *)
2618    "run a command via the shell",
2619    "\
2620 This call runs a command from the guest filesystem via the
2621 guest's C</bin/sh>.
2622
2623 This is like C<guestfs_command>, but passes the command to:
2624
2625  /bin/sh -c \"command\"
2626
2627 Depending on the guest's shell, this usually results in
2628 wildcards being expanded, shell expressions being interpolated
2629 and so on.
2630
2631 All the provisos about C<guestfs_command> apply to this call.");
2632
2633   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2634    [], (* XXX needs tests *)
2635    "run a command via the shell returning lines",
2636    "\
2637 This is the same as C<guestfs_sh>, but splits the result
2638 into a list of lines.
2639
2640 See also: C<guestfs_command_lines>");
2641
2642   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2643    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2644     * code in stubs.c, since all valid glob patterns must start with "/".
2645     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2646     *)
2647    [InitBasicFS, Always, TestOutputList (
2648       [["mkdir_p"; "/a/b/c"];
2649        ["touch"; "/a/b/c/d"];
2650        ["touch"; "/a/b/c/e"];
2651        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2652     InitBasicFS, Always, TestOutputList (
2653       [["mkdir_p"; "/a/b/c"];
2654        ["touch"; "/a/b/c/d"];
2655        ["touch"; "/a/b/c/e"];
2656        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2657     InitBasicFS, Always, TestOutputList (
2658       [["mkdir_p"; "/a/b/c"];
2659        ["touch"; "/a/b/c/d"];
2660        ["touch"; "/a/b/c/e"];
2661        ["glob_expand"; "/a/*/x/*"]], [])],
2662    "expand a wildcard path",
2663    "\
2664 This command searches for all the pathnames matching
2665 C<pattern> according to the wildcard expansion rules
2666 used by the shell.
2667
2668 If no paths match, then this returns an empty list
2669 (note: not an error).
2670
2671 It is just a wrapper around the C L<glob(3)> function
2672 with flags C<GLOB_MARK|GLOB_BRACE>.
2673 See that manual page for more details.");
2674
2675   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2676    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2677       [["scrub_device"; "/dev/sdc"]])],
2678    "scrub (securely wipe) a device",
2679    "\
2680 This command writes patterns over C<device> to make data retrieval
2681 more difficult.
2682
2683 It is an interface to the L<scrub(1)> program.  See that
2684 manual page for more details.");
2685
2686   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2687    [InitBasicFS, Always, TestRun (
2688       [["write_file"; "/file"; "content"; "0"];
2689        ["scrub_file"; "/file"]])],
2690    "scrub (securely wipe) a file",
2691    "\
2692 This command writes patterns over a file to make data retrieval
2693 more difficult.
2694
2695 The file is I<removed> after scrubbing.
2696
2697 It is an interface to the L<scrub(1)> program.  See that
2698 manual page for more details.");
2699
2700   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2701    [], (* XXX needs testing *)
2702    "scrub (securely wipe) free space",
2703    "\
2704 This command creates the directory C<dir> and then fills it
2705 with files until the filesystem is full, and scrubs the files
2706 as for C<guestfs_scrub_file>, and deletes them.
2707 The intention is to scrub any free space on the partition
2708 containing C<dir>.
2709
2710 It is an interface to the L<scrub(1)> program.  See that
2711 manual page for more details.");
2712
2713   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2714    [InitBasicFS, Always, TestRun (
2715       [["mkdir"; "/tmp"];
2716        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2717    "create a temporary directory",
2718    "\
2719 This command creates a temporary directory.  The
2720 C<template> parameter should be a full pathname for the
2721 temporary directory name with the final six characters being
2722 \"XXXXXX\".
2723
2724 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2725 the second one being suitable for Windows filesystems.
2726
2727 The name of the temporary directory that was created
2728 is returned.
2729
2730 The temporary directory is created with mode 0700
2731 and is owned by root.
2732
2733 The caller is responsible for deleting the temporary
2734 directory and its contents after use.
2735
2736 See also: L<mkdtemp(3)>");
2737
2738   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2739    [InitISOFS, Always, TestOutputInt (
2740       [["wc_l"; "/10klines"]], 10000)],
2741    "count lines in a file",
2742    "\
2743 This command counts the lines in a file, using the
2744 C<wc -l> external command.");
2745
2746   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2747    [InitISOFS, Always, TestOutputInt (
2748       [["wc_w"; "/10klines"]], 10000)],
2749    "count words in a file",
2750    "\
2751 This command counts the words in a file, using the
2752 C<wc -w> external command.");
2753
2754   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2755    [InitISOFS, Always, TestOutputInt (
2756       [["wc_c"; "/100kallspaces"]], 102400)],
2757    "count characters in a file",
2758    "\
2759 This command counts the characters in a file, using the
2760 C<wc -c> external command.");
2761
2762   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2763    [InitISOFS, Always, TestOutputList (
2764       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2765    "return first 10 lines of a file",
2766    "\
2767 This command returns up to the first 10 lines of a file as
2768 a list of strings.");
2769
2770   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2771    [InitISOFS, Always, TestOutputList (
2772       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2773     InitISOFS, Always, TestOutputList (
2774       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2775     InitISOFS, Always, TestOutputList (
2776       [["head_n"; "0"; "/10klines"]], [])],
2777    "return first N lines of a file",
2778    "\
2779 If the parameter C<nrlines> is a positive number, this returns the first
2780 C<nrlines> lines of the file C<path>.
2781
2782 If the parameter C<nrlines> is a negative number, this returns lines
2783 from the file C<path>, excluding the last C<nrlines> lines.
2784
2785 If the parameter C<nrlines> is zero, this returns an empty list.");
2786
2787   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2788    [InitISOFS, Always, TestOutputList (
2789       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2790    "return last 10 lines of a file",
2791    "\
2792 This command returns up to the last 10 lines of a file as
2793 a list of strings.");
2794
2795   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2796    [InitISOFS, Always, TestOutputList (
2797       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2798     InitISOFS, Always, TestOutputList (
2799       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2800     InitISOFS, Always, TestOutputList (
2801       [["tail_n"; "0"; "/10klines"]], [])],
2802    "return last N lines of a file",
2803    "\
2804 If the parameter C<nrlines> is a positive number, this returns the last
2805 C<nrlines> lines of the file C<path>.
2806
2807 If the parameter C<nrlines> is a negative number, this returns lines
2808 from the file C<path>, starting with the C<-nrlines>th line.
2809
2810 If the parameter C<nrlines> is zero, this returns an empty list.");
2811
2812   ("df", (RString "output", []), 125, [],
2813    [], (* XXX Tricky to test because it depends on the exact format
2814         * of the 'df' command and other imponderables.
2815         *)
2816    "report file system disk space usage",
2817    "\
2818 This command runs the C<df> command to report disk space used.
2819
2820 This command is mostly useful for interactive sessions.  It
2821 is I<not> intended that you try to parse the output string.
2822 Use C<statvfs> from programs.");
2823
2824   ("df_h", (RString "output", []), 126, [],
2825    [], (* XXX Tricky to test because it depends on the exact format
2826         * of the 'df' command and other imponderables.
2827         *)
2828    "report file system disk space usage (human readable)",
2829    "\
2830 This command runs the C<df -h> command to report disk space used
2831 in human-readable format.
2832
2833 This command is mostly useful for interactive sessions.  It
2834 is I<not> intended that you try to parse the output string.
2835 Use C<statvfs> from programs.");
2836
2837   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2838    [InitISOFS, Always, TestOutputInt (
2839       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2840    "estimate file space usage",
2841    "\
2842 This command runs the C<du -s> command to estimate file space
2843 usage for C<path>.
2844
2845 C<path> can be a file or a directory.  If C<path> is a directory
2846 then the estimate includes the contents of the directory and all
2847 subdirectories (recursively).
2848
2849 The result is the estimated size in I<kilobytes>
2850 (ie. units of 1024 bytes).");
2851
2852   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2853    [InitISOFS, Always, TestOutputList (
2854       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2855    "list files in an initrd",
2856    "\
2857 This command lists out files contained in an initrd.
2858
2859 The files are listed without any initial C</> character.  The
2860 files are listed in the order they appear (not necessarily
2861 alphabetical).  Directory names are listed as separate items.
2862
2863 Old Linux kernels (2.4 and earlier) used a compressed ext2
2864 filesystem as initrd.  We I<only> support the newer initramfs
2865 format (compressed cpio files).");
2866
2867   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2868    [],
2869    "mount a file using the loop device",
2870    "\
2871 This command lets you mount C<file> (a filesystem image
2872 in a file) on a mount point.  It is entirely equivalent to
2873 the command C<mount -o loop file mountpoint>.");
2874
2875   ("mkswap", (RErr, [Device "device"]), 130, [],
2876    [InitEmpty, Always, TestRun (
2877       [["part_disk"; "/dev/sda"; "mbr"];
2878        ["mkswap"; "/dev/sda1"]])],
2879    "create a swap partition",
2880    "\
2881 Create a swap partition on C<device>.");
2882
2883   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2884    [InitEmpty, Always, TestRun (
2885       [["part_disk"; "/dev/sda"; "mbr"];
2886        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2887    "create a swap partition with a label",
2888    "\
2889 Create a swap partition on C<device> with label C<label>.
2890
2891 Note that you cannot attach a swap label to a block device
2892 (eg. C</dev/sda>), just to a partition.  This appears to be
2893 a limitation of the kernel or swap tools.");
2894
2895   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2896    (let uuid = uuidgen () in
2897     [InitEmpty, Always, TestRun (
2898        [["part_disk"; "/dev/sda"; "mbr"];
2899         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2900    "create a swap partition with an explicit UUID",
2901    "\
2902 Create a swap partition on C<device> with UUID C<uuid>.");
2903
2904   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2905    [InitBasicFS, Always, TestOutputStruct (
2906       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2907        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2908        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2909     InitBasicFS, Always, TestOutputStruct (
2910       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2911        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2912    "make block, character or FIFO devices",
2913    "\
2914 This call creates block or character special devices, or
2915 named pipes (FIFOs).
2916
2917 The C<mode> parameter should be the mode, using the standard
2918 constants.  C<devmajor> and C<devminor> are the
2919 device major and minor numbers, only used when creating block
2920 and character special devices.");
2921
2922   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2923    [InitBasicFS, Always, TestOutputStruct (
2924       [["mkfifo"; "0o777"; "/node"];
2925        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2926    "make FIFO (named pipe)",
2927    "\
2928 This call creates a FIFO (named pipe) called C<path> with
2929 mode C<mode>.  It is just a convenient wrapper around
2930 C<guestfs_mknod>.");
2931
2932   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2933    [InitBasicFS, Always, TestOutputStruct (
2934       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2935        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2936    "make block device node",
2937    "\
2938 This call creates a block device node called C<path> with
2939 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2940 It is just a convenient wrapper around C<guestfs_mknod>.");
2941
2942   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2943    [InitBasicFS, Always, TestOutputStruct (
2944       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2945        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2946    "make char device node",
2947    "\
2948 This call creates a char device node called C<path> with
2949 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2950 It is just a convenient wrapper around C<guestfs_mknod>.");
2951
2952   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2953    [], (* XXX umask is one of those stateful things that we should
2954         * reset between each test.
2955         *)
2956    "set file mode creation mask (umask)",
2957    "\
2958 This function sets the mask used for creating new files and
2959 device nodes to C<mask & 0777>.
2960
2961 Typical umask values would be C<022> which creates new files
2962 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2963 C<002> which creates new files with permissions like
2964 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2965
2966 The default umask is C<022>.  This is important because it
2967 means that directories and device nodes will be created with
2968 C<0644> or C<0755> mode even if you specify C<0777>.
2969
2970 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2971
2972 This call returns the previous umask.");
2973
2974   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2975    [],
2976    "read directories entries",
2977    "\
2978 This returns the list of directory entries in directory C<dir>.
2979
2980 All entries in the directory are returned, including C<.> and
2981 C<..>.  The entries are I<not> sorted, but returned in the same
2982 order as the underlying filesystem.
2983
2984 Also this call returns basic file type information about each
2985 file.  The C<ftyp> field will contain one of the following characters:
2986
2987 =over 4
2988
2989 =item 'b'
2990
2991 Block special
2992
2993 =item 'c'
2994
2995 Char special
2996
2997 =item 'd'
2998
2999 Directory
3000
3001 =item 'f'
3002
3003 FIFO (named pipe)
3004
3005 =item 'l'
3006
3007 Symbolic link
3008
3009 =item 'r'
3010
3011 Regular file
3012
3013 =item 's'
3014
3015 Socket
3016
3017 =item 'u'
3018
3019 Unknown file type
3020
3021 =item '?'
3022
3023 The L<readdir(3)> returned a C<d_type> field with an
3024 unexpected value
3025
3026 =back
3027
3028 This function is primarily intended for use by programs.  To
3029 get a simple list of names, use C<guestfs_ls>.  To get a printable
3030 directory for human consumption, use C<guestfs_ll>.");
3031
3032   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3033    [],
3034    "create partitions on a block device",
3035    "\
3036 This is a simplified interface to the C<guestfs_sfdisk>
3037 command, where partition sizes are specified in megabytes
3038 only (rounded to the nearest cylinder) and you don't need
3039 to specify the cyls, heads and sectors parameters which
3040 were rarely if ever used anyway.
3041
3042 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3043 and C<guestfs_part_disk>");
3044
3045   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3046    [],
3047    "determine file type inside a compressed file",
3048    "\
3049 This command runs C<file> after first decompressing C<path>
3050 using C<method>.
3051
3052 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3053
3054 Since 1.0.63, use C<guestfs_file> instead which can now
3055 process compressed files.");
3056
3057   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3058    [],
3059    "list extended attributes of a file or directory",
3060    "\
3061 This call lists the extended attributes of the file or directory
3062 C<path>.
3063
3064 At the system call level, this is a combination of the
3065 L<listxattr(2)> and L<getxattr(2)> calls.
3066
3067 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3068
3069   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3070    [],
3071    "list extended attributes of a file or directory",
3072    "\
3073 This is the same as C<guestfs_getxattrs>, but if C<path>
3074 is a symbolic link, then it returns the extended attributes
3075 of the link itself.");
3076
3077   ("setxattr", (RErr, [String "xattr";
3078                        String "val"; Int "vallen"; (* will be BufferIn *)
3079                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3080    [],
3081    "set extended attribute of a file or directory",
3082    "\
3083 This call sets the extended attribute named C<xattr>
3084 of the file C<path> to the value C<val> (of length C<vallen>).
3085 The value is arbitrary 8 bit data.
3086
3087 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3088
3089   ("lsetxattr", (RErr, [String "xattr";
3090                         String "val"; Int "vallen"; (* will be BufferIn *)
3091                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3092    [],
3093    "set extended attribute of a file or directory",
3094    "\
3095 This is the same as C<guestfs_setxattr>, but if C<path>
3096 is a symbolic link, then it sets an extended attribute
3097 of the link itself.");
3098
3099   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3100    [],
3101    "remove extended attribute of a file or directory",
3102    "\
3103 This call removes the extended attribute named C<xattr>
3104 of the file C<path>.
3105
3106 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3107
3108   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3109    [],
3110    "remove extended attribute of a file or directory",
3111    "\
3112 This is the same as C<guestfs_removexattr>, but if C<path>
3113 is a symbolic link, then it removes an extended attribute
3114 of the link itself.");
3115
3116   ("mountpoints", (RHashtable "mps", []), 147, [],
3117    [],
3118    "show mountpoints",
3119    "\
3120 This call is similar to C<guestfs_mounts>.  That call returns
3121 a list of devices.  This one returns a hash table (map) of
3122 device name to directory where the device is mounted.");
3123
3124   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3125    (* This is a special case: while you would expect a parameter
3126     * of type "Pathname", that doesn't work, because it implies
3127     * NEED_ROOT in the generated calling code in stubs.c, and
3128     * this function cannot use NEED_ROOT.
3129     *)
3130    [],
3131    "create a mountpoint",
3132    "\
3133 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3134 specialized calls that can be used to create extra mountpoints
3135 before mounting the first filesystem.
3136
3137 These calls are I<only> necessary in some very limited circumstances,
3138 mainly the case where you want to mount a mix of unrelated and/or
3139 read-only filesystems together.
3140
3141 For example, live CDs often contain a \"Russian doll\" nest of
3142 filesystems, an ISO outer layer, with a squashfs image inside, with
3143 an ext2/3 image inside that.  You can unpack this as follows
3144 in guestfish:
3145
3146  add-ro Fedora-11-i686-Live.iso
3147  run
3148  mkmountpoint /cd
3149  mkmountpoint /squash
3150  mkmountpoint /ext3
3151  mount /dev/sda /cd
3152  mount-loop /cd/LiveOS/squashfs.img /squash
3153  mount-loop /squash/LiveOS/ext3fs.img /ext3
3154
3155 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3156
3157   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3158    [],
3159    "remove a mountpoint",
3160    "\
3161 This calls removes a mountpoint that was previously created
3162 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3163 for full details.");
3164
3165   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3166    [InitISOFS, Always, TestOutputBuffer (
3167       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3168    "read a file",
3169    "\
3170 This calls returns the contents of the file C<path> as a
3171 buffer.
3172
3173 Unlike C<guestfs_cat>, this function can correctly
3174 handle files that contain embedded ASCII NUL characters.
3175 However unlike C<guestfs_download>, this function is limited
3176 in the total size of file that can be handled.");
3177
3178   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3179    [InitISOFS, Always, TestOutputList (
3180       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3181     InitISOFS, Always, TestOutputList (
3182       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3183    "return lines matching a pattern",
3184    "\
3185 This calls the external C<grep> program and returns the
3186 matching lines.");
3187
3188   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3189    [InitISOFS, Always, TestOutputList (
3190       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3191    "return lines matching a pattern",
3192    "\
3193 This calls the external C<egrep> program and returns the
3194 matching lines.");
3195
3196   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3197    [InitISOFS, Always, TestOutputList (
3198       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3199    "return lines matching a pattern",
3200    "\
3201 This calls the external C<fgrep> program and returns the
3202 matching lines.");
3203
3204   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3205    [InitISOFS, Always, TestOutputList (
3206       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3207    "return lines matching a pattern",
3208    "\
3209 This calls the external C<grep -i> program and returns the
3210 matching lines.");
3211
3212   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3213    [InitISOFS, Always, TestOutputList (
3214       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3215    "return lines matching a pattern",
3216    "\
3217 This calls the external C<egrep -i> program and returns the
3218 matching lines.");
3219
3220   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3221    [InitISOFS, Always, TestOutputList (
3222       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3223    "return lines matching a pattern",
3224    "\
3225 This calls the external C<fgrep -i> program and returns the
3226 matching lines.");
3227
3228   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3229    [InitISOFS, Always, TestOutputList (
3230       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3231    "return lines matching a pattern",
3232    "\
3233 This calls the external C<zgrep> program and returns the
3234 matching lines.");
3235
3236   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3237    [InitISOFS, Always, TestOutputList (
3238       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3239    "return lines matching a pattern",
3240    "\
3241 This calls the external C<zegrep> program and returns the
3242 matching lines.");
3243
3244   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3245    [InitISOFS, Always, TestOutputList (
3246       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3247    "return lines matching a pattern",
3248    "\
3249 This calls the external C<zfgrep> program and returns the
3250 matching lines.");
3251
3252   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3253    [InitISOFS, Always, TestOutputList (
3254       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3255    "return lines matching a pattern",
3256    "\
3257 This calls the external C<zgrep -i> program and returns the
3258 matching lines.");
3259
3260   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3261    [InitISOFS, Always, TestOutputList (
3262       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3263    "return lines matching a pattern",
3264    "\
3265 This calls the external C<zegrep -i> program and returns the
3266 matching lines.");
3267
3268   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3269    [InitISOFS, Always, TestOutputList (
3270       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3271    "return lines matching a pattern",
3272    "\
3273 This calls the external C<zfgrep -i> program and returns the
3274 matching lines.");
3275
3276   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3277    [InitISOFS, Always, TestOutput (
3278       [["realpath"; "/../directory"]], "/directory")],
3279    "canonicalized absolute pathname",
3280    "\
3281 Return the canonicalized absolute pathname of C<path>.  The
3282 returned path has no C<.>, C<..> or symbolic link path elements.");
3283
3284   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3285    [InitBasicFS, Always, TestOutputStruct (
3286       [["touch"; "/a"];
3287        ["ln"; "/a"; "/b"];
3288        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3289    "create a hard link",
3290    "\
3291 This command creates a hard link using the C<ln> command.");
3292
3293   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3294    [InitBasicFS, Always, TestOutputStruct (
3295       [["touch"; "/a"];
3296        ["touch"; "/b"];
3297        ["ln_f"; "/a"; "/b"];
3298        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3299    "create a hard link",
3300    "\
3301 This command creates a hard link using the C<ln -f> command.
3302 The C<-f> option removes the link (C<linkname>) if it exists already.");
3303
3304   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3305    [InitBasicFS, Always, TestOutputStruct (
3306       [["touch"; "/a"];
3307        ["ln_s"; "a"; "/b"];
3308        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3309    "create a symbolic link",
3310    "\
3311 This command creates a symbolic link using the C<ln -s> command.");
3312
3313   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3314    [InitBasicFS, Always, TestOutput (
3315       [["mkdir_p"; "/a/b"];
3316        ["touch"; "/a/b/c"];
3317        ["ln_sf"; "../d"; "/a/b/c"];
3318        ["readlink"; "/a/b/c"]], "../d")],
3319    "create a symbolic link",
3320    "\
3321 This command creates a symbolic link using the C<ln -sf> command,
3322 The C<-f> option removes the link (C<linkname>) if it exists already.");
3323
3324   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3325    [] (* XXX tested above *),
3326    "read the target of a symbolic link",
3327    "\
3328 This command reads the target of a symbolic link.");
3329
3330   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3331    [InitBasicFS, Always, TestOutputStruct (
3332       [["fallocate"; "/a"; "1000000"];
3333        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3334    "preallocate a file in the guest filesystem",
3335    "\
3336 This command preallocates a file (containing zero bytes) named
3337 C<path> of size C<len> bytes.  If the file exists already, it
3338 is overwritten.
3339
3340 Do not confuse this with the guestfish-specific
3341 C<alloc> command which allocates a file in the host and
3342 attaches it as a device.");
3343
3344   ("swapon_device", (RErr, [Device "device"]), 170, [],
3345    [InitPartition, Always, TestRun (
3346       [["mkswap"; "/dev/sda1"];
3347        ["swapon_device"; "/dev/sda1"];
3348        ["swapoff_device"; "/dev/sda1"]])],
3349    "enable swap on device",
3350    "\
3351 This command enables the libguestfs appliance to use the
3352 swap device or partition named C<device>.  The increased
3353 memory is made available for all commands, for example
3354 those run using C<guestfs_command> or C<guestfs_sh>.
3355
3356 Note that you should not swap to existing guest swap
3357 partitions unless you know what you are doing.  They may
3358 contain hibernation information, or other information that
3359 the guest doesn't want you to trash.  You also risk leaking
3360 information about the host to the guest this way.  Instead,
3361 attach a new host device to the guest and swap on that.");
3362
3363   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3364    [], (* XXX tested by swapon_device *)
3365    "disable swap on device",
3366    "\
3367 This command disables the libguestfs appliance swap
3368 device or partition named C<device>.
3369 See C<guestfs_swapon_device>.");
3370
3371   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3372    [InitBasicFS, Always, TestRun (
3373       [["fallocate"; "/swap"; "8388608"];
3374        ["mkswap_file"; "/swap"];
3375        ["swapon_file"; "/swap"];
3376        ["swapoff_file"; "/swap"]])],
3377    "enable swap on file",
3378    "\
3379 This command enables swap to a file.
3380 See C<guestfs_swapon_device> for other notes.");
3381
3382   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3383    [], (* XXX tested by swapon_file *)
3384    "disable swap on file",
3385    "\
3386 This command disables the libguestfs appliance swap on file.");
3387
3388   ("swapon_label", (RErr, [String "label"]), 174, [],
3389    [InitEmpty, Always, TestRun (
3390       [["part_disk"; "/dev/sdb"; "mbr"];
3391        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3392        ["swapon_label"; "swapit"];
3393        ["swapoff_label"; "swapit"];
3394        ["zero"; "/dev/sdb"];
3395        ["blockdev_rereadpt"; "/dev/sdb"]])],
3396    "enable swap on labeled swap partition",
3397    "\
3398 This command enables swap to a labeled swap partition.
3399 See C<guestfs_swapon_device> for other notes.");
3400
3401   ("swapoff_label", (RErr, [String "label"]), 175, [],
3402    [], (* XXX tested by swapon_label *)
3403    "disable swap on labeled swap partition",
3404    "\
3405 This command disables the libguestfs appliance swap on
3406 labeled swap partition.");
3407
3408   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3409    (let uuid = uuidgen () in
3410     [InitEmpty, Always, TestRun (
3411        [["mkswap_U"; uuid; "/dev/sdb"];
3412         ["swapon_uuid"; uuid];
3413         ["swapoff_uuid"; uuid]])]),
3414    "enable swap on swap partition by UUID",
3415    "\
3416 This command enables swap to a swap partition with the given UUID.
3417 See C<guestfs_swapon_device> for other notes.");
3418
3419   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3420    [], (* XXX tested by swapon_uuid *)
3421    "disable swap on swap partition by UUID",
3422    "\
3423 This command disables the libguestfs appliance swap partition
3424 with the given UUID.");
3425
3426   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3427    [InitBasicFS, Always, TestRun (
3428       [["fallocate"; "/swap"; "8388608"];
3429        ["mkswap_file"; "/swap"]])],
3430    "create a swap file",
3431    "\
3432 Create a swap file.
3433
3434 This command just writes a swap file signature to an existing
3435 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3436
3437   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3438    [InitISOFS, Always, TestRun (
3439       [["inotify_init"; "0"]])],
3440    "create an inotify handle",
3441    "\
3442 This command creates a new inotify handle.
3443 The inotify subsystem can be used to notify events which happen to
3444 objects in the guest filesystem.
3445
3446 C<maxevents> is the maximum number of events which will be
3447 queued up between calls to C<guestfs_inotify_read> or
3448 C<guestfs_inotify_files>.
3449 If this is passed as C<0>, then the kernel (or previously set)
3450 default is used.  For Linux 2.6.29 the default was 16384 events.
3451 Beyond this limit, the kernel throws away events, but records
3452 the fact that it threw them away by setting a flag
3453 C<IN_Q_OVERFLOW> in the returned structure list (see
3454 C<guestfs_inotify_read>).
3455
3456 Before any events are generated, you have to add some
3457 watches to the internal watch list.  See:
3458 C<guestfs_inotify_add_watch>,
3459 C<guestfs_inotify_rm_watch> and
3460 C<guestfs_inotify_watch_all>.
3461
3462 Queued up events should be read periodically by calling
3463 C<guestfs_inotify_read>
3464 (or C<guestfs_inotify_files> which is just a helpful
3465 wrapper around C<guestfs_inotify_read>).  If you don't
3466 read the events out often enough then you risk the internal
3467 queue overflowing.
3468
3469 The handle should be closed after use by calling
3470 C<guestfs_inotify_close>.  This also removes any
3471 watches automatically.
3472
3473 See also L<inotify(7)> for an overview of the inotify interface
3474 as exposed by the Linux kernel, which is roughly what we expose
3475 via libguestfs.  Note that there is one global inotify handle
3476 per libguestfs instance.");
3477
3478   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3479    [InitBasicFS, Always, TestOutputList (
3480       [["inotify_init"; "0"];
3481        ["inotify_add_watch"; "/"; "1073741823"];
3482        ["touch"; "/a"];
3483        ["touch"; "/b"];
3484        ["inotify_files"]], ["a"; "b"])],
3485    "add an inotify watch",
3486    "\
3487 Watch C<path> for the events listed in C<mask>.
3488
3489 Note that if C<path> is a directory then events within that
3490 directory are watched, but this does I<not> happen recursively
3491 (in subdirectories).
3492
3493 Note for non-C or non-Linux callers: the inotify events are
3494 defined by the Linux kernel ABI and are listed in
3495 C</usr/include/sys/inotify.h>.");
3496
3497   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3498    [],
3499    "remove an inotify watch",
3500    "\
3501 Remove a previously defined inotify watch.
3502 See C<guestfs_inotify_add_watch>.");
3503
3504   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3505    [],
3506    "return list of inotify events",
3507    "\
3508 Return the complete queue of events that have happened
3509 since the previous read call.
3510
3511 If no events have happened, this returns an empty list.
3512
3513 I<Note>: In order to make sure that all events have been
3514 read, you must call this function repeatedly until it
3515 returns an empty list.  The reason is that the call will
3516 read events up to the maximum appliance-to-host message
3517 size and leave remaining events in the queue.");
3518
3519   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3520    [],
3521    "return list of watched files that had events",
3522    "\
3523 This function is a helpful wrapper around C<guestfs_inotify_read>
3524 which just returns a list of pathnames of objects that were
3525 touched.  The returned pathnames are sorted and deduplicated.");
3526
3527   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3528    [],
3529    "close the inotify handle",
3530    "\
3531 This closes the inotify handle which was previously
3532 opened by inotify_init.  It removes all watches, throws
3533 away any pending events, and deallocates all resources.");
3534
3535   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3536    [],
3537    "set SELinux security context",
3538    "\
3539 This sets the SELinux security context of the daemon
3540 to the string C<context>.
3541
3542 See the documentation about SELINUX in L<guestfs(3)>.");
3543
3544   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3545    [],
3546    "get SELinux security context",
3547    "\
3548 This gets the SELinux security context of the daemon.
3549
3550 See the documentation about SELINUX in L<guestfs(3)>,
3551 and C<guestfs_setcon>");
3552
3553   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3554    [InitEmpty, Always, TestOutput (
3555       [["part_disk"; "/dev/sda"; "mbr"];
3556        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3557        ["mount"; "/dev/sda1"; "/"];
3558        ["write_file"; "/new"; "new file contents"; "0"];
3559        ["cat"; "/new"]], "new file contents")],
3560    "make a filesystem with block size",
3561    "\
3562 This call is similar to C<guestfs_mkfs>, but it allows you to
3563 control the block size of the resulting filesystem.  Supported
3564 block sizes depend on the filesystem type, but typically they
3565 are C<1024>, C<2048> or C<4096> only.");
3566
3567   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3568    [InitEmpty, Always, TestOutput (
3569       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3570        ["mke2journal"; "4096"; "/dev/sda1"];
3571        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3572        ["mount"; "/dev/sda2"; "/"];
3573        ["write_file"; "/new"; "new file contents"; "0"];
3574        ["cat"; "/new"]], "new file contents")],
3575    "make ext2/3/4 external journal",
3576    "\
3577 This creates an ext2 external journal on C<device>.  It is equivalent
3578 to the command:
3579
3580  mke2fs -O journal_dev -b blocksize device");
3581
3582   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3583    [InitEmpty, Always, TestOutput (
3584       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3585        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3586        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3587        ["mount"; "/dev/sda2"; "/"];
3588        ["write_file"; "/new"; "new file contents"; "0"];
3589        ["cat"; "/new"]], "new file contents")],
3590    "make ext2/3/4 external journal with label",
3591    "\
3592 This creates an ext2 external journal on C<device> with label C<label>.");
3593
3594   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3595    (let uuid = uuidgen () in
3596     [InitEmpty, Always, TestOutput (
3597        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3598         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3599         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3600         ["mount"; "/dev/sda2"; "/"];
3601         ["write_file"; "/new"; "new file contents"; "0"];
3602         ["cat"; "/new"]], "new file contents")]),
3603    "make ext2/3/4 external journal with UUID",
3604    "\
3605 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3606
3607   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3608    [],
3609    "make ext2/3/4 filesystem with external journal",
3610    "\
3611 This creates an ext2/3/4 filesystem on C<device> with
3612 an external journal on C<journal>.  It is equivalent
3613 to the command:
3614
3615  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3616
3617 See also C<guestfs_mke2journal>.");
3618
3619   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3620    [],
3621    "make ext2/3/4 filesystem with external journal",
3622    "\
3623 This creates an ext2/3/4 filesystem on C<device> with
3624 an external journal on the journal labeled C<label>.
3625
3626 See also C<guestfs_mke2journal_L>.");
3627
3628   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3629    [],
3630    "make ext2/3/4 filesystem with external journal",
3631    "\
3632 This creates an ext2/3/4 filesystem on C<device> with
3633 an external journal on the journal with UUID C<uuid>.
3634
3635 See also C<guestfs_mke2journal_U>.");
3636
3637   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3638    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3639    "load a kernel module",
3640    "\
3641 This loads a kernel module in the appliance.
3642
3643 The kernel module must have been whitelisted when libguestfs
3644 was built (see C<appliance/kmod.whitelist.in> in the source).");
3645
3646   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3647    [InitNone, Always, TestOutput (
3648       [["echo_daemon"; "This is a test"]], "This is a test"
3649     )],
3650    "echo arguments back to the client",
3651    "\
3652 This command concatenate the list of C<words> passed with single spaces between
3653 them and returns the resulting string.
3654
3655 You can use this command to test the connection through to the daemon.
3656
3657 See also C<guestfs_ping_daemon>.");
3658
3659   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3660    [], (* There is a regression test for this. *)
3661    "find all files and directories, returning NUL-separated list",
3662    "\
3663 This command lists out all files and directories, recursively,
3664 starting at C<directory>, placing the resulting list in the
3665 external file called C<files>.
3666
3667 This command works the same way as C<guestfs_find> with the
3668 following exceptions:
3669
3670 =over 4
3671
3672 =item *
3673
3674 The resulting list is written to an external file.
3675
3676 =item *
3677
3678 Items (filenames) in the result are separated
3679 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3680
3681 =item *
3682
3683 This command is not limited in the number of names that it
3684 can return.
3685
3686 =item *
3687
3688 The result list is not sorted.
3689
3690 =back");
3691
3692   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3693    [InitISOFS, Always, TestOutput (
3694       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3695     InitISOFS, Always, TestOutput (
3696       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3697     InitISOFS, Always, TestOutput (
3698       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3699     InitISOFS, Always, TestLastFail (
3700       [["case_sensitive_path"; "/Known-1/"]]);
3701     InitBasicFS, Always, TestOutput (
3702       [["mkdir"; "/a"];
3703        ["mkdir"; "/a/bbb"];
3704        ["touch"; "/a/bbb/c"];
3705        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3706     InitBasicFS, Always, TestOutput (
3707       [["mkdir"; "/a"];
3708        ["mkdir"; "/a/bbb"];
3709        ["touch"; "/a/bbb/c"];
3710        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3711     InitBasicFS, Always, TestLastFail (
3712       [["mkdir"; "/a"];
3713        ["mkdir"; "/a/bbb"];
3714        ["touch"; "/a/bbb/c"];
3715        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3716    "return true path on case-insensitive filesystem",
3717    "\
3718 This can be used to resolve case insensitive paths on
3719 a filesystem which is case sensitive.  The use case is
3720 to resolve paths which you have read from Windows configuration
3721 files or the Windows Registry, to the true path.
3722
3723 The command handles a peculiarity of the Linux ntfs-3g
3724 filesystem driver (and probably others), which is that although
3725 the underlying filesystem is case-insensitive, the driver
3726 exports the filesystem to Linux as case-sensitive.
3727
3728 One consequence of this is that special directories such
3729 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3730 (or other things) depending on the precise details of how
3731 they were created.  In Windows itself this would not be
3732 a problem.
3733
3734 Bug or feature?  You decide:
3735 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3736
3737 This function resolves the true case of each element in the
3738 path and returns the case-sensitive path.
3739
3740 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3741 might return C<\"/WINDOWS/system32\"> (the exact return value
3742 would depend on details of how the directories were originally
3743 created under Windows).
3744
3745 I<Note>:
3746 This function does not handle drive names, backslashes etc.
3747
3748 See also C<guestfs_realpath>.");
3749
3750   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3751    [InitBasicFS, Always, TestOutput (
3752       [["vfs_type"; "/dev/sda1"]], "ext2")],
3753    "get the Linux VFS type corresponding to a mounted device",
3754    "\
3755 This command gets the block device type corresponding to
3756 a mounted device called C<device>.
3757
3758 Usually the result is the name of the Linux VFS module that
3759 is used to mount this device (probably determined automatically
3760 if you used the C<guestfs_mount> call).");
3761
3762   ("truncate", (RErr, [Pathname "path"]), 199, [],
3763    [InitBasicFS, Always, TestOutputStruct (
3764       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3765        ["truncate"; "/test"];
3766        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3767    "truncate a file to zero size",
3768    "\
3769 This command truncates C<path> to a zero-length file.  The
3770 file must exist already.");
3771
3772   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3773    [InitBasicFS, Always, TestOutputStruct (
3774       [["touch"; "/test"];
3775        ["truncate_size"; "/test"; "1000"];
3776        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3777    "truncate a file to a particular size",
3778    "\
3779 This command truncates C<path> to size C<size> bytes.  The file
3780 must exist already.  If the file is smaller than C<size> then
3781 the file is extended to the required size with null bytes.");
3782
3783   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3784    [InitBasicFS, Always, TestOutputStruct (
3785       [["touch"; "/test"];
3786        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3787        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3788    "set timestamp of a file with nanosecond precision",
3789    "\
3790 This command sets the timestamps of a file with nanosecond
3791 precision.
3792
3793 C<atsecs, atnsecs> are the last access time (atime) in secs and
3794 nanoseconds from the epoch.
3795
3796 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3797 secs and nanoseconds from the epoch.
3798
3799 If the C<*nsecs> field contains the special value C<-1> then
3800 the corresponding timestamp is set to the current time.  (The
3801 C<*secs> field is ignored in this case).
3802
3803 If the C<*nsecs> field contains the special value C<-2> then
3804 the corresponding timestamp is left unchanged.  (The
3805 C<*secs> field is ignored in this case).");
3806
3807   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3808    [InitBasicFS, Always, TestOutputStruct (
3809       [["mkdir_mode"; "/test"; "0o111"];
3810        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3811    "create a directory with a particular mode",
3812    "\
3813 This command creates a directory, setting the initial permissions
3814 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3815
3816   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3817    [], (* XXX *)
3818    "change file owner and group",
3819    "\
3820 Change the file owner to C<owner> and group to C<group>.
3821 This is like C<guestfs_chown> but if C<path> is a symlink then
3822 the link itself is changed, not the target.
3823
3824 Only numeric uid and gid are supported.  If you want to use
3825 names, you will need to locate and parse the password file
3826 yourself (Augeas support makes this relatively easy).");
3827
3828   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3829    [], (* XXX *)
3830    "lstat on multiple files",
3831    "\
3832 This call allows you to perform the C<guestfs_lstat> operation
3833 on multiple files, where all files are in the directory C<path>.
3834 C<names> is the list of files from this directory.
3835
3836 On return you get a list of stat structs, with a one-to-one
3837 correspondence to the C<names> list.  If any name did not exist
3838 or could not be lstat'd, then the C<ino> field of that structure
3839 is set to C<-1>.
3840
3841 This call is intended for programs that want to efficiently
3842 list a directory contents without making many round-trips.
3843 See also C<guestfs_lxattrlist> for a similarly efficient call
3844 for getting extended attributes.  Very long directory listings
3845 might cause the protocol message size to be exceeded, causing
3846 this call to fail.  The caller must split up such requests
3847 into smaller groups of names.");
3848
3849   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3850    [], (* XXX *)
3851    "lgetxattr on multiple files",
3852    "\
3853 This call allows you to get the extended attributes
3854 of multiple files, where all files are in the directory C<path>.
3855 C<names> is the list of files from this directory.
3856
3857 On return you get a flat list of xattr structs which must be
3858 interpreted sequentially.  The first xattr struct always has a zero-length
3859 C<attrname>.  C<attrval> in this struct is zero-length
3860 to indicate there was an error doing C<lgetxattr> for this
3861 file, I<or> is a C string which is a decimal number
3862 (the number of following attributes for this file, which could
3863 be C<\"0\">).  Then after the first xattr struct are the
3864 zero or more attributes for the first named file.
3865 This repeats for the second and subsequent files.
3866
3867 This call is intended for programs that want to efficiently
3868 list a directory contents without making many round-trips.
3869 See also C<guestfs_lstatlist> for a similarly efficient call
3870 for getting standard stats.  Very long directory listings
3871 might cause the protocol message size to be exceeded, causing
3872 this call to fail.  The caller must split up such requests
3873 into smaller groups of names.");
3874
3875   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3876    [], (* XXX *)
3877    "readlink on multiple files",
3878    "\
3879 This call allows you to do a C<readlink> operation
3880 on multiple files, where all files are in the directory C<path>.
3881 C<names> is the list of files from this directory.
3882
3883 On return you get a list of strings, with a one-to-one
3884 correspondence to the C<names> list.  Each string is the
3885 value of the symbol link.
3886
3887 If the C<readlink(2)> operation fails on any name, then
3888 the corresponding result string is the empty string C<\"\">.
3889 However the whole operation is completed even if there
3890 were C<readlink(2)> errors, and so you can call this
3891 function with names where you don't know if they are
3892 symbolic links already (albeit slightly less efficient).
3893
3894 This call is intended for programs that want to efficiently
3895 list a directory contents without making many round-trips.
3896 Very long directory listings might cause the protocol
3897 message size to be exceeded, causing
3898 this call to fail.  The caller must split up such requests
3899 into smaller groups of names.");
3900
3901   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3902    [InitISOFS, Always, TestOutputBuffer (
3903       [["pread"; "/known-4"; "1"; "3"]], "\n");
3904     InitISOFS, Always, TestOutputBuffer (
3905       [["pread"; "/empty"; "0"; "100"]], "")],
3906    "read part of a file",
3907    "\
3908 This command lets you read part of a file.  It reads C<count>
3909 bytes of the file, starting at C<offset>, from file C<path>.
3910
3911 This may read fewer bytes than requested.  For further details
3912 see the L<pread(2)> system call.");
3913
3914   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3915    [InitEmpty, Always, TestRun (
3916       [["part_init"; "/dev/sda"; "gpt"]])],
3917    "create an empty partition table",
3918    "\
3919 This creates an empty partition table on C<device> of one of the
3920 partition types listed below.  Usually C<parttype> should be
3921 either C<msdos> or C<gpt> (for large disks).
3922
3923 Initially there are no partitions.  Following this, you should
3924 call C<guestfs_part_add> for each partition required.
3925
3926 Possible values for C<parttype> are:
3927
3928 =over 4
3929
3930 =item B<efi> | B<gpt>
3931
3932 Intel EFI / GPT partition table.
3933
3934 This is recommended for >= 2 TB partitions that will be accessed
3935 from Linux and Intel-based Mac OS X.  It also has limited backwards
3936 compatibility with the C<mbr> format.
3937
3938 =item B<mbr> | B<msdos>
3939
3940 The standard PC \"Master Boot Record\" (MBR) format used
3941 by MS-DOS and Windows.  This partition type will B<only> work
3942 for device sizes up to 2 TB.  For large disks we recommend
3943 using C<gpt>.
3944
3945 =back
3946
3947 Other partition table types that may work but are not
3948 supported include:
3949
3950 =over 4
3951
3952 =item B<aix>
3953
3954 AIX disk labels.
3955
3956 =item B<amiga> | B<rdb>
3957
3958 Amiga \"Rigid Disk Block\" format.
3959
3960 =item B<bsd>
3961
3962 BSD disk labels.
3963
3964 =item B<dasd>
3965
3966 DASD, used on IBM mainframes.
3967
3968 =item B<dvh>
3969
3970 MIPS/SGI volumes.
3971
3972 =item B<mac>
3973
3974 Old Mac partition format.  Modern Macs use C<gpt>.
3975
3976 =item B<pc98>
3977
3978 NEC PC-98 format, common in Japan apparently.
3979
3980 =item B<sun>
3981
3982 Sun disk labels.
3983
3984 =back");
3985
3986   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
3987    [InitEmpty, Always, TestRun (
3988       [["part_init"; "/dev/sda"; "mbr"];
3989        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
3990     InitEmpty, Always, TestRun (
3991       [["part_init"; "/dev/sda"; "gpt"];
3992        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
3993        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
3994     InitEmpty, Always, TestRun (
3995       [["part_init"; "/dev/sda"; "mbr"];
3996        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
3997        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
3998        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
3999        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4000    "add a partition to the device",
4001    "\
4002 This command adds a partition to C<device>.  If there is no partition
4003 table on the device, call C<guestfs_part_init> first.
4004
4005 The C<prlogex> parameter is the type of partition.  Normally you
4006 should pass C<p> or C<primary> here, but MBR partition tables also
4007 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4008 types.
4009
4010 C<startsect> and C<endsect> are the start and end of the partition
4011 in I<sectors>.  C<endsect> may be negative, which means it counts
4012 backwards from the end of the disk (C<-1> is the last sector).
4013
4014 Creating a partition which covers the whole disk is not so easy.
4015 Use C<guestfs_part_disk> to do that.");
4016
4017   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4018    [InitEmpty, Always, TestRun (
4019       [["part_disk"; "/dev/sda"; "mbr"]]);
4020     InitEmpty, Always, TestRun (
4021       [["part_disk"; "/dev/sda"; "gpt"]])],
4022    "partition whole disk with a single primary partition",
4023    "\
4024 This command is simply a combination of C<guestfs_part_init>
4025 followed by C<guestfs_part_add> to create a single primary partition
4026 covering the whole disk.
4027
4028 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4029 but other possible values are described in C<guestfs_part_init>.");
4030
4031   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4032    [InitEmpty, Always, TestRun (
4033       [["part_disk"; "/dev/sda"; "mbr"];
4034        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4035    "make a partition bootable",
4036    "\
4037 This sets the bootable flag on partition numbered C<partnum> on
4038 device C<device>.  Note that partitions are numbered from 1.
4039
4040 The bootable flag is used by some PC BIOSes to determine which
4041 partition to boot from.  It is by no means universally recognized,
4042 and in any case if your operating system installed a boot
4043 sector on the device itself, then that takes precedence.");
4044
4045   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4046    [InitEmpty, Always, TestRun (
4047       [["part_disk"; "/dev/sda"; "gpt"];
4048        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4049    "set partition name",
4050    "\
4051 This sets the partition name on partition numbered C<partnum> on
4052 device C<device>.  Note that partitions are numbered from 1.
4053
4054 The partition name can only be set on certain types of partition
4055 table.  This works on C<gpt> but not on C<mbr> partitions.");
4056
4057   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4058    [], (* XXX Add a regression test for this. *)
4059    "list partitions on a device",
4060    "\
4061 This command parses the partition table on C<device> and
4062 returns the list of partitions found.
4063
4064 The fields in the returned structure are:
4065
4066 =over 4
4067
4068 =item B<part_num>
4069
4070 Partition number, counting from 1.
4071
4072 =item B<part_start>
4073
4074 Start of the partition I<in bytes>.  To get sectors you have to
4075 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4076
4077 =item B<part_end>
4078
4079 End of the partition in bytes.
4080
4081 =item B<part_size>
4082
4083 Size of the partition in bytes.
4084
4085 =back");
4086
4087   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4088    [InitEmpty, Always, TestOutput (
4089       [["part_disk"; "/dev/sda"; "gpt"];
4090        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4091    "get the partition table type",
4092    "\
4093 This command examines the partition table on C<device> and
4094 returns the partition table type (format) being used.
4095
4096 Common return values include: C<msdos> (a DOS/Windows style MBR
4097 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4098 values are possible, although unusual.  See C<guestfs_part_init>
4099 for a full list.");
4100
4101   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4102    [InitBasicFS, Always, TestOutputBuffer (
4103       [["fill"; "0x63"; "10"; "/test"];
4104        ["read_file"; "/test"]], "cccccccccc")],
4105    "fill a file with octets",
4106    "\
4107 This command creates a new file called C<path>.  The initial
4108 content of the file is C<len> octets of C<c>, where C<c>
4109 must be a number in the range C<[0..255]>.
4110
4111 To fill a file with zero bytes (sparsely), it is
4112 much more efficient to use C<guestfs_truncate_size>.");
4113
4114   ("available", (RErr, [StringList "groups"]), 216, [],
4115    [InitNone, Always, TestRun [["available"; ""]]],
4116    "test availability of some parts of the API",
4117    "\
4118 This command is used to check the availability of some
4119 groups of functionality in the appliance, which not all builds of
4120 the libguestfs appliance will be able to provide.
4121
4122 The libguestfs groups, and the functions that those
4123 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4124
4125 The argument C<groups> is a list of group names, eg:
4126 C<[\"inotify\", \"augeas\"]> would check for the availability of
4127 the Linux inotify functions and Augeas (configuration file
4128 editing) functions.
4129
4130 The command returns no error if I<all> requested groups are available.
4131
4132 It fails with an error if one or more of the requested
4133 groups is unavailable in the appliance.
4134
4135 If an unknown group name is included in the
4136 list of groups then an error is always returned.
4137
4138 I<Notes:>
4139
4140 =over 4
4141
4142 =item *
4143
4144 You must call C<guestfs_launch> before calling this function.
4145
4146 The reason is because we don't know what groups are
4147 supported by the appliance/daemon until it is running and can
4148 be queried.
4149
4150 =item *
4151
4152 If a group of functions is available, this does not necessarily
4153 mean that they will work.  You still have to check for errors
4154 when calling individual API functions even if they are
4155 available.
4156
4157 =item *
4158
4159 It is usually the job of distro packagers to build
4160 complete functionality into the libguestfs appliance.
4161 Upstream libguestfs, if built from source with all
4162 requirements satisfied, will support everything.
4163
4164 =item *
4165
4166 This call was added in version C<1.0.80>.  In previous
4167 versions of libguestfs all you could do would be to speculatively
4168 execute a command to find out if the daemon implemented it.
4169 See also C<guestfs_version>.
4170
4171 =back");
4172
4173   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4174    [InitBasicFS, Always, TestOutputBuffer (
4175       [["write_file"; "/src"; "hello, world"; "0"];
4176        ["dd"; "/src"; "/dest"];
4177        ["read_file"; "/dest"]], "hello, world")],
4178    "copy from source to destination using dd",
4179    "\
4180 This command copies from one source device or file C<src>
4181 to another destination device or file C<dest>.  Normally you
4182 would use this to copy to or from a device or partition, for
4183 example to duplicate a filesystem.
4184
4185 If the destination is a device, it must be as large or larger
4186 than the source file or device, otherwise the copy will fail.
4187 This command cannot do partial copies.");
4188
4189 ]
4190
4191 let all_functions = non_daemon_functions @ daemon_functions
4192
4193 (* In some places we want the functions to be displayed sorted
4194  * alphabetically, so this is useful:
4195  *)
4196 let all_functions_sorted =
4197   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4198                compare n1 n2) all_functions
4199
4200 (* Field types for structures. *)
4201 type field =
4202   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4203   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4204   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4205   | FUInt32
4206   | FInt32
4207   | FUInt64
4208   | FInt64
4209   | FBytes                      (* Any int measure that counts bytes. *)
4210   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4211   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4212
4213 (* Because we generate extra parsing code for LVM command line tools,
4214  * we have to pull out the LVM columns separately here.
4215  *)
4216 let lvm_pv_cols = [
4217   "pv_name", FString;
4218   "pv_uuid", FUUID;
4219   "pv_fmt", FString;
4220   "pv_size", FBytes;
4221   "dev_size", FBytes;
4222   "pv_free", FBytes;
4223   "pv_used", FBytes;
4224   "pv_attr", FString (* XXX *);
4225   "pv_pe_count", FInt64;
4226   "pv_pe_alloc_count", FInt64;
4227   "pv_tags", FString;
4228   "pe_start", FBytes;
4229   "pv_mda_count", FInt64;
4230   "pv_mda_free", FBytes;
4231   (* Not in Fedora 10:
4232      "pv_mda_size", FBytes;
4233   *)
4234 ]
4235 let lvm_vg_cols = [
4236   "vg_name", FString;
4237   "vg_uuid", FUUID;
4238   "vg_fmt", FString;
4239   "vg_attr", FString (* XXX *);
4240   "vg_size", FBytes;
4241   "vg_free", FBytes;
4242   "vg_sysid", FString;
4243   "vg_extent_size", FBytes;
4244   "vg_extent_count", FInt64;
4245   "vg_free_count", FInt64;
4246   "max_lv", FInt64;
4247   "max_pv", FInt64;
4248   "pv_count", FInt64;
4249   "lv_count", FInt64;
4250   "snap_count", FInt64;
4251   "vg_seqno", FInt64;
4252   "vg_tags", FString;
4253   "vg_mda_count", FInt64;
4254   "vg_mda_free", FBytes;
4255   (* Not in Fedora 10:
4256      "vg_mda_size", FBytes;
4257   *)
4258 ]
4259 let lvm_lv_cols = [
4260   "lv_name", FString;
4261   "lv_uuid", FUUID;
4262   "lv_attr", FString (* XXX *);
4263   "lv_major", FInt64;
4264   "lv_minor", FInt64;
4265   "lv_kernel_major", FInt64;
4266   "lv_kernel_minor", FInt64;
4267   "lv_size", FBytes;
4268   "seg_count", FInt64;
4269   "origin", FString;
4270   "snap_percent", FOptPercent;
4271   "copy_percent", FOptPercent;
4272   "move_pv", FString;
4273   "lv_tags", FString;
4274   "mirror_log", FString;
4275   "modules", FString;
4276 ]
4277
4278 (* Names and fields in all structures (in RStruct and RStructList)
4279  * that we support.
4280  *)
4281 let structs = [
4282   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4283    * not use this struct in any new code.
4284    *)
4285   "int_bool", [
4286     "i", FInt32;                (* for historical compatibility *)
4287     "b", FInt32;                (* for historical compatibility *)
4288   ];
4289
4290   (* LVM PVs, VGs, LVs. *)
4291   "lvm_pv", lvm_pv_cols;
4292   "lvm_vg", lvm_vg_cols;
4293   "lvm_lv", lvm_lv_cols;
4294
4295   (* Column names and types from stat structures.
4296    * NB. Can't use things like 'st_atime' because glibc header files
4297    * define some of these as macros.  Ugh.
4298    *)
4299   "stat", [
4300     "dev", FInt64;
4301     "ino", FInt64;
4302     "mode", FInt64;
4303     "nlink", FInt64;
4304     "uid", FInt64;
4305     "gid", FInt64;
4306     "rdev", FInt64;
4307     "size", FInt64;
4308     "blksize", FInt64;
4309     "blocks", FInt64;
4310     "atime", FInt64;
4311     "mtime", FInt64;
4312     "ctime", FInt64;
4313   ];
4314   "statvfs", [
4315     "bsize", FInt64;
4316     "frsize", FInt64;
4317     "blocks", FInt64;
4318     "bfree", FInt64;
4319     "bavail", FInt64;
4320     "files", FInt64;
4321     "ffree", FInt64;
4322     "favail", FInt64;
4323     "fsid", FInt64;
4324     "flag", FInt64;
4325     "namemax", FInt64;
4326   ];
4327
4328   (* Column names in dirent structure. *)
4329   "dirent", [
4330     "ino", FInt64;
4331     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4332     "ftyp", FChar;
4333     "name", FString;
4334   ];
4335
4336   (* Version numbers. *)
4337   "version", [
4338     "major", FInt64;
4339     "minor", FInt64;
4340     "release", FInt64;
4341     "extra", FString;
4342   ];
4343
4344   (* Extended attribute. *)
4345   "xattr", [
4346     "attrname", FString;
4347     "attrval", FBuffer;
4348   ];
4349
4350   (* Inotify events. *)
4351   "inotify_event", [
4352     "in_wd", FInt64;
4353     "in_mask", FUInt32;
4354     "in_cookie", FUInt32;
4355     "in_name", FString;
4356   ];
4357
4358   (* Partition table entry. *)
4359   "partition", [
4360     "part_num", FInt32;
4361     "part_start", FBytes;
4362     "part_end", FBytes;
4363     "part_size", FBytes;
4364   ];
4365 ] (* end of structs *)
4366
4367 (* Ugh, Java has to be different ..
4368  * These names are also used by the Haskell bindings.
4369  *)
4370 let java_structs = [
4371   "int_bool", "IntBool";
4372   "lvm_pv", "PV";
4373   "lvm_vg", "VG";
4374   "lvm_lv", "LV";
4375   "stat", "Stat";
4376   "statvfs", "StatVFS";
4377   "dirent", "Dirent";
4378   "version", "Version";
4379   "xattr", "XAttr";
4380   "inotify_event", "INotifyEvent";
4381   "partition", "Partition";
4382 ]
4383
4384 (* What structs are actually returned. *)
4385 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4386
4387 (* Returns a list of RStruct/RStructList structs that are returned
4388  * by any function.  Each element of returned list is a pair:
4389  *
4390  * (structname, RStructOnly)
4391  *    == there exists function which returns RStruct (_, structname)
4392  * (structname, RStructListOnly)
4393  *    == there exists function which returns RStructList (_, structname)
4394  * (structname, RStructAndList)
4395  *    == there are functions returning both RStruct (_, structname)
4396  *                                      and RStructList (_, structname)
4397  *)
4398 let rstructs_used_by functions =
4399   (* ||| is a "logical OR" for rstructs_used_t *)
4400   let (|||) a b =
4401     match a, b with
4402     | RStructAndList, _
4403     | _, RStructAndList -> RStructAndList
4404     | RStructOnly, RStructListOnly
4405     | RStructListOnly, RStructOnly -> RStructAndList
4406     | RStructOnly, RStructOnly -> RStructOnly
4407     | RStructListOnly, RStructListOnly -> RStructListOnly
4408   in
4409
4410   let h = Hashtbl.create 13 in
4411
4412   (* if elem->oldv exists, update entry using ||| operator,
4413    * else just add elem->newv to the hash
4414    *)
4415   let update elem newv =
4416     try  let oldv = Hashtbl.find h elem in
4417          Hashtbl.replace h elem (newv ||| oldv)
4418     with Not_found -> Hashtbl.add h elem newv
4419   in
4420
4421   List.iter (
4422     fun (_, style, _, _, _, _, _) ->
4423       match fst style with
4424       | RStruct (_, structname) -> update structname RStructOnly
4425       | RStructList (_, structname) -> update structname RStructListOnly
4426       | _ -> ()
4427   ) functions;
4428
4429   (* return key->values as a list of (key,value) *)
4430   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4431
4432 (* Used for testing language bindings. *)
4433 type callt =
4434   | CallString of string
4435   | CallOptString of string option
4436   | CallStringList of string list
4437   | CallInt of int
4438   | CallInt64 of int64
4439   | CallBool of bool
4440
4441 (* Used to memoize the result of pod2text. *)
4442 let pod2text_memo_filename = "src/.pod2text.data"
4443 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4444   try
4445     let chan = open_in pod2text_memo_filename in
4446     let v = input_value chan in
4447     close_in chan;
4448     v
4449   with
4450     _ -> Hashtbl.create 13
4451 let pod2text_memo_updated () =
4452   let chan = open_out pod2text_memo_filename in
4453   output_value chan pod2text_memo;
4454   close_out chan
4455
4456 (* Useful functions.
4457  * Note we don't want to use any external OCaml libraries which
4458  * makes this a bit harder than it should be.
4459  *)
4460 let failwithf fs = ksprintf failwith fs
4461
4462 let replace_char s c1 c2 =
4463   let s2 = String.copy s in
4464   let r = ref false in
4465   for i = 0 to String.length s2 - 1 do
4466     if String.unsafe_get s2 i = c1 then (
4467       String.unsafe_set s2 i c2;
4468       r := true
4469     )
4470   done;
4471   if not !r then s else s2
4472
4473 let isspace c =
4474   c = ' '
4475   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4476
4477 let triml ?(test = isspace) str =
4478   let i = ref 0 in
4479   let n = ref (String.length str) in
4480   while !n > 0 && test str.[!i]; do
4481     decr n;
4482     incr i
4483   done;
4484   if !i = 0 then str
4485   else String.sub str !i !n
4486
4487 let trimr ?(test = isspace) str =
4488   let n = ref (String.length str) in
4489   while !n > 0 && test str.[!n-1]; do
4490     decr n
4491   done;
4492   if !n = String.length str then str
4493   else String.sub str 0 !n
4494
4495 let trim ?(test = isspace) str =
4496   trimr ~test (triml ~test str)
4497
4498 let rec find s sub =
4499   let len = String.length s in
4500   let sublen = String.length sub in
4501   let rec loop i =
4502     if i <= len-sublen then (
4503       let rec loop2 j =
4504         if j < sublen then (
4505           if s.[i+j] = sub.[j] then loop2 (j+1)
4506           else -1
4507         ) else
4508           i (* found *)
4509       in
4510       let r = loop2 0 in
4511       if r = -1 then loop (i+1) else r
4512     ) else
4513       -1 (* not found *)
4514   in
4515   loop 0
4516
4517 let rec replace_str s s1 s2 =
4518   let len = String.length s in
4519   let sublen = String.length s1 in
4520   let i = find s s1 in
4521   if i = -1 then s
4522   else (
4523     let s' = String.sub s 0 i in
4524     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4525     s' ^ s2 ^ replace_str s'' s1 s2
4526   )
4527
4528 let rec string_split sep str =
4529   let len = String.length str in
4530   let seplen = String.length sep in
4531   let i = find str sep in
4532   if i = -1 then [str]
4533   else (
4534     let s' = String.sub str 0 i in
4535     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4536     s' :: string_split sep s''
4537   )
4538
4539 let files_equal n1 n2 =
4540   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4541   match Sys.command cmd with
4542   | 0 -> true
4543   | 1 -> false
4544   | i -> failwithf "%s: failed with error code %d" cmd i
4545
4546 let rec filter_map f = function
4547   | [] -> []
4548   | x :: xs ->
4549       match f x with
4550       | Some y -> y :: filter_map f xs
4551       | None -> filter_map f xs
4552
4553 let rec find_map f = function
4554   | [] -> raise Not_found
4555   | x :: xs ->
4556       match f x with
4557       | Some y -> y
4558       | None -> find_map f xs
4559
4560 let iteri f xs =
4561   let rec loop i = function
4562     | [] -> ()
4563     | x :: xs -> f i x; loop (i+1) xs
4564   in
4565   loop 0 xs
4566
4567 let mapi f xs =
4568   let rec loop i = function
4569     | [] -> []
4570     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4571   in
4572   loop 0 xs
4573
4574 let name_of_argt = function
4575   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4576   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4577   | FileIn n | FileOut n -> n
4578
4579 let java_name_of_struct typ =
4580   try List.assoc typ java_structs
4581   with Not_found ->
4582     failwithf
4583       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4584
4585 let cols_of_struct typ =
4586   try List.assoc typ structs
4587   with Not_found ->
4588     failwithf "cols_of_struct: unknown struct %s" typ
4589
4590 let seq_of_test = function
4591   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4592   | TestOutputListOfDevices (s, _)
4593   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4594   | TestOutputTrue s | TestOutputFalse s
4595   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4596   | TestOutputStruct (s, _)
4597   | TestLastFail s -> s
4598
4599 (* Handling for function flags. *)
4600 let protocol_limit_warning =
4601   "Because of the message protocol, there is a transfer limit
4602 of somewhere between 2MB and 4MB.  To transfer large files you should use
4603 FTP."
4604
4605 let danger_will_robinson =
4606   "B<This command is dangerous.  Without careful use you
4607 can easily destroy all your data>."
4608
4609 let deprecation_notice flags =
4610   try
4611     let alt =
4612       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4613     let txt =
4614       sprintf "This function is deprecated.
4615 In new code, use the C<%s> call instead.
4616
4617 Deprecated functions will not be removed from the API, but the
4618 fact that they are deprecated indicates that there are problems
4619 with correct use of these functions." alt in
4620     Some txt
4621   with
4622     Not_found -> None
4623
4624 (* Create list of optional groups. *)
4625 let optgroups =
4626   let h = Hashtbl.create 13 in
4627   List.iter (
4628     fun (name, _, _, flags, _, _, _) ->
4629       List.iter (
4630         function
4631         | Optional group ->
4632             let names = try Hashtbl.find h group with Not_found -> [] in
4633             Hashtbl.replace h group (name :: names)
4634         | _ -> ()
4635       ) flags
4636   ) daemon_functions;
4637   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4638   let groups =
4639     List.map (
4640       fun group -> group, List.sort compare (Hashtbl.find h group)
4641     ) groups in
4642   List.sort (fun x y -> compare (fst x) (fst y)) groups
4643
4644 (* Check function names etc. for consistency. *)
4645 let check_functions () =
4646   let contains_uppercase str =
4647     let len = String.length str in
4648     let rec loop i =
4649       if i >= len then false
4650       else (
4651         let c = str.[i] in
4652         if c >= 'A' && c <= 'Z' then true
4653         else loop (i+1)
4654       )
4655     in
4656     loop 0
4657   in
4658
4659   (* Check function names. *)
4660   List.iter (
4661     fun (name, _, _, _, _, _, _) ->
4662       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4663         failwithf "function name %s does not need 'guestfs' prefix" name;
4664       if name = "" then
4665         failwithf "function name is empty";
4666       if name.[0] < 'a' || name.[0] > 'z' then
4667         failwithf "function name %s must start with lowercase a-z" name;
4668       if String.contains name '-' then
4669         failwithf "function name %s should not contain '-', use '_' instead."
4670           name
4671   ) all_functions;
4672
4673   (* Check function parameter/return names. *)
4674   List.iter (
4675     fun (name, style, _, _, _, _, _) ->
4676       let check_arg_ret_name n =
4677         if contains_uppercase n then
4678           failwithf "%s param/ret %s should not contain uppercase chars"
4679             name n;
4680         if String.contains n '-' || String.contains n '_' then
4681           failwithf "%s param/ret %s should not contain '-' or '_'"
4682             name n;
4683         if n = "value" then
4684           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;
4685         if n = "int" || n = "char" || n = "short" || n = "long" then
4686           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4687         if n = "i" || n = "n" then
4688           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4689         if n = "argv" || n = "args" then
4690           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4691
4692         (* List Haskell, OCaml and C keywords here.
4693          * http://www.haskell.org/haskellwiki/Keywords
4694          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4695          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4696          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4697          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4698          * Omitting _-containing words, since they're handled above.
4699          * Omitting the OCaml reserved word, "val", is ok,
4700          * and saves us from renaming several parameters.
4701          *)
4702         let reserved = [
4703           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4704           "char"; "class"; "const"; "constraint"; "continue"; "data";
4705           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4706           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4707           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4708           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4709           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4710           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4711           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4712           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4713           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4714           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4715           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4716           "volatile"; "when"; "where"; "while";
4717           ] in
4718         if List.mem n reserved then
4719           failwithf "%s has param/ret using reserved word %s" name n;
4720       in
4721
4722       (match fst style with
4723        | RErr -> ()
4724        | RInt n | RInt64 n | RBool n
4725        | RConstString n | RConstOptString n | RString n
4726        | RStringList n | RStruct (n, _) | RStructList (n, _)
4727        | RHashtable n | RBufferOut n ->
4728            check_arg_ret_name n
4729       );
4730       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4731   ) all_functions;
4732
4733   (* Check short descriptions. *)
4734   List.iter (
4735     fun (name, _, _, _, _, shortdesc, _) ->
4736       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4737         failwithf "short description of %s should begin with lowercase." name;
4738       let c = shortdesc.[String.length shortdesc-1] in
4739       if c = '\n' || c = '.' then
4740         failwithf "short description of %s should not end with . or \\n." name
4741   ) all_functions;
4742
4743   (* Check long dscriptions. *)
4744   List.iter (
4745     fun (name, _, _, _, _, _, longdesc) ->
4746       if longdesc.[String.length longdesc-1] = '\n' then
4747         failwithf "long description of %s should not end with \\n." name
4748   ) all_functions;
4749
4750   (* Check proc_nrs. *)
4751   List.iter (
4752     fun (name, _, proc_nr, _, _, _, _) ->
4753       if proc_nr <= 0 then
4754         failwithf "daemon function %s should have proc_nr > 0" name
4755   ) daemon_functions;
4756
4757   List.iter (
4758     fun (name, _, proc_nr, _, _, _, _) ->
4759       if proc_nr <> -1 then
4760         failwithf "non-daemon function %s should have proc_nr -1" name
4761   ) non_daemon_functions;
4762
4763   let proc_nrs =
4764     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4765       daemon_functions in
4766   let proc_nrs =
4767     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4768   let rec loop = function
4769     | [] -> ()
4770     | [_] -> ()
4771     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4772         loop rest
4773     | (name1,nr1) :: (name2,nr2) :: _ ->
4774         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4775           name1 name2 nr1 nr2
4776   in
4777   loop proc_nrs;
4778
4779   (* Check tests. *)
4780   List.iter (
4781     function
4782       (* Ignore functions that have no tests.  We generate a
4783        * warning when the user does 'make check' instead.
4784        *)
4785     | name, _, _, _, [], _, _ -> ()
4786     | name, _, _, _, tests, _, _ ->
4787         let funcs =
4788           List.map (
4789             fun (_, _, test) ->
4790               match seq_of_test test with
4791               | [] ->
4792                   failwithf "%s has a test containing an empty sequence" name
4793               | cmds -> List.map List.hd cmds
4794           ) tests in
4795         let funcs = List.flatten funcs in
4796
4797         let tested = List.mem name funcs in
4798
4799         if not tested then
4800           failwithf "function %s has tests but does not test itself" name
4801   ) all_functions
4802
4803 (* 'pr' prints to the current output file. *)
4804 let chan = ref Pervasives.stdout
4805 let pr fs = ksprintf (output_string !chan) fs
4806
4807 (* Generate a header block in a number of standard styles. *)
4808 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4809 type license = GPLv2 | LGPLv2
4810
4811 let generate_header comment license =
4812   let c = match comment with
4813     | CStyle ->     pr "/* "; " *"
4814     | HashStyle ->  pr "# ";  "#"
4815     | OCamlStyle -> pr "(* "; " *"
4816     | HaskellStyle -> pr "{- "; "  " in
4817   pr "libguestfs generated file\n";
4818   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4819   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4820   pr "%s\n" c;
4821   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4822   pr "%s\n" c;
4823   (match license with
4824    | GPLv2 ->
4825        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4826        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4827        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4828        pr "%s (at your option) any later version.\n" c;
4829        pr "%s\n" c;
4830        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4831        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4832        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4833        pr "%s GNU General Public License for more details.\n" c;
4834        pr "%s\n" c;
4835        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4836        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4837        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4838
4839    | LGPLv2 ->
4840        pr "%s This library is free software; you can redistribute it and/or\n" c;
4841        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4842        pr "%s License as published by the Free Software Foundation; either\n" c;
4843        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4844        pr "%s\n" c;
4845        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4846        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4847        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4848        pr "%s Lesser General Public License for more details.\n" c;
4849        pr "%s\n" c;
4850        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4851        pr "%s License along with this library; if not, write to the Free Software\n" c;
4852        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4853   );
4854   (match comment with
4855    | CStyle -> pr " */\n"
4856    | HashStyle -> ()
4857    | OCamlStyle -> pr " *)\n"
4858    | HaskellStyle -> pr "-}\n"
4859   );
4860   pr "\n"
4861
4862 (* Start of main code generation functions below this line. *)
4863
4864 (* Generate the pod documentation for the C API. *)
4865 let rec generate_actions_pod () =
4866   List.iter (
4867     fun (shortname, style, _, flags, _, _, longdesc) ->
4868       if not (List.mem NotInDocs flags) then (
4869         let name = "guestfs_" ^ shortname in
4870         pr "=head2 %s\n\n" name;
4871         pr " ";
4872         generate_prototype ~extern:false ~handle:"handle" name style;
4873         pr "\n\n";
4874         pr "%s\n\n" longdesc;
4875         (match fst style with
4876          | RErr ->
4877              pr "This function returns 0 on success or -1 on error.\n\n"
4878          | RInt _ ->
4879              pr "On error this function returns -1.\n\n"
4880          | RInt64 _ ->
4881              pr "On error this function returns -1.\n\n"
4882          | RBool _ ->
4883              pr "This function returns a C truth value on success or -1 on error.\n\n"
4884          | RConstString _ ->
4885              pr "This function returns a string, or NULL on error.
4886 The string is owned by the guest handle and must I<not> be freed.\n\n"
4887          | RConstOptString _ ->
4888              pr "This function returns a string which may be NULL.
4889 There is way to return an error from this function.
4890 The string is owned by the guest handle and must I<not> be freed.\n\n"
4891          | RString _ ->
4892              pr "This function returns a string, or NULL on error.
4893 I<The caller must free the returned string after use>.\n\n"
4894          | RStringList _ ->
4895              pr "This function returns a NULL-terminated array of strings
4896 (like L<environ(3)>), or NULL if there was an error.
4897 I<The caller must free the strings and the array after use>.\n\n"
4898          | RStruct (_, typ) ->
4899              pr "This function returns a C<struct guestfs_%s *>,
4900 or NULL if there was an error.
4901 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4902          | RStructList (_, typ) ->
4903              pr "This function returns a C<struct guestfs_%s_list *>
4904 (see E<lt>guestfs-structs.hE<gt>),
4905 or NULL if there was an error.
4906 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4907          | RHashtable _ ->
4908              pr "This function returns a NULL-terminated array of
4909 strings, or NULL if there was an error.
4910 The array of strings will always have length C<2n+1>, where
4911 C<n> keys and values alternate, followed by the trailing NULL entry.
4912 I<The caller must free the strings and the array after use>.\n\n"
4913          | RBufferOut _ ->
4914              pr "This function returns a buffer, or NULL on error.
4915 The size of the returned buffer is written to C<*size_r>.
4916 I<The caller must free the returned buffer after use>.\n\n"
4917         );
4918         if List.mem ProtocolLimitWarning flags then
4919           pr "%s\n\n" protocol_limit_warning;
4920         if List.mem DangerWillRobinson flags then
4921           pr "%s\n\n" danger_will_robinson;
4922         match deprecation_notice flags with
4923         | None -> ()
4924         | Some txt -> pr "%s\n\n" txt
4925       )
4926   ) all_functions_sorted
4927
4928 and generate_structs_pod () =
4929   (* Structs documentation. *)
4930   List.iter (
4931     fun (typ, cols) ->
4932       pr "=head2 guestfs_%s\n" typ;
4933       pr "\n";
4934       pr " struct guestfs_%s {\n" typ;
4935       List.iter (
4936         function
4937         | name, FChar -> pr "   char %s;\n" name
4938         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4939         | name, FInt32 -> pr "   int32_t %s;\n" name
4940         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4941         | name, FInt64 -> pr "   int64_t %s;\n" name
4942         | name, FString -> pr "   char *%s;\n" name
4943         | name, FBuffer ->
4944             pr "   /* The next two fields describe a byte array. */\n";
4945             pr "   uint32_t %s_len;\n" name;
4946             pr "   char *%s;\n" name
4947         | name, FUUID ->
4948             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4949             pr "   char %s[32];\n" name
4950         | name, FOptPercent ->
4951             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4952             pr "   float %s;\n" name
4953       ) cols;
4954       pr " };\n";
4955       pr " \n";
4956       pr " struct guestfs_%s_list {\n" typ;
4957       pr "   uint32_t len; /* Number of elements in list. */\n";
4958       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4959       pr " };\n";
4960       pr " \n";
4961       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4962       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4963         typ typ;
4964       pr "\n"
4965   ) structs
4966
4967 and generate_availability_pod () =
4968   (* Availability documentation. *)
4969   pr "=over 4\n";
4970   pr "\n";
4971   List.iter (
4972     fun (group, functions) ->
4973       pr "=item B<%s>\n" group;
4974       pr "\n";
4975       pr "The following functions:\n";
4976       List.iter (pr "L</guestfs_%s>\n") functions;
4977       pr "\n"
4978   ) optgroups;
4979   pr "=back\n";
4980   pr "\n"
4981
4982 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4983  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4984  *
4985  * We have to use an underscore instead of a dash because otherwise
4986  * rpcgen generates incorrect code.
4987  *
4988  * This header is NOT exported to clients, but see also generate_structs_h.
4989  *)
4990 and generate_xdr () =
4991   generate_header CStyle LGPLv2;
4992
4993   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4994   pr "typedef string str<>;\n";
4995   pr "\n";
4996
4997   (* Internal structures. *)
4998   List.iter (
4999     function
5000     | typ, cols ->
5001         pr "struct guestfs_int_%s {\n" typ;
5002         List.iter (function
5003                    | name, FChar -> pr "  char %s;\n" name
5004                    | name, FString -> pr "  string %s<>;\n" name
5005                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5006                    | name, FUUID -> pr "  opaque %s[32];\n" name
5007                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5008                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5009                    | name, FOptPercent -> pr "  float %s;\n" name
5010                   ) cols;
5011         pr "};\n";
5012         pr "\n";
5013         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5014         pr "\n";
5015   ) structs;
5016
5017   List.iter (
5018     fun (shortname, style, _, _, _, _, _) ->
5019       let name = "guestfs_" ^ shortname in
5020
5021       (match snd style with
5022        | [] -> ()
5023        | args ->
5024            pr "struct %s_args {\n" name;
5025            List.iter (
5026              function
5027              | Pathname n | Device n | Dev_or_Path n | String n ->
5028                  pr "  string %s<>;\n" n
5029              | OptString n -> pr "  str *%s;\n" n
5030              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5031              | Bool n -> pr "  bool %s;\n" n
5032              | Int n -> pr "  int %s;\n" n
5033              | Int64 n -> pr "  hyper %s;\n" n
5034              | FileIn _ | FileOut _ -> ()
5035            ) args;
5036            pr "};\n\n"
5037       );
5038       (match fst style with
5039        | RErr -> ()
5040        | RInt n ->
5041            pr "struct %s_ret {\n" name;
5042            pr "  int %s;\n" n;
5043            pr "};\n\n"
5044        | RInt64 n ->
5045            pr "struct %s_ret {\n" name;
5046            pr "  hyper %s;\n" n;
5047            pr "};\n\n"
5048        | RBool n ->
5049            pr "struct %s_ret {\n" name;
5050            pr "  bool %s;\n" n;
5051            pr "};\n\n"
5052        | RConstString _ | RConstOptString _ ->
5053            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5054        | RString n ->
5055            pr "struct %s_ret {\n" name;
5056            pr "  string %s<>;\n" n;
5057            pr "};\n\n"
5058        | RStringList n ->
5059            pr "struct %s_ret {\n" name;
5060            pr "  str %s<>;\n" n;
5061            pr "};\n\n"
5062        | RStruct (n, typ) ->
5063            pr "struct %s_ret {\n" name;
5064            pr "  guestfs_int_%s %s;\n" typ n;
5065            pr "};\n\n"
5066        | RStructList (n, typ) ->
5067            pr "struct %s_ret {\n" name;
5068            pr "  guestfs_int_%s_list %s;\n" typ n;
5069            pr "};\n\n"
5070        | RHashtable n ->
5071            pr "struct %s_ret {\n" name;
5072            pr "  str %s<>;\n" n;
5073            pr "};\n\n"
5074        | RBufferOut n ->
5075            pr "struct %s_ret {\n" name;
5076            pr "  opaque %s<>;\n" n;
5077            pr "};\n\n"
5078       );
5079   ) daemon_functions;
5080
5081   (* Table of procedure numbers. *)
5082   pr "enum guestfs_procedure {\n";
5083   List.iter (
5084     fun (shortname, _, proc_nr, _, _, _, _) ->
5085       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5086   ) daemon_functions;
5087   pr "  GUESTFS_PROC_NR_PROCS\n";
5088   pr "};\n";
5089   pr "\n";
5090
5091   (* Having to choose a maximum message size is annoying for several
5092    * reasons (it limits what we can do in the API), but it (a) makes
5093    * the protocol a lot simpler, and (b) provides a bound on the size
5094    * of the daemon which operates in limited memory space.  For large
5095    * file transfers you should use FTP.
5096    *)
5097   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5098   pr "\n";
5099
5100   (* Message header, etc. *)
5101   pr "\
5102 /* The communication protocol is now documented in the guestfs(3)
5103  * manpage.
5104  */
5105
5106 const GUESTFS_PROGRAM = 0x2000F5F5;
5107 const GUESTFS_PROTOCOL_VERSION = 1;
5108
5109 /* These constants must be larger than any possible message length. */
5110 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5111 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5112
5113 enum guestfs_message_direction {
5114   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5115   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5116 };
5117
5118 enum guestfs_message_status {
5119   GUESTFS_STATUS_OK = 0,
5120   GUESTFS_STATUS_ERROR = 1
5121 };
5122
5123 const GUESTFS_ERROR_LEN = 256;
5124
5125 struct guestfs_message_error {
5126   string error_message<GUESTFS_ERROR_LEN>;
5127 };
5128
5129 struct guestfs_message_header {
5130   unsigned prog;                     /* GUESTFS_PROGRAM */
5131   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5132   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5133   guestfs_message_direction direction;
5134   unsigned serial;                   /* message serial number */
5135   guestfs_message_status status;
5136 };
5137
5138 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5139
5140 struct guestfs_chunk {
5141   int cancel;                        /* if non-zero, transfer is cancelled */
5142   /* data size is 0 bytes if the transfer has finished successfully */
5143   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5144 };
5145 "
5146
5147 (* Generate the guestfs-structs.h file. *)
5148 and generate_structs_h () =
5149   generate_header CStyle LGPLv2;
5150
5151   (* This is a public exported header file containing various
5152    * structures.  The structures are carefully written to have
5153    * exactly the same in-memory format as the XDR structures that
5154    * we use on the wire to the daemon.  The reason for creating
5155    * copies of these structures here is just so we don't have to
5156    * export the whole of guestfs_protocol.h (which includes much
5157    * unrelated and XDR-dependent stuff that we don't want to be
5158    * public, or required by clients).
5159    *
5160    * To reiterate, we will pass these structures to and from the
5161    * client with a simple assignment or memcpy, so the format
5162    * must be identical to what rpcgen / the RFC defines.
5163    *)
5164
5165   (* Public structures. *)
5166   List.iter (
5167     fun (typ, cols) ->
5168       pr "struct guestfs_%s {\n" typ;
5169       List.iter (
5170         function
5171         | name, FChar -> pr "  char %s;\n" name
5172         | name, FString -> pr "  char *%s;\n" name
5173         | name, FBuffer ->
5174             pr "  uint32_t %s_len;\n" name;
5175             pr "  char *%s;\n" name
5176         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5177         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5178         | name, FInt32 -> pr "  int32_t %s;\n" name
5179         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5180         | name, FInt64 -> pr "  int64_t %s;\n" name
5181         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5182       ) cols;
5183       pr "};\n";
5184       pr "\n";
5185       pr "struct guestfs_%s_list {\n" typ;
5186       pr "  uint32_t len;\n";
5187       pr "  struct guestfs_%s *val;\n" typ;
5188       pr "};\n";
5189       pr "\n";
5190       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5191       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5192       pr "\n"
5193   ) structs
5194
5195 (* Generate the guestfs-actions.h file. *)
5196 and generate_actions_h () =
5197   generate_header CStyle LGPLv2;
5198   List.iter (
5199     fun (shortname, style, _, _, _, _, _) ->
5200       let name = "guestfs_" ^ shortname in
5201       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5202         name style
5203   ) all_functions
5204
5205 (* Generate the guestfs-internal-actions.h file. *)
5206 and generate_internal_actions_h () =
5207   generate_header CStyle LGPLv2;
5208   List.iter (
5209     fun (shortname, style, _, _, _, _, _) ->
5210       let name = "guestfs__" ^ shortname in
5211       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5212         name style
5213   ) non_daemon_functions
5214
5215 (* Generate the client-side dispatch stubs. *)
5216 and generate_client_actions () =
5217   generate_header CStyle LGPLv2;
5218
5219   pr "\
5220 #include <stdio.h>
5221 #include <stdlib.h>
5222 #include <stdint.h>
5223 #include <inttypes.h>
5224
5225 #include \"guestfs.h\"
5226 #include \"guestfs-internal.h\"
5227 #include \"guestfs-internal-actions.h\"
5228 #include \"guestfs_protocol.h\"
5229
5230 #define error guestfs_error
5231 //#define perrorf guestfs_perrorf
5232 #define safe_malloc guestfs_safe_malloc
5233 #define safe_realloc guestfs_safe_realloc
5234 //#define safe_strdup guestfs_safe_strdup
5235 #define safe_memdup guestfs_safe_memdup
5236
5237 /* Check the return message from a call for validity. */
5238 static int
5239 check_reply_header (guestfs_h *g,
5240                     const struct guestfs_message_header *hdr,
5241                     unsigned int proc_nr, unsigned int serial)
5242 {
5243   if (hdr->prog != GUESTFS_PROGRAM) {
5244     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5245     return -1;
5246   }
5247   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5248     error (g, \"wrong protocol version (%%d/%%d)\",
5249            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5250     return -1;
5251   }
5252   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5253     error (g, \"unexpected message direction (%%d/%%d)\",
5254            hdr->direction, GUESTFS_DIRECTION_REPLY);
5255     return -1;
5256   }
5257   if (hdr->proc != proc_nr) {
5258     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5259     return -1;
5260   }
5261   if (hdr->serial != serial) {
5262     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5263     return -1;
5264   }
5265
5266   return 0;
5267 }
5268
5269 /* Check we are in the right state to run a high-level action. */
5270 static int
5271 check_state (guestfs_h *g, const char *caller)
5272 {
5273   if (!guestfs__is_ready (g)) {
5274     if (guestfs__is_config (g) || guestfs__is_launching (g))
5275       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5276         caller);
5277     else
5278       error (g, \"%%s called from the wrong state, %%d != READY\",
5279         caller, guestfs__get_state (g));
5280     return -1;
5281   }
5282   return 0;
5283 }
5284
5285 ";
5286
5287   (* Generate code to generate guestfish call traces. *)
5288   let trace_call shortname style =
5289     pr "  if (guestfs__get_trace (g)) {\n";
5290
5291     let needs_i =
5292       List.exists (function
5293                    | StringList _ | DeviceList _ -> true
5294                    | _ -> false) (snd style) in
5295     if needs_i then (
5296       pr "    int i;\n";
5297       pr "\n"
5298     );
5299
5300     pr "    printf (\"%s\");\n" shortname;
5301     List.iter (
5302       function
5303       | String n                        (* strings *)
5304       | Device n
5305       | Pathname n
5306       | Dev_or_Path n
5307       | FileIn n
5308       | FileOut n ->
5309           (* guestfish doesn't support string escaping, so neither do we *)
5310           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5311       | OptString n ->                  (* string option *)
5312           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5313           pr "    else printf (\" null\");\n"
5314       | StringList n
5315       | DeviceList n ->                 (* string list *)
5316           pr "    putchar (' ');\n";
5317           pr "    putchar ('\"');\n";
5318           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5319           pr "      if (i > 0) putchar (' ');\n";
5320           pr "      fputs (%s[i], stdout);\n" n;
5321           pr "    }\n";
5322           pr "    putchar ('\"');\n";
5323       | Bool n ->                       (* boolean *)
5324           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5325       | Int n ->                        (* int *)
5326           pr "    printf (\" %%d\", %s);\n" n
5327       | Int64 n ->
5328           pr "    printf (\" %%\" PRIi64, %s);\n" n
5329     ) (snd style);
5330     pr "    putchar ('\\n');\n";
5331     pr "  }\n";
5332     pr "\n";
5333   in
5334
5335   (* For non-daemon functions, generate a wrapper around each function. *)
5336   List.iter (
5337     fun (shortname, style, _, _, _, _, _) ->
5338       let name = "guestfs_" ^ shortname in
5339
5340       generate_prototype ~extern:false ~semicolon:false ~newline:true
5341         ~handle:"g" name style;
5342       pr "{\n";
5343       trace_call shortname style;
5344       pr "  return guestfs__%s " shortname;
5345       generate_c_call_args ~handle:"g" style;
5346       pr ";\n";
5347       pr "}\n";
5348       pr "\n"
5349   ) non_daemon_functions;
5350
5351   (* Client-side stubs for each function. *)
5352   List.iter (
5353     fun (shortname, style, _, _, _, _, _) ->
5354       let name = "guestfs_" ^ shortname in
5355
5356       (* Generate the action stub. *)
5357       generate_prototype ~extern:false ~semicolon:false ~newline:true
5358         ~handle:"g" name style;
5359
5360       let error_code =
5361         match fst style with
5362         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5363         | RConstString _ | RConstOptString _ ->
5364             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5365         | RString _ | RStringList _
5366         | RStruct _ | RStructList _
5367         | RHashtable _ | RBufferOut _ ->
5368             "NULL" in
5369
5370       pr "{\n";
5371
5372       (match snd style with
5373        | [] -> ()
5374        | _ -> pr "  struct %s_args args;\n" name
5375       );
5376
5377       pr "  guestfs_message_header hdr;\n";
5378       pr "  guestfs_message_error err;\n";
5379       let has_ret =
5380         match fst style with
5381         | RErr -> false
5382         | RConstString _ | RConstOptString _ ->
5383             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5384         | RInt _ | RInt64 _
5385         | RBool _ | RString _ | RStringList _
5386         | RStruct _ | RStructList _
5387         | RHashtable _ | RBufferOut _ ->
5388             pr "  struct %s_ret ret;\n" name;
5389             true in
5390
5391       pr "  int serial;\n";
5392       pr "  int r;\n";
5393       pr "\n";
5394       trace_call shortname style;
5395       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5396       pr "  guestfs___set_busy (g);\n";
5397       pr "\n";
5398
5399       (* Send the main header and arguments. *)
5400       (match snd style with
5401        | [] ->
5402            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5403              (String.uppercase shortname)
5404        | args ->
5405            List.iter (
5406              function
5407              | Pathname n | Device n | Dev_or_Path n | String n ->
5408                  pr "  args.%s = (char *) %s;\n" n n
5409              | OptString n ->
5410                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5411              | StringList n | DeviceList n ->
5412                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5413                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5414              | Bool n ->
5415                  pr "  args.%s = %s;\n" n n
5416              | Int n ->
5417                  pr "  args.%s = %s;\n" n n
5418              | Int64 n ->
5419                  pr "  args.%s = %s;\n" n n
5420              | FileIn _ | FileOut _ -> ()
5421            ) args;
5422            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5423              (String.uppercase shortname);
5424            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5425              name;
5426       );
5427       pr "  if (serial == -1) {\n";
5428       pr "    guestfs___end_busy (g);\n";
5429       pr "    return %s;\n" error_code;
5430       pr "  }\n";
5431       pr "\n";
5432
5433       (* Send any additional files (FileIn) requested. *)
5434       let need_read_reply_label = ref false in
5435       List.iter (
5436         function
5437         | FileIn n ->
5438             pr "  r = guestfs___send_file (g, %s);\n" n;
5439             pr "  if (r == -1) {\n";
5440             pr "    guestfs___end_busy (g);\n";
5441             pr "    return %s;\n" error_code;
5442             pr "  }\n";
5443             pr "  if (r == -2) /* daemon cancelled */\n";
5444             pr "    goto read_reply;\n";
5445             need_read_reply_label := true;
5446             pr "\n";
5447         | _ -> ()
5448       ) (snd style);
5449
5450       (* Wait for the reply from the remote end. *)
5451       if !need_read_reply_label then pr " read_reply:\n";
5452       pr "  memset (&hdr, 0, sizeof hdr);\n";
5453       pr "  memset (&err, 0, sizeof err);\n";
5454       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5455       pr "\n";
5456       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5457       if not has_ret then
5458         pr "NULL, NULL"
5459       else
5460         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5461       pr ");\n";
5462
5463       pr "  if (r == -1) {\n";
5464       pr "    guestfs___end_busy (g);\n";
5465       pr "    return %s;\n" error_code;
5466       pr "  }\n";
5467       pr "\n";
5468
5469       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5470         (String.uppercase shortname);
5471       pr "    guestfs___end_busy (g);\n";
5472       pr "    return %s;\n" error_code;
5473       pr "  }\n";
5474       pr "\n";
5475
5476       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5477       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5478       pr "    free (err.error_message);\n";
5479       pr "    guestfs___end_busy (g);\n";
5480       pr "    return %s;\n" error_code;
5481       pr "  }\n";
5482       pr "\n";
5483
5484       (* Expecting to receive further files (FileOut)? *)
5485       List.iter (
5486         function
5487         | FileOut n ->
5488             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5489             pr "    guestfs___end_busy (g);\n";
5490             pr "    return %s;\n" error_code;
5491             pr "  }\n";
5492             pr "\n";
5493         | _ -> ()
5494       ) (snd style);
5495
5496       pr "  guestfs___end_busy (g);\n";
5497
5498       (match fst style with
5499        | RErr -> pr "  return 0;\n"
5500        | RInt n | RInt64 n | RBool n ->
5501            pr "  return ret.%s;\n" n
5502        | RConstString _ | RConstOptString _ ->
5503            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5504        | RString n ->
5505            pr "  return ret.%s; /* caller will free */\n" n
5506        | RStringList n | RHashtable n ->
5507            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5508            pr "  ret.%s.%s_val =\n" n n;
5509            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5510            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5511              n n;
5512            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5513            pr "  return ret.%s.%s_val;\n" n n
5514        | RStruct (n, _) ->
5515            pr "  /* caller will free this */\n";
5516            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5517        | RStructList (n, _) ->
5518            pr "  /* caller will free this */\n";
5519            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5520        | RBufferOut n ->
5521            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5522            pr "   * _val might be NULL here.  To make the API saner for\n";
5523            pr "   * callers, we turn this case into a unique pointer (using\n";
5524            pr "   * malloc(1)).\n";
5525            pr "   */\n";
5526            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5527            pr "    *size_r = ret.%s.%s_len;\n" n n;
5528            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5529            pr "  } else {\n";
5530            pr "    free (ret.%s.%s_val);\n" n n;
5531            pr "    char *p = safe_malloc (g, 1);\n";
5532            pr "    *size_r = ret.%s.%s_len;\n" n n;
5533            pr "    return p;\n";
5534            pr "  }\n";
5535       );
5536
5537       pr "}\n\n"
5538   ) daemon_functions;
5539
5540   (* Functions to free structures. *)
5541   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5542   pr " * structure format is identical to the XDR format.  See note in\n";
5543   pr " * generator.ml.\n";
5544   pr " */\n";
5545   pr "\n";
5546
5547   List.iter (
5548     fun (typ, _) ->
5549       pr "void\n";
5550       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5551       pr "{\n";
5552       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5553       pr "  free (x);\n";
5554       pr "}\n";
5555       pr "\n";
5556
5557       pr "void\n";
5558       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5559       pr "{\n";
5560       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5561       pr "  free (x);\n";
5562       pr "}\n";
5563       pr "\n";
5564
5565   ) structs;
5566
5567 (* Generate daemon/actions.h. *)
5568 and generate_daemon_actions_h () =
5569   generate_header CStyle GPLv2;
5570
5571   pr "#include \"../src/guestfs_protocol.h\"\n";
5572   pr "\n";
5573
5574   List.iter (
5575     fun (name, style, _, _, _, _, _) ->
5576       generate_prototype
5577         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5578         name style;
5579   ) daemon_functions
5580
5581 (* Generate the server-side stubs. *)
5582 and generate_daemon_actions () =
5583   generate_header CStyle GPLv2;
5584
5585   pr "#include <config.h>\n";
5586   pr "\n";
5587   pr "#include <stdio.h>\n";
5588   pr "#include <stdlib.h>\n";
5589   pr "#include <string.h>\n";
5590   pr "#include <inttypes.h>\n";
5591   pr "#include <rpc/types.h>\n";
5592   pr "#include <rpc/xdr.h>\n";
5593   pr "\n";
5594   pr "#include \"daemon.h\"\n";
5595   pr "#include \"c-ctype.h\"\n";
5596   pr "#include \"../src/guestfs_protocol.h\"\n";
5597   pr "#include \"actions.h\"\n";
5598   pr "\n";
5599
5600   List.iter (
5601     fun (name, style, _, _, _, _, _) ->
5602       (* Generate server-side stubs. *)
5603       pr "static void %s_stub (XDR *xdr_in)\n" name;
5604       pr "{\n";
5605       let error_code =
5606         match fst style with
5607         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5608         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5609         | RBool _ -> pr "  int r;\n"; "-1"
5610         | RConstString _ | RConstOptString _ ->
5611             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5612         | RString _ -> pr "  char *r;\n"; "NULL"
5613         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5614         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5615         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5616         | RBufferOut _ ->
5617             pr "  size_t size = 1;\n";
5618             pr "  char *r;\n";
5619             "NULL" in
5620
5621       (match snd style with
5622        | [] -> ()
5623        | args ->
5624            pr "  struct guestfs_%s_args args;\n" name;
5625            List.iter (
5626              function
5627              | Device n | Dev_or_Path n
5628              | Pathname n
5629              | String n -> ()
5630              | OptString n -> pr "  char *%s;\n" n
5631              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5632              | Bool n -> pr "  int %s;\n" n
5633              | Int n -> pr "  int %s;\n" n
5634              | Int64 n -> pr "  int64_t %s;\n" n
5635              | FileIn _ | FileOut _ -> ()
5636            ) args
5637       );
5638       pr "\n";
5639
5640       (match snd style with
5641        | [] -> ()
5642        | args ->
5643            pr "  memset (&args, 0, sizeof args);\n";
5644            pr "\n";
5645            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5646            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5647            pr "    return;\n";
5648            pr "  }\n";
5649            let pr_args n =
5650              pr "  char *%s = args.%s;\n" n n
5651            in
5652            let pr_list_handling_code n =
5653              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5654              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5655              pr "  if (%s == NULL) {\n" n;
5656              pr "    reply_with_perror (\"realloc\");\n";
5657              pr "    goto done;\n";
5658              pr "  }\n";
5659              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5660              pr "  args.%s.%s_val = %s;\n" n n n;
5661            in
5662            List.iter (
5663              function
5664              | Pathname n ->
5665                  pr_args n;
5666                  pr "  ABS_PATH (%s, goto done);\n" n;
5667              | Device n ->
5668                  pr_args n;
5669                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5670              | Dev_or_Path n ->
5671                  pr_args n;
5672                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5673              | String n -> pr_args n
5674              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5675              | StringList n ->
5676                  pr_list_handling_code n;
5677              | DeviceList n ->
5678                  pr_list_handling_code n;
5679                  pr "  /* Ensure that each is a device,\n";
5680                  pr "   * and perform device name translation. */\n";
5681                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5682                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5683                  pr "  }\n";
5684              | Bool n -> pr "  %s = args.%s;\n" n n
5685              | Int n -> pr "  %s = args.%s;\n" n n
5686              | Int64 n -> pr "  %s = args.%s;\n" n n
5687              | FileIn _ | FileOut _ -> ()
5688            ) args;
5689            pr "\n"
5690       );
5691
5692
5693       (* this is used at least for do_equal *)
5694       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5695         (* Emit NEED_ROOT just once, even when there are two or
5696            more Pathname args *)
5697         pr "  NEED_ROOT (goto done);\n";
5698       );
5699
5700       (* Don't want to call the impl with any FileIn or FileOut
5701        * parameters, since these go "outside" the RPC protocol.
5702        *)
5703       let args' =
5704         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5705           (snd style) in
5706       pr "  r = do_%s " name;
5707       generate_c_call_args (fst style, args');
5708       pr ";\n";
5709
5710       (match fst style with
5711        | RErr | RInt _ | RInt64 _ | RBool _
5712        | RConstString _ | RConstOptString _
5713        | RString _ | RStringList _ | RHashtable _
5714        | RStruct (_, _) | RStructList (_, _) ->
5715            pr "  if (r == %s)\n" error_code;
5716            pr "    /* do_%s has already called reply_with_error */\n" name;
5717            pr "    goto done;\n";
5718            pr "\n"
5719        | RBufferOut _ ->
5720            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5721            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5722            pr "   */\n";
5723            pr "  if (size == 1 && r == %s)\n" error_code;
5724            pr "    /* do_%s has already called reply_with_error */\n" name;
5725            pr "    goto done;\n";
5726            pr "\n"
5727       );
5728
5729       (* If there are any FileOut parameters, then the impl must
5730        * send its own reply.
5731        *)
5732       let no_reply =
5733         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5734       if no_reply then
5735         pr "  /* do_%s has already sent a reply */\n" name
5736       else (
5737         match fst style with
5738         | RErr -> pr "  reply (NULL, NULL);\n"
5739         | RInt n | RInt64 n | RBool n ->
5740             pr "  struct guestfs_%s_ret ret;\n" name;
5741             pr "  ret.%s = r;\n" n;
5742             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5743               name
5744         | RConstString _ | RConstOptString _ ->
5745             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5746         | RString n ->
5747             pr "  struct guestfs_%s_ret ret;\n" name;
5748             pr "  ret.%s = r;\n" n;
5749             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5750               name;
5751             pr "  free (r);\n"
5752         | RStringList n | RHashtable n ->
5753             pr "  struct guestfs_%s_ret ret;\n" name;
5754             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5755             pr "  ret.%s.%s_val = r;\n" n n;
5756             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5757               name;
5758             pr "  free_strings (r);\n"
5759         | RStruct (n, _) ->
5760             pr "  struct guestfs_%s_ret ret;\n" name;
5761             pr "  ret.%s = *r;\n" n;
5762             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5763               name;
5764             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5765               name
5766         | RStructList (n, _) ->
5767             pr "  struct guestfs_%s_ret ret;\n" name;
5768             pr "  ret.%s = *r;\n" n;
5769             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5770               name;
5771             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5772               name
5773         | RBufferOut n ->
5774             pr "  struct guestfs_%s_ret ret;\n" name;
5775             pr "  ret.%s.%s_val = r;\n" n n;
5776             pr "  ret.%s.%s_len = size;\n" n n;
5777             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5778               name;
5779             pr "  free (r);\n"
5780       );
5781
5782       (* Free the args. *)
5783       (match snd style with
5784        | [] ->
5785            pr "done: ;\n";
5786        | _ ->
5787            pr "done:\n";
5788            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5789              name
5790       );
5791
5792       pr "}\n\n";
5793   ) daemon_functions;
5794
5795   (* Dispatch function. *)
5796   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5797   pr "{\n";
5798   pr "  switch (proc_nr) {\n";
5799
5800   List.iter (
5801     fun (name, style, _, _, _, _, _) ->
5802       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5803       pr "      %s_stub (xdr_in);\n" name;
5804       pr "      break;\n"
5805   ) daemon_functions;
5806
5807   pr "    default:\n";
5808   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";
5809   pr "  }\n";
5810   pr "}\n";
5811   pr "\n";
5812
5813   (* LVM columns and tokenization functions. *)
5814   (* XXX This generates crap code.  We should rethink how we
5815    * do this parsing.
5816    *)
5817   List.iter (
5818     function
5819     | typ, cols ->
5820         pr "static const char *lvm_%s_cols = \"%s\";\n"
5821           typ (String.concat "," (List.map fst cols));
5822         pr "\n";
5823
5824         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5825         pr "{\n";
5826         pr "  char *tok, *p, *next;\n";
5827         pr "  int i, j;\n";
5828         pr "\n";
5829         (*
5830           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5831           pr "\n";
5832         *)
5833         pr "  if (!str) {\n";
5834         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5835         pr "    return -1;\n";
5836         pr "  }\n";
5837         pr "  if (!*str || c_isspace (*str)) {\n";
5838         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5839         pr "    return -1;\n";
5840         pr "  }\n";
5841         pr "  tok = str;\n";
5842         List.iter (
5843           fun (name, coltype) ->
5844             pr "  if (!tok) {\n";
5845             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5846             pr "    return -1;\n";
5847             pr "  }\n";
5848             pr "  p = strchrnul (tok, ',');\n";
5849             pr "  if (*p) next = p+1; else next = NULL;\n";
5850             pr "  *p = '\\0';\n";
5851             (match coltype with
5852              | FString ->
5853                  pr "  r->%s = strdup (tok);\n" name;
5854                  pr "  if (r->%s == NULL) {\n" name;
5855                  pr "    perror (\"strdup\");\n";
5856                  pr "    return -1;\n";
5857                  pr "  }\n"
5858              | FUUID ->
5859                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5860                  pr "    if (tok[j] == '\\0') {\n";
5861                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5862                  pr "      return -1;\n";
5863                  pr "    } else if (tok[j] != '-')\n";
5864                  pr "      r->%s[i++] = tok[j];\n" name;
5865                  pr "  }\n";
5866              | FBytes ->
5867                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5868                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5869                  pr "    return -1;\n";
5870                  pr "  }\n";
5871              | FInt64 ->
5872                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5873                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5874                  pr "    return -1;\n";
5875                  pr "  }\n";
5876              | FOptPercent ->
5877                  pr "  if (tok[0] == '\\0')\n";
5878                  pr "    r->%s = -1;\n" name;
5879                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5880                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5881                  pr "    return -1;\n";
5882                  pr "  }\n";
5883              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5884                  assert false (* can never be an LVM column *)
5885             );
5886             pr "  tok = next;\n";
5887         ) cols;
5888
5889         pr "  if (tok != NULL) {\n";
5890         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5891         pr "    return -1;\n";
5892         pr "  }\n";
5893         pr "  return 0;\n";
5894         pr "}\n";
5895         pr "\n";
5896
5897         pr "guestfs_int_lvm_%s_list *\n" typ;
5898         pr "parse_command_line_%ss (void)\n" typ;
5899         pr "{\n";
5900         pr "  char *out, *err;\n";
5901         pr "  char *p, *pend;\n";
5902         pr "  int r, i;\n";
5903         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5904         pr "  void *newp;\n";
5905         pr "\n";
5906         pr "  ret = malloc (sizeof *ret);\n";
5907         pr "  if (!ret) {\n";
5908         pr "    reply_with_perror (\"malloc\");\n";
5909         pr "    return NULL;\n";
5910         pr "  }\n";
5911         pr "\n";
5912         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5913         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5914         pr "\n";
5915         pr "  r = command (&out, &err,\n";
5916         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5917         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5918         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5919         pr "  if (r == -1) {\n";
5920         pr "    reply_with_error (\"%%s\", err);\n";
5921         pr "    free (out);\n";
5922         pr "    free (err);\n";
5923         pr "    free (ret);\n";
5924         pr "    return NULL;\n";
5925         pr "  }\n";
5926         pr "\n";
5927         pr "  free (err);\n";
5928         pr "\n";
5929         pr "  /* Tokenize each line of the output. */\n";
5930         pr "  p = out;\n";
5931         pr "  i = 0;\n";
5932         pr "  while (p) {\n";
5933         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5934         pr "    if (pend) {\n";
5935         pr "      *pend = '\\0';\n";
5936         pr "      pend++;\n";
5937         pr "    }\n";
5938         pr "\n";
5939         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
5940         pr "      p++;\n";
5941         pr "\n";
5942         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5943         pr "      p = pend;\n";
5944         pr "      continue;\n";
5945         pr "    }\n";
5946         pr "\n";
5947         pr "    /* Allocate some space to store this next entry. */\n";
5948         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5949         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5950         pr "    if (newp == NULL) {\n";
5951         pr "      reply_with_perror (\"realloc\");\n";
5952         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5953         pr "      free (ret);\n";
5954         pr "      free (out);\n";
5955         pr "      return NULL;\n";
5956         pr "    }\n";
5957         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5958         pr "\n";
5959         pr "    /* Tokenize the next entry. */\n";
5960         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5961         pr "    if (r == -1) {\n";
5962         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5963         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5964         pr "      free (ret);\n";
5965         pr "      free (out);\n";
5966         pr "      return NULL;\n";
5967         pr "    }\n";
5968         pr "\n";
5969         pr "    ++i;\n";
5970         pr "    p = pend;\n";
5971         pr "  }\n";
5972         pr "\n";
5973         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5974         pr "\n";
5975         pr "  free (out);\n";
5976         pr "  return ret;\n";
5977         pr "}\n"
5978
5979   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5980
5981 (* Generate a list of function names, for debugging in the daemon.. *)
5982 and generate_daemon_names () =
5983   generate_header CStyle GPLv2;
5984
5985   pr "#include <config.h>\n";
5986   pr "\n";
5987   pr "#include \"daemon.h\"\n";
5988   pr "\n";
5989
5990   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5991   pr "const char *function_names[] = {\n";
5992   List.iter (
5993     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5994   ) daemon_functions;
5995   pr "};\n";
5996
5997 (* Generate the optional groups for the daemon to implement
5998  * guestfs_available.
5999  *)
6000 and generate_daemon_optgroups_c () =
6001   generate_header CStyle GPLv2;
6002
6003   pr "#include <config.h>\n";
6004   pr "\n";
6005   pr "#include \"daemon.h\"\n";
6006   pr "#include \"optgroups.h\"\n";
6007   pr "\n";
6008
6009   pr "struct optgroup optgroups[] = {\n";
6010   List.iter (
6011     fun (group, _) ->
6012       pr "  { \"%s\", optgroup_%s_available },\n" group group
6013   ) optgroups;
6014   pr "  { NULL, NULL }\n";
6015   pr "};\n"
6016
6017 and generate_daemon_optgroups_h () =
6018   generate_header CStyle GPLv2;
6019
6020   List.iter (
6021     fun (group, _) ->
6022       pr "extern int optgroup_%s_available (void);\n" group
6023   ) optgroups
6024
6025 (* Generate the tests. *)
6026 and generate_tests () =
6027   generate_header CStyle GPLv2;
6028
6029   pr "\
6030 #include <stdio.h>
6031 #include <stdlib.h>
6032 #include <string.h>
6033 #include <unistd.h>
6034 #include <sys/types.h>
6035 #include <fcntl.h>
6036
6037 #include \"guestfs.h\"
6038 #include \"guestfs-internal.h\"
6039
6040 static guestfs_h *g;
6041 static int suppress_error = 0;
6042
6043 static void print_error (guestfs_h *g, void *data, const char *msg)
6044 {
6045   if (!suppress_error)
6046     fprintf (stderr, \"%%s\\n\", msg);
6047 }
6048
6049 /* FIXME: nearly identical code appears in fish.c */
6050 static void print_strings (char *const *argv)
6051 {
6052   int argc;
6053
6054   for (argc = 0; argv[argc] != NULL; ++argc)
6055     printf (\"\\t%%s\\n\", argv[argc]);
6056 }
6057
6058 /*
6059 static void print_table (char const *const *argv)
6060 {
6061   int i;
6062
6063   for (i = 0; argv[i] != NULL; i += 2)
6064     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6065 }
6066 */
6067
6068 ";
6069
6070   (* Generate a list of commands which are not tested anywhere. *)
6071   pr "static void no_test_warnings (void)\n";
6072   pr "{\n";
6073
6074   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6075   List.iter (
6076     fun (_, _, _, _, tests, _, _) ->
6077       let tests = filter_map (
6078         function
6079         | (_, (Always|If _|Unless _), test) -> Some test
6080         | (_, Disabled, _) -> None
6081       ) tests in
6082       let seq = List.concat (List.map seq_of_test tests) in
6083       let cmds_tested = List.map List.hd seq in
6084       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6085   ) all_functions;
6086
6087   List.iter (
6088     fun (name, _, _, _, _, _, _) ->
6089       if not (Hashtbl.mem hash name) then
6090         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6091   ) all_functions;
6092
6093   pr "}\n";
6094   pr "\n";
6095
6096   (* Generate the actual tests.  Note that we generate the tests
6097    * in reverse order, deliberately, so that (in general) the
6098    * newest tests run first.  This makes it quicker and easier to
6099    * debug them.
6100    *)
6101   let test_names =
6102     List.map (
6103       fun (name, _, _, flags, tests, _, _) ->
6104         mapi (generate_one_test name flags) tests
6105     ) (List.rev all_functions) in
6106   let test_names = List.concat test_names in
6107   let nr_tests = List.length test_names in
6108
6109   pr "\
6110 int main (int argc, char *argv[])
6111 {
6112   char c = 0;
6113   unsigned long int n_failed = 0;
6114   const char *filename;
6115   int fd;
6116   int nr_tests, test_num = 0;
6117
6118   setbuf (stdout, NULL);
6119
6120   no_test_warnings ();
6121
6122   g = guestfs_create ();
6123   if (g == NULL) {
6124     printf (\"guestfs_create FAILED\\n\");
6125     exit (EXIT_FAILURE);
6126   }
6127
6128   guestfs_set_error_handler (g, print_error, NULL);
6129
6130   guestfs_set_path (g, \"../appliance\");
6131
6132   filename = \"test1.img\";
6133   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6134   if (fd == -1) {
6135     perror (filename);
6136     exit (EXIT_FAILURE);
6137   }
6138   if (lseek (fd, %d, SEEK_SET) == -1) {
6139     perror (\"lseek\");
6140     close (fd);
6141     unlink (filename);
6142     exit (EXIT_FAILURE);
6143   }
6144   if (write (fd, &c, 1) == -1) {
6145     perror (\"write\");
6146     close (fd);
6147     unlink (filename);
6148     exit (EXIT_FAILURE);
6149   }
6150   if (close (fd) == -1) {
6151     perror (filename);
6152     unlink (filename);
6153     exit (EXIT_FAILURE);
6154   }
6155   if (guestfs_add_drive (g, filename) == -1) {
6156     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6157     exit (EXIT_FAILURE);
6158   }
6159
6160   filename = \"test2.img\";
6161   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6162   if (fd == -1) {
6163     perror (filename);
6164     exit (EXIT_FAILURE);
6165   }
6166   if (lseek (fd, %d, SEEK_SET) == -1) {
6167     perror (\"lseek\");
6168     close (fd);
6169     unlink (filename);
6170     exit (EXIT_FAILURE);
6171   }
6172   if (write (fd, &c, 1) == -1) {
6173     perror (\"write\");
6174     close (fd);
6175     unlink (filename);
6176     exit (EXIT_FAILURE);
6177   }
6178   if (close (fd) == -1) {
6179     perror (filename);
6180     unlink (filename);
6181     exit (EXIT_FAILURE);
6182   }
6183   if (guestfs_add_drive (g, filename) == -1) {
6184     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6185     exit (EXIT_FAILURE);
6186   }
6187
6188   filename = \"test3.img\";
6189   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6190   if (fd == -1) {
6191     perror (filename);
6192     exit (EXIT_FAILURE);
6193   }
6194   if (lseek (fd, %d, SEEK_SET) == -1) {
6195     perror (\"lseek\");
6196     close (fd);
6197     unlink (filename);
6198     exit (EXIT_FAILURE);
6199   }
6200   if (write (fd, &c, 1) == -1) {
6201     perror (\"write\");
6202     close (fd);
6203     unlink (filename);
6204     exit (EXIT_FAILURE);
6205   }
6206   if (close (fd) == -1) {
6207     perror (filename);
6208     unlink (filename);
6209     exit (EXIT_FAILURE);
6210   }
6211   if (guestfs_add_drive (g, filename) == -1) {
6212     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6213     exit (EXIT_FAILURE);
6214   }
6215
6216   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6217     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6218     exit (EXIT_FAILURE);
6219   }
6220
6221   if (guestfs_launch (g) == -1) {
6222     printf (\"guestfs_launch FAILED\\n\");
6223     exit (EXIT_FAILURE);
6224   }
6225
6226   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6227   alarm (600);
6228
6229   /* Cancel previous alarm. */
6230   alarm (0);
6231
6232   nr_tests = %d;
6233
6234 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6235
6236   iteri (
6237     fun i test_name ->
6238       pr "  test_num++;\n";
6239       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6240       pr "  if (%s () == -1) {\n" test_name;
6241       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6242       pr "    n_failed++;\n";
6243       pr "  }\n";
6244   ) test_names;
6245   pr "\n";
6246
6247   pr "  guestfs_close (g);\n";
6248   pr "  unlink (\"test1.img\");\n";
6249   pr "  unlink (\"test2.img\");\n";
6250   pr "  unlink (\"test3.img\");\n";
6251   pr "\n";
6252
6253   pr "  if (n_failed > 0) {\n";
6254   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6255   pr "    exit (EXIT_FAILURE);\n";
6256   pr "  }\n";
6257   pr "\n";
6258
6259   pr "  exit (EXIT_SUCCESS);\n";
6260   pr "}\n"
6261
6262 and generate_one_test name flags i (init, prereq, test) =
6263   let test_name = sprintf "test_%s_%d" name i in
6264
6265   pr "\
6266 static int %s_skip (void)
6267 {
6268   const char *str;
6269
6270   str = getenv (\"TEST_ONLY\");
6271   if (str)
6272     return strstr (str, \"%s\") == NULL;
6273   str = getenv (\"SKIP_%s\");
6274   if (str && STREQ (str, \"1\")) return 1;
6275   str = getenv (\"SKIP_TEST_%s\");
6276   if (str && STREQ (str, \"1\")) return 1;
6277   return 0;
6278 }
6279
6280 " test_name name (String.uppercase test_name) (String.uppercase name);
6281
6282   (match prereq with
6283    | Disabled | Always -> ()
6284    | If code | Unless code ->
6285        pr "static int %s_prereq (void)\n" test_name;
6286        pr "{\n";
6287        pr "  %s\n" code;
6288        pr "}\n";
6289        pr "\n";
6290   );
6291
6292   pr "\
6293 static int %s (void)
6294 {
6295   if (%s_skip ()) {
6296     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6297     return 0;
6298   }
6299
6300 " test_name test_name test_name;
6301
6302   (* Optional functions should only be tested if the relevant
6303    * support is available in the daemon.
6304    *)
6305   List.iter (
6306     function
6307     | Optional group ->
6308         pr "  {\n";
6309         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6310         pr "    int r;\n";
6311         pr "    suppress_error = 1;\n";
6312         pr "    r = guestfs_available (g, (char **) groups);\n";
6313         pr "    suppress_error = 0;\n";
6314         pr "    if (r == -1) {\n";
6315         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6316         pr "      return 0;\n";
6317         pr "    }\n";
6318         pr "  }\n";
6319     | _ -> ()
6320   ) flags;
6321
6322   (match prereq with
6323    | Disabled ->
6324        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6325    | If _ ->
6326        pr "  if (! %s_prereq ()) {\n" test_name;
6327        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6328        pr "    return 0;\n";
6329        pr "  }\n";
6330        pr "\n";
6331        generate_one_test_body name i test_name init test;
6332    | Unless _ ->
6333        pr "  if (%s_prereq ()) {\n" test_name;
6334        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6335        pr "    return 0;\n";
6336        pr "  }\n";
6337        pr "\n";
6338        generate_one_test_body name i test_name init test;
6339    | Always ->
6340        generate_one_test_body name i test_name init test
6341   );
6342
6343   pr "  return 0;\n";
6344   pr "}\n";
6345   pr "\n";
6346   test_name
6347
6348 and generate_one_test_body name i test_name init test =
6349   (match init with
6350    | InitNone (* XXX at some point, InitNone and InitEmpty became
6351                * folded together as the same thing.  Really we should
6352                * make InitNone do nothing at all, but the tests may
6353                * need to be checked to make sure this is OK.
6354                *)
6355    | InitEmpty ->
6356        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6357        List.iter (generate_test_command_call test_name)
6358          [["blockdev_setrw"; "/dev/sda"];
6359           ["umount_all"];
6360           ["lvm_remove_all"]]
6361    | InitPartition ->
6362        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6363        List.iter (generate_test_command_call test_name)
6364          [["blockdev_setrw"; "/dev/sda"];
6365           ["umount_all"];
6366           ["lvm_remove_all"];
6367           ["part_disk"; "/dev/sda"; "mbr"]]
6368    | InitBasicFS ->
6369        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6370        List.iter (generate_test_command_call test_name)
6371          [["blockdev_setrw"; "/dev/sda"];
6372           ["umount_all"];
6373           ["lvm_remove_all"];
6374           ["part_disk"; "/dev/sda"; "mbr"];
6375           ["mkfs"; "ext2"; "/dev/sda1"];
6376           ["mount"; "/dev/sda1"; "/"]]
6377    | InitBasicFSonLVM ->
6378        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6379          test_name;
6380        List.iter (generate_test_command_call test_name)
6381          [["blockdev_setrw"; "/dev/sda"];
6382           ["umount_all"];
6383           ["lvm_remove_all"];
6384           ["part_disk"; "/dev/sda"; "mbr"];
6385           ["pvcreate"; "/dev/sda1"];
6386           ["vgcreate"; "VG"; "/dev/sda1"];
6387           ["lvcreate"; "LV"; "VG"; "8"];
6388           ["mkfs"; "ext2"; "/dev/VG/LV"];
6389           ["mount"; "/dev/VG/LV"; "/"]]
6390    | InitISOFS ->
6391        pr "  /* InitISOFS for %s */\n" test_name;
6392        List.iter (generate_test_command_call test_name)
6393          [["blockdev_setrw"; "/dev/sda"];
6394           ["umount_all"];
6395           ["lvm_remove_all"];
6396           ["mount_ro"; "/dev/sdd"; "/"]]
6397   );
6398
6399   let get_seq_last = function
6400     | [] ->
6401         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6402           test_name
6403     | seq ->
6404         let seq = List.rev seq in
6405         List.rev (List.tl seq), List.hd seq
6406   in
6407
6408   match test with
6409   | TestRun seq ->
6410       pr "  /* TestRun for %s (%d) */\n" name i;
6411       List.iter (generate_test_command_call test_name) seq
6412   | TestOutput (seq, expected) ->
6413       pr "  /* TestOutput for %s (%d) */\n" name i;
6414       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6415       let seq, last = get_seq_last seq in
6416       let test () =
6417         pr "    if (STRNEQ (r, expected)) {\n";
6418         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6419         pr "      return -1;\n";
6420         pr "    }\n"
6421       in
6422       List.iter (generate_test_command_call test_name) seq;
6423       generate_test_command_call ~test test_name last
6424   | TestOutputList (seq, expected) ->
6425       pr "  /* TestOutputList for %s (%d) */\n" name i;
6426       let seq, last = get_seq_last seq in
6427       let test () =
6428         iteri (
6429           fun i str ->
6430             pr "    if (!r[%d]) {\n" i;
6431             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6432             pr "      print_strings (r);\n";
6433             pr "      return -1;\n";
6434             pr "    }\n";
6435             pr "    {\n";
6436             pr "      const char *expected = \"%s\";\n" (c_quote str);
6437             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6438             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6439             pr "        return -1;\n";
6440             pr "      }\n";
6441             pr "    }\n"
6442         ) expected;
6443         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6444         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6445           test_name;
6446         pr "      print_strings (r);\n";
6447         pr "      return -1;\n";
6448         pr "    }\n"
6449       in
6450       List.iter (generate_test_command_call test_name) seq;
6451       generate_test_command_call ~test test_name last
6452   | TestOutputListOfDevices (seq, expected) ->
6453       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6454       let seq, last = get_seq_last seq in
6455       let test () =
6456         iteri (
6457           fun i str ->
6458             pr "    if (!r[%d]) {\n" i;
6459             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6460             pr "      print_strings (r);\n";
6461             pr "      return -1;\n";
6462             pr "    }\n";
6463             pr "    {\n";
6464             pr "      const char *expected = \"%s\";\n" (c_quote str);
6465             pr "      r[%d][5] = 's';\n" i;
6466             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6467             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6468             pr "        return -1;\n";
6469             pr "      }\n";
6470             pr "    }\n"
6471         ) expected;
6472         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6473         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6474           test_name;
6475         pr "      print_strings (r);\n";
6476         pr "      return -1;\n";
6477         pr "    }\n"
6478       in
6479       List.iter (generate_test_command_call test_name) seq;
6480       generate_test_command_call ~test test_name last
6481   | TestOutputInt (seq, expected) ->
6482       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6483       let seq, last = get_seq_last seq in
6484       let test () =
6485         pr "    if (r != %d) {\n" expected;
6486         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6487           test_name expected;
6488         pr "               (int) r);\n";
6489         pr "      return -1;\n";
6490         pr "    }\n"
6491       in
6492       List.iter (generate_test_command_call test_name) seq;
6493       generate_test_command_call ~test test_name last
6494   | TestOutputIntOp (seq, op, expected) ->
6495       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6496       let seq, last = get_seq_last seq in
6497       let test () =
6498         pr "    if (! (r %s %d)) {\n" op expected;
6499         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6500           test_name op expected;
6501         pr "               (int) r);\n";
6502         pr "      return -1;\n";
6503         pr "    }\n"
6504       in
6505       List.iter (generate_test_command_call test_name) seq;
6506       generate_test_command_call ~test test_name last
6507   | TestOutputTrue seq ->
6508       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6509       let seq, last = get_seq_last seq in
6510       let test () =
6511         pr "    if (!r) {\n";
6512         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6513           test_name;
6514         pr "      return -1;\n";
6515         pr "    }\n"
6516       in
6517       List.iter (generate_test_command_call test_name) seq;
6518       generate_test_command_call ~test test_name last
6519   | TestOutputFalse seq ->
6520       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6521       let seq, last = get_seq_last seq in
6522       let test () =
6523         pr "    if (r) {\n";
6524         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6525           test_name;
6526         pr "      return -1;\n";
6527         pr "    }\n"
6528       in
6529       List.iter (generate_test_command_call test_name) seq;
6530       generate_test_command_call ~test test_name last
6531   | TestOutputLength (seq, expected) ->
6532       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6533       let seq, last = get_seq_last seq in
6534       let test () =
6535         pr "    int j;\n";
6536         pr "    for (j = 0; j < %d; ++j)\n" expected;
6537         pr "      if (r[j] == NULL) {\n";
6538         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6539           test_name;
6540         pr "        print_strings (r);\n";
6541         pr "        return -1;\n";
6542         pr "      }\n";
6543         pr "    if (r[j] != NULL) {\n";
6544         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6545           test_name;
6546         pr "      print_strings (r);\n";
6547         pr "      return -1;\n";
6548         pr "    }\n"
6549       in
6550       List.iter (generate_test_command_call test_name) seq;
6551       generate_test_command_call ~test test_name last
6552   | TestOutputBuffer (seq, expected) ->
6553       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6554       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6555       let seq, last = get_seq_last seq in
6556       let len = String.length expected in
6557       let test () =
6558         pr "    if (size != %d) {\n" len;
6559         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6560         pr "      return -1;\n";
6561         pr "    }\n";
6562         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6563         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6564         pr "      return -1;\n";
6565         pr "    }\n"
6566       in
6567       List.iter (generate_test_command_call test_name) seq;
6568       generate_test_command_call ~test test_name last
6569   | TestOutputStruct (seq, checks) ->
6570       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6571       let seq, last = get_seq_last seq in
6572       let test () =
6573         List.iter (
6574           function
6575           | CompareWithInt (field, expected) ->
6576               pr "    if (r->%s != %d) {\n" field expected;
6577               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6578                 test_name field expected;
6579               pr "               (int) r->%s);\n" field;
6580               pr "      return -1;\n";
6581               pr "    }\n"
6582           | CompareWithIntOp (field, op, expected) ->
6583               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6584               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6585                 test_name field op expected;
6586               pr "               (int) r->%s);\n" field;
6587               pr "      return -1;\n";
6588               pr "    }\n"
6589           | CompareWithString (field, expected) ->
6590               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6591               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6592                 test_name field expected;
6593               pr "               r->%s);\n" field;
6594               pr "      return -1;\n";
6595               pr "    }\n"
6596           | CompareFieldsIntEq (field1, field2) ->
6597               pr "    if (r->%s != r->%s) {\n" field1 field2;
6598               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6599                 test_name field1 field2;
6600               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6601               pr "      return -1;\n";
6602               pr "    }\n"
6603           | CompareFieldsStrEq (field1, field2) ->
6604               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6605               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6606                 test_name field1 field2;
6607               pr "               r->%s, r->%s);\n" field1 field2;
6608               pr "      return -1;\n";
6609               pr "    }\n"
6610         ) checks
6611       in
6612       List.iter (generate_test_command_call test_name) seq;
6613       generate_test_command_call ~test test_name last
6614   | TestLastFail seq ->
6615       pr "  /* TestLastFail for %s (%d) */\n" name i;
6616       let seq, last = get_seq_last seq in
6617       List.iter (generate_test_command_call test_name) seq;
6618       generate_test_command_call test_name ~expect_error:true last
6619
6620 (* Generate the code to run a command, leaving the result in 'r'.
6621  * If you expect to get an error then you should set expect_error:true.
6622  *)
6623 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6624   match cmd with
6625   | [] -> assert false
6626   | name :: args ->
6627       (* Look up the command to find out what args/ret it has. *)
6628       let style =
6629         try
6630           let _, style, _, _, _, _, _ =
6631             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6632           style
6633         with Not_found ->
6634           failwithf "%s: in test, command %s was not found" test_name name in
6635
6636       if List.length (snd style) <> List.length args then
6637         failwithf "%s: in test, wrong number of args given to %s"
6638           test_name name;
6639
6640       pr "  {\n";
6641
6642       List.iter (
6643         function
6644         | OptString n, "NULL" -> ()
6645         | Pathname n, arg
6646         | Device n, arg
6647         | Dev_or_Path n, arg
6648         | String n, arg
6649         | OptString n, arg ->
6650             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6651         | Int _, _
6652         | Int64 _, _
6653         | Bool _, _
6654         | FileIn _, _ | FileOut _, _ -> ()
6655         | StringList n, "" | DeviceList n, "" ->
6656             pr "    const char *const %s[1] = { NULL };\n" n
6657         | StringList n, arg | DeviceList n, arg ->
6658             let strs = string_split " " arg in
6659             iteri (
6660               fun i str ->
6661                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6662             ) strs;
6663             pr "    const char *const %s[] = {\n" n;
6664             iteri (
6665               fun i _ -> pr "      %s_%d,\n" n i
6666             ) strs;
6667             pr "      NULL\n";
6668             pr "    };\n";
6669       ) (List.combine (snd style) args);
6670
6671       let error_code =
6672         match fst style with
6673         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6674         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6675         | RConstString _ | RConstOptString _ ->
6676             pr "    const char *r;\n"; "NULL"
6677         | RString _ -> pr "    char *r;\n"; "NULL"
6678         | RStringList _ | RHashtable _ ->
6679             pr "    char **r;\n";
6680             pr "    int i;\n";
6681             "NULL"
6682         | RStruct (_, typ) ->
6683             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6684         | RStructList (_, typ) ->
6685             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6686         | RBufferOut _ ->
6687             pr "    char *r;\n";
6688             pr "    size_t size;\n";
6689             "NULL" in
6690
6691       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6692       pr "    r = guestfs_%s (g" name;
6693
6694       (* Generate the parameters. *)
6695       List.iter (
6696         function
6697         | OptString _, "NULL" -> pr ", NULL"
6698         | Pathname n, _
6699         | Device n, _ | Dev_or_Path n, _
6700         | String n, _
6701         | OptString n, _ ->
6702             pr ", %s" n
6703         | FileIn _, arg | FileOut _, arg ->
6704             pr ", \"%s\"" (c_quote arg)
6705         | StringList n, _ | DeviceList n, _ ->
6706             pr ", (char **) %s" n
6707         | Int _, arg ->
6708             let i =
6709               try int_of_string arg
6710               with Failure "int_of_string" ->
6711                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6712             pr ", %d" i
6713         | Int64 _, arg ->
6714             let i =
6715               try Int64.of_string arg
6716               with Failure "int_of_string" ->
6717                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6718             pr ", %Ld" i
6719         | Bool _, arg ->
6720             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6721       ) (List.combine (snd style) args);
6722
6723       (match fst style with
6724        | RBufferOut _ -> pr ", &size"
6725        | _ -> ()
6726       );
6727
6728       pr ");\n";
6729
6730       if not expect_error then
6731         pr "    if (r == %s)\n" error_code
6732       else
6733         pr "    if (r != %s)\n" error_code;
6734       pr "      return -1;\n";
6735
6736       (* Insert the test code. *)
6737       (match test with
6738        | None -> ()
6739        | Some f -> f ()
6740       );
6741
6742       (match fst style with
6743        | RErr | RInt _ | RInt64 _ | RBool _
6744        | RConstString _ | RConstOptString _ -> ()
6745        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6746        | RStringList _ | RHashtable _ ->
6747            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6748            pr "      free (r[i]);\n";
6749            pr "    free (r);\n"
6750        | RStruct (_, typ) ->
6751            pr "    guestfs_free_%s (r);\n" typ
6752        | RStructList (_, typ) ->
6753            pr "    guestfs_free_%s_list (r);\n" typ
6754       );
6755
6756       pr "  }\n"
6757
6758 and c_quote str =
6759   let str = replace_str str "\r" "\\r" in
6760   let str = replace_str str "\n" "\\n" in
6761   let str = replace_str str "\t" "\\t" in
6762   let str = replace_str str "\000" "\\0" in
6763   str
6764
6765 (* Generate a lot of different functions for guestfish. *)
6766 and generate_fish_cmds () =
6767   generate_header CStyle GPLv2;
6768
6769   let all_functions =
6770     List.filter (
6771       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6772     ) all_functions in
6773   let all_functions_sorted =
6774     List.filter (
6775       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6776     ) all_functions_sorted in
6777
6778   pr "#include <stdio.h>\n";
6779   pr "#include <stdlib.h>\n";
6780   pr "#include <string.h>\n";
6781   pr "#include <inttypes.h>\n";
6782   pr "\n";
6783   pr "#include <guestfs.h>\n";
6784   pr "#include \"c-ctype.h\"\n";
6785   pr "#include \"fish.h\"\n";
6786   pr "\n";
6787
6788   (* list_commands function, which implements guestfish -h *)
6789   pr "void list_commands (void)\n";
6790   pr "{\n";
6791   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6792   pr "  list_builtin_commands ();\n";
6793   List.iter (
6794     fun (name, _, _, flags, _, shortdesc, _) ->
6795       let name = replace_char name '_' '-' in
6796       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6797         name shortdesc
6798   ) all_functions_sorted;
6799   pr "  printf (\"    %%s\\n\",";
6800   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6801   pr "}\n";
6802   pr "\n";
6803
6804   (* display_command function, which implements guestfish -h cmd *)
6805   pr "void display_command (const char *cmd)\n";
6806   pr "{\n";
6807   List.iter (
6808     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6809       let name2 = replace_char name '_' '-' in
6810       let alias =
6811         try find_map (function FishAlias n -> Some n | _ -> None) flags
6812         with Not_found -> name in
6813       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6814       let synopsis =
6815         match snd style with
6816         | [] -> name2
6817         | args ->
6818             sprintf "%s %s"
6819               name2 (String.concat " " (List.map name_of_argt args)) in
6820
6821       let warnings =
6822         if List.mem ProtocolLimitWarning flags then
6823           ("\n\n" ^ protocol_limit_warning)
6824         else "" in
6825
6826       (* For DangerWillRobinson commands, we should probably have
6827        * guestfish prompt before allowing you to use them (especially
6828        * in interactive mode). XXX
6829        *)
6830       let warnings =
6831         warnings ^
6832           if List.mem DangerWillRobinson flags then
6833             ("\n\n" ^ danger_will_robinson)
6834           else "" in
6835
6836       let warnings =
6837         warnings ^
6838           match deprecation_notice flags with
6839           | None -> ""
6840           | Some txt -> "\n\n" ^ txt in
6841
6842       let describe_alias =
6843         if name <> alias then
6844           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6845         else "" in
6846
6847       pr "  if (";
6848       pr "STRCASEEQ (cmd, \"%s\")" name;
6849       if name <> name2 then
6850         pr " || STRCASEEQ (cmd, \"%s\")" name2;
6851       if name <> alias then
6852         pr " || STRCASEEQ (cmd, \"%s\")" alias;
6853       pr ")\n";
6854       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6855         name2 shortdesc
6856         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
6857          "=head1 DESCRIPTION\n\n" ^
6858          longdesc ^ warnings ^ describe_alias);
6859       pr "  else\n"
6860   ) all_functions;
6861   pr "    display_builtin_command (cmd);\n";
6862   pr "}\n";
6863   pr "\n";
6864
6865   let emit_print_list_function typ =
6866     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6867       typ typ typ;
6868     pr "{\n";
6869     pr "  unsigned int i;\n";
6870     pr "\n";
6871     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6872     pr "    printf (\"[%%d] = {\\n\", i);\n";
6873     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6874     pr "    printf (\"}\\n\");\n";
6875     pr "  }\n";
6876     pr "}\n";
6877     pr "\n";
6878   in
6879
6880   (* print_* functions *)
6881   List.iter (
6882     fun (typ, cols) ->
6883       let needs_i =
6884         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6885
6886       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6887       pr "{\n";
6888       if needs_i then (
6889         pr "  unsigned int i;\n";
6890         pr "\n"
6891       );
6892       List.iter (
6893         function
6894         | name, FString ->
6895             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6896         | name, FUUID ->
6897             pr "  printf (\"%%s%s: \", indent);\n" name;
6898             pr "  for (i = 0; i < 32; ++i)\n";
6899             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
6900             pr "  printf (\"\\n\");\n"
6901         | name, FBuffer ->
6902             pr "  printf (\"%%s%s: \", indent);\n" name;
6903             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6904             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6905             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
6906             pr "    else\n";
6907             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
6908             pr "  printf (\"\\n\");\n"
6909         | name, (FUInt64|FBytes) ->
6910             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6911               name typ name
6912         | name, FInt64 ->
6913             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6914               name typ name
6915         | name, FUInt32 ->
6916             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6917               name typ name
6918         | name, FInt32 ->
6919             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6920               name typ name
6921         | name, FChar ->
6922             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6923               name typ name
6924         | name, FOptPercent ->
6925             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6926               typ name name typ name;
6927             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6928       ) cols;
6929       pr "}\n";
6930       pr "\n";
6931   ) structs;
6932
6933   (* Emit a print_TYPE_list function definition only if that function is used. *)
6934   List.iter (
6935     function
6936     | typ, (RStructListOnly | RStructAndList) ->
6937         (* generate the function for typ *)
6938         emit_print_list_function typ
6939     | typ, _ -> () (* empty *)
6940   ) (rstructs_used_by all_functions);
6941
6942   (* Emit a print_TYPE function definition only if that function is used. *)
6943   List.iter (
6944     function
6945     | typ, (RStructOnly | RStructAndList) ->
6946         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6947         pr "{\n";
6948         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6949         pr "}\n";
6950         pr "\n";
6951     | typ, _ -> () (* empty *)
6952   ) (rstructs_used_by all_functions);
6953
6954   (* run_<action> actions *)
6955   List.iter (
6956     fun (name, style, _, flags, _, _, _) ->
6957       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6958       pr "{\n";
6959       (match fst style with
6960        | RErr
6961        | RInt _
6962        | RBool _ -> pr "  int r;\n"
6963        | RInt64 _ -> pr "  int64_t r;\n"
6964        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6965        | RString _ -> pr "  char *r;\n"
6966        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6967        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6968        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6969        | RBufferOut _ ->
6970            pr "  char *r;\n";
6971            pr "  size_t size;\n";
6972       );
6973       List.iter (
6974         function
6975         | Device n
6976         | String n
6977         | OptString n
6978         | FileIn n
6979         | FileOut n -> pr "  const char *%s;\n" n
6980         | Pathname n
6981         | Dev_or_Path n -> pr "  char *%s;\n" n
6982         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6983         | Bool n -> pr "  int %s;\n" n
6984         | Int n -> pr "  int %s;\n" n
6985         | Int64 n -> pr "  int64_t %s;\n" n
6986       ) (snd style);
6987
6988       (* Check and convert parameters. *)
6989       let argc_expected = List.length (snd style) in
6990       pr "  if (argc != %d) {\n" argc_expected;
6991       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6992         argc_expected;
6993       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6994       pr "    return -1;\n";
6995       pr "  }\n";
6996       iteri (
6997         fun i ->
6998           function
6999           | Device name
7000           | String name ->
7001               pr "  %s = argv[%d];\n" name i
7002           | Pathname name
7003           | Dev_or_Path name ->
7004               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7005               pr "  if (%s == NULL) return -1;\n" name
7006           | OptString name ->
7007               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7008                 name i i
7009           | FileIn name ->
7010               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7011                 name i i
7012           | FileOut name ->
7013               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7014                 name i i
7015           | StringList name | DeviceList name ->
7016               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7017               pr "  if (%s == NULL) return -1;\n" name;
7018           | Bool name ->
7019               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7020           | Int name ->
7021               pr "  %s = atoi (argv[%d]);\n" name i
7022           | Int64 name ->
7023               pr "  %s = atoll (argv[%d]);\n" name i
7024       ) (snd style);
7025
7026       (* Call C API function. *)
7027       let fn =
7028         try find_map (function FishAction n -> Some n | _ -> None) flags
7029         with Not_found -> sprintf "guestfs_%s" name in
7030       pr "  r = %s " fn;
7031       generate_c_call_args ~handle:"g" style;
7032       pr ";\n";
7033
7034       List.iter (
7035         function
7036         | Device name | String name
7037         | OptString name | FileIn name | FileOut name | Bool name
7038         | Int name | Int64 name -> ()
7039         | Pathname name | Dev_or_Path name ->
7040             pr "  free (%s);\n" name
7041         | StringList name | DeviceList name ->
7042             pr "  free_strings (%s);\n" name
7043       ) (snd style);
7044
7045       (* Check return value for errors and display command results. *)
7046       (match fst style with
7047        | RErr -> pr "  return r;\n"
7048        | RInt _ ->
7049            pr "  if (r == -1) return -1;\n";
7050            pr "  printf (\"%%d\\n\", r);\n";
7051            pr "  return 0;\n"
7052        | RInt64 _ ->
7053            pr "  if (r == -1) return -1;\n";
7054            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7055            pr "  return 0;\n"
7056        | RBool _ ->
7057            pr "  if (r == -1) return -1;\n";
7058            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7059            pr "  return 0;\n"
7060        | RConstString _ ->
7061            pr "  if (r == NULL) return -1;\n";
7062            pr "  printf (\"%%s\\n\", r);\n";
7063            pr "  return 0;\n"
7064        | RConstOptString _ ->
7065            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7066            pr "  return 0;\n"
7067        | RString _ ->
7068            pr "  if (r == NULL) return -1;\n";
7069            pr "  printf (\"%%s\\n\", r);\n";
7070            pr "  free (r);\n";
7071            pr "  return 0;\n"
7072        | RStringList _ ->
7073            pr "  if (r == NULL) return -1;\n";
7074            pr "  print_strings (r);\n";
7075            pr "  free_strings (r);\n";
7076            pr "  return 0;\n"
7077        | RStruct (_, typ) ->
7078            pr "  if (r == NULL) return -1;\n";
7079            pr "  print_%s (r);\n" typ;
7080            pr "  guestfs_free_%s (r);\n" typ;
7081            pr "  return 0;\n"
7082        | RStructList (_, typ) ->
7083            pr "  if (r == NULL) return -1;\n";
7084            pr "  print_%s_list (r);\n" typ;
7085            pr "  guestfs_free_%s_list (r);\n" typ;
7086            pr "  return 0;\n"
7087        | RHashtable _ ->
7088            pr "  if (r == NULL) return -1;\n";
7089            pr "  print_table (r);\n";
7090            pr "  free_strings (r);\n";
7091            pr "  return 0;\n"
7092        | RBufferOut _ ->
7093            pr "  if (r == NULL) return -1;\n";
7094            pr "  fwrite (r, size, 1, stdout);\n";
7095            pr "  free (r);\n";
7096            pr "  return 0;\n"
7097       );
7098       pr "}\n";
7099       pr "\n"
7100   ) all_functions;
7101
7102   (* run_action function *)
7103   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7104   pr "{\n";
7105   List.iter (
7106     fun (name, _, _, flags, _, _, _) ->
7107       let name2 = replace_char name '_' '-' in
7108       let alias =
7109         try find_map (function FishAlias n -> Some n | _ -> None) flags
7110         with Not_found -> name in
7111       pr "  if (";
7112       pr "STRCASEEQ (cmd, \"%s\")" name;
7113       if name <> name2 then
7114         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7115       if name <> alias then
7116         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7117       pr ")\n";
7118       pr "    return run_%s (cmd, argc, argv);\n" name;
7119       pr "  else\n";
7120   ) all_functions;
7121   pr "    {\n";
7122   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7123   pr "      return -1;\n";
7124   pr "    }\n";
7125   pr "  return 0;\n";
7126   pr "}\n";
7127   pr "\n"
7128
7129 (* Readline completion for guestfish. *)
7130 and generate_fish_completion () =
7131   generate_header CStyle GPLv2;
7132
7133   let all_functions =
7134     List.filter (
7135       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7136     ) all_functions in
7137
7138   pr "\
7139 #include <config.h>
7140
7141 #include <stdio.h>
7142 #include <stdlib.h>
7143 #include <string.h>
7144
7145 #ifdef HAVE_LIBREADLINE
7146 #include <readline/readline.h>
7147 #endif
7148
7149 #include \"fish.h\"
7150
7151 #ifdef HAVE_LIBREADLINE
7152
7153 static const char *const commands[] = {
7154   BUILTIN_COMMANDS_FOR_COMPLETION,
7155 ";
7156
7157   (* Get the commands, including the aliases.  They don't need to be
7158    * sorted - the generator() function just does a dumb linear search.
7159    *)
7160   let commands =
7161     List.map (
7162       fun (name, _, _, flags, _, _, _) ->
7163         let name2 = replace_char name '_' '-' in
7164         let alias =
7165           try find_map (function FishAlias n -> Some n | _ -> None) flags
7166           with Not_found -> name in
7167
7168         if name <> alias then [name2; alias] else [name2]
7169     ) all_functions in
7170   let commands = List.flatten commands in
7171
7172   List.iter (pr "  \"%s\",\n") commands;
7173
7174   pr "  NULL
7175 };
7176
7177 static char *
7178 generator (const char *text, int state)
7179 {
7180   static int index, len;
7181   const char *name;
7182
7183   if (!state) {
7184     index = 0;
7185     len = strlen (text);
7186   }
7187
7188   rl_attempted_completion_over = 1;
7189
7190   while ((name = commands[index]) != NULL) {
7191     index++;
7192     if (STRCASEEQLEN (name, text, len))
7193       return strdup (name);
7194   }
7195
7196   return NULL;
7197 }
7198
7199 #endif /* HAVE_LIBREADLINE */
7200
7201 char **do_completion (const char *text, int start, int end)
7202 {
7203   char **matches = NULL;
7204
7205 #ifdef HAVE_LIBREADLINE
7206   rl_completion_append_character = ' ';
7207
7208   if (start == 0)
7209     matches = rl_completion_matches (text, generator);
7210   else if (complete_dest_paths)
7211     matches = rl_completion_matches (text, complete_dest_paths_generator);
7212 #endif
7213
7214   return matches;
7215 }
7216 ";
7217
7218 (* Generate the POD documentation for guestfish. *)
7219 and generate_fish_actions_pod () =
7220   let all_functions_sorted =
7221     List.filter (
7222       fun (_, _, _, flags, _, _, _) ->
7223         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7224     ) all_functions_sorted in
7225
7226   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7227
7228   List.iter (
7229     fun (name, style, _, flags, _, _, longdesc) ->
7230       let longdesc =
7231         Str.global_substitute rex (
7232           fun s ->
7233             let sub =
7234               try Str.matched_group 1 s
7235               with Not_found ->
7236                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7237             "C<" ^ replace_char sub '_' '-' ^ ">"
7238         ) longdesc in
7239       let name = replace_char name '_' '-' in
7240       let alias =
7241         try find_map (function FishAlias n -> Some n | _ -> None) flags
7242         with Not_found -> name in
7243
7244       pr "=head2 %s" name;
7245       if name <> alias then
7246         pr " | %s" alias;
7247       pr "\n";
7248       pr "\n";
7249       pr " %s" name;
7250       List.iter (
7251         function
7252         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7253         | OptString n -> pr " %s" n
7254         | StringList n | DeviceList n -> pr " '%s ...'" n
7255         | Bool _ -> pr " true|false"
7256         | Int n -> pr " %s" n
7257         | Int64 n -> pr " %s" n
7258         | FileIn n | FileOut n -> pr " (%s|-)" n
7259       ) (snd style);
7260       pr "\n";
7261       pr "\n";
7262       pr "%s\n\n" longdesc;
7263
7264       if List.exists (function FileIn _ | FileOut _ -> true
7265                       | _ -> false) (snd style) then
7266         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7267
7268       if List.mem ProtocolLimitWarning flags then
7269         pr "%s\n\n" protocol_limit_warning;
7270
7271       if List.mem DangerWillRobinson flags then
7272         pr "%s\n\n" danger_will_robinson;
7273
7274       match deprecation_notice flags with
7275       | None -> ()
7276       | Some txt -> pr "%s\n\n" txt
7277   ) all_functions_sorted
7278
7279 (* Generate a C function prototype. *)
7280 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7281     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7282     ?(prefix = "")
7283     ?handle name style =
7284   if extern then pr "extern ";
7285   if static then pr "static ";
7286   (match fst style with
7287    | RErr -> pr "int "
7288    | RInt _ -> pr "int "
7289    | RInt64 _ -> pr "int64_t "
7290    | RBool _ -> pr "int "
7291    | RConstString _ | RConstOptString _ -> pr "const char *"
7292    | RString _ | RBufferOut _ -> pr "char *"
7293    | RStringList _ | RHashtable _ -> pr "char **"
7294    | RStruct (_, typ) ->
7295        if not in_daemon then pr "struct guestfs_%s *" typ
7296        else pr "guestfs_int_%s *" typ
7297    | RStructList (_, typ) ->
7298        if not in_daemon then pr "struct guestfs_%s_list *" typ
7299        else pr "guestfs_int_%s_list *" typ
7300   );
7301   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7302   pr "%s%s (" prefix name;
7303   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7304     pr "void"
7305   else (
7306     let comma = ref false in
7307     (match handle with
7308      | None -> ()
7309      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7310     );
7311     let next () =
7312       if !comma then (
7313         if single_line then pr ", " else pr ",\n\t\t"
7314       );
7315       comma := true
7316     in
7317     List.iter (
7318       function
7319       | Pathname n
7320       | Device n | Dev_or_Path n
7321       | String n
7322       | OptString n ->
7323           next ();
7324           pr "const char *%s" n
7325       | StringList n | DeviceList n ->
7326           next ();
7327           pr "char *const *%s" n
7328       | Bool n -> next (); pr "int %s" n
7329       | Int n -> next (); pr "int %s" n
7330       | Int64 n -> next (); pr "int64_t %s" n
7331       | FileIn n
7332       | FileOut n ->
7333           if not in_daemon then (next (); pr "const char *%s" n)
7334     ) (snd style);
7335     if is_RBufferOut then (next (); pr "size_t *size_r");
7336   );
7337   pr ")";
7338   if semicolon then pr ";";
7339   if newline then pr "\n"
7340
7341 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7342 and generate_c_call_args ?handle ?(decl = false) style =
7343   pr "(";
7344   let comma = ref false in
7345   let next () =
7346     if !comma then pr ", ";
7347     comma := true
7348   in
7349   (match handle with
7350    | None -> ()
7351    | Some handle -> pr "%s" handle; comma := true
7352   );
7353   List.iter (
7354     fun arg ->
7355       next ();
7356       pr "%s" (name_of_argt arg)
7357   ) (snd style);
7358   (* For RBufferOut calls, add implicit &size parameter. *)
7359   if not decl then (
7360     match fst style with
7361     | RBufferOut _ ->
7362         next ();
7363         pr "&size"
7364     | _ -> ()
7365   );
7366   pr ")"
7367
7368 (* Generate the OCaml bindings interface. *)
7369 and generate_ocaml_mli () =
7370   generate_header OCamlStyle LGPLv2;
7371
7372   pr "\
7373 (** For API documentation you should refer to the C API
7374     in the guestfs(3) manual page.  The OCaml API uses almost
7375     exactly the same calls. *)
7376
7377 type t
7378 (** A [guestfs_h] handle. *)
7379
7380 exception Error of string
7381 (** This exception is raised when there is an error. *)
7382
7383 exception Handle_closed of string
7384 (** This exception is raised if you use a {!Guestfs.t} handle
7385     after calling {!close} on it.  The string is the name of
7386     the function. *)
7387
7388 val create : unit -> t
7389 (** Create a {!Guestfs.t} handle. *)
7390
7391 val close : t -> unit
7392 (** Close the {!Guestfs.t} handle and free up all resources used
7393     by it immediately.
7394
7395     Handles are closed by the garbage collector when they become
7396     unreferenced, but callers can call this in order to provide
7397     predictable cleanup. *)
7398
7399 ";
7400   generate_ocaml_structure_decls ();
7401
7402   (* The actions. *)
7403   List.iter (
7404     fun (name, style, _, _, _, shortdesc, _) ->
7405       generate_ocaml_prototype name style;
7406       pr "(** %s *)\n" shortdesc;
7407       pr "\n"
7408   ) all_functions_sorted
7409
7410 (* Generate the OCaml bindings implementation. *)
7411 and generate_ocaml_ml () =
7412   generate_header OCamlStyle LGPLv2;
7413
7414   pr "\
7415 type t
7416
7417 exception Error of string
7418 exception Handle_closed of string
7419
7420 external create : unit -> t = \"ocaml_guestfs_create\"
7421 external close : t -> unit = \"ocaml_guestfs_close\"
7422
7423 (* Give the exceptions names, so they can be raised from the C code. *)
7424 let () =
7425   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7426   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7427
7428 ";
7429
7430   generate_ocaml_structure_decls ();
7431
7432   (* The actions. *)
7433   List.iter (
7434     fun (name, style, _, _, _, shortdesc, _) ->
7435       generate_ocaml_prototype ~is_external:true name style;
7436   ) all_functions_sorted
7437
7438 (* Generate the OCaml bindings C implementation. *)
7439 and generate_ocaml_c () =
7440   generate_header CStyle LGPLv2;
7441
7442   pr "\
7443 #include <stdio.h>
7444 #include <stdlib.h>
7445 #include <string.h>
7446
7447 #include <caml/config.h>
7448 #include <caml/alloc.h>
7449 #include <caml/callback.h>
7450 #include <caml/fail.h>
7451 #include <caml/memory.h>
7452 #include <caml/mlvalues.h>
7453 #include <caml/signals.h>
7454
7455 #include <guestfs.h>
7456
7457 #include \"guestfs_c.h\"
7458
7459 /* Copy a hashtable of string pairs into an assoc-list.  We return
7460  * the list in reverse order, but hashtables aren't supposed to be
7461  * ordered anyway.
7462  */
7463 static CAMLprim value
7464 copy_table (char * const * argv)
7465 {
7466   CAMLparam0 ();
7467   CAMLlocal5 (rv, pairv, kv, vv, cons);
7468   int i;
7469
7470   rv = Val_int (0);
7471   for (i = 0; argv[i] != NULL; i += 2) {
7472     kv = caml_copy_string (argv[i]);
7473     vv = caml_copy_string (argv[i+1]);
7474     pairv = caml_alloc (2, 0);
7475     Store_field (pairv, 0, kv);
7476     Store_field (pairv, 1, vv);
7477     cons = caml_alloc (2, 0);
7478     Store_field (cons, 1, rv);
7479     rv = cons;
7480     Store_field (cons, 0, pairv);
7481   }
7482
7483   CAMLreturn (rv);
7484 }
7485
7486 ";
7487
7488   (* Struct copy functions. *)
7489
7490   let emit_ocaml_copy_list_function typ =
7491     pr "static CAMLprim value\n";
7492     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7493     pr "{\n";
7494     pr "  CAMLparam0 ();\n";
7495     pr "  CAMLlocal2 (rv, v);\n";
7496     pr "  unsigned int i;\n";
7497     pr "\n";
7498     pr "  if (%ss->len == 0)\n" typ;
7499     pr "    CAMLreturn (Atom (0));\n";
7500     pr "  else {\n";
7501     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7502     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7503     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7504     pr "      caml_modify (&Field (rv, i), v);\n";
7505     pr "    }\n";
7506     pr "    CAMLreturn (rv);\n";
7507     pr "  }\n";
7508     pr "}\n";
7509     pr "\n";
7510   in
7511
7512   List.iter (
7513     fun (typ, cols) ->
7514       let has_optpercent_col =
7515         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7516
7517       pr "static CAMLprim value\n";
7518       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7519       pr "{\n";
7520       pr "  CAMLparam0 ();\n";
7521       if has_optpercent_col then
7522         pr "  CAMLlocal3 (rv, v, v2);\n"
7523       else
7524         pr "  CAMLlocal2 (rv, v);\n";
7525       pr "\n";
7526       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7527       iteri (
7528         fun i col ->
7529           (match col with
7530            | name, FString ->
7531                pr "  v = caml_copy_string (%s->%s);\n" typ name
7532            | name, FBuffer ->
7533                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7534                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7535                  typ name typ name
7536            | name, FUUID ->
7537                pr "  v = caml_alloc_string (32);\n";
7538                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7539            | name, (FBytes|FInt64|FUInt64) ->
7540                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7541            | name, (FInt32|FUInt32) ->
7542                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7543            | name, FOptPercent ->
7544                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7545                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7546                pr "    v = caml_alloc (1, 0);\n";
7547                pr "    Store_field (v, 0, v2);\n";
7548                pr "  } else /* None */\n";
7549                pr "    v = Val_int (0);\n";
7550            | name, FChar ->
7551                pr "  v = Val_int (%s->%s);\n" typ name
7552           );
7553           pr "  Store_field (rv, %d, v);\n" i
7554       ) cols;
7555       pr "  CAMLreturn (rv);\n";
7556       pr "}\n";
7557       pr "\n";
7558   ) structs;
7559
7560   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7561   List.iter (
7562     function
7563     | typ, (RStructListOnly | RStructAndList) ->
7564         (* generate the function for typ *)
7565         emit_ocaml_copy_list_function typ
7566     | typ, _ -> () (* empty *)
7567   ) (rstructs_used_by all_functions);
7568
7569   (* The wrappers. *)
7570   List.iter (
7571     fun (name, style, _, _, _, _, _) ->
7572       pr "/* Automatically generated wrapper for function\n";
7573       pr " * ";
7574       generate_ocaml_prototype name style;
7575       pr " */\n";
7576       pr "\n";
7577
7578       let params =
7579         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7580
7581       let needs_extra_vs =
7582         match fst style with RConstOptString _ -> true | _ -> false in
7583
7584       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7585       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7586       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7587       pr "\n";
7588
7589       pr "CAMLprim value\n";
7590       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7591       List.iter (pr ", value %s") (List.tl params);
7592       pr ")\n";
7593       pr "{\n";
7594
7595       (match params with
7596        | [p1; p2; p3; p4; p5] ->
7597            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7598        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7599            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7600            pr "  CAMLxparam%d (%s);\n"
7601              (List.length rest) (String.concat ", " rest)
7602        | ps ->
7603            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7604       );
7605       if not needs_extra_vs then
7606         pr "  CAMLlocal1 (rv);\n"
7607       else
7608         pr "  CAMLlocal3 (rv, v, v2);\n";
7609       pr "\n";
7610
7611       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7612       pr "  if (g == NULL)\n";
7613       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7614       pr "\n";
7615
7616       List.iter (
7617         function
7618         | Pathname n
7619         | Device n | Dev_or_Path n
7620         | String n
7621         | FileIn n
7622         | FileOut n ->
7623             pr "  const char *%s = String_val (%sv);\n" n n
7624         | OptString n ->
7625             pr "  const char *%s =\n" n;
7626             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7627               n n
7628         | StringList n | DeviceList n ->
7629             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7630         | Bool n ->
7631             pr "  int %s = Bool_val (%sv);\n" n n
7632         | Int n ->
7633             pr "  int %s = Int_val (%sv);\n" n n
7634         | Int64 n ->
7635             pr "  int64_t %s = Int64_val (%sv);\n" n n
7636       ) (snd style);
7637       let error_code =
7638         match fst style with
7639         | RErr -> pr "  int r;\n"; "-1"
7640         | RInt _ -> pr "  int r;\n"; "-1"
7641         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7642         | RBool _ -> pr "  int r;\n"; "-1"
7643         | RConstString _ | RConstOptString _ ->
7644             pr "  const char *r;\n"; "NULL"
7645         | RString _ -> pr "  char *r;\n"; "NULL"
7646         | RStringList _ ->
7647             pr "  int i;\n";
7648             pr "  char **r;\n";
7649             "NULL"
7650         | RStruct (_, typ) ->
7651             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7652         | RStructList (_, typ) ->
7653             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7654         | RHashtable _ ->
7655             pr "  int i;\n";
7656             pr "  char **r;\n";
7657             "NULL"
7658         | RBufferOut _ ->
7659             pr "  char *r;\n";
7660             pr "  size_t size;\n";
7661             "NULL" in
7662       pr "\n";
7663
7664       pr "  caml_enter_blocking_section ();\n";
7665       pr "  r = guestfs_%s " name;
7666       generate_c_call_args ~handle:"g" style;
7667       pr ";\n";
7668       pr "  caml_leave_blocking_section ();\n";
7669
7670       List.iter (
7671         function
7672         | StringList n | DeviceList n ->
7673             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7674         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7675         | Bool _ | Int _ | Int64 _
7676         | FileIn _ | FileOut _ -> ()
7677       ) (snd style);
7678
7679       pr "  if (r == %s)\n" error_code;
7680       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7681       pr "\n";
7682
7683       (match fst style with
7684        | RErr -> pr "  rv = Val_unit;\n"
7685        | RInt _ -> pr "  rv = Val_int (r);\n"
7686        | RInt64 _ ->
7687            pr "  rv = caml_copy_int64 (r);\n"
7688        | RBool _ -> pr "  rv = Val_bool (r);\n"
7689        | RConstString _ ->
7690            pr "  rv = caml_copy_string (r);\n"
7691        | RConstOptString _ ->
7692            pr "  if (r) { /* Some string */\n";
7693            pr "    v = caml_alloc (1, 0);\n";
7694            pr "    v2 = caml_copy_string (r);\n";
7695            pr "    Store_field (v, 0, v2);\n";
7696            pr "  } else /* None */\n";
7697            pr "    v = Val_int (0);\n";
7698        | RString _ ->
7699            pr "  rv = caml_copy_string (r);\n";
7700            pr "  free (r);\n"
7701        | RStringList _ ->
7702            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7703            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7704            pr "  free (r);\n"
7705        | RStruct (_, typ) ->
7706            pr "  rv = copy_%s (r);\n" typ;
7707            pr "  guestfs_free_%s (r);\n" typ;
7708        | RStructList (_, typ) ->
7709            pr "  rv = copy_%s_list (r);\n" typ;
7710            pr "  guestfs_free_%s_list (r);\n" typ;
7711        | RHashtable _ ->
7712            pr "  rv = copy_table (r);\n";
7713            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7714            pr "  free (r);\n";
7715        | RBufferOut _ ->
7716            pr "  rv = caml_alloc_string (size);\n";
7717            pr "  memcpy (String_val (rv), r, size);\n";
7718       );
7719
7720       pr "  CAMLreturn (rv);\n";
7721       pr "}\n";
7722       pr "\n";
7723
7724       if List.length params > 5 then (
7725         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7726         pr "CAMLprim value ";
7727         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7728         pr "CAMLprim value\n";
7729         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7730         pr "{\n";
7731         pr "  return ocaml_guestfs_%s (argv[0]" name;
7732         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7733         pr ");\n";
7734         pr "}\n";
7735         pr "\n"
7736       )
7737   ) all_functions_sorted
7738
7739 and generate_ocaml_structure_decls () =
7740   List.iter (
7741     fun (typ, cols) ->
7742       pr "type %s = {\n" typ;
7743       List.iter (
7744         function
7745         | name, FString -> pr "  %s : string;\n" name
7746         | name, FBuffer -> pr "  %s : string;\n" name
7747         | name, FUUID -> pr "  %s : string;\n" name
7748         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7749         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7750         | name, FChar -> pr "  %s : char;\n" name
7751         | name, FOptPercent -> pr "  %s : float option;\n" name
7752       ) cols;
7753       pr "}\n";
7754       pr "\n"
7755   ) structs
7756
7757 and generate_ocaml_prototype ?(is_external = false) name style =
7758   if is_external then pr "external " else pr "val ";
7759   pr "%s : t -> " name;
7760   List.iter (
7761     function
7762     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7763     | OptString _ -> pr "string option -> "
7764     | StringList _ | DeviceList _ -> pr "string array -> "
7765     | Bool _ -> pr "bool -> "
7766     | Int _ -> pr "int -> "
7767     | Int64 _ -> pr "int64 -> "
7768   ) (snd style);
7769   (match fst style with
7770    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7771    | RInt _ -> pr "int"
7772    | RInt64 _ -> pr "int64"
7773    | RBool _ -> pr "bool"
7774    | RConstString _ -> pr "string"
7775    | RConstOptString _ -> pr "string option"
7776    | RString _ | RBufferOut _ -> pr "string"
7777    | RStringList _ -> pr "string array"
7778    | RStruct (_, typ) -> pr "%s" typ
7779    | RStructList (_, typ) -> pr "%s array" typ
7780    | RHashtable _ -> pr "(string * string) list"
7781   );
7782   if is_external then (
7783     pr " = ";
7784     if List.length (snd style) + 1 > 5 then
7785       pr "\"ocaml_guestfs_%s_byte\" " name;
7786     pr "\"ocaml_guestfs_%s\"" name
7787   );
7788   pr "\n"
7789
7790 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7791 and generate_perl_xs () =
7792   generate_header CStyle LGPLv2;
7793
7794   pr "\
7795 #include \"EXTERN.h\"
7796 #include \"perl.h\"
7797 #include \"XSUB.h\"
7798
7799 #include <guestfs.h>
7800
7801 #ifndef PRId64
7802 #define PRId64 \"lld\"
7803 #endif
7804
7805 static SV *
7806 my_newSVll(long long val) {
7807 #ifdef USE_64_BIT_ALL
7808   return newSViv(val);
7809 #else
7810   char buf[100];
7811   int len;
7812   len = snprintf(buf, 100, \"%%\" PRId64, val);
7813   return newSVpv(buf, len);
7814 #endif
7815 }
7816
7817 #ifndef PRIu64
7818 #define PRIu64 \"llu\"
7819 #endif
7820
7821 static SV *
7822 my_newSVull(unsigned long long val) {
7823 #ifdef USE_64_BIT_ALL
7824   return newSVuv(val);
7825 #else
7826   char buf[100];
7827   int len;
7828   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7829   return newSVpv(buf, len);
7830 #endif
7831 }
7832
7833 /* http://www.perlmonks.org/?node_id=680842 */
7834 static char **
7835 XS_unpack_charPtrPtr (SV *arg) {
7836   char **ret;
7837   AV *av;
7838   I32 i;
7839
7840   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7841     croak (\"array reference expected\");
7842
7843   av = (AV *)SvRV (arg);
7844   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7845   if (!ret)
7846     croak (\"malloc failed\");
7847
7848   for (i = 0; i <= av_len (av); i++) {
7849     SV **elem = av_fetch (av, i, 0);
7850
7851     if (!elem || !*elem)
7852       croak (\"missing element in list\");
7853
7854     ret[i] = SvPV_nolen (*elem);
7855   }
7856
7857   ret[i] = NULL;
7858
7859   return ret;
7860 }
7861
7862 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7863
7864 PROTOTYPES: ENABLE
7865
7866 guestfs_h *
7867 _create ()
7868    CODE:
7869       RETVAL = guestfs_create ();
7870       if (!RETVAL)
7871         croak (\"could not create guestfs handle\");
7872       guestfs_set_error_handler (RETVAL, NULL, NULL);
7873  OUTPUT:
7874       RETVAL
7875
7876 void
7877 DESTROY (g)
7878       guestfs_h *g;
7879  PPCODE:
7880       guestfs_close (g);
7881
7882 ";
7883
7884   List.iter (
7885     fun (name, style, _, _, _, _, _) ->
7886       (match fst style with
7887        | RErr -> pr "void\n"
7888        | RInt _ -> pr "SV *\n"
7889        | RInt64 _ -> pr "SV *\n"
7890        | RBool _ -> pr "SV *\n"
7891        | RConstString _ -> pr "SV *\n"
7892        | RConstOptString _ -> pr "SV *\n"
7893        | RString _ -> pr "SV *\n"
7894        | RBufferOut _ -> pr "SV *\n"
7895        | RStringList _
7896        | RStruct _ | RStructList _
7897        | RHashtable _ ->
7898            pr "void\n" (* all lists returned implictly on the stack *)
7899       );
7900       (* Call and arguments. *)
7901       pr "%s " name;
7902       generate_c_call_args ~handle:"g" ~decl:true style;
7903       pr "\n";
7904       pr "      guestfs_h *g;\n";
7905       iteri (
7906         fun i ->
7907           function
7908           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7909               pr "      char *%s;\n" n
7910           | OptString n ->
7911               (* http://www.perlmonks.org/?node_id=554277
7912                * Note that the implicit handle argument means we have
7913                * to add 1 to the ST(x) operator.
7914                *)
7915               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7916           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7917           | Bool n -> pr "      int %s;\n" n
7918           | Int n -> pr "      int %s;\n" n
7919           | Int64 n -> pr "      int64_t %s;\n" n
7920       ) (snd style);
7921
7922       let do_cleanups () =
7923         List.iter (
7924           function
7925           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7926           | Bool _ | Int _ | Int64 _
7927           | FileIn _ | FileOut _ -> ()
7928           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7929         ) (snd style)
7930       in
7931
7932       (* Code. *)
7933       (match fst style with
7934        | RErr ->
7935            pr "PREINIT:\n";
7936            pr "      int r;\n";
7937            pr " PPCODE:\n";
7938            pr "      r = guestfs_%s " name;
7939            generate_c_call_args ~handle:"g" style;
7940            pr ";\n";
7941            do_cleanups ();
7942            pr "      if (r == -1)\n";
7943            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7944        | RInt n
7945        | RBool n ->
7946            pr "PREINIT:\n";
7947            pr "      int %s;\n" n;
7948            pr "   CODE:\n";
7949            pr "      %s = guestfs_%s " n name;
7950            generate_c_call_args ~handle:"g" style;
7951            pr ";\n";
7952            do_cleanups ();
7953            pr "      if (%s == -1)\n" n;
7954            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7955            pr "      RETVAL = newSViv (%s);\n" n;
7956            pr " OUTPUT:\n";
7957            pr "      RETVAL\n"
7958        | RInt64 n ->
7959            pr "PREINIT:\n";
7960            pr "      int64_t %s;\n" n;
7961            pr "   CODE:\n";
7962            pr "      %s = guestfs_%s " n name;
7963            generate_c_call_args ~handle:"g" style;
7964            pr ";\n";
7965            do_cleanups ();
7966            pr "      if (%s == -1)\n" n;
7967            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7968            pr "      RETVAL = my_newSVll (%s);\n" n;
7969            pr " OUTPUT:\n";
7970            pr "      RETVAL\n"
7971        | RConstString n ->
7972            pr "PREINIT:\n";
7973            pr "      const char *%s;\n" n;
7974            pr "   CODE:\n";
7975            pr "      %s = guestfs_%s " n name;
7976            generate_c_call_args ~handle:"g" style;
7977            pr ";\n";
7978            do_cleanups ();
7979            pr "      if (%s == NULL)\n" n;
7980            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7981            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7982            pr " OUTPUT:\n";
7983            pr "      RETVAL\n"
7984        | RConstOptString n ->
7985            pr "PREINIT:\n";
7986            pr "      const char *%s;\n" n;
7987            pr "   CODE:\n";
7988            pr "      %s = guestfs_%s " n name;
7989            generate_c_call_args ~handle:"g" style;
7990            pr ";\n";
7991            do_cleanups ();
7992            pr "      if (%s == NULL)\n" n;
7993            pr "        RETVAL = &PL_sv_undef;\n";
7994            pr "      else\n";
7995            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7996            pr " OUTPUT:\n";
7997            pr "      RETVAL\n"
7998        | RString n ->
7999            pr "PREINIT:\n";
8000            pr "      char *%s;\n" n;
8001            pr "   CODE:\n";
8002            pr "      %s = guestfs_%s " n name;
8003            generate_c_call_args ~handle:"g" style;
8004            pr ";\n";
8005            do_cleanups ();
8006            pr "      if (%s == NULL)\n" n;
8007            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8008            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8009            pr "      free (%s);\n" n;
8010            pr " OUTPUT:\n";
8011            pr "      RETVAL\n"
8012        | RStringList n | RHashtable n ->
8013            pr "PREINIT:\n";
8014            pr "      char **%s;\n" n;
8015            pr "      int i, n;\n";
8016            pr " PPCODE:\n";
8017            pr "      %s = guestfs_%s " n name;
8018            generate_c_call_args ~handle:"g" style;
8019            pr ";\n";
8020            do_cleanups ();
8021            pr "      if (%s == NULL)\n" n;
8022            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8023            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8024            pr "      EXTEND (SP, n);\n";
8025            pr "      for (i = 0; i < n; ++i) {\n";
8026            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8027            pr "        free (%s[i]);\n" n;
8028            pr "      }\n";
8029            pr "      free (%s);\n" n;
8030        | RStruct (n, typ) ->
8031            let cols = cols_of_struct typ in
8032            generate_perl_struct_code typ cols name style n do_cleanups
8033        | RStructList (n, typ) ->
8034            let cols = cols_of_struct typ in
8035            generate_perl_struct_list_code typ cols name style n do_cleanups
8036        | RBufferOut n ->
8037            pr "PREINIT:\n";
8038            pr "      char *%s;\n" n;
8039            pr "      size_t size;\n";
8040            pr "   CODE:\n";
8041            pr "      %s = guestfs_%s " n name;
8042            generate_c_call_args ~handle:"g" style;
8043            pr ";\n";
8044            do_cleanups ();
8045            pr "      if (%s == NULL)\n" n;
8046            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8047            pr "      RETVAL = newSVpv (%s, size);\n" n;
8048            pr "      free (%s);\n" n;
8049            pr " OUTPUT:\n";
8050            pr "      RETVAL\n"
8051       );
8052
8053       pr "\n"
8054   ) all_functions
8055
8056 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8057   pr "PREINIT:\n";
8058   pr "      struct guestfs_%s_list *%s;\n" typ n;
8059   pr "      int i;\n";
8060   pr "      HV *hv;\n";
8061   pr " PPCODE:\n";
8062   pr "      %s = guestfs_%s " n name;
8063   generate_c_call_args ~handle:"g" style;
8064   pr ";\n";
8065   do_cleanups ();
8066   pr "      if (%s == NULL)\n" n;
8067   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8068   pr "      EXTEND (SP, %s->len);\n" n;
8069   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8070   pr "        hv = newHV ();\n";
8071   List.iter (
8072     function
8073     | name, FString ->
8074         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8075           name (String.length name) n name
8076     | name, FUUID ->
8077         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8078           name (String.length name) n name
8079     | name, FBuffer ->
8080         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8081           name (String.length name) n name n name
8082     | name, (FBytes|FUInt64) ->
8083         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8084           name (String.length name) n name
8085     | name, FInt64 ->
8086         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8087           name (String.length name) n name
8088     | name, (FInt32|FUInt32) ->
8089         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8090           name (String.length name) n name
8091     | name, FChar ->
8092         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8093           name (String.length name) n name
8094     | name, FOptPercent ->
8095         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8096           name (String.length name) n name
8097   ) cols;
8098   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8099   pr "      }\n";
8100   pr "      guestfs_free_%s_list (%s);\n" typ n
8101
8102 and generate_perl_struct_code typ cols name style n do_cleanups =
8103   pr "PREINIT:\n";
8104   pr "      struct guestfs_%s *%s;\n" typ n;
8105   pr " PPCODE:\n";
8106   pr "      %s = guestfs_%s " n name;
8107   generate_c_call_args ~handle:"g" style;
8108   pr ";\n";
8109   do_cleanups ();
8110   pr "      if (%s == NULL)\n" n;
8111   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8112   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8113   List.iter (
8114     fun ((name, _) as col) ->
8115       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8116
8117       match col with
8118       | name, FString ->
8119           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8120             n name
8121       | name, FBuffer ->
8122           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8123             n name n name
8124       | name, FUUID ->
8125           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8126             n name
8127       | name, (FBytes|FUInt64) ->
8128           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8129             n name
8130       | name, FInt64 ->
8131           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8132             n name
8133       | name, (FInt32|FUInt32) ->
8134           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8135             n name
8136       | name, FChar ->
8137           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8138             n name
8139       | name, FOptPercent ->
8140           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8141             n name
8142   ) cols;
8143   pr "      free (%s);\n" n
8144
8145 (* Generate Sys/Guestfs.pm. *)
8146 and generate_perl_pm () =
8147   generate_header HashStyle LGPLv2;
8148
8149   pr "\
8150 =pod
8151
8152 =head1 NAME
8153
8154 Sys::Guestfs - Perl bindings for libguestfs
8155
8156 =head1 SYNOPSIS
8157
8158  use Sys::Guestfs;
8159
8160  my $h = Sys::Guestfs->new ();
8161  $h->add_drive ('guest.img');
8162  $h->launch ();
8163  $h->mount ('/dev/sda1', '/');
8164  $h->touch ('/hello');
8165  $h->sync ();
8166
8167 =head1 DESCRIPTION
8168
8169 The C<Sys::Guestfs> module provides a Perl XS binding to the
8170 libguestfs API for examining and modifying virtual machine
8171 disk images.
8172
8173 Amongst the things this is good for: making batch configuration
8174 changes to guests, getting disk used/free statistics (see also:
8175 virt-df), migrating between virtualization systems (see also:
8176 virt-p2v), performing partial backups, performing partial guest
8177 clones, cloning guests and changing registry/UUID/hostname info, and
8178 much else besides.
8179
8180 Libguestfs uses Linux kernel and qemu code, and can access any type of
8181 guest filesystem that Linux and qemu can, including but not limited
8182 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8183 schemes, qcow, qcow2, vmdk.
8184
8185 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8186 LVs, what filesystem is in each LV, etc.).  It can also run commands
8187 in the context of the guest.  Also you can access filesystems over FTP.
8188
8189 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8190 functions for using libguestfs from Perl, including integration
8191 with libvirt.
8192
8193 =head1 ERRORS
8194
8195 All errors turn into calls to C<croak> (see L<Carp(3)>).
8196
8197 =head1 METHODS
8198
8199 =over 4
8200
8201 =cut
8202
8203 package Sys::Guestfs;
8204
8205 use strict;
8206 use warnings;
8207
8208 require XSLoader;
8209 XSLoader::load ('Sys::Guestfs');
8210
8211 =item $h = Sys::Guestfs->new ();
8212
8213 Create a new guestfs handle.
8214
8215 =cut
8216
8217 sub new {
8218   my $proto = shift;
8219   my $class = ref ($proto) || $proto;
8220
8221   my $self = Sys::Guestfs::_create ();
8222   bless $self, $class;
8223   return $self;
8224 }
8225
8226 ";
8227
8228   (* Actions.  We only need to print documentation for these as
8229    * they are pulled in from the XS code automatically.
8230    *)
8231   List.iter (
8232     fun (name, style, _, flags, _, _, longdesc) ->
8233       if not (List.mem NotInDocs flags) then (
8234         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8235         pr "=item ";
8236         generate_perl_prototype name style;
8237         pr "\n\n";
8238         pr "%s\n\n" longdesc;
8239         if List.mem ProtocolLimitWarning flags then
8240           pr "%s\n\n" protocol_limit_warning;
8241         if List.mem DangerWillRobinson flags then
8242           pr "%s\n\n" danger_will_robinson;
8243         match deprecation_notice flags with
8244         | None -> ()
8245         | Some txt -> pr "%s\n\n" txt
8246       )
8247   ) all_functions_sorted;
8248
8249   (* End of file. *)
8250   pr "\
8251 =cut
8252
8253 1;
8254
8255 =back
8256
8257 =head1 COPYRIGHT
8258
8259 Copyright (C) 2009 Red Hat Inc.
8260
8261 =head1 LICENSE
8262
8263 Please see the file COPYING.LIB for the full license.
8264
8265 =head1 SEE ALSO
8266
8267 L<guestfs(3)>,
8268 L<guestfish(1)>,
8269 L<http://libguestfs.org>,
8270 L<Sys::Guestfs::Lib(3)>.
8271
8272 =cut
8273 "
8274
8275 and generate_perl_prototype name style =
8276   (match fst style with
8277    | RErr -> ()
8278    | RBool n
8279    | RInt n
8280    | RInt64 n
8281    | RConstString n
8282    | RConstOptString n
8283    | RString n
8284    | RBufferOut n -> pr "$%s = " n
8285    | RStruct (n,_)
8286    | RHashtable n -> pr "%%%s = " n
8287    | RStringList n
8288    | RStructList (n,_) -> pr "@%s = " n
8289   );
8290   pr "$h->%s (" name;
8291   let comma = ref false in
8292   List.iter (
8293     fun arg ->
8294       if !comma then pr ", ";
8295       comma := true;
8296       match arg with
8297       | Pathname n | Device n | Dev_or_Path n | String n
8298       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8299           pr "$%s" n
8300       | StringList n | DeviceList n ->
8301           pr "\\@%s" n
8302   ) (snd style);
8303   pr ");"
8304
8305 (* Generate Python C module. *)
8306 and generate_python_c () =
8307   generate_header CStyle LGPLv2;
8308
8309   pr "\
8310 #include <Python.h>
8311
8312 #include <stdio.h>
8313 #include <stdlib.h>
8314 #include <assert.h>
8315
8316 #include \"guestfs.h\"
8317
8318 typedef struct {
8319   PyObject_HEAD
8320   guestfs_h *g;
8321 } Pyguestfs_Object;
8322
8323 static guestfs_h *
8324 get_handle (PyObject *obj)
8325 {
8326   assert (obj);
8327   assert (obj != Py_None);
8328   return ((Pyguestfs_Object *) obj)->g;
8329 }
8330
8331 static PyObject *
8332 put_handle (guestfs_h *g)
8333 {
8334   assert (g);
8335   return
8336     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8337 }
8338
8339 /* This list should be freed (but not the strings) after use. */
8340 static char **
8341 get_string_list (PyObject *obj)
8342 {
8343   int i, len;
8344   char **r;
8345
8346   assert (obj);
8347
8348   if (!PyList_Check (obj)) {
8349     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8350     return NULL;
8351   }
8352
8353   len = PyList_Size (obj);
8354   r = malloc (sizeof (char *) * (len+1));
8355   if (r == NULL) {
8356     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8357     return NULL;
8358   }
8359
8360   for (i = 0; i < len; ++i)
8361     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8362   r[len] = NULL;
8363
8364   return r;
8365 }
8366
8367 static PyObject *
8368 put_string_list (char * const * const argv)
8369 {
8370   PyObject *list;
8371   int argc, i;
8372
8373   for (argc = 0; argv[argc] != NULL; ++argc)
8374     ;
8375
8376   list = PyList_New (argc);
8377   for (i = 0; i < argc; ++i)
8378     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8379
8380   return list;
8381 }
8382
8383 static PyObject *
8384 put_table (char * const * const argv)
8385 {
8386   PyObject *list, *item;
8387   int argc, i;
8388
8389   for (argc = 0; argv[argc] != NULL; ++argc)
8390     ;
8391
8392   list = PyList_New (argc >> 1);
8393   for (i = 0; i < argc; i += 2) {
8394     item = PyTuple_New (2);
8395     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8396     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8397     PyList_SetItem (list, i >> 1, item);
8398   }
8399
8400   return list;
8401 }
8402
8403 static void
8404 free_strings (char **argv)
8405 {
8406   int argc;
8407
8408   for (argc = 0; argv[argc] != NULL; ++argc)
8409     free (argv[argc]);
8410   free (argv);
8411 }
8412
8413 static PyObject *
8414 py_guestfs_create (PyObject *self, PyObject *args)
8415 {
8416   guestfs_h *g;
8417
8418   g = guestfs_create ();
8419   if (g == NULL) {
8420     PyErr_SetString (PyExc_RuntimeError,
8421                      \"guestfs.create: failed to allocate handle\");
8422     return NULL;
8423   }
8424   guestfs_set_error_handler (g, NULL, NULL);
8425   return put_handle (g);
8426 }
8427
8428 static PyObject *
8429 py_guestfs_close (PyObject *self, PyObject *args)
8430 {
8431   PyObject *py_g;
8432   guestfs_h *g;
8433
8434   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8435     return NULL;
8436   g = get_handle (py_g);
8437
8438   guestfs_close (g);
8439
8440   Py_INCREF (Py_None);
8441   return Py_None;
8442 }
8443
8444 ";
8445
8446   let emit_put_list_function typ =
8447     pr "static PyObject *\n";
8448     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8449     pr "{\n";
8450     pr "  PyObject *list;\n";
8451     pr "  int i;\n";
8452     pr "\n";
8453     pr "  list = PyList_New (%ss->len);\n" typ;
8454     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8455     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8456     pr "  return list;\n";
8457     pr "};\n";
8458     pr "\n"
8459   in
8460
8461   (* Structures, turned into Python dictionaries. *)
8462   List.iter (
8463     fun (typ, cols) ->
8464       pr "static PyObject *\n";
8465       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8466       pr "{\n";
8467       pr "  PyObject *dict;\n";
8468       pr "\n";
8469       pr "  dict = PyDict_New ();\n";
8470       List.iter (
8471         function
8472         | name, FString ->
8473             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8474             pr "                        PyString_FromString (%s->%s));\n"
8475               typ name
8476         | name, FBuffer ->
8477             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8478             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8479               typ name typ name
8480         | name, FUUID ->
8481             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8482             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8483               typ name
8484         | name, (FBytes|FUInt64) ->
8485             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8486             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8487               typ name
8488         | name, FInt64 ->
8489             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8490             pr "                        PyLong_FromLongLong (%s->%s));\n"
8491               typ name
8492         | name, FUInt32 ->
8493             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8494             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8495               typ name
8496         | name, FInt32 ->
8497             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8498             pr "                        PyLong_FromLong (%s->%s));\n"
8499               typ name
8500         | name, FOptPercent ->
8501             pr "  if (%s->%s >= 0)\n" typ name;
8502             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8503             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8504               typ name;
8505             pr "  else {\n";
8506             pr "    Py_INCREF (Py_None);\n";
8507             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8508             pr "  }\n"
8509         | name, FChar ->
8510             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8511             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8512       ) cols;
8513       pr "  return dict;\n";
8514       pr "};\n";
8515       pr "\n";
8516
8517   ) structs;
8518
8519   (* Emit a put_TYPE_list function definition only if that function is used. *)
8520   List.iter (
8521     function
8522     | typ, (RStructListOnly | RStructAndList) ->
8523         (* generate the function for typ *)
8524         emit_put_list_function typ
8525     | typ, _ -> () (* empty *)
8526   ) (rstructs_used_by all_functions);
8527
8528   (* Python wrapper functions. *)
8529   List.iter (
8530     fun (name, style, _, _, _, _, _) ->
8531       pr "static PyObject *\n";
8532       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8533       pr "{\n";
8534
8535       pr "  PyObject *py_g;\n";
8536       pr "  guestfs_h *g;\n";
8537       pr "  PyObject *py_r;\n";
8538
8539       let error_code =
8540         match fst style with
8541         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8542         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8543         | RConstString _ | RConstOptString _ ->
8544             pr "  const char *r;\n"; "NULL"
8545         | RString _ -> pr "  char *r;\n"; "NULL"
8546         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8547         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8548         | RStructList (_, typ) ->
8549             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8550         | RBufferOut _ ->
8551             pr "  char *r;\n";
8552             pr "  size_t size;\n";
8553             "NULL" in
8554
8555       List.iter (
8556         function
8557         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8558             pr "  const char *%s;\n" n
8559         | OptString n -> pr "  const char *%s;\n" n
8560         | StringList n | DeviceList n ->
8561             pr "  PyObject *py_%s;\n" n;
8562             pr "  char **%s;\n" n
8563         | Bool n -> pr "  int %s;\n" n
8564         | Int n -> pr "  int %s;\n" n
8565         | Int64 n -> pr "  long long %s;\n" n
8566       ) (snd style);
8567
8568       pr "\n";
8569
8570       (* Convert the parameters. *)
8571       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8572       List.iter (
8573         function
8574         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8575         | OptString _ -> pr "z"
8576         | StringList _ | DeviceList _ -> pr "O"
8577         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8578         | Int _ -> pr "i"
8579         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8580                              * emulate C's int/long/long long in Python?
8581                              *)
8582       ) (snd style);
8583       pr ":guestfs_%s\",\n" name;
8584       pr "                         &py_g";
8585       List.iter (
8586         function
8587         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8588         | OptString n -> pr ", &%s" n
8589         | StringList n | DeviceList n -> pr ", &py_%s" n
8590         | Bool n -> pr ", &%s" n
8591         | Int n -> pr ", &%s" n
8592         | Int64 n -> pr ", &%s" n
8593       ) (snd style);
8594
8595       pr "))\n";
8596       pr "    return NULL;\n";
8597
8598       pr "  g = get_handle (py_g);\n";
8599       List.iter (
8600         function
8601         | Pathname _ | Device _ | Dev_or_Path _ | String _
8602         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8603         | StringList n | DeviceList n ->
8604             pr "  %s = get_string_list (py_%s);\n" n n;
8605             pr "  if (!%s) return NULL;\n" n
8606       ) (snd style);
8607
8608       pr "\n";
8609
8610       pr "  r = guestfs_%s " name;
8611       generate_c_call_args ~handle:"g" style;
8612       pr ";\n";
8613
8614       List.iter (
8615         function
8616         | Pathname _ | Device _ | Dev_or_Path _ | String _
8617         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8618         | StringList n | DeviceList n ->
8619             pr "  free (%s);\n" n
8620       ) (snd style);
8621
8622       pr "  if (r == %s) {\n" error_code;
8623       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8624       pr "    return NULL;\n";
8625       pr "  }\n";
8626       pr "\n";
8627
8628       (match fst style with
8629        | RErr ->
8630            pr "  Py_INCREF (Py_None);\n";
8631            pr "  py_r = Py_None;\n"
8632        | RInt _
8633        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8634        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8635        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8636        | RConstOptString _ ->
8637            pr "  if (r)\n";
8638            pr "    py_r = PyString_FromString (r);\n";
8639            pr "  else {\n";
8640            pr "    Py_INCREF (Py_None);\n";
8641            pr "    py_r = Py_None;\n";
8642            pr "  }\n"
8643        | RString _ ->
8644            pr "  py_r = PyString_FromString (r);\n";
8645            pr "  free (r);\n"
8646        | RStringList _ ->
8647            pr "  py_r = put_string_list (r);\n";
8648            pr "  free_strings (r);\n"
8649        | RStruct (_, typ) ->
8650            pr "  py_r = put_%s (r);\n" typ;
8651            pr "  guestfs_free_%s (r);\n" typ
8652        | RStructList (_, typ) ->
8653            pr "  py_r = put_%s_list (r);\n" typ;
8654            pr "  guestfs_free_%s_list (r);\n" typ
8655        | RHashtable n ->
8656            pr "  py_r = put_table (r);\n";
8657            pr "  free_strings (r);\n"
8658        | RBufferOut _ ->
8659            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8660            pr "  free (r);\n"
8661       );
8662
8663       pr "  return py_r;\n";
8664       pr "}\n";
8665       pr "\n"
8666   ) all_functions;
8667
8668   (* Table of functions. *)
8669   pr "static PyMethodDef methods[] = {\n";
8670   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8671   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8672   List.iter (
8673     fun (name, _, _, _, _, _, _) ->
8674       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8675         name name
8676   ) all_functions;
8677   pr "  { NULL, NULL, 0, NULL }\n";
8678   pr "};\n";
8679   pr "\n";
8680
8681   (* Init function. *)
8682   pr "\
8683 void
8684 initlibguestfsmod (void)
8685 {
8686   static int initialized = 0;
8687
8688   if (initialized) return;
8689   Py_InitModule ((char *) \"libguestfsmod\", methods);
8690   initialized = 1;
8691 }
8692 "
8693
8694 (* Generate Python module. *)
8695 and generate_python_py () =
8696   generate_header HashStyle LGPLv2;
8697
8698   pr "\
8699 u\"\"\"Python bindings for libguestfs
8700
8701 import guestfs
8702 g = guestfs.GuestFS ()
8703 g.add_drive (\"guest.img\")
8704 g.launch ()
8705 parts = g.list_partitions ()
8706
8707 The guestfs module provides a Python binding to the libguestfs API
8708 for examining and modifying virtual machine disk images.
8709
8710 Amongst the things this is good for: making batch configuration
8711 changes to guests, getting disk used/free statistics (see also:
8712 virt-df), migrating between virtualization systems (see also:
8713 virt-p2v), performing partial backups, performing partial guest
8714 clones, cloning guests and changing registry/UUID/hostname info, and
8715 much else besides.
8716
8717 Libguestfs uses Linux kernel and qemu code, and can access any type of
8718 guest filesystem that Linux and qemu can, including but not limited
8719 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8720 schemes, qcow, qcow2, vmdk.
8721
8722 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8723 LVs, what filesystem is in each LV, etc.).  It can also run commands
8724 in the context of the guest.  Also you can access filesystems over FTP.
8725
8726 Errors which happen while using the API are turned into Python
8727 RuntimeError exceptions.
8728
8729 To create a guestfs handle you usually have to perform the following
8730 sequence of calls:
8731
8732 # Create the handle, call add_drive at least once, and possibly
8733 # several times if the guest has multiple block devices:
8734 g = guestfs.GuestFS ()
8735 g.add_drive (\"guest.img\")
8736
8737 # Launch the qemu subprocess and wait for it to become ready:
8738 g.launch ()
8739
8740 # Now you can issue commands, for example:
8741 logvols = g.lvs ()
8742
8743 \"\"\"
8744
8745 import libguestfsmod
8746
8747 class GuestFS:
8748     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8749
8750     def __init__ (self):
8751         \"\"\"Create a new libguestfs handle.\"\"\"
8752         self._o = libguestfsmod.create ()
8753
8754     def __del__ (self):
8755         libguestfsmod.close (self._o)
8756
8757 ";
8758
8759   List.iter (
8760     fun (name, style, _, flags, _, _, longdesc) ->
8761       pr "    def %s " name;
8762       generate_py_call_args ~handle:"self" (snd style);
8763       pr ":\n";
8764
8765       if not (List.mem NotInDocs flags) then (
8766         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8767         let doc =
8768           match fst style with
8769           | RErr | RInt _ | RInt64 _ | RBool _
8770           | RConstOptString _ | RConstString _
8771           | RString _ | RBufferOut _ -> doc
8772           | RStringList _ ->
8773               doc ^ "\n\nThis function returns a list of strings."
8774           | RStruct (_, typ) ->
8775               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8776           | RStructList (_, typ) ->
8777               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8778           | RHashtable _ ->
8779               doc ^ "\n\nThis function returns a dictionary." in
8780         let doc =
8781           if List.mem ProtocolLimitWarning flags then
8782             doc ^ "\n\n" ^ protocol_limit_warning
8783           else doc in
8784         let doc =
8785           if List.mem DangerWillRobinson flags then
8786             doc ^ "\n\n" ^ danger_will_robinson
8787           else doc in
8788         let doc =
8789           match deprecation_notice flags with
8790           | None -> doc
8791           | Some txt -> doc ^ "\n\n" ^ txt in
8792         let doc = pod2text ~width:60 name doc in
8793         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8794         let doc = String.concat "\n        " doc in
8795         pr "        u\"\"\"%s\"\"\"\n" doc;
8796       );
8797       pr "        return libguestfsmod.%s " name;
8798       generate_py_call_args ~handle:"self._o" (snd style);
8799       pr "\n";
8800       pr "\n";
8801   ) all_functions
8802
8803 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8804 and generate_py_call_args ~handle args =
8805   pr "(%s" handle;
8806   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8807   pr ")"
8808
8809 (* Useful if you need the longdesc POD text as plain text.  Returns a
8810  * list of lines.
8811  *
8812  * Because this is very slow (the slowest part of autogeneration),
8813  * we memoize the results.
8814  *)
8815 and pod2text ~width name longdesc =
8816   let key = width, name, longdesc in
8817   try Hashtbl.find pod2text_memo key
8818   with Not_found ->
8819     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8820     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8821     close_out chan;
8822     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8823     let chan = open_process_in cmd in
8824     let lines = ref [] in
8825     let rec loop i =
8826       let line = input_line chan in
8827       if i = 1 then             (* discard the first line of output *)
8828         loop (i+1)
8829       else (
8830         let line = triml line in
8831         lines := line :: !lines;
8832         loop (i+1)
8833       ) in
8834     let lines = try loop 1 with End_of_file -> List.rev !lines in
8835     unlink filename;
8836     (match close_process_in chan with
8837      | WEXITED 0 -> ()
8838      | WEXITED i ->
8839          failwithf "pod2text: process exited with non-zero status (%d)" i
8840      | WSIGNALED i | WSTOPPED i ->
8841          failwithf "pod2text: process signalled or stopped by signal %d" i
8842     );
8843     Hashtbl.add pod2text_memo key lines;
8844     pod2text_memo_updated ();
8845     lines
8846
8847 (* Generate ruby bindings. *)
8848 and generate_ruby_c () =
8849   generate_header CStyle LGPLv2;
8850
8851   pr "\
8852 #include <stdio.h>
8853 #include <stdlib.h>
8854
8855 #include <ruby.h>
8856
8857 #include \"guestfs.h\"
8858
8859 #include \"extconf.h\"
8860
8861 /* For Ruby < 1.9 */
8862 #ifndef RARRAY_LEN
8863 #define RARRAY_LEN(r) (RARRAY((r))->len)
8864 #endif
8865
8866 static VALUE m_guestfs;                 /* guestfs module */
8867 static VALUE c_guestfs;                 /* guestfs_h handle */
8868 static VALUE e_Error;                   /* used for all errors */
8869
8870 static void ruby_guestfs_free (void *p)
8871 {
8872   if (!p) return;
8873   guestfs_close ((guestfs_h *) p);
8874 }
8875
8876 static VALUE ruby_guestfs_create (VALUE m)
8877 {
8878   guestfs_h *g;
8879
8880   g = guestfs_create ();
8881   if (!g)
8882     rb_raise (e_Error, \"failed to create guestfs handle\");
8883
8884   /* Don't print error messages to stderr by default. */
8885   guestfs_set_error_handler (g, NULL, NULL);
8886
8887   /* Wrap it, and make sure the close function is called when the
8888    * handle goes away.
8889    */
8890   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8891 }
8892
8893 static VALUE ruby_guestfs_close (VALUE gv)
8894 {
8895   guestfs_h *g;
8896   Data_Get_Struct (gv, guestfs_h, g);
8897
8898   ruby_guestfs_free (g);
8899   DATA_PTR (gv) = NULL;
8900
8901   return Qnil;
8902 }
8903
8904 ";
8905
8906   List.iter (
8907     fun (name, style, _, _, _, _, _) ->
8908       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8909       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8910       pr ")\n";
8911       pr "{\n";
8912       pr "  guestfs_h *g;\n";
8913       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8914       pr "  if (!g)\n";
8915       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8916         name;
8917       pr "\n";
8918
8919       List.iter (
8920         function
8921         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8922             pr "  Check_Type (%sv, T_STRING);\n" n;
8923             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8924             pr "  if (!%s)\n" n;
8925             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8926             pr "              \"%s\", \"%s\");\n" n name
8927         | OptString n ->
8928             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8929         | StringList n | DeviceList n ->
8930             pr "  char **%s;\n" n;
8931             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8932             pr "  {\n";
8933             pr "    int i, len;\n";
8934             pr "    len = RARRAY_LEN (%sv);\n" n;
8935             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8936               n;
8937             pr "    for (i = 0; i < len; ++i) {\n";
8938             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8939             pr "      %s[i] = StringValueCStr (v);\n" n;
8940             pr "    }\n";
8941             pr "    %s[len] = NULL;\n" n;
8942             pr "  }\n";
8943         | Bool n ->
8944             pr "  int %s = RTEST (%sv);\n" n n
8945         | Int n ->
8946             pr "  int %s = NUM2INT (%sv);\n" n n
8947         | Int64 n ->
8948             pr "  long long %s = NUM2LL (%sv);\n" n n
8949       ) (snd style);
8950       pr "\n";
8951
8952       let error_code =
8953         match fst style with
8954         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8955         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8956         | RConstString _ | RConstOptString _ ->
8957             pr "  const char *r;\n"; "NULL"
8958         | RString _ -> pr "  char *r;\n"; "NULL"
8959         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8960         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8961         | RStructList (_, typ) ->
8962             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8963         | RBufferOut _ ->
8964             pr "  char *r;\n";
8965             pr "  size_t size;\n";
8966             "NULL" in
8967       pr "\n";
8968
8969       pr "  r = guestfs_%s " name;
8970       generate_c_call_args ~handle:"g" style;
8971       pr ";\n";
8972
8973       List.iter (
8974         function
8975         | Pathname _ | Device _ | Dev_or_Path _ | String _
8976         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8977         | StringList n | DeviceList n ->
8978             pr "  free (%s);\n" n
8979       ) (snd style);
8980
8981       pr "  if (r == %s)\n" error_code;
8982       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8983       pr "\n";
8984
8985       (match fst style with
8986        | RErr ->
8987            pr "  return Qnil;\n"
8988        | RInt _ | RBool _ ->
8989            pr "  return INT2NUM (r);\n"
8990        | RInt64 _ ->
8991            pr "  return ULL2NUM (r);\n"
8992        | RConstString _ ->
8993            pr "  return rb_str_new2 (r);\n";
8994        | RConstOptString _ ->
8995            pr "  if (r)\n";
8996            pr "    return rb_str_new2 (r);\n";
8997            pr "  else\n";
8998            pr "    return Qnil;\n";
8999        | RString _ ->
9000            pr "  VALUE rv = rb_str_new2 (r);\n";
9001            pr "  free (r);\n";
9002            pr "  return rv;\n";
9003        | RStringList _ ->
9004            pr "  int i, len = 0;\n";
9005            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9006            pr "  VALUE rv = rb_ary_new2 (len);\n";
9007            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9008            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9009            pr "    free (r[i]);\n";
9010            pr "  }\n";
9011            pr "  free (r);\n";
9012            pr "  return rv;\n"
9013        | RStruct (_, typ) ->
9014            let cols = cols_of_struct typ in
9015            generate_ruby_struct_code typ cols
9016        | RStructList (_, typ) ->
9017            let cols = cols_of_struct typ in
9018            generate_ruby_struct_list_code typ cols
9019        | RHashtable _ ->
9020            pr "  VALUE rv = rb_hash_new ();\n";
9021            pr "  int i;\n";
9022            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9023            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9024            pr "    free (r[i]);\n";
9025            pr "    free (r[i+1]);\n";
9026            pr "  }\n";
9027            pr "  free (r);\n";
9028            pr "  return rv;\n"
9029        | RBufferOut _ ->
9030            pr "  VALUE rv = rb_str_new (r, size);\n";
9031            pr "  free (r);\n";
9032            pr "  return rv;\n";
9033       );
9034
9035       pr "}\n";
9036       pr "\n"
9037   ) all_functions;
9038
9039   pr "\
9040 /* Initialize the module. */
9041 void Init__guestfs ()
9042 {
9043   m_guestfs = rb_define_module (\"Guestfs\");
9044   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9045   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9046
9047   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9048   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9049
9050 ";
9051   (* Define the rest of the methods. *)
9052   List.iter (
9053     fun (name, style, _, _, _, _, _) ->
9054       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9055       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9056   ) all_functions;
9057
9058   pr "}\n"
9059
9060 (* Ruby code to return a struct. *)
9061 and generate_ruby_struct_code typ cols =
9062   pr "  VALUE rv = rb_hash_new ();\n";
9063   List.iter (
9064     function
9065     | name, FString ->
9066         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9067     | name, FBuffer ->
9068         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9069     | name, FUUID ->
9070         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9071     | name, (FBytes|FUInt64) ->
9072         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9073     | name, FInt64 ->
9074         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9075     | name, FUInt32 ->
9076         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9077     | name, FInt32 ->
9078         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9079     | name, FOptPercent ->
9080         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9081     | name, FChar -> (* XXX wrong? *)
9082         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9083   ) cols;
9084   pr "  guestfs_free_%s (r);\n" typ;
9085   pr "  return rv;\n"
9086
9087 (* Ruby code to return a struct list. *)
9088 and generate_ruby_struct_list_code typ cols =
9089   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9090   pr "  int i;\n";
9091   pr "  for (i = 0; i < r->len; ++i) {\n";
9092   pr "    VALUE hv = rb_hash_new ();\n";
9093   List.iter (
9094     function
9095     | name, FString ->
9096         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9097     | name, FBuffer ->
9098         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
9099     | name, FUUID ->
9100         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9101     | name, (FBytes|FUInt64) ->
9102         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9103     | name, FInt64 ->
9104         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9105     | name, FUInt32 ->
9106         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9107     | name, FInt32 ->
9108         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9109     | name, FOptPercent ->
9110         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9111     | name, FChar -> (* XXX wrong? *)
9112         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9113   ) cols;
9114   pr "    rb_ary_push (rv, hv);\n";
9115   pr "  }\n";
9116   pr "  guestfs_free_%s_list (r);\n" typ;
9117   pr "  return rv;\n"
9118
9119 (* Generate Java bindings GuestFS.java file. *)
9120 and generate_java_java () =
9121   generate_header CStyle LGPLv2;
9122
9123   pr "\
9124 package com.redhat.et.libguestfs;
9125
9126 import java.util.HashMap;
9127 import com.redhat.et.libguestfs.LibGuestFSException;
9128 import com.redhat.et.libguestfs.PV;
9129 import com.redhat.et.libguestfs.VG;
9130 import com.redhat.et.libguestfs.LV;
9131 import com.redhat.et.libguestfs.Stat;
9132 import com.redhat.et.libguestfs.StatVFS;
9133 import com.redhat.et.libguestfs.IntBool;
9134 import com.redhat.et.libguestfs.Dirent;
9135
9136 /**
9137  * The GuestFS object is a libguestfs handle.
9138  *
9139  * @author rjones
9140  */
9141 public class GuestFS {
9142   // Load the native code.
9143   static {
9144     System.loadLibrary (\"guestfs_jni\");
9145   }
9146
9147   /**
9148    * The native guestfs_h pointer.
9149    */
9150   long g;
9151
9152   /**
9153    * Create a libguestfs handle.
9154    *
9155    * @throws LibGuestFSException
9156    */
9157   public GuestFS () throws LibGuestFSException
9158   {
9159     g = _create ();
9160   }
9161   private native long _create () throws LibGuestFSException;
9162
9163   /**
9164    * Close a libguestfs handle.
9165    *
9166    * You can also leave handles to be collected by the garbage
9167    * collector, but this method ensures that the resources used
9168    * by the handle are freed up immediately.  If you call any
9169    * other methods after closing the handle, you will get an
9170    * exception.
9171    *
9172    * @throws LibGuestFSException
9173    */
9174   public void close () throws LibGuestFSException
9175   {
9176     if (g != 0)
9177       _close (g);
9178     g = 0;
9179   }
9180   private native void _close (long g) throws LibGuestFSException;
9181
9182   public void finalize () throws LibGuestFSException
9183   {
9184     close ();
9185   }
9186
9187 ";
9188
9189   List.iter (
9190     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9191       if not (List.mem NotInDocs flags); then (
9192         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9193         let doc =
9194           if List.mem ProtocolLimitWarning flags then
9195             doc ^ "\n\n" ^ protocol_limit_warning
9196           else doc in
9197         let doc =
9198           if List.mem DangerWillRobinson flags then
9199             doc ^ "\n\n" ^ danger_will_robinson
9200           else doc in
9201         let doc =
9202           match deprecation_notice flags with
9203           | None -> doc
9204           | Some txt -> doc ^ "\n\n" ^ txt in
9205         let doc = pod2text ~width:60 name doc in
9206         let doc = List.map (            (* RHBZ#501883 *)
9207           function
9208           | "" -> "<p>"
9209           | nonempty -> nonempty
9210         ) doc in
9211         let doc = String.concat "\n   * " doc in
9212
9213         pr "  /**\n";
9214         pr "   * %s\n" shortdesc;
9215         pr "   * <p>\n";
9216         pr "   * %s\n" doc;
9217         pr "   * @throws LibGuestFSException\n";
9218         pr "   */\n";
9219         pr "  ";
9220       );
9221       generate_java_prototype ~public:true ~semicolon:false name style;
9222       pr "\n";
9223       pr "  {\n";
9224       pr "    if (g == 0)\n";
9225       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9226         name;
9227       pr "    ";
9228       if fst style <> RErr then pr "return ";
9229       pr "_%s " name;
9230       generate_java_call_args ~handle:"g" (snd style);
9231       pr ";\n";
9232       pr "  }\n";
9233       pr "  ";
9234       generate_java_prototype ~privat:true ~native:true name style;
9235       pr "\n";
9236       pr "\n";
9237   ) all_functions;
9238
9239   pr "}\n"
9240
9241 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9242 and generate_java_call_args ~handle args =
9243   pr "(%s" handle;
9244   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9245   pr ")"
9246
9247 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9248     ?(semicolon=true) name style =
9249   if privat then pr "private ";
9250   if public then pr "public ";
9251   if native then pr "native ";
9252
9253   (* return type *)
9254   (match fst style with
9255    | RErr -> pr "void ";
9256    | RInt _ -> pr "int ";
9257    | RInt64 _ -> pr "long ";
9258    | RBool _ -> pr "boolean ";
9259    | RConstString _ | RConstOptString _ | RString _
9260    | RBufferOut _ -> pr "String ";
9261    | RStringList _ -> pr "String[] ";
9262    | RStruct (_, typ) ->
9263        let name = java_name_of_struct typ in
9264        pr "%s " name;
9265    | RStructList (_, typ) ->
9266        let name = java_name_of_struct typ in
9267        pr "%s[] " name;
9268    | RHashtable _ -> pr "HashMap<String,String> ";
9269   );
9270
9271   if native then pr "_%s " name else pr "%s " name;
9272   pr "(";
9273   let needs_comma = ref false in
9274   if native then (
9275     pr "long g";
9276     needs_comma := true
9277   );
9278
9279   (* args *)
9280   List.iter (
9281     fun arg ->
9282       if !needs_comma then pr ", ";
9283       needs_comma := true;
9284
9285       match arg with
9286       | Pathname n
9287       | Device n | Dev_or_Path n
9288       | String n
9289       | OptString n
9290       | FileIn n
9291       | FileOut n ->
9292           pr "String %s" n
9293       | StringList n | DeviceList n ->
9294           pr "String[] %s" n
9295       | Bool n ->
9296           pr "boolean %s" n
9297       | Int n ->
9298           pr "int %s" n
9299       | Int64 n ->
9300           pr "long %s" n
9301   ) (snd style);
9302
9303   pr ")\n";
9304   pr "    throws LibGuestFSException";
9305   if semicolon then pr ";"
9306
9307 and generate_java_struct jtyp cols =
9308   generate_header CStyle LGPLv2;
9309
9310   pr "\
9311 package com.redhat.et.libguestfs;
9312
9313 /**
9314  * Libguestfs %s structure.
9315  *
9316  * @author rjones
9317  * @see GuestFS
9318  */
9319 public class %s {
9320 " jtyp jtyp;
9321
9322   List.iter (
9323     function
9324     | name, FString
9325     | name, FUUID
9326     | name, FBuffer -> pr "  public String %s;\n" name
9327     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9328     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9329     | name, FChar -> pr "  public char %s;\n" name
9330     | name, FOptPercent ->
9331         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9332         pr "  public float %s;\n" name
9333   ) cols;
9334
9335   pr "}\n"
9336
9337 and generate_java_c () =
9338   generate_header CStyle LGPLv2;
9339
9340   pr "\
9341 #include <stdio.h>
9342 #include <stdlib.h>
9343 #include <string.h>
9344
9345 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9346 #include \"guestfs.h\"
9347
9348 /* Note that this function returns.  The exception is not thrown
9349  * until after the wrapper function returns.
9350  */
9351 static void
9352 throw_exception (JNIEnv *env, const char *msg)
9353 {
9354   jclass cl;
9355   cl = (*env)->FindClass (env,
9356                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9357   (*env)->ThrowNew (env, cl, msg);
9358 }
9359
9360 JNIEXPORT jlong JNICALL
9361 Java_com_redhat_et_libguestfs_GuestFS__1create
9362   (JNIEnv *env, jobject obj)
9363 {
9364   guestfs_h *g;
9365
9366   g = guestfs_create ();
9367   if (g == NULL) {
9368     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9369     return 0;
9370   }
9371   guestfs_set_error_handler (g, NULL, NULL);
9372   return (jlong) (long) g;
9373 }
9374
9375 JNIEXPORT void JNICALL
9376 Java_com_redhat_et_libguestfs_GuestFS__1close
9377   (JNIEnv *env, jobject obj, jlong jg)
9378 {
9379   guestfs_h *g = (guestfs_h *) (long) jg;
9380   guestfs_close (g);
9381 }
9382
9383 ";
9384
9385   List.iter (
9386     fun (name, style, _, _, _, _, _) ->
9387       pr "JNIEXPORT ";
9388       (match fst style with
9389        | RErr -> pr "void ";
9390        | RInt _ -> pr "jint ";
9391        | RInt64 _ -> pr "jlong ";
9392        | RBool _ -> pr "jboolean ";
9393        | RConstString _ | RConstOptString _ | RString _
9394        | RBufferOut _ -> pr "jstring ";
9395        | RStruct _ | RHashtable _ ->
9396            pr "jobject ";
9397        | RStringList _ | RStructList _ ->
9398            pr "jobjectArray ";
9399       );
9400       pr "JNICALL\n";
9401       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9402       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9403       pr "\n";
9404       pr "  (JNIEnv *env, jobject obj, jlong jg";
9405       List.iter (
9406         function
9407         | Pathname n
9408         | Device n | Dev_or_Path n
9409         | String n
9410         | OptString n
9411         | FileIn n
9412         | FileOut n ->
9413             pr ", jstring j%s" n
9414         | StringList n | DeviceList n ->
9415             pr ", jobjectArray j%s" n
9416         | Bool n ->
9417             pr ", jboolean j%s" n
9418         | Int n ->
9419             pr ", jint j%s" n
9420         | Int64 n ->
9421             pr ", jlong j%s" n
9422       ) (snd style);
9423       pr ")\n";
9424       pr "{\n";
9425       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9426       let error_code, no_ret =
9427         match fst style with
9428         | RErr -> pr "  int r;\n"; "-1", ""
9429         | RBool _
9430         | RInt _ -> pr "  int r;\n"; "-1", "0"
9431         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9432         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9433         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9434         | RString _ ->
9435             pr "  jstring jr;\n";
9436             pr "  char *r;\n"; "NULL", "NULL"
9437         | RStringList _ ->
9438             pr "  jobjectArray jr;\n";
9439             pr "  int r_len;\n";
9440             pr "  jclass cl;\n";
9441             pr "  jstring jstr;\n";
9442             pr "  char **r;\n"; "NULL", "NULL"
9443         | RStruct (_, typ) ->
9444             pr "  jobject jr;\n";
9445             pr "  jclass cl;\n";
9446             pr "  jfieldID fl;\n";
9447             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9448         | RStructList (_, typ) ->
9449             pr "  jobjectArray jr;\n";
9450             pr "  jclass cl;\n";
9451             pr "  jfieldID fl;\n";
9452             pr "  jobject jfl;\n";
9453             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9454         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9455         | RBufferOut _ ->
9456             pr "  jstring jr;\n";
9457             pr "  char *r;\n";
9458             pr "  size_t size;\n";
9459             "NULL", "NULL" in
9460       List.iter (
9461         function
9462         | Pathname n
9463         | Device n | Dev_or_Path n
9464         | String n
9465         | OptString n
9466         | FileIn n
9467         | FileOut n ->
9468             pr "  const char *%s;\n" n
9469         | StringList n | DeviceList n ->
9470             pr "  int %s_len;\n" n;
9471             pr "  const char **%s;\n" n
9472         | Bool n
9473         | Int n ->
9474             pr "  int %s;\n" n
9475         | Int64 n ->
9476             pr "  int64_t %s;\n" n
9477       ) (snd style);
9478
9479       let needs_i =
9480         (match fst style with
9481          | RStringList _ | RStructList _ -> true
9482          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9483          | RConstOptString _
9484          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9485           List.exists (function
9486                        | StringList _ -> true
9487                        | DeviceList _ -> true
9488                        | _ -> false) (snd style) in
9489       if needs_i then
9490         pr "  int i;\n";
9491
9492       pr "\n";
9493
9494       (* Get the parameters. *)
9495       List.iter (
9496         function
9497         | Pathname n
9498         | Device n | Dev_or_Path n
9499         | String n
9500         | FileIn n
9501         | FileOut n ->
9502             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9503         | OptString n ->
9504             (* This is completely undocumented, but Java null becomes
9505              * a NULL parameter.
9506              *)
9507             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9508         | StringList n | DeviceList n ->
9509             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9510             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9511             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9512             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9513               n;
9514             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9515             pr "  }\n";
9516             pr "  %s[%s_len] = NULL;\n" n n;
9517         | Bool n
9518         | Int n
9519         | Int64 n ->
9520             pr "  %s = j%s;\n" n n
9521       ) (snd style);
9522
9523       (* Make the call. *)
9524       pr "  r = guestfs_%s " name;
9525       generate_c_call_args ~handle:"g" style;
9526       pr ";\n";
9527
9528       (* Release the parameters. *)
9529       List.iter (
9530         function
9531         | Pathname n
9532         | Device n | Dev_or_Path n
9533         | String n
9534         | FileIn n
9535         | FileOut n ->
9536             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9537         | OptString n ->
9538             pr "  if (j%s)\n" n;
9539             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9540         | StringList n | DeviceList n ->
9541             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9542             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9543               n;
9544             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9545             pr "  }\n";
9546             pr "  free (%s);\n" n
9547         | Bool n
9548         | Int n
9549         | Int64 n -> ()
9550       ) (snd style);
9551
9552       (* Check for errors. *)
9553       pr "  if (r == %s) {\n" error_code;
9554       pr "    throw_exception (env, guestfs_last_error (g));\n";
9555       pr "    return %s;\n" no_ret;
9556       pr "  }\n";
9557
9558       (* Return value. *)
9559       (match fst style with
9560        | RErr -> ()
9561        | RInt _ -> pr "  return (jint) r;\n"
9562        | RBool _ -> pr "  return (jboolean) r;\n"
9563        | RInt64 _ -> pr "  return (jlong) r;\n"
9564        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9565        | RConstOptString _ ->
9566            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9567        | RString _ ->
9568            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9569            pr "  free (r);\n";
9570            pr "  return jr;\n"
9571        | RStringList _ ->
9572            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9573            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9574            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9575            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9576            pr "  for (i = 0; i < r_len; ++i) {\n";
9577            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9578            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9579            pr "    free (r[i]);\n";
9580            pr "  }\n";
9581            pr "  free (r);\n";
9582            pr "  return jr;\n"
9583        | RStruct (_, typ) ->
9584            let jtyp = java_name_of_struct typ in
9585            let cols = cols_of_struct typ in
9586            generate_java_struct_return typ jtyp cols
9587        | RStructList (_, typ) ->
9588            let jtyp = java_name_of_struct typ in
9589            let cols = cols_of_struct typ in
9590            generate_java_struct_list_return typ jtyp cols
9591        | RHashtable _ ->
9592            (* XXX *)
9593            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9594            pr "  return NULL;\n"
9595        | RBufferOut _ ->
9596            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9597            pr "  free (r);\n";
9598            pr "  return jr;\n"
9599       );
9600
9601       pr "}\n";
9602       pr "\n"
9603   ) all_functions
9604
9605 and generate_java_struct_return typ jtyp cols =
9606   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9607   pr "  jr = (*env)->AllocObject (env, cl);\n";
9608   List.iter (
9609     function
9610     | name, FString ->
9611         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9612         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9613     | name, FUUID ->
9614         pr "  {\n";
9615         pr "    char s[33];\n";
9616         pr "    memcpy (s, r->%s, 32);\n" name;
9617         pr "    s[32] = 0;\n";
9618         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9619         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9620         pr "  }\n";
9621     | name, FBuffer ->
9622         pr "  {\n";
9623         pr "    int len = r->%s_len;\n" name;
9624         pr "    char s[len+1];\n";
9625         pr "    memcpy (s, r->%s, len);\n" name;
9626         pr "    s[len] = 0;\n";
9627         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9628         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9629         pr "  }\n";
9630     | name, (FBytes|FUInt64|FInt64) ->
9631         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9632         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9633     | name, (FUInt32|FInt32) ->
9634         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9635         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9636     | name, FOptPercent ->
9637         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9638         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9639     | name, FChar ->
9640         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9641         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9642   ) cols;
9643   pr "  free (r);\n";
9644   pr "  return jr;\n"
9645
9646 and generate_java_struct_list_return typ jtyp cols =
9647   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9648   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9649   pr "  for (i = 0; i < r->len; ++i) {\n";
9650   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9651   List.iter (
9652     function
9653     | name, FString ->
9654         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9655         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9656     | name, FUUID ->
9657         pr "    {\n";
9658         pr "      char s[33];\n";
9659         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9660         pr "      s[32] = 0;\n";
9661         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9662         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9663         pr "    }\n";
9664     | name, FBuffer ->
9665         pr "    {\n";
9666         pr "      int len = r->val[i].%s_len;\n" name;
9667         pr "      char s[len+1];\n";
9668         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9669         pr "      s[len] = 0;\n";
9670         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9671         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9672         pr "    }\n";
9673     | name, (FBytes|FUInt64|FInt64) ->
9674         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9675         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9676     | name, (FUInt32|FInt32) ->
9677         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9678         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9679     | name, FOptPercent ->
9680         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9681         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9682     | name, FChar ->
9683         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9684         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9685   ) cols;
9686   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9687   pr "  }\n";
9688   pr "  guestfs_free_%s_list (r);\n" typ;
9689   pr "  return jr;\n"
9690
9691 and generate_java_makefile_inc () =
9692   generate_header HashStyle GPLv2;
9693
9694   pr "java_built_sources = \\\n";
9695   List.iter (
9696     fun (typ, jtyp) ->
9697         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9698   ) java_structs;
9699   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9700
9701 and generate_haskell_hs () =
9702   generate_header HaskellStyle LGPLv2;
9703
9704   (* XXX We only know how to generate partial FFI for Haskell
9705    * at the moment.  Please help out!
9706    *)
9707   let can_generate style =
9708     match style with
9709     | RErr, _
9710     | RInt _, _
9711     | RInt64 _, _ -> true
9712     | RBool _, _
9713     | RConstString _, _
9714     | RConstOptString _, _
9715     | RString _, _
9716     | RStringList _, _
9717     | RStruct _, _
9718     | RStructList _, _
9719     | RHashtable _, _
9720     | RBufferOut _, _ -> false in
9721
9722   pr "\
9723 {-# INCLUDE <guestfs.h> #-}
9724 {-# LANGUAGE ForeignFunctionInterface #-}
9725
9726 module Guestfs (
9727   create";
9728
9729   (* List out the names of the actions we want to export. *)
9730   List.iter (
9731     fun (name, style, _, _, _, _, _) ->
9732       if can_generate style then pr ",\n  %s" name
9733   ) all_functions;
9734
9735   pr "
9736   ) where
9737
9738 -- Unfortunately some symbols duplicate ones already present
9739 -- in Prelude.  We don't know which, so we hard-code a list
9740 -- here.
9741 import Prelude hiding (truncate)
9742
9743 import Foreign
9744 import Foreign.C
9745 import Foreign.C.Types
9746 import IO
9747 import Control.Exception
9748 import Data.Typeable
9749
9750 data GuestfsS = GuestfsS            -- represents the opaque C struct
9751 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9752 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9753
9754 -- XXX define properly later XXX
9755 data PV = PV
9756 data VG = VG
9757 data LV = LV
9758 data IntBool = IntBool
9759 data Stat = Stat
9760 data StatVFS = StatVFS
9761 data Hashtable = Hashtable
9762
9763 foreign import ccall unsafe \"guestfs_create\" c_create
9764   :: IO GuestfsP
9765 foreign import ccall unsafe \"&guestfs_close\" c_close
9766   :: FunPtr (GuestfsP -> IO ())
9767 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9768   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9769
9770 create :: IO GuestfsH
9771 create = do
9772   p <- c_create
9773   c_set_error_handler p nullPtr nullPtr
9774   h <- newForeignPtr c_close p
9775   return h
9776
9777 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9778   :: GuestfsP -> IO CString
9779
9780 -- last_error :: GuestfsH -> IO (Maybe String)
9781 -- last_error h = do
9782 --   str <- withForeignPtr h (\\p -> c_last_error p)
9783 --   maybePeek peekCString str
9784
9785 last_error :: GuestfsH -> IO (String)
9786 last_error h = do
9787   str <- withForeignPtr h (\\p -> c_last_error p)
9788   if (str == nullPtr)
9789     then return \"no error\"
9790     else peekCString str
9791
9792 ";
9793
9794   (* Generate wrappers for each foreign function. *)
9795   List.iter (
9796     fun (name, style, _, _, _, _, _) ->
9797       if can_generate style then (
9798         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9799         pr "  :: ";
9800         generate_haskell_prototype ~handle:"GuestfsP" style;
9801         pr "\n";
9802         pr "\n";
9803         pr "%s :: " name;
9804         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9805         pr "\n";
9806         pr "%s %s = do\n" name
9807           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9808         pr "  r <- ";
9809         (* Convert pointer arguments using with* functions. *)
9810         List.iter (
9811           function
9812           | FileIn n
9813           | FileOut n
9814           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9815           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9816           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9817           | Bool _ | Int _ | Int64 _ -> ()
9818         ) (snd style);
9819         (* Convert integer arguments. *)
9820         let args =
9821           List.map (
9822             function
9823             | Bool n -> sprintf "(fromBool %s)" n
9824             | Int n -> sprintf "(fromIntegral %s)" n
9825             | Int64 n -> sprintf "(fromIntegral %s)" n
9826             | FileIn n | FileOut n
9827             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9828           ) (snd style) in
9829         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9830           (String.concat " " ("p" :: args));
9831         (match fst style with
9832          | RErr | RInt _ | RInt64 _ | RBool _ ->
9833              pr "  if (r == -1)\n";
9834              pr "    then do\n";
9835              pr "      err <- last_error h\n";
9836              pr "      fail err\n";
9837          | RConstString _ | RConstOptString _ | RString _
9838          | RStringList _ | RStruct _
9839          | RStructList _ | RHashtable _ | RBufferOut _ ->
9840              pr "  if (r == nullPtr)\n";
9841              pr "    then do\n";
9842              pr "      err <- last_error h\n";
9843              pr "      fail err\n";
9844         );
9845         (match fst style with
9846          | RErr ->
9847              pr "    else return ()\n"
9848          | RInt _ ->
9849              pr "    else return (fromIntegral r)\n"
9850          | RInt64 _ ->
9851              pr "    else return (fromIntegral r)\n"
9852          | RBool _ ->
9853              pr "    else return (toBool r)\n"
9854          | RConstString _
9855          | RConstOptString _
9856          | RString _
9857          | RStringList _
9858          | RStruct _
9859          | RStructList _
9860          | RHashtable _
9861          | RBufferOut _ ->
9862              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9863         );
9864         pr "\n";
9865       )
9866   ) all_functions
9867
9868 and generate_haskell_prototype ~handle ?(hs = false) style =
9869   pr "%s -> " handle;
9870   let string = if hs then "String" else "CString" in
9871   let int = if hs then "Int" else "CInt" in
9872   let bool = if hs then "Bool" else "CInt" in
9873   let int64 = if hs then "Integer" else "Int64" in
9874   List.iter (
9875     fun arg ->
9876       (match arg with
9877        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9878        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9879        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9880        | Bool _ -> pr "%s" bool
9881        | Int _ -> pr "%s" int
9882        | Int64 _ -> pr "%s" int
9883        | FileIn _ -> pr "%s" string
9884        | FileOut _ -> pr "%s" string
9885       );
9886       pr " -> ";
9887   ) (snd style);
9888   pr "IO (";
9889   (match fst style with
9890    | RErr -> if not hs then pr "CInt"
9891    | RInt _ -> pr "%s" int
9892    | RInt64 _ -> pr "%s" int64
9893    | RBool _ -> pr "%s" bool
9894    | RConstString _ -> pr "%s" string
9895    | RConstOptString _ -> pr "Maybe %s" string
9896    | RString _ -> pr "%s" string
9897    | RStringList _ -> pr "[%s]" string
9898    | RStruct (_, typ) ->
9899        let name = java_name_of_struct typ in
9900        pr "%s" name
9901    | RStructList (_, typ) ->
9902        let name = java_name_of_struct typ in
9903        pr "[%s]" name
9904    | RHashtable _ -> pr "Hashtable"
9905    | RBufferOut _ -> pr "%s" string
9906   );
9907   pr ")"
9908
9909 and generate_bindtests () =
9910   generate_header CStyle LGPLv2;
9911
9912   pr "\
9913 #include <stdio.h>
9914 #include <stdlib.h>
9915 #include <inttypes.h>
9916 #include <string.h>
9917
9918 #include \"guestfs.h\"
9919 #include \"guestfs-internal.h\"
9920 #include \"guestfs-internal-actions.h\"
9921 #include \"guestfs_protocol.h\"
9922
9923 #define error guestfs_error
9924 #define safe_calloc guestfs_safe_calloc
9925 #define safe_malloc guestfs_safe_malloc
9926
9927 static void
9928 print_strings (char *const *argv)
9929 {
9930   int argc;
9931
9932   printf (\"[\");
9933   for (argc = 0; argv[argc] != NULL; ++argc) {
9934     if (argc > 0) printf (\", \");
9935     printf (\"\\\"%%s\\\"\", argv[argc]);
9936   }
9937   printf (\"]\\n\");
9938 }
9939
9940 /* The test0 function prints its parameters to stdout. */
9941 ";
9942
9943   let test0, tests =
9944     match test_functions with
9945     | [] -> assert false
9946     | test0 :: tests -> test0, tests in
9947
9948   let () =
9949     let (name, style, _, _, _, _, _) = test0 in
9950     generate_prototype ~extern:false ~semicolon:false ~newline:true
9951       ~handle:"g" ~prefix:"guestfs__" name style;
9952     pr "{\n";
9953     List.iter (
9954       function
9955       | Pathname n
9956       | Device n | Dev_or_Path n
9957       | String n
9958       | FileIn n
9959       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9960       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9961       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9962       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9963       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9964       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
9965     ) (snd style);
9966     pr "  /* Java changes stdout line buffering so we need this: */\n";
9967     pr "  fflush (stdout);\n";
9968     pr "  return 0;\n";
9969     pr "}\n";
9970     pr "\n" in
9971
9972   List.iter (
9973     fun (name, style, _, _, _, _, _) ->
9974       if String.sub name (String.length name - 3) 3 <> "err" then (
9975         pr "/* Test normal return. */\n";
9976         generate_prototype ~extern:false ~semicolon:false ~newline:true
9977           ~handle:"g" ~prefix:"guestfs__" name style;
9978         pr "{\n";
9979         (match fst style with
9980          | RErr ->
9981              pr "  return 0;\n"
9982          | RInt _ ->
9983              pr "  int r;\n";
9984              pr "  sscanf (val, \"%%d\", &r);\n";
9985              pr "  return r;\n"
9986          | RInt64 _ ->
9987              pr "  int64_t r;\n";
9988              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9989              pr "  return r;\n"
9990          | RBool _ ->
9991              pr "  return STREQ (val, \"true\");\n"
9992          | RConstString _
9993          | RConstOptString _ ->
9994              (* Can't return the input string here.  Return a static
9995               * string so we ensure we get a segfault if the caller
9996               * tries to free it.
9997               *)
9998              pr "  return \"static string\";\n"
9999          | RString _ ->
10000              pr "  return strdup (val);\n"
10001          | RStringList _ ->
10002              pr "  char **strs;\n";
10003              pr "  int n, i;\n";
10004              pr "  sscanf (val, \"%%d\", &n);\n";
10005              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10006              pr "  for (i = 0; i < n; ++i) {\n";
10007              pr "    strs[i] = safe_malloc (g, 16);\n";
10008              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10009              pr "  }\n";
10010              pr "  strs[n] = NULL;\n";
10011              pr "  return strs;\n"
10012          | RStruct (_, typ) ->
10013              pr "  struct guestfs_%s *r;\n" typ;
10014              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10015              pr "  return r;\n"
10016          | RStructList (_, typ) ->
10017              pr "  struct guestfs_%s_list *r;\n" typ;
10018              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10019              pr "  sscanf (val, \"%%d\", &r->len);\n";
10020              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10021              pr "  return r;\n"
10022          | RHashtable _ ->
10023              pr "  char **strs;\n";
10024              pr "  int n, i;\n";
10025              pr "  sscanf (val, \"%%d\", &n);\n";
10026              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10027              pr "  for (i = 0; i < n; ++i) {\n";
10028              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10029              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10030              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10031              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10032              pr "  }\n";
10033              pr "  strs[n*2] = NULL;\n";
10034              pr "  return strs;\n"
10035          | RBufferOut _ ->
10036              pr "  return strdup (val);\n"
10037         );
10038         pr "}\n";
10039         pr "\n"
10040       ) else (
10041         pr "/* Test error return. */\n";
10042         generate_prototype ~extern:false ~semicolon:false ~newline:true
10043           ~handle:"g" ~prefix:"guestfs__" name style;
10044         pr "{\n";
10045         pr "  error (g, \"error\");\n";
10046         (match fst style with
10047          | RErr | RInt _ | RInt64 _ | RBool _ ->
10048              pr "  return -1;\n"
10049          | RConstString _ | RConstOptString _
10050          | RString _ | RStringList _ | RStruct _
10051          | RStructList _
10052          | RHashtable _
10053          | RBufferOut _ ->
10054              pr "  return NULL;\n"
10055         );
10056         pr "}\n";
10057         pr "\n"
10058       )
10059   ) tests
10060
10061 and generate_ocaml_bindtests () =
10062   generate_header OCamlStyle GPLv2;
10063
10064   pr "\
10065 let () =
10066   let g = Guestfs.create () in
10067 ";
10068
10069   let mkargs args =
10070     String.concat " " (
10071       List.map (
10072         function
10073         | CallString s -> "\"" ^ s ^ "\""
10074         | CallOptString None -> "None"
10075         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10076         | CallStringList xs ->
10077             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10078         | CallInt i when i >= 0 -> string_of_int i
10079         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10080         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10081         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10082         | CallBool b -> string_of_bool b
10083       ) args
10084     )
10085   in
10086
10087   generate_lang_bindtests (
10088     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10089   );
10090
10091   pr "print_endline \"EOF\"\n"
10092
10093 and generate_perl_bindtests () =
10094   pr "#!/usr/bin/perl -w\n";
10095   generate_header HashStyle GPLv2;
10096
10097   pr "\
10098 use strict;
10099
10100 use Sys::Guestfs;
10101
10102 my $g = Sys::Guestfs->new ();
10103 ";
10104
10105   let mkargs args =
10106     String.concat ", " (
10107       List.map (
10108         function
10109         | CallString s -> "\"" ^ s ^ "\""
10110         | CallOptString None -> "undef"
10111         | CallOptString (Some s) -> sprintf "\"%s\"" s
10112         | CallStringList xs ->
10113             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10114         | CallInt i -> string_of_int i
10115         | CallInt64 i -> Int64.to_string i
10116         | CallBool b -> if b then "1" else "0"
10117       ) args
10118     )
10119   in
10120
10121   generate_lang_bindtests (
10122     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10123   );
10124
10125   pr "print \"EOF\\n\"\n"
10126
10127 and generate_python_bindtests () =
10128   generate_header HashStyle GPLv2;
10129
10130   pr "\
10131 import guestfs
10132
10133 g = guestfs.GuestFS ()
10134 ";
10135
10136   let mkargs args =
10137     String.concat ", " (
10138       List.map (
10139         function
10140         | CallString s -> "\"" ^ s ^ "\""
10141         | CallOptString None -> "None"
10142         | CallOptString (Some s) -> sprintf "\"%s\"" s
10143         | CallStringList xs ->
10144             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10145         | CallInt i -> string_of_int i
10146         | CallInt64 i -> Int64.to_string i
10147         | CallBool b -> if b then "1" else "0"
10148       ) args
10149     )
10150   in
10151
10152   generate_lang_bindtests (
10153     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10154   );
10155
10156   pr "print \"EOF\"\n"
10157
10158 and generate_ruby_bindtests () =
10159   generate_header HashStyle GPLv2;
10160
10161   pr "\
10162 require 'guestfs'
10163
10164 g = Guestfs::create()
10165 ";
10166
10167   let mkargs args =
10168     String.concat ", " (
10169       List.map (
10170         function
10171         | CallString s -> "\"" ^ s ^ "\""
10172         | CallOptString None -> "nil"
10173         | CallOptString (Some s) -> sprintf "\"%s\"" s
10174         | CallStringList xs ->
10175             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10176         | CallInt i -> string_of_int i
10177         | CallInt64 i -> Int64.to_string i
10178         | CallBool b -> string_of_bool b
10179       ) args
10180     )
10181   in
10182
10183   generate_lang_bindtests (
10184     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10185   );
10186
10187   pr "print \"EOF\\n\"\n"
10188
10189 and generate_java_bindtests () =
10190   generate_header CStyle GPLv2;
10191
10192   pr "\
10193 import com.redhat.et.libguestfs.*;
10194
10195 public class Bindtests {
10196     public static void main (String[] argv)
10197     {
10198         try {
10199             GuestFS g = new GuestFS ();
10200 ";
10201
10202   let mkargs args =
10203     String.concat ", " (
10204       List.map (
10205         function
10206         | CallString s -> "\"" ^ s ^ "\""
10207         | CallOptString None -> "null"
10208         | CallOptString (Some s) -> sprintf "\"%s\"" s
10209         | CallStringList xs ->
10210             "new String[]{" ^
10211               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10212         | CallInt i -> string_of_int i
10213         | CallInt64 i -> Int64.to_string i
10214         | CallBool b -> string_of_bool b
10215       ) args
10216     )
10217   in
10218
10219   generate_lang_bindtests (
10220     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10221   );
10222
10223   pr "
10224             System.out.println (\"EOF\");
10225         }
10226         catch (Exception exn) {
10227             System.err.println (exn);
10228             System.exit (1);
10229         }
10230     }
10231 }
10232 "
10233
10234 and generate_haskell_bindtests () =
10235   generate_header HaskellStyle GPLv2;
10236
10237   pr "\
10238 module Bindtests where
10239 import qualified Guestfs
10240
10241 main = do
10242   g <- Guestfs.create
10243 ";
10244
10245   let mkargs args =
10246     String.concat " " (
10247       List.map (
10248         function
10249         | CallString s -> "\"" ^ s ^ "\""
10250         | CallOptString None -> "Nothing"
10251         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10252         | CallStringList xs ->
10253             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10254         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10255         | CallInt i -> string_of_int i
10256         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10257         | CallInt64 i -> Int64.to_string i
10258         | CallBool true -> "True"
10259         | CallBool false -> "False"
10260       ) args
10261     )
10262   in
10263
10264   generate_lang_bindtests (
10265     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10266   );
10267
10268   pr "  putStrLn \"EOF\"\n"
10269
10270 (* Language-independent bindings tests - we do it this way to
10271  * ensure there is parity in testing bindings across all languages.
10272  *)
10273 and generate_lang_bindtests call =
10274   call "test0" [CallString "abc"; CallOptString (Some "def");
10275                 CallStringList []; CallBool false;
10276                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10277   call "test0" [CallString "abc"; CallOptString None;
10278                 CallStringList []; CallBool false;
10279                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10280   call "test0" [CallString ""; CallOptString (Some "def");
10281                 CallStringList []; CallBool false;
10282                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10283   call "test0" [CallString ""; CallOptString (Some "");
10284                 CallStringList []; CallBool false;
10285                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10286   call "test0" [CallString "abc"; CallOptString (Some "def");
10287                 CallStringList ["1"]; CallBool false;
10288                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10289   call "test0" [CallString "abc"; CallOptString (Some "def");
10290                 CallStringList ["1"; "2"]; CallBool false;
10291                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10292   call "test0" [CallString "abc"; CallOptString (Some "def");
10293                 CallStringList ["1"]; CallBool true;
10294                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10295   call "test0" [CallString "abc"; CallOptString (Some "def");
10296                 CallStringList ["1"]; CallBool false;
10297                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10298   call "test0" [CallString "abc"; CallOptString (Some "def");
10299                 CallStringList ["1"]; CallBool false;
10300                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10301   call "test0" [CallString "abc"; CallOptString (Some "def");
10302                 CallStringList ["1"]; CallBool false;
10303                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10304   call "test0" [CallString "abc"; CallOptString (Some "def");
10305                 CallStringList ["1"]; CallBool false;
10306                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10307   call "test0" [CallString "abc"; CallOptString (Some "def");
10308                 CallStringList ["1"]; CallBool false;
10309                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10310   call "test0" [CallString "abc"; CallOptString (Some "def");
10311                 CallStringList ["1"]; CallBool false;
10312                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10313
10314 (* XXX Add here tests of the return and error functions. *)
10315
10316 (* This is used to generate the src/MAX_PROC_NR file which
10317  * contains the maximum procedure number, a surrogate for the
10318  * ABI version number.  See src/Makefile.am for the details.
10319  *)
10320 and generate_max_proc_nr () =
10321   let proc_nrs = List.map (
10322     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
10323   ) daemon_functions in
10324
10325   let max_proc_nr = List.fold_left max 0 proc_nrs in
10326
10327   pr "%d\n" max_proc_nr
10328
10329 let output_to filename =
10330   let filename_new = filename ^ ".new" in
10331   chan := open_out filename_new;
10332   let close () =
10333     close_out !chan;
10334     chan := Pervasives.stdout;
10335
10336     (* Is the new file different from the current file? *)
10337     if Sys.file_exists filename && files_equal filename filename_new then
10338       unlink filename_new               (* same, so skip it *)
10339     else (
10340       (* different, overwrite old one *)
10341       (try chmod filename 0o644 with Unix_error _ -> ());
10342       rename filename_new filename;
10343       chmod filename 0o444;
10344       printf "written %s\n%!" filename;
10345     )
10346   in
10347   close
10348
10349 let perror msg = function
10350   | Unix_error (err, _, _) ->
10351       eprintf "%s: %s\n" msg (error_message err)
10352   | exn ->
10353       eprintf "%s: %s\n" msg (Printexc.to_string exn)
10354
10355 (* Main program. *)
10356 let () =
10357   let lock_fd =
10358     try openfile "HACKING" [O_RDWR] 0
10359     with
10360     | Unix_error (ENOENT, _, _) ->
10361         eprintf "\
10362 You are probably running this from the wrong directory.
10363 Run it from the top source directory using the command
10364   src/generator.ml
10365 ";
10366         exit 1
10367     | exn ->
10368         perror "open: HACKING" exn;
10369         exit 1 in
10370
10371   (* Acquire a lock so parallel builds won't try to run the generator
10372    * twice at the same time.  Subsequent builds will wait for the first
10373    * one to finish.  Note the lock is released implicitly when the
10374    * program exits.
10375    *)
10376   (try lockf lock_fd F_LOCK 1
10377    with exn ->
10378      perror "lock: HACKING" exn;
10379      exit 1);
10380
10381   check_functions ();
10382
10383   let close = output_to "src/guestfs_protocol.x" in
10384   generate_xdr ();
10385   close ();
10386
10387   let close = output_to "src/guestfs-structs.h" in
10388   generate_structs_h ();
10389   close ();
10390
10391   let close = output_to "src/guestfs-actions.h" in
10392   generate_actions_h ();
10393   close ();
10394
10395   let close = output_to "src/guestfs-internal-actions.h" in
10396   generate_internal_actions_h ();
10397   close ();
10398
10399   let close = output_to "src/guestfs-actions.c" in
10400   generate_client_actions ();
10401   close ();
10402
10403   let close = output_to "daemon/actions.h" in
10404   generate_daemon_actions_h ();
10405   close ();
10406
10407   let close = output_to "daemon/stubs.c" in
10408   generate_daemon_actions ();
10409   close ();
10410
10411   let close = output_to "daemon/names.c" in
10412   generate_daemon_names ();
10413   close ();
10414
10415   let close = output_to "daemon/optgroups.c" in
10416   generate_daemon_optgroups_c ();
10417   close ();
10418
10419   let close = output_to "daemon/optgroups.h" in
10420   generate_daemon_optgroups_h ();
10421   close ();
10422
10423   let close = output_to "capitests/tests.c" in
10424   generate_tests ();
10425   close ();
10426
10427   let close = output_to "src/guestfs-bindtests.c" in
10428   generate_bindtests ();
10429   close ();
10430
10431   let close = output_to "fish/cmds.c" in
10432   generate_fish_cmds ();
10433   close ();
10434
10435   let close = output_to "fish/completion.c" in
10436   generate_fish_completion ();
10437   close ();
10438
10439   let close = output_to "guestfs-structs.pod" in
10440   generate_structs_pod ();
10441   close ();
10442
10443   let close = output_to "guestfs-actions.pod" in
10444   generate_actions_pod ();
10445   close ();
10446
10447   let close = output_to "guestfs-availability.pod" in
10448   generate_availability_pod ();
10449   close ();
10450
10451   let close = output_to "guestfish-actions.pod" in
10452   generate_fish_actions_pod ();
10453   close ();
10454
10455   let close = output_to "ocaml/guestfs.mli" in
10456   generate_ocaml_mli ();
10457   close ();
10458
10459   let close = output_to "ocaml/guestfs.ml" in
10460   generate_ocaml_ml ();
10461   close ();
10462
10463   let close = output_to "ocaml/guestfs_c_actions.c" in
10464   generate_ocaml_c ();
10465   close ();
10466
10467   let close = output_to "ocaml/bindtests.ml" in
10468   generate_ocaml_bindtests ();
10469   close ();
10470
10471   let close = output_to "perl/Guestfs.xs" in
10472   generate_perl_xs ();
10473   close ();
10474
10475   let close = output_to "perl/lib/Sys/Guestfs.pm" in
10476   generate_perl_pm ();
10477   close ();
10478
10479   let close = output_to "perl/bindtests.pl" in
10480   generate_perl_bindtests ();
10481   close ();
10482
10483   let close = output_to "python/guestfs-py.c" in
10484   generate_python_c ();
10485   close ();
10486
10487   let close = output_to "python/guestfs.py" in
10488   generate_python_py ();
10489   close ();
10490
10491   let close = output_to "python/bindtests.py" in
10492   generate_python_bindtests ();
10493   close ();
10494
10495   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
10496   generate_ruby_c ();
10497   close ();
10498
10499   let close = output_to "ruby/bindtests.rb" in
10500   generate_ruby_bindtests ();
10501   close ();
10502
10503   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
10504   generate_java_java ();
10505   close ();
10506
10507   List.iter (
10508     fun (typ, jtyp) ->
10509       let cols = cols_of_struct typ in
10510       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
10511       let close = output_to filename in
10512       generate_java_struct jtyp cols;
10513       close ();
10514   ) java_structs;
10515
10516   let close = output_to "java/Makefile.inc" in
10517   generate_java_makefile_inc ();
10518   close ();
10519
10520   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
10521   generate_java_c ();
10522   close ();
10523
10524   let close = output_to "java/Bindtests.java" in
10525   generate_java_bindtests ();
10526   close ();
10527
10528   let close = output_to "haskell/Guestfs.hs" in
10529   generate_haskell_hs ();
10530   close ();
10531
10532   let close = output_to "haskell/Bindtests.hs" in
10533   generate_haskell_bindtests ();
10534   close ();
10535
10536   let close = output_to "src/MAX_PROC_NR" in
10537   generate_max_proc_nr ();
10538   close ();
10539
10540   (* Always generate this file last, and unconditionally.  It's used
10541    * by the Makefile to know when we must re-run the generator.
10542    *)
10543   let chan = open_out "src/stamp-generator" in
10544   fprintf chan "1\n";
10545   close_out chan