Fix type punning warning about use of CMSG_DATA in Rawhide.
[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 below), and
25  * daemon/<somefile>.c to write the implementation.
26  *
27  * After editing this file, run it (./src/generator.ml) to regenerate all the
28  * output files.  Note that if you are using a separate build directory you
29  * must run generator.ml from the _source_ directory.
30  *
31  * IMPORTANT: This script should NOT print any warnings.  If it prints
32  * warnings, you should treat them as errors.
33  *)
34
35 #load "unix.cma";;
36 #load "str.cma";;
37
38 open Printf
39
40 type style = ret * args
41 and ret =
42     (* "RErr" as a return value means an int used as a simple error
43      * indication, ie. 0 or -1.
44      *)
45   | RErr
46
47     (* "RInt" as a return value means an int which is -1 for error
48      * or any value >= 0 on success.  Only use this for smallish
49      * positive ints (0 <= i < 2^30).
50      *)
51   | RInt of string
52
53     (* "RInt64" is the same as RInt, but is guaranteed to be able
54      * to return a full 64 bit value, _except_ that -1 means error
55      * (so -1 cannot be a valid, non-error return value).
56      *)
57   | RInt64 of string
58
59     (* "RBool" is a bool return value which can be true/false or
60      * -1 for error.
61      *)
62   | RBool of string
63
64     (* "RConstString" is a string that refers to a constant value.
65      * The return value must NOT be NULL (since NULL indicates
66      * an error).
67      *
68      * Try to avoid using this.  In particular you cannot use this
69      * for values returned from the daemon, because there is no
70      * thread-safe way to return them in the C API.
71      *)
72   | RConstString of string
73
74     (* "RConstOptString" is an even more broken version of
75      * "RConstString".  The returned string may be NULL and there
76      * is no way to return an error indication.  Avoid using this!
77      *)
78   | RConstOptString of string
79
80     (* "RString" is a returned string.  It must NOT be NULL, since
81      * a NULL return indicates an error.  The caller frees this.
82      *)
83   | RString of string
84
85     (* "RStringList" is a list of strings.  No string in the list
86      * can be NULL.  The caller frees the strings and the array.
87      *)
88   | RStringList of string
89
90     (* "RStruct" is a function which returns a single named structure
91      * or an error indication (in C, a struct, and in other languages
92      * with varying representations, but usually very efficient).  See
93      * after the function list below for the structures.
94      *)
95   | RStruct of string * string          (* name of retval, name of struct *)
96
97     (* "RStructList" is a function which returns either a list/array
98      * of structures (could be zero-length), or an error indication.
99      *)
100   | RStructList of string * string      (* name of retval, name of struct *)
101
102     (* Key-value pairs of untyped strings.  Turns into a hashtable or
103      * dictionary in languages which support it.  DON'T use this as a
104      * general "bucket" for results.  Prefer a stronger typed return
105      * value if one is available, or write a custom struct.  Don't use
106      * this if the list could potentially be very long, since it is
107      * inefficient.  Keys should be unique.  NULLs are not permitted.
108      *)
109   | RHashtable of string
110
111     (* "RBufferOut" is handled almost exactly like RString, but
112      * it allows the string to contain arbitrary 8 bit data including
113      * ASCII NUL.  In the C API this causes an implicit extra parameter
114      * to be added of type <size_t *size_r>.  The extra parameter
115      * returns the actual size of the return buffer in bytes.
116      *
117      * Other programming languages support strings with arbitrary 8 bit
118      * data.
119      *
120      * At the RPC layer we have to use the opaque<> type instead of
121      * string<>.  Returned data is still limited to the max message
122      * size (ie. ~ 2 MB).
123      *)
124   | RBufferOut of string
125
126 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
127
128     (* Note in future we should allow a "variable args" parameter as
129      * the final parameter, to allow commands like
130      *   chmod mode file [file(s)...]
131      * This is not implemented yet, but many commands (such as chmod)
132      * are currently defined with the argument order keeping this future
133      * possibility in mind.
134      *)
135 and argt =
136   | String of string    (* const char *name, cannot be NULL *)
137   | Device of string    (* /dev device name, cannot be NULL *)
138   | Pathname of string  (* file name, cannot be NULL *)
139   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
140   | OptString of string (* const char *name, may be NULL *)
141   | StringList of string(* list of strings (each string cannot be NULL) *)
142   | DeviceList of string(* list of Device names (each cannot be NULL) *)
143   | Bool of string      (* boolean *)
144   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
145     (* These are treated as filenames (simple string parameters) in
146      * the C API and bindings.  But in the RPC protocol, we transfer
147      * the actual file content up to or down from the daemon.
148      * FileIn: local machine -> daemon (in request)
149      * FileOut: daemon -> local machine (in reply)
150      * In guestfish (only), the special name "-" means read from
151      * stdin or write to stdout.
152      *)
153   | FileIn of string
154   | FileOut of string
155 (* Not implemented:
156     (* Opaque buffer which can contain arbitrary 8 bit data.
157      * In the C API, this is expressed as <char *, int> pair.
158      * Most other languages have a string type which can contain
159      * ASCII NUL.  We use whatever type is appropriate for each
160      * language.
161      * Buffers are limited by the total message size.  To transfer
162      * large blocks of data, use FileIn/FileOut parameters instead.
163      * To return an arbitrary buffer, use RBufferOut.
164      *)
165   | BufferIn of string
166 *)
167
168 type flags =
169   | ProtocolLimitWarning  (* display warning about protocol size limits *)
170   | DangerWillRobinson    (* flags particularly dangerous commands *)
171   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
172   | FishAction of string  (* call this function in guestfish *)
173   | NotInFish             (* do not export via guestfish *)
174   | NotInDocs             (* do not add this function to documentation *)
175   | DeprecatedBy of string (* function is deprecated, use .. instead *)
176
177 (* You can supply zero or as many tests as you want per API call.
178  *
179  * Note that the test environment has 3 block devices, of size 500MB,
180  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
181  * a fourth ISO block device with some known files on it (/dev/sdd).
182  *
183  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
184  * Number of cylinders was 63 for IDE emulated disks with precisely
185  * the same size.  How exactly this is calculated is a mystery.
186  *
187  * The ISO block device (/dev/sdd) comes from images/test.iso.
188  *
189  * To be able to run the tests in a reasonable amount of time,
190  * the virtual machine and block devices are reused between tests.
191  * So don't try testing kill_subprocess :-x
192  *
193  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
194  *
195  * Don't assume anything about the previous contents of the block
196  * devices.  Use 'Init*' to create some initial scenarios.
197  *
198  * You can add a prerequisite clause to any individual test.  This
199  * is a run-time check, which, if it fails, causes the test to be
200  * skipped.  Useful if testing a command which might not work on
201  * all variations of libguestfs builds.  A test that has prerequisite
202  * of 'Always' is run unconditionally.
203  *
204  * In addition, packagers can skip individual tests by setting the
205  * environment variables:     eg:
206  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
207  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
208  *)
209 type tests = (test_init * test_prereq * test) list
210 and test =
211     (* Run the command sequence and just expect nothing to fail. *)
212   | TestRun of seq
213
214     (* Run the command sequence and expect the output of the final
215      * command to be the string.
216      *)
217   | TestOutput of seq * string
218
219     (* Run the command sequence and expect the output of the final
220      * command to be the list of strings.
221      *)
222   | TestOutputList of seq * string list
223
224     (* Run the command sequence and expect the output of the final
225      * command to be the list of block devices (could be either
226      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
227      * character of each string).
228      *)
229   | TestOutputListOfDevices of seq * string list
230
231     (* Run the command sequence and expect the output of the final
232      * command to be the integer.
233      *)
234   | TestOutputInt of seq * int
235
236     (* Run the command sequence and expect the output of the final
237      * command to be <op> <int>, eg. ">=", "1".
238      *)
239   | TestOutputIntOp of seq * string * int
240
241     (* Run the command sequence and expect the output of the final
242      * command to be a true value (!= 0 or != NULL).
243      *)
244   | TestOutputTrue of seq
245
246     (* Run the command sequence and expect the output of the final
247      * command to be a false value (== 0 or == NULL, but not an error).
248      *)
249   | TestOutputFalse of seq
250
251     (* Run the command sequence and expect the output of the final
252      * command to be a list of the given length (but don't care about
253      * content).
254      *)
255   | TestOutputLength of seq * int
256
257     (* Run the command sequence and expect the output of the final
258      * command to be a buffer (RBufferOut), ie. string + size.
259      *)
260   | TestOutputBuffer of seq * string
261
262     (* Run the command sequence and expect the output of the final
263      * command to be a structure.
264      *)
265   | TestOutputStruct of seq * test_field_compare list
266
267     (* Run the command sequence and expect the final command (only)
268      * to fail.
269      *)
270   | TestLastFail of seq
271
272 and test_field_compare =
273   | CompareWithInt of string * int
274   | CompareWithIntOp of string * string * int
275   | CompareWithString of string * string
276   | CompareFieldsIntEq of string * string
277   | CompareFieldsStrEq of string * string
278
279 (* Test prerequisites. *)
280 and test_prereq =
281     (* Test always runs. *)
282   | Always
283
284     (* Test is currently disabled - eg. it fails, or it tests some
285      * unimplemented feature.
286      *)
287   | Disabled
288
289     (* 'string' is some C code (a function body) that should return
290      * true or false.  The test will run if the code returns true.
291      *)
292   | If of string
293
294     (* As for 'If' but the test runs _unless_ the code returns true. *)
295   | Unless of string
296
297 (* Some initial scenarios for testing. *)
298 and test_init =
299     (* Do nothing, block devices could contain random stuff including
300      * LVM PVs, and some filesystems might be mounted.  This is usually
301      * a bad idea.
302      *)
303   | InitNone
304
305     (* Block devices are empty and no filesystems are mounted. *)
306   | InitEmpty
307
308     (* /dev/sda contains a single partition /dev/sda1, with random
309      * content.  /dev/sdb and /dev/sdc may have random content.
310      * No LVM.
311      *)
312   | InitPartition
313
314     (* /dev/sda contains a single partition /dev/sda1, which is formatted
315      * as ext2, empty [except for lost+found] and mounted on /.
316      * /dev/sdb and /dev/sdc may have random content.
317      * No LVM.
318      *)
319   | InitBasicFS
320
321     (* /dev/sda:
322      *   /dev/sda1 (is a PV):
323      *     /dev/VG/LV (size 8MB):
324      *       formatted as ext2, empty [except for lost+found], mounted on /
325      * /dev/sdb and /dev/sdc may have random content.
326      *)
327   | InitBasicFSonLVM
328
329     (* /dev/sdd (the ISO, see images/ directory in source)
330      * is mounted on /
331      *)
332   | InitISOFS
333
334 (* Sequence of commands for testing. *)
335 and seq = cmd list
336 and cmd = string list
337
338 (* Note about long descriptions: When referring to another
339  * action, use the format C<guestfs_other> (ie. the full name of
340  * the C function).  This will be replaced as appropriate in other
341  * language bindings.
342  *
343  * Apart from that, long descriptions are just perldoc paragraphs.
344  *)
345
346 (* Generate a random UUID (used in tests). *)
347 let uuidgen () =
348   let chan = Unix.open_process_in "uuidgen" in
349   let uuid = input_line chan in
350   (match Unix.close_process_in chan with
351    | Unix.WEXITED 0 -> ()
352    | Unix.WEXITED _ ->
353        failwith "uuidgen: process exited with non-zero status"
354    | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
355        failwith "uuidgen: process signalled or stopped by signal"
356   );
357   uuid
358
359 (* These test functions are used in the language binding tests. *)
360
361 let test_all_args = [
362   String "str";
363   OptString "optstr";
364   StringList "strlist";
365   Bool "b";
366   Int "integer";
367   FileIn "filein";
368   FileOut "fileout";
369 ]
370
371 let test_all_rets = [
372   (* except for RErr, which is tested thoroughly elsewhere *)
373   "test0rint",         RInt "valout";
374   "test0rint64",       RInt64 "valout";
375   "test0rbool",        RBool "valout";
376   "test0rconststring", RConstString "valout";
377   "test0rconstoptstring", RConstOptString "valout";
378   "test0rstring",      RString "valout";
379   "test0rstringlist",  RStringList "valout";
380   "test0rstruct",      RStruct ("valout", "lvm_pv");
381   "test0rstructlist",  RStructList ("valout", "lvm_pv");
382   "test0rhashtable",   RHashtable "valout";
383 ]
384
385 let test_functions = [
386   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
387    [],
388    "internal test function - do not use",
389    "\
390 This is an internal test function which is used to test whether
391 the automatically generated bindings can handle every possible
392 parameter type correctly.
393
394 It echos the contents of each parameter to stdout.
395
396 You probably don't want to call this function.");
397 ] @ List.flatten (
398   List.map (
399     fun (name, ret) ->
400       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
401         [],
402         "internal test function - do not use",
403         "\
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 return type correctly.
407
408 It converts string C<val> to the return type.
409
410 You probably don't want to call this function.");
411        (name ^ "err", (ret, []), -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 This function always returns an error.
420
421 You probably don't want to call this function.")]
422   ) test_all_rets
423 )
424
425 (* non_daemon_functions are any functions which don't get processed
426  * in the daemon, eg. functions for setting and getting local
427  * configuration values.
428  *)
429
430 let non_daemon_functions = test_functions @ [
431   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
432    [],
433    "launch the qemu subprocess",
434    "\
435 Internally libguestfs is implemented by running a virtual machine
436 using L<qemu(1)>.
437
438 You should call this after configuring the handle
439 (eg. adding drives) but before performing any actions.");
440
441   ("wait_ready", (RErr, []), -1, [NotInFish],
442    [],
443    "wait until the qemu subprocess launches",
444    "\
445 Internally libguestfs is implemented by running a virtual machine
446 using L<qemu(1)>.
447
448 You should call this after C<guestfs_launch> to wait for the launch
449 to complete.");
450
451   ("kill_subprocess", (RErr, []), -1, [],
452    [],
453    "kill the qemu subprocess",
454    "\
455 This kills the qemu subprocess.  You should never need to call this.");
456
457   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
458    [],
459    "add an image to examine or modify",
460    "\
461 This function adds a virtual machine disk image C<filename> to the
462 guest.  The first time you call this function, the disk appears as IDE
463 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
464 so on.
465
466 You don't necessarily need to be root when using libguestfs.  However
467 you obviously do need sufficient permissions to access the filename
468 for whatever operations you want to perform (ie. read access if you
469 just want to read the image or write access if you want to modify the
470 image).
471
472 This is equivalent to the qemu parameter
473 C<-drive file=filename,cache=off,if=...>.
474 C<cache=off> is omitted in cases where it is not supported by
475 the underlying filesystem.
476
477 Note that this call checks for the existence of C<filename>.  This
478 stops you from specifying other types of drive which are supported
479 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
480 the general C<guestfs_config> call instead.");
481
482   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
483    [],
484    "add a CD-ROM disk image to examine",
485    "\
486 This function adds a virtual CD-ROM disk image to the guest.
487
488 This is equivalent to the qemu parameter C<-cdrom filename>.
489
490 Note that this call checks for the existence of C<filename>.  This
491 stops you from specifying other types of drive which are supported
492 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
493 the general C<guestfs_config> call instead.");
494
495   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
496    [],
497    "add a drive in snapshot mode (read-only)",
498    "\
499 This adds a drive in snapshot mode, making it effectively
500 read-only.
501
502 Note that writes to the device are allowed, and will be seen for
503 the duration of the guestfs handle, but they are written
504 to a temporary file which is discarded as soon as the guestfs
505 handle is closed.  We don't currently have any method to enable
506 changes to be committed, although qemu can support this.
507
508 This is equivalent to the qemu parameter
509 C<-drive file=filename,snapshot=on,if=...>.
510
511 Note that this call checks for the existence of C<filename>.  This
512 stops you from specifying other types of drive which are supported
513 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
514 the general C<guestfs_config> call instead.");
515
516   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
517    [],
518    "add qemu parameters",
519    "\
520 This can be used to add arbitrary qemu command line parameters
521 of the form C<-param value>.  Actually it's not quite arbitrary - we
522 prevent you from setting some parameters which would interfere with
523 parameters that we use.
524
525 The first character of C<param> string must be a C<-> (dash).
526
527 C<value> can be NULL.");
528
529   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
530    [],
531    "set the qemu binary",
532    "\
533 Set the qemu binary that we will use.
534
535 The default is chosen when the library was compiled by the
536 configure script.
537
538 You can also override this by setting the C<LIBGUESTFS_QEMU>
539 environment variable.
540
541 Setting C<qemu> to C<NULL> restores the default qemu binary.");
542
543   ("get_qemu", (RConstString "qemu", []), -1, [],
544    [InitNone, Always, TestRun (
545       [["get_qemu"]])],
546    "get the qemu binary",
547    "\
548 Return the current qemu binary.
549
550 This is always non-NULL.  If it wasn't set already, then this will
551 return the default qemu binary name.");
552
553   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
554    [],
555    "set the search path",
556    "\
557 Set the path that libguestfs searches for kernel and initrd.img.
558
559 The default is C<$libdir/guestfs> unless overridden by setting
560 C<LIBGUESTFS_PATH> environment variable.
561
562 Setting C<path> to C<NULL> restores the default path.");
563
564   ("get_path", (RConstString "path", []), -1, [],
565    [InitNone, Always, TestRun (
566       [["get_path"]])],
567    "get the search path",
568    "\
569 Return the current search path.
570
571 This is always non-NULL.  If it wasn't set already, then this will
572 return the default path.");
573
574   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
575    [],
576    "add options to kernel command line",
577    "\
578 This function is used to add additional options to the
579 guest kernel command line.
580
581 The default is C<NULL> unless overridden by setting
582 C<LIBGUESTFS_APPEND> environment variable.
583
584 Setting C<append> to C<NULL> means I<no> additional options
585 are passed (libguestfs always adds a few of its own).");
586
587   ("get_append", (RConstOptString "append", []), -1, [],
588    (* This cannot be tested with the current framework.  The
589     * function can return NULL in normal operations, which the
590     * test framework interprets as an error.
591     *)
592    [],
593    "get the additional kernel options",
594    "\
595 Return the additional kernel options which are added to the
596 guest kernel command line.
597
598 If C<NULL> then no options are added.");
599
600   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
601    [],
602    "set autosync mode",
603    "\
604 If C<autosync> is true, this enables autosync.  Libguestfs will make a
605 best effort attempt to run C<guestfs_umount_all> followed by
606 C<guestfs_sync> when the handle is closed
607 (also if the program exits without closing handles).
608
609 This is disabled by default (except in guestfish where it is
610 enabled by default).");
611
612   ("get_autosync", (RBool "autosync", []), -1, [],
613    [InitNone, Always, TestRun (
614       [["get_autosync"]])],
615    "get autosync mode",
616    "\
617 Get the autosync flag.");
618
619   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
620    [],
621    "set verbose mode",
622    "\
623 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
624
625 Verbose messages are disabled unless the environment variable
626 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
627
628   ("get_verbose", (RBool "verbose", []), -1, [],
629    [],
630    "get verbose mode",
631    "\
632 This returns the verbose messages flag.");
633
634   ("is_ready", (RBool "ready", []), -1, [],
635    [InitNone, Always, TestOutputTrue (
636       [["is_ready"]])],
637    "is ready to accept commands",
638    "\
639 This returns true iff this handle is ready to accept commands
640 (in the C<READY> state).
641
642 For more information on states, see L<guestfs(3)>.");
643
644   ("is_config", (RBool "config", []), -1, [],
645    [InitNone, Always, TestOutputFalse (
646       [["is_config"]])],
647    "is in configuration state",
648    "\
649 This returns true iff this handle is being configured
650 (in the C<CONFIG> state).
651
652 For more information on states, see L<guestfs(3)>.");
653
654   ("is_launching", (RBool "launching", []), -1, [],
655    [InitNone, Always, TestOutputFalse (
656       [["is_launching"]])],
657    "is launching subprocess",
658    "\
659 This returns true iff this handle is launching the subprocess
660 (in the C<LAUNCHING> state).
661
662 For more information on states, see L<guestfs(3)>.");
663
664   ("is_busy", (RBool "busy", []), -1, [],
665    [InitNone, Always, TestOutputFalse (
666       [["is_busy"]])],
667    "is busy processing a command",
668    "\
669 This returns true iff this handle is busy processing a command
670 (in the C<BUSY> state).
671
672 For more information on states, see L<guestfs(3)>.");
673
674   ("get_state", (RInt "state", []), -1, [],
675    [],
676    "get the current state",
677    "\
678 This returns the current state as an opaque integer.  This is
679 only useful for printing debug and internal error messages.
680
681 For more information on states, see L<guestfs(3)>.");
682
683   ("set_busy", (RErr, []), -1, [NotInFish],
684    [],
685    "set state to busy",
686    "\
687 This sets the state to C<BUSY>.  This is only used when implementing
688 actions using the low-level API.
689
690 For more information on states, see L<guestfs(3)>.");
691
692   ("set_ready", (RErr, []), -1, [NotInFish],
693    [],
694    "set state to ready",
695    "\
696 This sets the state to C<READY>.  This is only used when implementing
697 actions using the low-level API.
698
699 For more information on states, see L<guestfs(3)>.");
700
701   ("end_busy", (RErr, []), -1, [NotInFish],
702    [],
703    "leave the busy state",
704    "\
705 This sets the state to C<READY>, or if in C<CONFIG> then it leaves the
706 state as is.  This is only used when implementing
707 actions using the low-level API.
708
709 For more information on states, see L<guestfs(3)>.");
710
711   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
712    [InitNone, Always, TestOutputInt (
713       [["set_memsize"; "500"];
714        ["get_memsize"]], 500)],
715    "set memory allocated to the qemu subprocess",
716    "\
717 This sets the memory size in megabytes allocated to the
718 qemu subprocess.  This only has any effect if called before
719 C<guestfs_launch>.
720
721 You can also change this by setting the environment
722 variable C<LIBGUESTFS_MEMSIZE> before the handle is
723 created.
724
725 For more information on the architecture of libguestfs,
726 see L<guestfs(3)>.");
727
728   ("get_memsize", (RInt "memsize", []), -1, [],
729    [InitNone, Always, TestOutputIntOp (
730       [["get_memsize"]], ">=", 256)],
731    "get memory allocated to the qemu subprocess",
732    "\
733 This gets the memory size in megabytes allocated to the
734 qemu subprocess.
735
736 If C<guestfs_set_memsize> was not called
737 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
738 then this returns the compiled-in default value for memsize.
739
740 For more information on the architecture of libguestfs,
741 see L<guestfs(3)>.");
742
743   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
744    [InitNone, Always, TestOutputIntOp (
745       [["get_pid"]], ">=", 1)],
746    "get PID of qemu subprocess",
747    "\
748 Return the process ID of the qemu subprocess.  If there is no
749 qemu subprocess, then this will return an error.
750
751 This is an internal call used for debugging and testing.");
752
753   ("version", (RStruct ("version", "version"), []), -1, [],
754    [InitNone, Always, TestOutputStruct (
755       [["version"]], [CompareWithInt ("major", 1)])],
756    "get the library version number",
757    "\
758 Return the libguestfs version number that the program is linked
759 against.
760
761 Note that because of dynamic linking this is not necessarily
762 the version of libguestfs that you compiled against.  You can
763 compile the program, and then at runtime dynamically link
764 against a completely different C<libguestfs.so> library.
765
766 This call was added in version C<1.0.58>.  In previous
767 versions of libguestfs there was no way to get the version
768 number.  From C code you can use ELF weak linking tricks to find out if
769 this symbol exists (if it doesn't, then it's an earlier version).
770
771 The call returns a structure with four elements.  The first
772 three (C<major>, C<minor> and C<release>) are numbers and
773 correspond to the usual version triplet.  The fourth element
774 (C<extra>) is a string and is normally empty, but may be
775 used for distro-specific information.
776
777 To construct the original version string:
778 C<$major.$minor.$release$extra>
779
780 I<Note:> Don't use this call to test for availability
781 of features.  Distro backports makes this unreliable.");
782
783   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
784    [InitNone, Always, TestOutputTrue (
785       [["set_selinux"; "true"];
786        ["get_selinux"]])],
787    "set SELinux enabled or disabled at appliance boot",
788    "\
789 This sets the selinux flag that is passed to the appliance
790 at boot time.  The default is C<selinux=0> (disabled).
791
792 Note that if SELinux is enabled, it is always in
793 Permissive mode (C<enforcing=0>).
794
795 For more information on the architecture of libguestfs,
796 see L<guestfs(3)>.");
797
798   ("get_selinux", (RBool "selinux", []), -1, [],
799    [],
800    "get SELinux enabled flag",
801    "\
802 This returns the current setting of the selinux flag which
803 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
804
805 For more information on the architecture of libguestfs,
806 see L<guestfs(3)>.");
807
808   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
809    [InitNone, Always, TestOutputTrue (
810       [["set_trace"; "true"];
811        ["get_trace"]])],
812    "enable or disable command traces",
813    "\
814 If the command trace flag is set to 1, then commands are
815 printed on stdout before they are executed in a format
816 which is very similar to the one used by guestfish.  In
817 other words, you can run a program with this enabled, and
818 you will get out a script which you can feed to guestfish
819 to perform the same set of actions.
820
821 If you want to trace C API calls into libguestfs (and
822 other libraries) then possibly a better way is to use
823 the external ltrace(1) command.
824
825 Command traces are disabled unless the environment variable
826 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
827
828   ("get_trace", (RBool "trace", []), -1, [],
829    [],
830    "get command trace enabled flag",
831    "\
832 Return the command trace flag.");
833
834 ]
835
836 (* daemon_functions are any functions which cause some action
837  * to take place in the daemon.
838  *)
839
840 let daemon_functions = [
841   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
842    [InitEmpty, Always, TestOutput (
843       [["sfdiskM"; "/dev/sda"; ","];
844        ["mkfs"; "ext2"; "/dev/sda1"];
845        ["mount"; "/dev/sda1"; "/"];
846        ["write_file"; "/new"; "new file contents"; "0"];
847        ["cat"; "/new"]], "new file contents")],
848    "mount a guest disk at a position in the filesystem",
849    "\
850 Mount a guest disk at a position in the filesystem.  Block devices
851 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
852 the guest.  If those block devices contain partitions, they will have
853 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
854 names can be used.
855
856 The rules are the same as for L<mount(2)>:  A filesystem must
857 first be mounted on C</> before others can be mounted.  Other
858 filesystems can only be mounted on directories which already
859 exist.
860
861 The mounted filesystem is writable, if we have sufficient permissions
862 on the underlying device.
863
864 The filesystem options C<sync> and C<noatime> are set with this
865 call, in order to improve reliability.");
866
867   ("sync", (RErr, []), 2, [],
868    [ InitEmpty, Always, TestRun [["sync"]]],
869    "sync disks, writes are flushed through to the disk image",
870    "\
871 This syncs the disk, so that any writes are flushed through to the
872 underlying disk image.
873
874 You should always call this if you have modified a disk image, before
875 closing the handle.");
876
877   ("touch", (RErr, [Pathname "path"]), 3, [],
878    [InitBasicFS, Always, TestOutputTrue (
879       [["touch"; "/new"];
880        ["exists"; "/new"]])],
881    "update file timestamps or create a new file",
882    "\
883 Touch acts like the L<touch(1)> command.  It can be used to
884 update the timestamps on a file, or, if the file does not exist,
885 to create a new zero-length file.");
886
887   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
888    [InitISOFS, Always, TestOutput (
889       [["cat"; "/known-2"]], "abcdef\n")],
890    "list the contents of a file",
891    "\
892 Return the contents of the file named C<path>.
893
894 Note that this function cannot correctly handle binary files
895 (specifically, files containing C<\\0> character which is treated
896 as end of string).  For those you need to use the C<guestfs_read_file>
897 or C<guestfs_download> functions which have a more complex interface.");
898
899   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
900    [], (* XXX Tricky to test because it depends on the exact format
901         * of the 'ls -l' command, which changes between F10 and F11.
902         *)
903    "list the files in a directory (long format)",
904    "\
905 List the files in C<directory> (relative to the root directory,
906 there is no cwd) in the format of 'ls -la'.
907
908 This command is mostly useful for interactive sessions.  It
909 is I<not> intended that you try to parse the output string.");
910
911   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
912    [InitBasicFS, Always, TestOutputList (
913       [["touch"; "/new"];
914        ["touch"; "/newer"];
915        ["touch"; "/newest"];
916        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
917    "list the files in a directory",
918    "\
919 List the files in C<directory> (relative to the root directory,
920 there is no cwd).  The '.' and '..' entries are not returned, but
921 hidden files are shown.
922
923 This command is mostly useful for interactive sessions.  Programs
924 should probably use C<guestfs_readdir> instead.");
925
926   ("list_devices", (RStringList "devices", []), 7, [],
927    [InitEmpty, Always, TestOutputListOfDevices (
928       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
929    "list the block devices",
930    "\
931 List all the block devices.
932
933 The full block device names are returned, eg. C</dev/sda>");
934
935   ("list_partitions", (RStringList "partitions", []), 8, [],
936    [InitBasicFS, Always, TestOutputListOfDevices (
937       [["list_partitions"]], ["/dev/sda1"]);
938     InitEmpty, Always, TestOutputListOfDevices (
939       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
940        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
941    "list the partitions",
942    "\
943 List all the partitions detected on all block devices.
944
945 The full partition device names are returned, eg. C</dev/sda1>
946
947 This does not return logical volumes.  For that you will need to
948 call C<guestfs_lvs>.");
949
950   ("pvs", (RStringList "physvols", []), 9, [],
951    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
952       [["pvs"]], ["/dev/sda1"]);
953     InitEmpty, Always, TestOutputListOfDevices (
954       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
955        ["pvcreate"; "/dev/sda1"];
956        ["pvcreate"; "/dev/sda2"];
957        ["pvcreate"; "/dev/sda3"];
958        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
959    "list the LVM physical volumes (PVs)",
960    "\
961 List all the physical volumes detected.  This is the equivalent
962 of the L<pvs(8)> command.
963
964 This returns a list of just the device names that contain
965 PVs (eg. C</dev/sda2>).
966
967 See also C<guestfs_pvs_full>.");
968
969   ("vgs", (RStringList "volgroups", []), 10, [],
970    [InitBasicFSonLVM, Always, TestOutputList (
971       [["vgs"]], ["VG"]);
972     InitEmpty, Always, TestOutputList (
973       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
974        ["pvcreate"; "/dev/sda1"];
975        ["pvcreate"; "/dev/sda2"];
976        ["pvcreate"; "/dev/sda3"];
977        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
978        ["vgcreate"; "VG2"; "/dev/sda3"];
979        ["vgs"]], ["VG1"; "VG2"])],
980    "list the LVM volume groups (VGs)",
981    "\
982 List all the volumes groups detected.  This is the equivalent
983 of the L<vgs(8)> command.
984
985 This returns a list of just the volume group names that were
986 detected (eg. C<VolGroup00>).
987
988 See also C<guestfs_vgs_full>.");
989
990   ("lvs", (RStringList "logvols", []), 11, [],
991    [InitBasicFSonLVM, Always, TestOutputList (
992       [["lvs"]], ["/dev/VG/LV"]);
993     InitEmpty, Always, TestOutputList (
994       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
995        ["pvcreate"; "/dev/sda1"];
996        ["pvcreate"; "/dev/sda2"];
997        ["pvcreate"; "/dev/sda3"];
998        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
999        ["vgcreate"; "VG2"; "/dev/sda3"];
1000        ["lvcreate"; "LV1"; "VG1"; "50"];
1001        ["lvcreate"; "LV2"; "VG1"; "50"];
1002        ["lvcreate"; "LV3"; "VG2"; "50"];
1003        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1004    "list the LVM logical volumes (LVs)",
1005    "\
1006 List all the logical volumes detected.  This is the equivalent
1007 of the L<lvs(8)> command.
1008
1009 This returns a list of the logical volume device names
1010 (eg. C</dev/VolGroup00/LogVol00>).
1011
1012 See also C<guestfs_lvs_full>.");
1013
1014   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
1015    [], (* XXX how to test? *)
1016    "list the LVM physical volumes (PVs)",
1017    "\
1018 List all the physical volumes detected.  This is the equivalent
1019 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1020
1021   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
1022    [], (* XXX how to test? *)
1023    "list the LVM volume groups (VGs)",
1024    "\
1025 List all the volumes groups detected.  This is the equivalent
1026 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1027
1028   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1029    [], (* XXX how to test? *)
1030    "list the LVM logical volumes (LVs)",
1031    "\
1032 List all the logical volumes detected.  This is the equivalent
1033 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1034
1035   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1036    [InitISOFS, Always, TestOutputList (
1037       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1038     InitISOFS, Always, TestOutputList (
1039       [["read_lines"; "/empty"]], [])],
1040    "read file as lines",
1041    "\
1042 Return the contents of the file named C<path>.
1043
1044 The file contents are returned as a list of lines.  Trailing
1045 C<LF> and C<CRLF> character sequences are I<not> returned.
1046
1047 Note that this function cannot correctly handle binary files
1048 (specifically, files containing C<\\0> character which is treated
1049 as end of line).  For those you need to use the C<guestfs_read_file>
1050 function which has a more complex interface.");
1051
1052   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1053    [], (* XXX Augeas code needs tests. *)
1054    "create a new Augeas handle",
1055    "\
1056 Create a new Augeas handle for editing configuration files.
1057 If there was any previous Augeas handle associated with this
1058 guestfs session, then it is closed.
1059
1060 You must call this before using any other C<guestfs_aug_*>
1061 commands.
1062
1063 C<root> is the filesystem root.  C<root> must not be NULL,
1064 use C</> instead.
1065
1066 The flags are the same as the flags defined in
1067 E<lt>augeas.hE<gt>, the logical I<or> of the following
1068 integers:
1069
1070 =over 4
1071
1072 =item C<AUG_SAVE_BACKUP> = 1
1073
1074 Keep the original file with a C<.augsave> extension.
1075
1076 =item C<AUG_SAVE_NEWFILE> = 2
1077
1078 Save changes into a file with extension C<.augnew>, and
1079 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1080
1081 =item C<AUG_TYPE_CHECK> = 4
1082
1083 Typecheck lenses (can be expensive).
1084
1085 =item C<AUG_NO_STDINC> = 8
1086
1087 Do not use standard load path for modules.
1088
1089 =item C<AUG_SAVE_NOOP> = 16
1090
1091 Make save a no-op, just record what would have been changed.
1092
1093 =item C<AUG_NO_LOAD> = 32
1094
1095 Do not load the tree in C<guestfs_aug_init>.
1096
1097 =back
1098
1099 To close the handle, you can call C<guestfs_aug_close>.
1100
1101 To find out more about Augeas, see L<http://augeas.net/>.");
1102
1103   ("aug_close", (RErr, []), 26, [],
1104    [], (* XXX Augeas code needs tests. *)
1105    "close the current Augeas handle",
1106    "\
1107 Close the current Augeas handle and free up any resources
1108 used by it.  After calling this, you have to call
1109 C<guestfs_aug_init> again before you can use any other
1110 Augeas functions.");
1111
1112   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1113    [], (* XXX Augeas code needs tests. *)
1114    "define an Augeas variable",
1115    "\
1116 Defines an Augeas variable C<name> whose value is the result
1117 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1118 undefined.
1119
1120 On success this returns the number of nodes in C<expr>, or
1121 C<0> if C<expr> evaluates to something which is not a nodeset.");
1122
1123   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1124    [], (* XXX Augeas code needs tests. *)
1125    "define an Augeas node",
1126    "\
1127 Defines a variable C<name> whose value is the result of
1128 evaluating C<expr>.
1129
1130 If C<expr> evaluates to an empty nodeset, a node is created,
1131 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1132 C<name> will be the nodeset containing that single node.
1133
1134 On success this returns a pair containing the
1135 number of nodes in the nodeset, and a boolean flag
1136 if a node was created.");
1137
1138   ("aug_get", (RString "val", [String "augpath"]), 19, [],
1139    [], (* XXX Augeas code needs tests. *)
1140    "look up the value of an Augeas path",
1141    "\
1142 Look up the value associated with C<path>.  If C<path>
1143 matches exactly one node, the C<value> is returned.");
1144
1145   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1146    [], (* XXX Augeas code needs tests. *)
1147    "set Augeas path to value",
1148    "\
1149 Set the value associated with C<path> to C<value>.");
1150
1151   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1152    [], (* XXX Augeas code needs tests. *)
1153    "insert a sibling Augeas node",
1154    "\
1155 Create a new sibling C<label> for C<path>, inserting it into
1156 the tree before or after C<path> (depending on the boolean
1157 flag C<before>).
1158
1159 C<path> must match exactly one existing node in the tree, and
1160 C<label> must be a label, ie. not contain C</>, C<*> or end
1161 with a bracketed index C<[N]>.");
1162
1163   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1164    [], (* XXX Augeas code needs tests. *)
1165    "remove an Augeas path",
1166    "\
1167 Remove C<path> and all of its children.
1168
1169 On success this returns the number of entries which were removed.");
1170
1171   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1172    [], (* XXX Augeas code needs tests. *)
1173    "move Augeas node",
1174    "\
1175 Move the node C<src> to C<dest>.  C<src> must match exactly
1176 one node.  C<dest> is overwritten if it exists.");
1177
1178   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1179    [], (* XXX Augeas code needs tests. *)
1180    "return Augeas nodes which match augpath",
1181    "\
1182 Returns a list of paths which match the path expression C<path>.
1183 The returned paths are sufficiently qualified so that they match
1184 exactly one node in the current tree.");
1185
1186   ("aug_save", (RErr, []), 25, [],
1187    [], (* XXX Augeas code needs tests. *)
1188    "write all pending Augeas changes to disk",
1189    "\
1190 This writes all pending changes to disk.
1191
1192 The flags which were passed to C<guestfs_aug_init> affect exactly
1193 how files are saved.");
1194
1195   ("aug_load", (RErr, []), 27, [],
1196    [], (* XXX Augeas code needs tests. *)
1197    "load files into the tree",
1198    "\
1199 Load files into the tree.
1200
1201 See C<aug_load> in the Augeas documentation for the full gory
1202 details.");
1203
1204   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1205    [], (* XXX Augeas code needs tests. *)
1206    "list Augeas nodes under augpath",
1207    "\
1208 This is just a shortcut for listing C<guestfs_aug_match>
1209 C<path/*> and sorting the resulting nodes into alphabetical order.");
1210
1211   ("rm", (RErr, [Pathname "path"]), 29, [],
1212    [InitBasicFS, Always, TestRun
1213       [["touch"; "/new"];
1214        ["rm"; "/new"]];
1215     InitBasicFS, Always, TestLastFail
1216       [["rm"; "/new"]];
1217     InitBasicFS, Always, TestLastFail
1218       [["mkdir"; "/new"];
1219        ["rm"; "/new"]]],
1220    "remove a file",
1221    "\
1222 Remove the single file C<path>.");
1223
1224   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1225    [InitBasicFS, Always, TestRun
1226       [["mkdir"; "/new"];
1227        ["rmdir"; "/new"]];
1228     InitBasicFS, Always, TestLastFail
1229       [["rmdir"; "/new"]];
1230     InitBasicFS, Always, TestLastFail
1231       [["touch"; "/new"];
1232        ["rmdir"; "/new"]]],
1233    "remove a directory",
1234    "\
1235 Remove the single directory C<path>.");
1236
1237   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1238    [InitBasicFS, Always, TestOutputFalse
1239       [["mkdir"; "/new"];
1240        ["mkdir"; "/new/foo"];
1241        ["touch"; "/new/foo/bar"];
1242        ["rm_rf"; "/new"];
1243        ["exists"; "/new"]]],
1244    "remove a file or directory recursively",
1245    "\
1246 Remove the file or directory C<path>, recursively removing the
1247 contents if its a directory.  This is like the C<rm -rf> shell
1248 command.");
1249
1250   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1251    [InitBasicFS, Always, TestOutputTrue
1252       [["mkdir"; "/new"];
1253        ["is_dir"; "/new"]];
1254     InitBasicFS, Always, TestLastFail
1255       [["mkdir"; "/new/foo/bar"]]],
1256    "create a directory",
1257    "\
1258 Create a directory named C<path>.");
1259
1260   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1261    [InitBasicFS, Always, TestOutputTrue
1262       [["mkdir_p"; "/new/foo/bar"];
1263        ["is_dir"; "/new/foo/bar"]];
1264     InitBasicFS, Always, TestOutputTrue
1265       [["mkdir_p"; "/new/foo/bar"];
1266        ["is_dir"; "/new/foo"]];
1267     InitBasicFS, Always, TestOutputTrue
1268       [["mkdir_p"; "/new/foo/bar"];
1269        ["is_dir"; "/new"]];
1270     (* Regression tests for RHBZ#503133: *)
1271     InitBasicFS, Always, TestRun
1272       [["mkdir"; "/new"];
1273        ["mkdir_p"; "/new"]];
1274     InitBasicFS, Always, TestLastFail
1275       [["touch"; "/new"];
1276        ["mkdir_p"; "/new"]]],
1277    "create a directory and parents",
1278    "\
1279 Create a directory named C<path>, creating any parent directories
1280 as necessary.  This is like the C<mkdir -p> shell command.");
1281
1282   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1283    [], (* XXX Need stat command to test *)
1284    "change file mode",
1285    "\
1286 Change the mode (permissions) of C<path> to C<mode>.  Only
1287 numeric modes are supported.");
1288
1289   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1290    [], (* XXX Need stat command to test *)
1291    "change file owner and group",
1292    "\
1293 Change the file owner to C<owner> and group to C<group>.
1294
1295 Only numeric uid and gid are supported.  If you want to use
1296 names, you will need to locate and parse the password file
1297 yourself (Augeas support makes this relatively easy).");
1298
1299   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1300    [InitISOFS, Always, TestOutputTrue (
1301       [["exists"; "/empty"]]);
1302     InitISOFS, Always, TestOutputTrue (
1303       [["exists"; "/directory"]])],
1304    "test if file or directory exists",
1305    "\
1306 This returns C<true> if and only if there is a file, directory
1307 (or anything) with the given C<path> name.
1308
1309 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1310
1311   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1312    [InitISOFS, Always, TestOutputTrue (
1313       [["is_file"; "/known-1"]]);
1314     InitISOFS, Always, TestOutputFalse (
1315       [["is_file"; "/directory"]])],
1316    "test if file exists",
1317    "\
1318 This returns C<true> if and only if there is a file
1319 with the given C<path> name.  Note that it returns false for
1320 other objects like directories.
1321
1322 See also C<guestfs_stat>.");
1323
1324   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1325    [InitISOFS, Always, TestOutputFalse (
1326       [["is_dir"; "/known-3"]]);
1327     InitISOFS, Always, TestOutputTrue (
1328       [["is_dir"; "/directory"]])],
1329    "test if file exists",
1330    "\
1331 This returns C<true> if and only if there is a directory
1332 with the given C<path> name.  Note that it returns false for
1333 other objects like files.
1334
1335 See also C<guestfs_stat>.");
1336
1337   ("pvcreate", (RErr, [Device "device"]), 39, [],
1338    [InitEmpty, Always, TestOutputListOfDevices (
1339       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1340        ["pvcreate"; "/dev/sda1"];
1341        ["pvcreate"; "/dev/sda2"];
1342        ["pvcreate"; "/dev/sda3"];
1343        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1344    "create an LVM physical volume",
1345    "\
1346 This creates an LVM physical volume on the named C<device>,
1347 where C<device> should usually be a partition name such
1348 as C</dev/sda1>.");
1349
1350   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
1351    [InitEmpty, Always, TestOutputList (
1352       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1353        ["pvcreate"; "/dev/sda1"];
1354        ["pvcreate"; "/dev/sda2"];
1355        ["pvcreate"; "/dev/sda3"];
1356        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1357        ["vgcreate"; "VG2"; "/dev/sda3"];
1358        ["vgs"]], ["VG1"; "VG2"])],
1359    "create an LVM volume group",
1360    "\
1361 This creates an LVM volume group called C<volgroup>
1362 from the non-empty list of physical volumes C<physvols>.");
1363
1364   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1365    [InitEmpty, Always, TestOutputList (
1366       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1367        ["pvcreate"; "/dev/sda1"];
1368        ["pvcreate"; "/dev/sda2"];
1369        ["pvcreate"; "/dev/sda3"];
1370        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1371        ["vgcreate"; "VG2"; "/dev/sda3"];
1372        ["lvcreate"; "LV1"; "VG1"; "50"];
1373        ["lvcreate"; "LV2"; "VG1"; "50"];
1374        ["lvcreate"; "LV3"; "VG2"; "50"];
1375        ["lvcreate"; "LV4"; "VG2"; "50"];
1376        ["lvcreate"; "LV5"; "VG2"; "50"];
1377        ["lvs"]],
1378       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1379        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1380    "create an LVM volume group",
1381    "\
1382 This creates an LVM volume group called C<logvol>
1383 on the volume group C<volgroup>, with C<size> megabytes.");
1384
1385   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1386    [InitEmpty, Always, TestOutput (
1387       [["sfdiskM"; "/dev/sda"; ","];
1388        ["mkfs"; "ext2"; "/dev/sda1"];
1389        ["mount"; "/dev/sda1"; "/"];
1390        ["write_file"; "/new"; "new file contents"; "0"];
1391        ["cat"; "/new"]], "new file contents")],
1392    "make a filesystem",
1393    "\
1394 This creates a filesystem on C<device> (usually a partition
1395 or LVM logical volume).  The filesystem type is C<fstype>, for
1396 example C<ext3>.");
1397
1398   ("sfdisk", (RErr, [Device "device";
1399                      Int "cyls"; Int "heads"; Int "sectors";
1400                      StringList "lines"]), 43, [DangerWillRobinson],
1401    [],
1402    "create partitions on a block device",
1403    "\
1404 This is a direct interface to the L<sfdisk(8)> program for creating
1405 partitions on block devices.
1406
1407 C<device> should be a block device, for example C</dev/sda>.
1408
1409 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1410 and sectors on the device, which are passed directly to sfdisk as
1411 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1412 of these, then the corresponding parameter is omitted.  Usually for
1413 'large' disks, you can just pass C<0> for these, but for small
1414 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1415 out the right geometry and you will need to tell it.
1416
1417 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1418 information refer to the L<sfdisk(8)> manpage.
1419
1420 To create a single partition occupying the whole disk, you would
1421 pass C<lines> as a single element list, when the single element being
1422 the string C<,> (comma).
1423
1424 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1425
1426   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1427    [InitBasicFS, Always, TestOutput (
1428       [["write_file"; "/new"; "new file contents"; "0"];
1429        ["cat"; "/new"]], "new file contents");
1430     InitBasicFS, Always, TestOutput (
1431       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1432        ["cat"; "/new"]], "\nnew file contents\n");
1433     InitBasicFS, Always, TestOutput (
1434       [["write_file"; "/new"; "\n\n"; "0"];
1435        ["cat"; "/new"]], "\n\n");
1436     InitBasicFS, Always, TestOutput (
1437       [["write_file"; "/new"; ""; "0"];
1438        ["cat"; "/new"]], "");
1439     InitBasicFS, Always, TestOutput (
1440       [["write_file"; "/new"; "\n\n\n"; "0"];
1441        ["cat"; "/new"]], "\n\n\n");
1442     InitBasicFS, Always, TestOutput (
1443       [["write_file"; "/new"; "\n"; "0"];
1444        ["cat"; "/new"]], "\n")],
1445    "create a file",
1446    "\
1447 This call creates a file called C<path>.  The contents of the
1448 file is the string C<content> (which can contain any 8 bit data),
1449 with length C<size>.
1450
1451 As a special case, if C<size> is C<0>
1452 then the length is calculated using C<strlen> (so in this case
1453 the content cannot contain embedded ASCII NULs).
1454
1455 I<NB.> Owing to a bug, writing content containing ASCII NUL
1456 characters does I<not> work, even if the length is specified.
1457 We hope to resolve this bug in a future version.  In the meantime
1458 use C<guestfs_upload>.");
1459
1460   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1461    [InitEmpty, Always, TestOutputListOfDevices (
1462       [["sfdiskM"; "/dev/sda"; ","];
1463        ["mkfs"; "ext2"; "/dev/sda1"];
1464        ["mount"; "/dev/sda1"; "/"];
1465        ["mounts"]], ["/dev/sda1"]);
1466     InitEmpty, Always, TestOutputList (
1467       [["sfdiskM"; "/dev/sda"; ","];
1468        ["mkfs"; "ext2"; "/dev/sda1"];
1469        ["mount"; "/dev/sda1"; "/"];
1470        ["umount"; "/"];
1471        ["mounts"]], [])],
1472    "unmount a filesystem",
1473    "\
1474 This unmounts the given filesystem.  The filesystem may be
1475 specified either by its mountpoint (path) or the device which
1476 contains the filesystem.");
1477
1478   ("mounts", (RStringList "devices", []), 46, [],
1479    [InitBasicFS, Always, TestOutputListOfDevices (
1480       [["mounts"]], ["/dev/sda1"])],
1481    "show mounted filesystems",
1482    "\
1483 This returns the list of currently mounted filesystems.  It returns
1484 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1485
1486 Some internal mounts are not shown.
1487
1488 See also: C<guestfs_mountpoints>");
1489
1490   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1491    [InitBasicFS, Always, TestOutputList (
1492       [["umount_all"];
1493        ["mounts"]], []);
1494     (* check that umount_all can unmount nested mounts correctly: *)
1495     InitEmpty, Always, TestOutputList (
1496       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1497        ["mkfs"; "ext2"; "/dev/sda1"];
1498        ["mkfs"; "ext2"; "/dev/sda2"];
1499        ["mkfs"; "ext2"; "/dev/sda3"];
1500        ["mount"; "/dev/sda1"; "/"];
1501        ["mkdir"; "/mp1"];
1502        ["mount"; "/dev/sda2"; "/mp1"];
1503        ["mkdir"; "/mp1/mp2"];
1504        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1505        ["mkdir"; "/mp1/mp2/mp3"];
1506        ["umount_all"];
1507        ["mounts"]], [])],
1508    "unmount all filesystems",
1509    "\
1510 This unmounts all mounted filesystems.
1511
1512 Some internal mounts are not unmounted by this call.");
1513
1514   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1515    [],
1516    "remove all LVM LVs, VGs and PVs",
1517    "\
1518 This command removes all LVM logical volumes, volume groups
1519 and physical volumes.");
1520
1521   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1522    [InitISOFS, Always, TestOutput (
1523       [["file"; "/empty"]], "empty");
1524     InitISOFS, Always, TestOutput (
1525       [["file"; "/known-1"]], "ASCII text");
1526     InitISOFS, Always, TestLastFail (
1527       [["file"; "/notexists"]])],
1528    "determine file type",
1529    "\
1530 This call uses the standard L<file(1)> command to determine
1531 the type or contents of the file.  This also works on devices,
1532 for example to find out whether a partition contains a filesystem.
1533
1534 This call will also transparently look inside various types
1535 of compressed file.
1536
1537 The exact command which runs is C<file -zbsL path>.  Note in
1538 particular that the filename is not prepended to the output
1539 (the C<-b> option).");
1540
1541   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1542    [InitBasicFS, Always, TestOutput (
1543       [["upload"; "test-command"; "/test-command"];
1544        ["chmod"; "0o755"; "/test-command"];
1545        ["command"; "/test-command 1"]], "Result1");
1546     InitBasicFS, Always, TestOutput (
1547       [["upload"; "test-command"; "/test-command"];
1548        ["chmod"; "0o755"; "/test-command"];
1549        ["command"; "/test-command 2"]], "Result2\n");
1550     InitBasicFS, Always, TestOutput (
1551       [["upload"; "test-command"; "/test-command"];
1552        ["chmod"; "0o755"; "/test-command"];
1553        ["command"; "/test-command 3"]], "\nResult3");
1554     InitBasicFS, Always, TestOutput (
1555       [["upload"; "test-command"; "/test-command"];
1556        ["chmod"; "0o755"; "/test-command"];
1557        ["command"; "/test-command 4"]], "\nResult4\n");
1558     InitBasicFS, Always, TestOutput (
1559       [["upload"; "test-command"; "/test-command"];
1560        ["chmod"; "0o755"; "/test-command"];
1561        ["command"; "/test-command 5"]], "\nResult5\n\n");
1562     InitBasicFS, Always, TestOutput (
1563       [["upload"; "test-command"; "/test-command"];
1564        ["chmod"; "0o755"; "/test-command"];
1565        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1566     InitBasicFS, Always, TestOutput (
1567       [["upload"; "test-command"; "/test-command"];
1568        ["chmod"; "0o755"; "/test-command"];
1569        ["command"; "/test-command 7"]], "");
1570     InitBasicFS, Always, TestOutput (
1571       [["upload"; "test-command"; "/test-command"];
1572        ["chmod"; "0o755"; "/test-command"];
1573        ["command"; "/test-command 8"]], "\n");
1574     InitBasicFS, Always, TestOutput (
1575       [["upload"; "test-command"; "/test-command"];
1576        ["chmod"; "0o755"; "/test-command"];
1577        ["command"; "/test-command 9"]], "\n\n");
1578     InitBasicFS, Always, TestOutput (
1579       [["upload"; "test-command"; "/test-command"];
1580        ["chmod"; "0o755"; "/test-command"];
1581        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1582     InitBasicFS, Always, TestOutput (
1583       [["upload"; "test-command"; "/test-command"];
1584        ["chmod"; "0o755"; "/test-command"];
1585        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1586     InitBasicFS, Always, TestLastFail (
1587       [["upload"; "test-command"; "/test-command"];
1588        ["chmod"; "0o755"; "/test-command"];
1589        ["command"; "/test-command"]])],
1590    "run a command from the guest filesystem",
1591    "\
1592 This call runs a command from the guest filesystem.  The
1593 filesystem must be mounted, and must contain a compatible
1594 operating system (ie. something Linux, with the same
1595 or compatible processor architecture).
1596
1597 The single parameter is an argv-style list of arguments.
1598 The first element is the name of the program to run.
1599 Subsequent elements are parameters.  The list must be
1600 non-empty (ie. must contain a program name).  Note that
1601 the command runs directly, and is I<not> invoked via
1602 the shell (see C<guestfs_sh>).
1603
1604 The return value is anything printed to I<stdout> by
1605 the command.
1606
1607 If the command returns a non-zero exit status, then
1608 this function returns an error message.  The error message
1609 string is the content of I<stderr> from the command.
1610
1611 The C<$PATH> environment variable will contain at least
1612 C</usr/bin> and C</bin>.  If you require a program from
1613 another location, you should provide the full path in the
1614 first parameter.
1615
1616 Shared libraries and data files required by the program
1617 must be available on filesystems which are mounted in the
1618 correct places.  It is the caller's responsibility to ensure
1619 all filesystems that are needed are mounted at the right
1620 locations.");
1621
1622   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1623    [InitBasicFS, Always, TestOutputList (
1624       [["upload"; "test-command"; "/test-command"];
1625        ["chmod"; "0o755"; "/test-command"];
1626        ["command_lines"; "/test-command 1"]], ["Result1"]);
1627     InitBasicFS, Always, TestOutputList (
1628       [["upload"; "test-command"; "/test-command"];
1629        ["chmod"; "0o755"; "/test-command"];
1630        ["command_lines"; "/test-command 2"]], ["Result2"]);
1631     InitBasicFS, Always, TestOutputList (
1632       [["upload"; "test-command"; "/test-command"];
1633        ["chmod"; "0o755"; "/test-command"];
1634        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1635     InitBasicFS, Always, TestOutputList (
1636       [["upload"; "test-command"; "/test-command"];
1637        ["chmod"; "0o755"; "/test-command"];
1638        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1639     InitBasicFS, Always, TestOutputList (
1640       [["upload"; "test-command"; "/test-command"];
1641        ["chmod"; "0o755"; "/test-command"];
1642        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1643     InitBasicFS, Always, TestOutputList (
1644       [["upload"; "test-command"; "/test-command"];
1645        ["chmod"; "0o755"; "/test-command"];
1646        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1647     InitBasicFS, Always, TestOutputList (
1648       [["upload"; "test-command"; "/test-command"];
1649        ["chmod"; "0o755"; "/test-command"];
1650        ["command_lines"; "/test-command 7"]], []);
1651     InitBasicFS, Always, TestOutputList (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command_lines"; "/test-command 8"]], [""]);
1655     InitBasicFS, Always, TestOutputList (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command_lines"; "/test-command 9"]], ["";""]);
1659     InitBasicFS, Always, TestOutputList (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1663     InitBasicFS, Always, TestOutputList (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1667    "run a command, returning lines",
1668    "\
1669 This is the same as C<guestfs_command>, but splits the
1670 result into a list of lines.
1671
1672 See also: C<guestfs_sh_lines>");
1673
1674   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1675    [InitISOFS, Always, TestOutputStruct (
1676       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1677    "get file information",
1678    "\
1679 Returns file information for the given C<path>.
1680
1681 This is the same as the C<stat(2)> system call.");
1682
1683   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1684    [InitISOFS, Always, TestOutputStruct (
1685       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1686    "get file information for a symbolic link",
1687    "\
1688 Returns file information for the given C<path>.
1689
1690 This is the same as C<guestfs_stat> except that if C<path>
1691 is a symbolic link, then the link is stat-ed, not the file it
1692 refers to.
1693
1694 This is the same as the C<lstat(2)> system call.");
1695
1696   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1697    [InitISOFS, Always, TestOutputStruct (
1698       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1699    "get file system statistics",
1700    "\
1701 Returns file system statistics for any mounted file system.
1702 C<path> should be a file or directory in the mounted file system
1703 (typically it is the mount point itself, but it doesn't need to be).
1704
1705 This is the same as the C<statvfs(2)> system call.");
1706
1707   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1708    [], (* XXX test *)
1709    "get ext2/ext3/ext4 superblock details",
1710    "\
1711 This returns the contents of the ext2, ext3 or ext4 filesystem
1712 superblock on C<device>.
1713
1714 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1715 manpage for more details.  The list of fields returned isn't
1716 clearly defined, and depends on both the version of C<tune2fs>
1717 that libguestfs was built against, and the filesystem itself.");
1718
1719   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1720    [InitEmpty, Always, TestOutputTrue (
1721       [["blockdev_setro"; "/dev/sda"];
1722        ["blockdev_getro"; "/dev/sda"]])],
1723    "set block device to read-only",
1724    "\
1725 Sets the block device named C<device> to read-only.
1726
1727 This uses the L<blockdev(8)> command.");
1728
1729   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1730    [InitEmpty, Always, TestOutputFalse (
1731       [["blockdev_setrw"; "/dev/sda"];
1732        ["blockdev_getro"; "/dev/sda"]])],
1733    "set block device to read-write",
1734    "\
1735 Sets the block device named C<device> to read-write.
1736
1737 This uses the L<blockdev(8)> command.");
1738
1739   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1740    [InitEmpty, Always, TestOutputTrue (
1741       [["blockdev_setro"; "/dev/sda"];
1742        ["blockdev_getro"; "/dev/sda"]])],
1743    "is block device set to read-only",
1744    "\
1745 Returns a boolean indicating if the block device is read-only
1746 (true if read-only, false if not).
1747
1748 This uses the L<blockdev(8)> command.");
1749
1750   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1751    [InitEmpty, Always, TestOutputInt (
1752       [["blockdev_getss"; "/dev/sda"]], 512)],
1753    "get sectorsize of block device",
1754    "\
1755 This returns the size of sectors on a block device.
1756 Usually 512, but can be larger for modern devices.
1757
1758 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1759 for that).
1760
1761 This uses the L<blockdev(8)> command.");
1762
1763   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1764    [InitEmpty, Always, TestOutputInt (
1765       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1766    "get blocksize of block device",
1767    "\
1768 This returns the block size of a device.
1769
1770 (Note this is different from both I<size in blocks> and
1771 I<filesystem block size>).
1772
1773 This uses the L<blockdev(8)> command.");
1774
1775   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1776    [], (* XXX test *)
1777    "set blocksize of block device",
1778    "\
1779 This sets the block size of a device.
1780
1781 (Note this is different from both I<size in blocks> and
1782 I<filesystem block size>).
1783
1784 This uses the L<blockdev(8)> command.");
1785
1786   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1787    [InitEmpty, Always, TestOutputInt (
1788       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1789    "get total size of device in 512-byte sectors",
1790    "\
1791 This returns the size of the device in units of 512-byte sectors
1792 (even if the sectorsize isn't 512 bytes ... weird).
1793
1794 See also C<guestfs_blockdev_getss> for the real sector size of
1795 the device, and C<guestfs_blockdev_getsize64> for the more
1796 useful I<size in bytes>.
1797
1798 This uses the L<blockdev(8)> command.");
1799
1800   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1801    [InitEmpty, Always, TestOutputInt (
1802       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1803    "get total size of device in bytes",
1804    "\
1805 This returns the size of the device in bytes.
1806
1807 See also C<guestfs_blockdev_getsz>.
1808
1809 This uses the L<blockdev(8)> command.");
1810
1811   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1812    [InitEmpty, Always, TestRun
1813       [["blockdev_flushbufs"; "/dev/sda"]]],
1814    "flush device buffers",
1815    "\
1816 This tells the kernel to flush internal buffers associated
1817 with C<device>.
1818
1819 This uses the L<blockdev(8)> command.");
1820
1821   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1822    [InitEmpty, Always, TestRun
1823       [["blockdev_rereadpt"; "/dev/sda"]]],
1824    "reread partition table",
1825    "\
1826 Reread the partition table on C<device>.
1827
1828 This uses the L<blockdev(8)> command.");
1829
1830   ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1831    [InitBasicFS, Always, TestOutput (
1832       (* Pick a file from cwd which isn't likely to change. *)
1833       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1834        ["checksum"; "md5"; "/COPYING.LIB"]],
1835         Digest.to_hex (Digest.file "COPYING.LIB"))],
1836    "upload a file from the local machine",
1837    "\
1838 Upload local file C<filename> to C<remotefilename> on the
1839 filesystem.
1840
1841 C<filename> can also be a named pipe.
1842
1843 See also C<guestfs_download>.");
1844
1845   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1846    [InitBasicFS, Always, TestOutput (
1847       (* Pick a file from cwd which isn't likely to change. *)
1848       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1849        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1850        ["upload"; "testdownload.tmp"; "/upload"];
1851        ["checksum"; "md5"; "/upload"]],
1852         Digest.to_hex (Digest.file "COPYING.LIB"))],
1853    "download a file to the local machine",
1854    "\
1855 Download file C<remotefilename> and save it as C<filename>
1856 on the local machine.
1857
1858 C<filename> can also be a named pipe.
1859
1860 See also C<guestfs_upload>, C<guestfs_cat>.");
1861
1862   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1863    [InitISOFS, Always, TestOutput (
1864       [["checksum"; "crc"; "/known-3"]], "2891671662");
1865     InitISOFS, Always, TestLastFail (
1866       [["checksum"; "crc"; "/notexists"]]);
1867     InitISOFS, Always, TestOutput (
1868       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1869     InitISOFS, Always, TestOutput (
1870       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1871     InitISOFS, Always, TestOutput (
1872       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1873     InitISOFS, Always, TestOutput (
1874       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1875     InitISOFS, Always, TestOutput (
1876       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1877     InitISOFS, Always, TestOutput (
1878       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1879    "compute MD5, SHAx or CRC checksum of file",
1880    "\
1881 This call computes the MD5, SHAx or CRC checksum of the
1882 file named C<path>.
1883
1884 The type of checksum to compute is given by the C<csumtype>
1885 parameter which must have one of the following values:
1886
1887 =over 4
1888
1889 =item C<crc>
1890
1891 Compute the cyclic redundancy check (CRC) specified by POSIX
1892 for the C<cksum> command.
1893
1894 =item C<md5>
1895
1896 Compute the MD5 hash (using the C<md5sum> program).
1897
1898 =item C<sha1>
1899
1900 Compute the SHA1 hash (using the C<sha1sum> program).
1901
1902 =item C<sha224>
1903
1904 Compute the SHA224 hash (using the C<sha224sum> program).
1905
1906 =item C<sha256>
1907
1908 Compute the SHA256 hash (using the C<sha256sum> program).
1909
1910 =item C<sha384>
1911
1912 Compute the SHA384 hash (using the C<sha384sum> program).
1913
1914 =item C<sha512>
1915
1916 Compute the SHA512 hash (using the C<sha512sum> program).
1917
1918 =back
1919
1920 The checksum is returned as a printable string.");
1921
1922   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1923    [InitBasicFS, Always, TestOutput (
1924       [["tar_in"; "../images/helloworld.tar"; "/"];
1925        ["cat"; "/hello"]], "hello\n")],
1926    "unpack tarfile to directory",
1927    "\
1928 This command uploads and unpacks local file C<tarfile> (an
1929 I<uncompressed> tar file) into C<directory>.
1930
1931 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1932
1933   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1934    [],
1935    "pack directory into tarfile",
1936    "\
1937 This command packs the contents of C<directory> and downloads
1938 it to local file C<tarfile>.
1939
1940 To download a compressed tarball, use C<guestfs_tgz_out>.");
1941
1942   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1943    [InitBasicFS, Always, TestOutput (
1944       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1945        ["cat"; "/hello"]], "hello\n")],
1946    "unpack compressed tarball to directory",
1947    "\
1948 This command uploads and unpacks local file C<tarball> (a
1949 I<gzip compressed> tar file) into C<directory>.
1950
1951 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1952
1953   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1954    [],
1955    "pack directory into compressed tarball",
1956    "\
1957 This command packs the contents of C<directory> and downloads
1958 it to local file C<tarball>.
1959
1960 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1961
1962   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1963    [InitBasicFS, Always, TestLastFail (
1964       [["umount"; "/"];
1965        ["mount_ro"; "/dev/sda1"; "/"];
1966        ["touch"; "/new"]]);
1967     InitBasicFS, Always, TestOutput (
1968       [["write_file"; "/new"; "data"; "0"];
1969        ["umount"; "/"];
1970        ["mount_ro"; "/dev/sda1"; "/"];
1971        ["cat"; "/new"]], "data")],
1972    "mount a guest disk, read-only",
1973    "\
1974 This is the same as the C<guestfs_mount> command, but it
1975 mounts the filesystem with the read-only (I<-o ro>) flag.");
1976
1977   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
1978    [],
1979    "mount a guest disk with mount options",
1980    "\
1981 This is the same as the C<guestfs_mount> command, but it
1982 allows you to set the mount options as for the
1983 L<mount(8)> I<-o> flag.");
1984
1985   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
1986    [],
1987    "mount a guest disk with mount options and vfstype",
1988    "\
1989 This is the same as the C<guestfs_mount> command, but it
1990 allows you to set both the mount options and the vfstype
1991 as for the L<mount(8)> I<-o> and I<-t> flags.");
1992
1993   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1994    [],
1995    "debugging and internals",
1996    "\
1997 The C<guestfs_debug> command exposes some internals of
1998 C<guestfsd> (the guestfs daemon) that runs inside the
1999 qemu subprocess.
2000
2001 There is no comprehensive help for this command.  You have
2002 to look at the file C<daemon/debug.c> in the libguestfs source
2003 to find out what you can do.");
2004
2005   ("lvremove", (RErr, [Device "device"]), 77, [],
2006    [InitEmpty, Always, TestOutputList (
2007       [["sfdiskM"; "/dev/sda"; ","];
2008        ["pvcreate"; "/dev/sda1"];
2009        ["vgcreate"; "VG"; "/dev/sda1"];
2010        ["lvcreate"; "LV1"; "VG"; "50"];
2011        ["lvcreate"; "LV2"; "VG"; "50"];
2012        ["lvremove"; "/dev/VG/LV1"];
2013        ["lvs"]], ["/dev/VG/LV2"]);
2014     InitEmpty, Always, TestOutputList (
2015       [["sfdiskM"; "/dev/sda"; ","];
2016        ["pvcreate"; "/dev/sda1"];
2017        ["vgcreate"; "VG"; "/dev/sda1"];
2018        ["lvcreate"; "LV1"; "VG"; "50"];
2019        ["lvcreate"; "LV2"; "VG"; "50"];
2020        ["lvremove"; "/dev/VG"];
2021        ["lvs"]], []);
2022     InitEmpty, Always, TestOutputList (
2023       [["sfdiskM"; "/dev/sda"; ","];
2024        ["pvcreate"; "/dev/sda1"];
2025        ["vgcreate"; "VG"; "/dev/sda1"];
2026        ["lvcreate"; "LV1"; "VG"; "50"];
2027        ["lvcreate"; "LV2"; "VG"; "50"];
2028        ["lvremove"; "/dev/VG"];
2029        ["vgs"]], ["VG"])],
2030    "remove an LVM logical volume",
2031    "\
2032 Remove an LVM logical volume C<device>, where C<device> is
2033 the path to the LV, such as C</dev/VG/LV>.
2034
2035 You can also remove all LVs in a volume group by specifying
2036 the VG name, C</dev/VG>.");
2037
2038   ("vgremove", (RErr, [String "vgname"]), 78, [],
2039    [InitEmpty, Always, TestOutputList (
2040       [["sfdiskM"; "/dev/sda"; ","];
2041        ["pvcreate"; "/dev/sda1"];
2042        ["vgcreate"; "VG"; "/dev/sda1"];
2043        ["lvcreate"; "LV1"; "VG"; "50"];
2044        ["lvcreate"; "LV2"; "VG"; "50"];
2045        ["vgremove"; "VG"];
2046        ["lvs"]], []);
2047     InitEmpty, Always, TestOutputList (
2048       [["sfdiskM"; "/dev/sda"; ","];
2049        ["pvcreate"; "/dev/sda1"];
2050        ["vgcreate"; "VG"; "/dev/sda1"];
2051        ["lvcreate"; "LV1"; "VG"; "50"];
2052        ["lvcreate"; "LV2"; "VG"; "50"];
2053        ["vgremove"; "VG"];
2054        ["vgs"]], [])],
2055    "remove an LVM volume group",
2056    "\
2057 Remove an LVM volume group C<vgname>, (for example C<VG>).
2058
2059 This also forcibly removes all logical volumes in the volume
2060 group (if any).");
2061
2062   ("pvremove", (RErr, [Device "device"]), 79, [],
2063    [InitEmpty, Always, TestOutputListOfDevices (
2064       [["sfdiskM"; "/dev/sda"; ","];
2065        ["pvcreate"; "/dev/sda1"];
2066        ["vgcreate"; "VG"; "/dev/sda1"];
2067        ["lvcreate"; "LV1"; "VG"; "50"];
2068        ["lvcreate"; "LV2"; "VG"; "50"];
2069        ["vgremove"; "VG"];
2070        ["pvremove"; "/dev/sda1"];
2071        ["lvs"]], []);
2072     InitEmpty, Always, TestOutputListOfDevices (
2073       [["sfdiskM"; "/dev/sda"; ","];
2074        ["pvcreate"; "/dev/sda1"];
2075        ["vgcreate"; "VG"; "/dev/sda1"];
2076        ["lvcreate"; "LV1"; "VG"; "50"];
2077        ["lvcreate"; "LV2"; "VG"; "50"];
2078        ["vgremove"; "VG"];
2079        ["pvremove"; "/dev/sda1"];
2080        ["vgs"]], []);
2081     InitEmpty, Always, TestOutputListOfDevices (
2082       [["sfdiskM"; "/dev/sda"; ","];
2083        ["pvcreate"; "/dev/sda1"];
2084        ["vgcreate"; "VG"; "/dev/sda1"];
2085        ["lvcreate"; "LV1"; "VG"; "50"];
2086        ["lvcreate"; "LV2"; "VG"; "50"];
2087        ["vgremove"; "VG"];
2088        ["pvremove"; "/dev/sda1"];
2089        ["pvs"]], [])],
2090    "remove an LVM physical volume",
2091    "\
2092 This wipes a physical volume C<device> so that LVM will no longer
2093 recognise it.
2094
2095 The implementation uses the C<pvremove> command which refuses to
2096 wipe physical volumes that contain any volume groups, so you have
2097 to remove those first.");
2098
2099   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2100    [InitBasicFS, Always, TestOutput (
2101       [["set_e2label"; "/dev/sda1"; "testlabel"];
2102        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2103    "set the ext2/3/4 filesystem label",
2104    "\
2105 This sets the ext2/3/4 filesystem label of the filesystem on
2106 C<device> to C<label>.  Filesystem labels are limited to
2107 16 characters.
2108
2109 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2110 to return the existing label on a filesystem.");
2111
2112   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2113    [],
2114    "get the ext2/3/4 filesystem label",
2115    "\
2116 This returns the ext2/3/4 filesystem label of the filesystem on
2117 C<device>.");
2118
2119   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2120    (let uuid = uuidgen () in
2121     [InitBasicFS, Always, TestOutput (
2122        [["set_e2uuid"; "/dev/sda1"; uuid];
2123         ["get_e2uuid"; "/dev/sda1"]], uuid);
2124      InitBasicFS, Always, TestOutput (
2125        [["set_e2uuid"; "/dev/sda1"; "clear"];
2126         ["get_e2uuid"; "/dev/sda1"]], "");
2127      (* We can't predict what UUIDs will be, so just check the commands run. *)
2128      InitBasicFS, Always, TestRun (
2129        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2130      InitBasicFS, Always, TestRun (
2131        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2132    "set the ext2/3/4 filesystem UUID",
2133    "\
2134 This sets the ext2/3/4 filesystem UUID of the filesystem on
2135 C<device> to C<uuid>.  The format of the UUID and alternatives
2136 such as C<clear>, C<random> and C<time> are described in the
2137 L<tune2fs(8)> manpage.
2138
2139 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2140 to return the existing UUID of a filesystem.");
2141
2142   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2143    [],
2144    "get the ext2/3/4 filesystem UUID",
2145    "\
2146 This returns the ext2/3/4 filesystem UUID of the filesystem on
2147 C<device>.");
2148
2149   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2150    [InitBasicFS, Always, TestOutputInt (
2151       [["umount"; "/dev/sda1"];
2152        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2153     InitBasicFS, Always, TestOutputInt (
2154       [["umount"; "/dev/sda1"];
2155        ["zero"; "/dev/sda1"];
2156        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2157    "run the filesystem checker",
2158    "\
2159 This runs the filesystem checker (fsck) on C<device> which
2160 should have filesystem type C<fstype>.
2161
2162 The returned integer is the status.  See L<fsck(8)> for the
2163 list of status codes from C<fsck>.
2164
2165 Notes:
2166
2167 =over 4
2168
2169 =item *
2170
2171 Multiple status codes can be summed together.
2172
2173 =item *
2174
2175 A non-zero return code can mean \"success\", for example if
2176 errors have been corrected on the filesystem.
2177
2178 =item *
2179
2180 Checking or repairing NTFS volumes is not supported
2181 (by linux-ntfs).
2182
2183 =back
2184
2185 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2186
2187   ("zero", (RErr, [Device "device"]), 85, [],
2188    [InitBasicFS, Always, TestOutput (
2189       [["umount"; "/dev/sda1"];
2190        ["zero"; "/dev/sda1"];
2191        ["file"; "/dev/sda1"]], "data")],
2192    "write zeroes to the device",
2193    "\
2194 This command writes zeroes over the first few blocks of C<device>.
2195
2196 How many blocks are zeroed isn't specified (but it's I<not> enough
2197 to securely wipe the device).  It should be sufficient to remove
2198 any partition tables, filesystem superblocks and so on.
2199
2200 See also: C<guestfs_scrub_device>.");
2201
2202   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2203    (* Test disabled because grub-install incompatible with virtio-blk driver.
2204     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2205     *)
2206    [InitBasicFS, Disabled, TestOutputTrue (
2207       [["grub_install"; "/"; "/dev/sda1"];
2208        ["is_dir"; "/boot"]])],
2209    "install GRUB",
2210    "\
2211 This command installs GRUB (the Grand Unified Bootloader) on
2212 C<device>, with the root directory being C<root>.");
2213
2214   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2215    [InitBasicFS, Always, TestOutput (
2216       [["write_file"; "/old"; "file content"; "0"];
2217        ["cp"; "/old"; "/new"];
2218        ["cat"; "/new"]], "file content");
2219     InitBasicFS, Always, TestOutputTrue (
2220       [["write_file"; "/old"; "file content"; "0"];
2221        ["cp"; "/old"; "/new"];
2222        ["is_file"; "/old"]]);
2223     InitBasicFS, Always, TestOutput (
2224       [["write_file"; "/old"; "file content"; "0"];
2225        ["mkdir"; "/dir"];
2226        ["cp"; "/old"; "/dir/new"];
2227        ["cat"; "/dir/new"]], "file content")],
2228    "copy a file",
2229    "\
2230 This copies a file from C<src> to C<dest> where C<dest> is
2231 either a destination filename or destination directory.");
2232
2233   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2234    [InitBasicFS, Always, TestOutput (
2235       [["mkdir"; "/olddir"];
2236        ["mkdir"; "/newdir"];
2237        ["write_file"; "/olddir/file"; "file content"; "0"];
2238        ["cp_a"; "/olddir"; "/newdir"];
2239        ["cat"; "/newdir/olddir/file"]], "file content")],
2240    "copy a file or directory recursively",
2241    "\
2242 This copies a file or directory from C<src> to C<dest>
2243 recursively using the C<cp -a> command.");
2244
2245   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2246    [InitBasicFS, Always, TestOutput (
2247       [["write_file"; "/old"; "file content"; "0"];
2248        ["mv"; "/old"; "/new"];
2249        ["cat"; "/new"]], "file content");
2250     InitBasicFS, Always, TestOutputFalse (
2251       [["write_file"; "/old"; "file content"; "0"];
2252        ["mv"; "/old"; "/new"];
2253        ["is_file"; "/old"]])],
2254    "move a file",
2255    "\
2256 This moves a file from C<src> to C<dest> where C<dest> is
2257 either a destination filename or destination directory.");
2258
2259   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2260    [InitEmpty, Always, TestRun (
2261       [["drop_caches"; "3"]])],
2262    "drop kernel page cache, dentries and inodes",
2263    "\
2264 This instructs the guest kernel to drop its page cache,
2265 and/or dentries and inode caches.  The parameter C<whattodrop>
2266 tells the kernel what precisely to drop, see
2267 L<http://linux-mm.org/Drop_Caches>
2268
2269 Setting C<whattodrop> to 3 should drop everything.
2270
2271 This automatically calls L<sync(2)> before the operation,
2272 so that the maximum guest memory is freed.");
2273
2274   ("dmesg", (RString "kmsgs", []), 91, [],
2275    [InitEmpty, Always, TestRun (
2276       [["dmesg"]])],
2277    "return kernel messages",
2278    "\
2279 This returns the kernel messages (C<dmesg> output) from
2280 the guest kernel.  This is sometimes useful for extended
2281 debugging of problems.
2282
2283 Another way to get the same information is to enable
2284 verbose messages with C<guestfs_set_verbose> or by setting
2285 the environment variable C<LIBGUESTFS_DEBUG=1> before
2286 running the program.");
2287
2288   ("ping_daemon", (RErr, []), 92, [],
2289    [InitEmpty, Always, TestRun (
2290       [["ping_daemon"]])],
2291    "ping the guest daemon",
2292    "\
2293 This is a test probe into the guestfs daemon running inside
2294 the qemu subprocess.  Calling this function checks that the
2295 daemon responds to the ping message, without affecting the daemon
2296 or attached block device(s) in any other way.");
2297
2298   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2299    [InitBasicFS, Always, TestOutputTrue (
2300       [["write_file"; "/file1"; "contents of a file"; "0"];
2301        ["cp"; "/file1"; "/file2"];
2302        ["equal"; "/file1"; "/file2"]]);
2303     InitBasicFS, Always, TestOutputFalse (
2304       [["write_file"; "/file1"; "contents of a file"; "0"];
2305        ["write_file"; "/file2"; "contents of another file"; "0"];
2306        ["equal"; "/file1"; "/file2"]]);
2307     InitBasicFS, Always, TestLastFail (
2308       [["equal"; "/file1"; "/file2"]])],
2309    "test if two files have equal contents",
2310    "\
2311 This compares the two files C<file1> and C<file2> and returns
2312 true if their content is exactly equal, or false otherwise.
2313
2314 The external L<cmp(1)> program is used for the comparison.");
2315
2316   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2317    [InitISOFS, Always, TestOutputList (
2318       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2319     InitISOFS, Always, TestOutputList (
2320       [["strings"; "/empty"]], [])],
2321    "print the printable strings in a file",
2322    "\
2323 This runs the L<strings(1)> command on a file and returns
2324 the list of printable strings found.");
2325
2326   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2327    [InitISOFS, Always, TestOutputList (
2328       [["strings_e"; "b"; "/known-5"]], []);
2329     InitBasicFS, Disabled, TestOutputList (
2330       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2331        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2332    "print the printable strings in a file",
2333    "\
2334 This is like the C<guestfs_strings> command, but allows you to
2335 specify the encoding.
2336
2337 See the L<strings(1)> manpage for the full list of encodings.
2338
2339 Commonly useful encodings are C<l> (lower case L) which will
2340 show strings inside Windows/x86 files.
2341
2342 The returned strings are transcoded to UTF-8.");
2343
2344   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2345    [InitISOFS, Always, TestOutput (
2346       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2347     (* Test for RHBZ#501888c2 regression which caused large hexdump
2348      * commands to segfault.
2349      *)
2350     InitISOFS, Always, TestRun (
2351       [["hexdump"; "/100krandom"]])],
2352    "dump a file in hexadecimal",
2353    "\
2354 This runs C<hexdump -C> on the given C<path>.  The result is
2355 the human-readable, canonical hex dump of the file.");
2356
2357   ("zerofree", (RErr, [Device "device"]), 97, [],
2358    [InitNone, Always, TestOutput (
2359       [["sfdiskM"; "/dev/sda"; ","];
2360        ["mkfs"; "ext3"; "/dev/sda1"];
2361        ["mount"; "/dev/sda1"; "/"];
2362        ["write_file"; "/new"; "test file"; "0"];
2363        ["umount"; "/dev/sda1"];
2364        ["zerofree"; "/dev/sda1"];
2365        ["mount"; "/dev/sda1"; "/"];
2366        ["cat"; "/new"]], "test file")],
2367    "zero unused inodes and disk blocks on ext2/3 filesystem",
2368    "\
2369 This runs the I<zerofree> program on C<device>.  This program
2370 claims to zero unused inodes and disk blocks on an ext2/3
2371 filesystem, thus making it possible to compress the filesystem
2372 more effectively.
2373
2374 You should B<not> run this program if the filesystem is
2375 mounted.
2376
2377 It is possible that using this program can damage the filesystem
2378 or data on the filesystem.");
2379
2380   ("pvresize", (RErr, [Device "device"]), 98, [],
2381    [],
2382    "resize an LVM physical volume",
2383    "\
2384 This resizes (expands or shrinks) an existing LVM physical
2385 volume to match the new size of the underlying device.");
2386
2387   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2388                        Int "cyls"; Int "heads"; Int "sectors";
2389                        String "line"]), 99, [DangerWillRobinson],
2390    [],
2391    "modify a single partition on a block device",
2392    "\
2393 This runs L<sfdisk(8)> option to modify just the single
2394 partition C<n> (note: C<n> counts from 1).
2395
2396 For other parameters, see C<guestfs_sfdisk>.  You should usually
2397 pass C<0> for the cyls/heads/sectors parameters.");
2398
2399   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2400    [],
2401    "display the partition table",
2402    "\
2403 This displays the partition table on C<device>, in the
2404 human-readable output of the L<sfdisk(8)> command.  It is
2405 not intended to be parsed.");
2406
2407   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2408    [],
2409    "display the kernel geometry",
2410    "\
2411 This displays the kernel's idea of the geometry of C<device>.
2412
2413 The result is in human-readable format, and not designed to
2414 be parsed.");
2415
2416   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2417    [],
2418    "display the disk geometry from the partition table",
2419    "\
2420 This displays the disk geometry of C<device> read from the
2421 partition table.  Especially in the case where the underlying
2422 block device has been resized, this can be different from the
2423 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2424
2425 The result is in human-readable format, and not designed to
2426 be parsed.");
2427
2428   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2429    [],
2430    "activate or deactivate all volume groups",
2431    "\
2432 This command activates or (if C<activate> is false) deactivates
2433 all logical volumes in all volume groups.
2434 If activated, then they are made known to the
2435 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2436 then those devices disappear.
2437
2438 This command is the same as running C<vgchange -a y|n>");
2439
2440   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2441    [],
2442    "activate or deactivate some volume groups",
2443    "\
2444 This command activates or (if C<activate> is false) deactivates
2445 all logical volumes in the listed volume groups C<volgroups>.
2446 If activated, then they are made known to the
2447 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2448 then those devices disappear.
2449
2450 This command is the same as running C<vgchange -a y|n volgroups...>
2451
2452 Note that if C<volgroups> is an empty list then B<all> volume groups
2453 are activated or deactivated.");
2454
2455   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2456    [InitNone, Always, TestOutput (
2457       [["sfdiskM"; "/dev/sda"; ","];
2458        ["pvcreate"; "/dev/sda1"];
2459        ["vgcreate"; "VG"; "/dev/sda1"];
2460        ["lvcreate"; "LV"; "VG"; "10"];
2461        ["mkfs"; "ext2"; "/dev/VG/LV"];
2462        ["mount"; "/dev/VG/LV"; "/"];
2463        ["write_file"; "/new"; "test content"; "0"];
2464        ["umount"; "/"];
2465        ["lvresize"; "/dev/VG/LV"; "20"];
2466        ["e2fsck_f"; "/dev/VG/LV"];
2467        ["resize2fs"; "/dev/VG/LV"];
2468        ["mount"; "/dev/VG/LV"; "/"];
2469        ["cat"; "/new"]], "test content")],
2470    "resize an LVM logical volume",
2471    "\
2472 This resizes (expands or shrinks) an existing LVM logical
2473 volume to C<mbytes>.  When reducing, data in the reduced part
2474 is lost.");
2475
2476   ("resize2fs", (RErr, [Device "device"]), 106, [],
2477    [], (* lvresize tests this *)
2478    "resize an ext2/ext3 filesystem",
2479    "\
2480 This resizes an ext2 or ext3 filesystem to match the size of
2481 the underlying device.
2482
2483 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2484 on the C<device> before calling this command.  For unknown reasons
2485 C<resize2fs> sometimes gives an error about this and sometimes not.
2486 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2487 calling this function.");
2488
2489   ("find", (RStringList "names", [Pathname "directory"]), 107, [],
2490    [InitBasicFS, Always, TestOutputList (
2491       [["find"; "/"]], ["lost+found"]);
2492     InitBasicFS, Always, TestOutputList (
2493       [["touch"; "/a"];
2494        ["mkdir"; "/b"];
2495        ["touch"; "/b/c"];
2496        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2497     InitBasicFS, Always, TestOutputList (
2498       [["mkdir_p"; "/a/b/c"];
2499        ["touch"; "/a/b/c/d"];
2500        ["find"; "/a/b/"]], ["c"; "c/d"])],
2501    "find all files and directories",
2502    "\
2503 This command lists out all files and directories, recursively,
2504 starting at C<directory>.  It is essentially equivalent to
2505 running the shell command C<find directory -print> but some
2506 post-processing happens on the output, described below.
2507
2508 This returns a list of strings I<without any prefix>.  Thus
2509 if the directory structure was:
2510
2511  /tmp/a
2512  /tmp/b
2513  /tmp/c/d
2514
2515 then the returned list from C<guestfs_find> C</tmp> would be
2516 4 elements:
2517
2518  a
2519  b
2520  c
2521  c/d
2522
2523 If C<directory> is not a directory, then this command returns
2524 an error.
2525
2526 The returned list is sorted.");
2527
2528   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2529    [], (* lvresize tests this *)
2530    "check an ext2/ext3 filesystem",
2531    "\
2532 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2533 filesystem checker on C<device>, noninteractively (C<-p>),
2534 even if the filesystem appears to be clean (C<-f>).
2535
2536 This command is only needed because of C<guestfs_resize2fs>
2537 (q.v.).  Normally you should use C<guestfs_fsck>.");
2538
2539   ("sleep", (RErr, [Int "secs"]), 109, [],
2540    [InitNone, Always, TestRun (
2541       [["sleep"; "1"]])],
2542    "sleep for some seconds",
2543    "\
2544 Sleep for C<secs> seconds.");
2545
2546   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2547    [InitNone, Always, TestOutputInt (
2548       [["sfdiskM"; "/dev/sda"; ","];
2549        ["mkfs"; "ntfs"; "/dev/sda1"];
2550        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2551     InitNone, Always, TestOutputInt (
2552       [["sfdiskM"; "/dev/sda"; ","];
2553        ["mkfs"; "ext2"; "/dev/sda1"];
2554        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2555    "probe NTFS volume",
2556    "\
2557 This command runs the L<ntfs-3g.probe(8)> command which probes
2558 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2559 be mounted read-write, and some cannot be mounted at all).
2560
2561 C<rw> is a boolean flag.  Set it to true if you want to test
2562 if the volume can be mounted read-write.  Set it to false if
2563 you want to test if the volume can be mounted read-only.
2564
2565 The return value is an integer which C<0> if the operation
2566 would succeed, or some non-zero value documented in the
2567 L<ntfs-3g.probe(8)> manual page.");
2568
2569   ("sh", (RString "output", [String "command"]), 111, [],
2570    [], (* XXX needs tests *)
2571    "run a command via the shell",
2572    "\
2573 This call runs a command from the guest filesystem via the
2574 guest's C</bin/sh>.
2575
2576 This is like C<guestfs_command>, but passes the command to:
2577
2578  /bin/sh -c \"command\"
2579
2580 Depending on the guest's shell, this usually results in
2581 wildcards being expanded, shell expressions being interpolated
2582 and so on.
2583
2584 All the provisos about C<guestfs_command> apply to this call.");
2585
2586   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2587    [], (* XXX needs tests *)
2588    "run a command via the shell returning lines",
2589    "\
2590 This is the same as C<guestfs_sh>, but splits the result
2591 into a list of lines.
2592
2593 See also: C<guestfs_command_lines>");
2594
2595   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2596    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2597     * code in stubs.c, since all valid glob patterns must start with "/".
2598     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2599     *)
2600    [InitBasicFS, Always, TestOutputList (
2601       [["mkdir_p"; "/a/b/c"];
2602        ["touch"; "/a/b/c/d"];
2603        ["touch"; "/a/b/c/e"];
2604        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2605     InitBasicFS, Always, TestOutputList (
2606       [["mkdir_p"; "/a/b/c"];
2607        ["touch"; "/a/b/c/d"];
2608        ["touch"; "/a/b/c/e"];
2609        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2610     InitBasicFS, Always, TestOutputList (
2611       [["mkdir_p"; "/a/b/c"];
2612        ["touch"; "/a/b/c/d"];
2613        ["touch"; "/a/b/c/e"];
2614        ["glob_expand"; "/a/*/x/*"]], [])],
2615    "expand a wildcard path",
2616    "\
2617 This command searches for all the pathnames matching
2618 C<pattern> according to the wildcard expansion rules
2619 used by the shell.
2620
2621 If no paths match, then this returns an empty list
2622 (note: not an error).
2623
2624 It is just a wrapper around the C L<glob(3)> function
2625 with flags C<GLOB_MARK|GLOB_BRACE>.
2626 See that manual page for more details.");
2627
2628   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2629    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2630       [["scrub_device"; "/dev/sdc"]])],
2631    "scrub (securely wipe) a device",
2632    "\
2633 This command writes patterns over C<device> to make data retrieval
2634 more difficult.
2635
2636 It is an interface to the L<scrub(1)> program.  See that
2637 manual page for more details.");
2638
2639   ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2640    [InitBasicFS, Always, TestRun (
2641       [["write_file"; "/file"; "content"; "0"];
2642        ["scrub_file"; "/file"]])],
2643    "scrub (securely wipe) a file",
2644    "\
2645 This command writes patterns over a file to make data retrieval
2646 more difficult.
2647
2648 The file is I<removed> after scrubbing.
2649
2650 It is an interface to the L<scrub(1)> program.  See that
2651 manual page for more details.");
2652
2653   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2654    [], (* XXX needs testing *)
2655    "scrub (securely wipe) free space",
2656    "\
2657 This command creates the directory C<dir> and then fills it
2658 with files until the filesystem is full, and scrubs the files
2659 as for C<guestfs_scrub_file>, and deletes them.
2660 The intention is to scrub any free space on the partition
2661 containing C<dir>.
2662
2663 It is an interface to the L<scrub(1)> program.  See that
2664 manual page for more details.");
2665
2666   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2667    [InitBasicFS, Always, TestRun (
2668       [["mkdir"; "/tmp"];
2669        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2670    "create a temporary directory",
2671    "\
2672 This command creates a temporary directory.  The
2673 C<template> parameter should be a full pathname for the
2674 temporary directory name with the final six characters being
2675 \"XXXXXX\".
2676
2677 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2678 the second one being suitable for Windows filesystems.
2679
2680 The name of the temporary directory that was created
2681 is returned.
2682
2683 The temporary directory is created with mode 0700
2684 and is owned by root.
2685
2686 The caller is responsible for deleting the temporary
2687 directory and its contents after use.
2688
2689 See also: L<mkdtemp(3)>");
2690
2691   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2692    [InitISOFS, Always, TestOutputInt (
2693       [["wc_l"; "/10klines"]], 10000)],
2694    "count lines in a file",
2695    "\
2696 This command counts the lines in a file, using the
2697 C<wc -l> external command.");
2698
2699   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2700    [InitISOFS, Always, TestOutputInt (
2701       [["wc_w"; "/10klines"]], 10000)],
2702    "count words in a file",
2703    "\
2704 This command counts the words in a file, using the
2705 C<wc -w> external command.");
2706
2707   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2708    [InitISOFS, Always, TestOutputInt (
2709       [["wc_c"; "/100kallspaces"]], 102400)],
2710    "count characters in a file",
2711    "\
2712 This command counts the characters in a file, using the
2713 C<wc -c> external command.");
2714
2715   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2716    [InitISOFS, Always, TestOutputList (
2717       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2718    "return first 10 lines of a file",
2719    "\
2720 This command returns up to the first 10 lines of a file as
2721 a list of strings.");
2722
2723   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2724    [InitISOFS, Always, TestOutputList (
2725       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2726     InitISOFS, Always, TestOutputList (
2727       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2728     InitISOFS, Always, TestOutputList (
2729       [["head_n"; "0"; "/10klines"]], [])],
2730    "return first N lines of a file",
2731    "\
2732 If the parameter C<nrlines> is a positive number, this returns the first
2733 C<nrlines> lines of the file C<path>.
2734
2735 If the parameter C<nrlines> is a negative number, this returns lines
2736 from the file C<path>, excluding the last C<nrlines> lines.
2737
2738 If the parameter C<nrlines> is zero, this returns an empty list.");
2739
2740   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2741    [InitISOFS, Always, TestOutputList (
2742       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2743    "return last 10 lines of a file",
2744    "\
2745 This command returns up to the last 10 lines of a file as
2746 a list of strings.");
2747
2748   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2749    [InitISOFS, Always, TestOutputList (
2750       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2751     InitISOFS, Always, TestOutputList (
2752       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2753     InitISOFS, Always, TestOutputList (
2754       [["tail_n"; "0"; "/10klines"]], [])],
2755    "return last N lines of a file",
2756    "\
2757 If the parameter C<nrlines> is a positive number, this returns the last
2758 C<nrlines> lines of the file C<path>.
2759
2760 If the parameter C<nrlines> is a negative number, this returns lines
2761 from the file C<path>, starting with the C<-nrlines>th line.
2762
2763 If the parameter C<nrlines> is zero, this returns an empty list.");
2764
2765   ("df", (RString "output", []), 125, [],
2766    [], (* XXX Tricky to test because it depends on the exact format
2767         * of the 'df' command and other imponderables.
2768         *)
2769    "report file system disk space usage",
2770    "\
2771 This command runs the C<df> command to report disk space used.
2772
2773 This command is mostly useful for interactive sessions.  It
2774 is I<not> intended that you try to parse the output string.
2775 Use C<statvfs> from programs.");
2776
2777   ("df_h", (RString "output", []), 126, [],
2778    [], (* XXX Tricky to test because it depends on the exact format
2779         * of the 'df' command and other imponderables.
2780         *)
2781    "report file system disk space usage (human readable)",
2782    "\
2783 This command runs the C<df -h> command to report disk space used
2784 in human-readable format.
2785
2786 This command is mostly useful for interactive sessions.  It
2787 is I<not> intended that you try to parse the output string.
2788 Use C<statvfs> from programs.");
2789
2790   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2791    [InitISOFS, Always, TestOutputInt (
2792       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2793    "estimate file space usage",
2794    "\
2795 This command runs the C<du -s> command to estimate file space
2796 usage for C<path>.
2797
2798 C<path> can be a file or a directory.  If C<path> is a directory
2799 then the estimate includes the contents of the directory and all
2800 subdirectories (recursively).
2801
2802 The result is the estimated size in I<kilobytes>
2803 (ie. units of 1024 bytes).");
2804
2805   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2806    [InitISOFS, Always, TestOutputList (
2807       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2808    "list files in an initrd",
2809    "\
2810 This command lists out files contained in an initrd.
2811
2812 The files are listed without any initial C</> character.  The
2813 files are listed in the order they appear (not necessarily
2814 alphabetical).  Directory names are listed as separate items.
2815
2816 Old Linux kernels (2.4 and earlier) used a compressed ext2
2817 filesystem as initrd.  We I<only> support the newer initramfs
2818 format (compressed cpio files).");
2819
2820   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2821    [],
2822    "mount a file using the loop device",
2823    "\
2824 This command lets you mount C<file> (a filesystem image
2825 in a file) on a mount point.  It is entirely equivalent to
2826 the command C<mount -o loop file mountpoint>.");
2827
2828   ("mkswap", (RErr, [Device "device"]), 130, [],
2829    [InitEmpty, Always, TestRun (
2830       [["sfdiskM"; "/dev/sda"; ","];
2831        ["mkswap"; "/dev/sda1"]])],
2832    "create a swap partition",
2833    "\
2834 Create a swap partition on C<device>.");
2835
2836   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2837    [InitEmpty, Always, TestRun (
2838       [["sfdiskM"; "/dev/sda"; ","];
2839        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2840    "create a swap partition with a label",
2841    "\
2842 Create a swap partition on C<device> with label C<label>.
2843
2844 Note that you cannot attach a swap label to a block device
2845 (eg. C</dev/sda>), just to a partition.  This appears to be
2846 a limitation of the kernel or swap tools.");
2847
2848   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2849    (let uuid = uuidgen () in
2850     [InitEmpty, Always, TestRun (
2851        [["sfdiskM"; "/dev/sda"; ","];
2852         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2853    "create a swap partition with an explicit UUID",
2854    "\
2855 Create a swap partition on C<device> with UUID C<uuid>.");
2856
2857   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2858    [InitBasicFS, Always, TestOutputStruct (
2859       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2860        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2861        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2862     InitBasicFS, Always, TestOutputStruct (
2863       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2864        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2865    "make block, character or FIFO devices",
2866    "\
2867 This call creates block or character special devices, or
2868 named pipes (FIFOs).
2869
2870 The C<mode> parameter should be the mode, using the standard
2871 constants.  C<devmajor> and C<devminor> are the
2872 device major and minor numbers, only used when creating block
2873 and character special devices.");
2874
2875   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2876    [InitBasicFS, Always, TestOutputStruct (
2877       [["mkfifo"; "0o777"; "/node"];
2878        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2879    "make FIFO (named pipe)",
2880    "\
2881 This call creates a FIFO (named pipe) called C<path> with
2882 mode C<mode>.  It is just a convenient wrapper around
2883 C<guestfs_mknod>.");
2884
2885   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2886    [InitBasicFS, Always, TestOutputStruct (
2887       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2888        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2889    "make block device node",
2890    "\
2891 This call creates a block device node called C<path> with
2892 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2893 It is just a convenient wrapper around C<guestfs_mknod>.");
2894
2895   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2896    [InitBasicFS, Always, TestOutputStruct (
2897       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2898        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2899    "make char device node",
2900    "\
2901 This call creates a char device node called C<path> with
2902 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2903 It is just a convenient wrapper around C<guestfs_mknod>.");
2904
2905   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2906    [], (* XXX umask is one of those stateful things that we should
2907         * reset between each test.
2908         *)
2909    "set file mode creation mask (umask)",
2910    "\
2911 This function sets the mask used for creating new files and
2912 device nodes to C<mask & 0777>.
2913
2914 Typical umask values would be C<022> which creates new files
2915 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2916 C<002> which creates new files with permissions like
2917 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2918
2919 The default umask is C<022>.  This is important because it
2920 means that directories and device nodes will be created with
2921 C<0644> or C<0755> mode even if you specify C<0777>.
2922
2923 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2924
2925 This call returns the previous umask.");
2926
2927   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2928    [],
2929    "read directories entries",
2930    "\
2931 This returns the list of directory entries in directory C<dir>.
2932
2933 All entries in the directory are returned, including C<.> and
2934 C<..>.  The entries are I<not> sorted, but returned in the same
2935 order as the underlying filesystem.
2936
2937 Also this call returns basic file type information about each
2938 file.  The C<ftyp> field will contain one of the following characters:
2939
2940 =over 4
2941
2942 =item 'b'
2943
2944 Block special
2945
2946 =item 'c'
2947
2948 Char special
2949
2950 =item 'd'
2951
2952 Directory
2953
2954 =item 'f'
2955
2956 FIFO (named pipe)
2957
2958 =item 'l'
2959
2960 Symbolic link
2961
2962 =item 'r'
2963
2964 Regular file
2965
2966 =item 's'
2967
2968 Socket
2969
2970 =item 'u'
2971
2972 Unknown file type
2973
2974 =item '?'
2975
2976 The L<readdir(3)> returned a C<d_type> field with an
2977 unexpected value
2978
2979 =back
2980
2981 This function is primarily intended for use by programs.  To
2982 get a simple list of names, use C<guestfs_ls>.  To get a printable
2983 directory for human consumption, use C<guestfs_ll>.");
2984
2985   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
2986    [],
2987    "create partitions on a block device",
2988    "\
2989 This is a simplified interface to the C<guestfs_sfdisk>
2990 command, where partition sizes are specified in megabytes
2991 only (rounded to the nearest cylinder) and you don't need
2992 to specify the cyls, heads and sectors parameters which
2993 were rarely if ever used anyway.
2994
2995 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
2996
2997   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
2998    [],
2999    "determine file type inside a compressed file",
3000    "\
3001 This command runs C<file> after first decompressing C<path>
3002 using C<method>.
3003
3004 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3005
3006 Since 1.0.63, use C<guestfs_file> instead which can now
3007 process compressed files.");
3008
3009   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
3010    [],
3011    "list extended attributes of a file or directory",
3012    "\
3013 This call lists the extended attributes of the file or directory
3014 C<path>.
3015
3016 At the system call level, this is a combination of the
3017 L<listxattr(2)> and L<getxattr(2)> calls.
3018
3019 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3020
3021   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
3022    [],
3023    "list extended attributes of a file or directory",
3024    "\
3025 This is the same as C<guestfs_getxattrs>, but if C<path>
3026 is a symbolic link, then it returns the extended attributes
3027 of the link itself.");
3028
3029   ("setxattr", (RErr, [String "xattr";
3030                        String "val"; Int "vallen"; (* will be BufferIn *)
3031                        Pathname "path"]), 143, [],
3032    [],
3033    "set extended attribute of a file or directory",
3034    "\
3035 This call sets the extended attribute named C<xattr>
3036 of the file C<path> to the value C<val> (of length C<vallen>).
3037 The value is arbitrary 8 bit data.
3038
3039 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3040
3041   ("lsetxattr", (RErr, [String "xattr";
3042                         String "val"; Int "vallen"; (* will be BufferIn *)
3043                         Pathname "path"]), 144, [],
3044    [],
3045    "set extended attribute of a file or directory",
3046    "\
3047 This is the same as C<guestfs_setxattr>, but if C<path>
3048 is a symbolic link, then it sets an extended attribute
3049 of the link itself.");
3050
3051   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3052    [],
3053    "remove extended attribute of a file or directory",
3054    "\
3055 This call removes the extended attribute named C<xattr>
3056 of the file C<path>.
3057
3058 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3059
3060   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3061    [],
3062    "remove extended attribute of a file or directory",
3063    "\
3064 This is the same as C<guestfs_removexattr>, but if C<path>
3065 is a symbolic link, then it removes an extended attribute
3066 of the link itself.");
3067
3068   ("mountpoints", (RHashtable "mps", []), 147, [],
3069    [],
3070    "show mountpoints",
3071    "\
3072 This call is similar to C<guestfs_mounts>.  That call returns
3073 a list of devices.  This one returns a hash table (map) of
3074 device name to directory where the device is mounted.");
3075
3076   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3077   (* This is a special case: while you would expect a parameter
3078    * of type "Pathname", that doesn't work, because it implies
3079    * NEED_ROOT in the generated calling code in stubs.c, and
3080    * this function cannot use NEED_ROOT.
3081    *)
3082    [],
3083    "create a mountpoint",
3084    "\
3085 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3086 specialized calls that can be used to create extra mountpoints
3087 before mounting the first filesystem.
3088
3089 These calls are I<only> necessary in some very limited circumstances,
3090 mainly the case where you want to mount a mix of unrelated and/or
3091 read-only filesystems together.
3092
3093 For example, live CDs often contain a \"Russian doll\" nest of
3094 filesystems, an ISO outer layer, with a squashfs image inside, with
3095 an ext2/3 image inside that.  You can unpack this as follows
3096 in guestfish:
3097
3098  add-ro Fedora-11-i686-Live.iso
3099  run
3100  mkmountpoint /cd
3101  mkmountpoint /squash
3102  mkmountpoint /ext3
3103  mount /dev/sda /cd
3104  mount-loop /cd/LiveOS/squashfs.img /squash
3105  mount-loop /squash/LiveOS/ext3fs.img /ext3
3106
3107 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3108
3109   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3110    [],
3111    "remove a mountpoint",
3112    "\
3113 This calls removes a mountpoint that was previously created
3114 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3115 for full details.");
3116
3117   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3118    [InitISOFS, Always, TestOutputBuffer (
3119       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3120    "read a file",
3121    "\
3122 This calls returns the contents of the file C<path> as a
3123 buffer.
3124
3125 Unlike C<guestfs_cat>, this function can correctly
3126 handle files that contain embedded ASCII NUL characters.
3127 However unlike C<guestfs_download>, this function is limited
3128 in the total size of file that can be handled.");
3129
3130   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3131    [InitISOFS, Always, TestOutputList (
3132       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3133     InitISOFS, Always, TestOutputList (
3134       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3135    "return lines matching a pattern",
3136    "\
3137 This calls the external C<grep> program and returns the
3138 matching lines.");
3139
3140   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3141    [InitISOFS, Always, TestOutputList (
3142       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3143    "return lines matching a pattern",
3144    "\
3145 This calls the external C<egrep> program and returns the
3146 matching lines.");
3147
3148   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3149    [InitISOFS, Always, TestOutputList (
3150       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3151    "return lines matching a pattern",
3152    "\
3153 This calls the external C<fgrep> program and returns the
3154 matching lines.");
3155
3156   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3157    [InitISOFS, Always, TestOutputList (
3158       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3159    "return lines matching a pattern",
3160    "\
3161 This calls the external C<grep -i> program and returns the
3162 matching lines.");
3163
3164   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3165    [InitISOFS, Always, TestOutputList (
3166       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3167    "return lines matching a pattern",
3168    "\
3169 This calls the external C<egrep -i> program and returns the
3170 matching lines.");
3171
3172   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3173    [InitISOFS, Always, TestOutputList (
3174       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3175    "return lines matching a pattern",
3176    "\
3177 This calls the external C<fgrep -i> program and returns the
3178 matching lines.");
3179
3180   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3181    [InitISOFS, Always, TestOutputList (
3182       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3183    "return lines matching a pattern",
3184    "\
3185 This calls the external C<zgrep> program and returns the
3186 matching lines.");
3187
3188   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3189    [InitISOFS, Always, TestOutputList (
3190       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3191    "return lines matching a pattern",
3192    "\
3193 This calls the external C<zegrep> program and returns the
3194 matching lines.");
3195
3196   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3197    [InitISOFS, Always, TestOutputList (
3198       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3199    "return lines matching a pattern",
3200    "\
3201 This calls the external C<zfgrep> program and returns the
3202 matching lines.");
3203
3204   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3205    [InitISOFS, Always, TestOutputList (
3206       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3207    "return lines matching a pattern",
3208    "\
3209 This calls the external C<zgrep -i> program and returns the
3210 matching lines.");
3211
3212   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3213    [InitISOFS, Always, TestOutputList (
3214       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3215    "return lines matching a pattern",
3216    "\
3217 This calls the external C<zegrep -i> program and returns the
3218 matching lines.");
3219
3220   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3221    [InitISOFS, Always, TestOutputList (
3222       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3223    "return lines matching a pattern",
3224    "\
3225 This calls the external C<zfgrep -i> program and returns the
3226 matching lines.");
3227
3228   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3229    [InitISOFS, Always, TestOutput (
3230       [["realpath"; "/../directory"]], "/directory")],
3231    "canonicalized absolute pathname",
3232    "\
3233 Return the canonicalized absolute pathname of C<path>.  The
3234 returned path has no C<.>, C<..> or symbolic link path elements.");
3235
3236   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3237    [InitBasicFS, Always, TestOutputStruct (
3238       [["touch"; "/a"];
3239        ["ln"; "/a"; "/b"];
3240        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3241    "create a hard link",
3242    "\
3243 This command creates a hard link using the C<ln> command.");
3244
3245   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3246    [InitBasicFS, Always, TestOutputStruct (
3247       [["touch"; "/a"];
3248        ["touch"; "/b"];
3249        ["ln_f"; "/a"; "/b"];
3250        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3251    "create a hard link",
3252    "\
3253 This command creates a hard link using the C<ln -f> command.
3254 The C<-f> option removes the link (C<linkname>) if it exists already.");
3255
3256   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3257    [InitBasicFS, Always, TestOutputStruct (
3258       [["touch"; "/a"];
3259        ["ln_s"; "a"; "/b"];
3260        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3261    "create a symbolic link",
3262    "\
3263 This command creates a symbolic link using the C<ln -s> command.");
3264
3265   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3266    [InitBasicFS, Always, TestOutput (
3267       [["mkdir_p"; "/a/b"];
3268        ["touch"; "/a/b/c"];
3269        ["ln_sf"; "../d"; "/a/b/c"];
3270        ["readlink"; "/a/b/c"]], "../d")],
3271    "create a symbolic link",
3272    "\
3273 This command creates a symbolic link using the C<ln -sf> command,
3274 The C<-f> option removes the link (C<linkname>) if it exists already.");
3275
3276   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3277    [] (* XXX tested above *),
3278    "read the target of a symbolic link",
3279    "\
3280 This command reads the target of a symbolic link.");
3281
3282   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3283    [InitBasicFS, Always, TestOutputStruct (
3284       [["fallocate"; "/a"; "1000000"];
3285        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3286    "preallocate a file in the guest filesystem",
3287    "\
3288 This command preallocates a file (containing zero bytes) named
3289 C<path> of size C<len> bytes.  If the file exists already, it
3290 is overwritten.
3291
3292 Do not confuse this with the guestfish-specific
3293 C<alloc> command which allocates a file in the host and
3294 attaches it as a device.");
3295
3296   ("swapon_device", (RErr, [Device "device"]), 170, [],
3297    [InitPartition, Always, TestRun (
3298       [["mkswap"; "/dev/sda1"];
3299        ["swapon_device"; "/dev/sda1"];
3300        ["swapoff_device"; "/dev/sda1"]])],
3301    "enable swap on device",
3302    "\
3303 This command enables the libguestfs appliance to use the
3304 swap device or partition named C<device>.  The increased
3305 memory is made available for all commands, for example
3306 those run using C<guestfs_command> or C<guestfs_sh>.
3307
3308 Note that you should not swap to existing guest swap
3309 partitions unless you know what you are doing.  They may
3310 contain hibernation information, or other information that
3311 the guest doesn't want you to trash.  You also risk leaking
3312 information about the host to the guest this way.  Instead,
3313 attach a new host device to the guest and swap on that.");
3314
3315   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3316    [], (* XXX tested by swapon_device *)
3317    "disable swap on device",
3318    "\
3319 This command disables the libguestfs appliance swap
3320 device or partition named C<device>.
3321 See C<guestfs_swapon_device>.");
3322
3323   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3324    [InitBasicFS, Always, TestRun (
3325       [["fallocate"; "/swap"; "8388608"];
3326        ["mkswap_file"; "/swap"];
3327        ["swapon_file"; "/swap"];
3328        ["swapoff_file"; "/swap"]])],
3329    "enable swap on file",
3330    "\
3331 This command enables swap to a file.
3332 See C<guestfs_swapon_device> for other notes.");
3333
3334   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3335    [], (* XXX tested by swapon_file *)
3336    "disable swap on file",
3337    "\
3338 This command disables the libguestfs appliance swap on file.");
3339
3340   ("swapon_label", (RErr, [String "label"]), 174, [],
3341    [InitEmpty, Always, TestRun (
3342       [["sfdiskM"; "/dev/sdb"; ","];
3343        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3344        ["swapon_label"; "swapit"];
3345        ["swapoff_label"; "swapit"];
3346        ["zero"; "/dev/sdb"];
3347        ["blockdev_rereadpt"; "/dev/sdb"]])],
3348    "enable swap on labeled swap partition",
3349    "\
3350 This command enables swap to a labeled swap partition.
3351 See C<guestfs_swapon_device> for other notes.");
3352
3353   ("swapoff_label", (RErr, [String "label"]), 175, [],
3354    [], (* XXX tested by swapon_label *)
3355    "disable swap on labeled swap partition",
3356    "\
3357 This command disables the libguestfs appliance swap on
3358 labeled swap partition.");
3359
3360   ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3361    (let uuid = uuidgen () in
3362     [InitEmpty, Always, TestRun (
3363        [["mkswap_U"; uuid; "/dev/sdb"];
3364         ["swapon_uuid"; uuid];
3365         ["swapoff_uuid"; uuid]])]),
3366    "enable swap on swap partition by UUID",
3367    "\
3368 This command enables swap to a swap partition with the given UUID.
3369 See C<guestfs_swapon_device> for other notes.");
3370
3371   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3372    [], (* XXX tested by swapon_uuid *)
3373    "disable swap on swap partition by UUID",
3374    "\
3375 This command disables the libguestfs appliance swap partition
3376 with the given UUID.");
3377
3378   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3379    [InitBasicFS, Always, TestRun (
3380       [["fallocate"; "/swap"; "8388608"];
3381        ["mkswap_file"; "/swap"]])],
3382    "create a swap file",
3383    "\
3384 Create a swap file.
3385
3386 This command just writes a swap file signature to an existing
3387 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3388
3389   ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3390    [InitISOFS, Always, TestRun (
3391       [["inotify_init"; "0"]])],
3392    "create an inotify handle",
3393    "\
3394 This command creates a new inotify handle.
3395 The inotify subsystem can be used to notify events which happen to
3396 objects in the guest filesystem.
3397
3398 C<maxevents> is the maximum number of events which will be
3399 queued up between calls to C<guestfs_inotify_read> or
3400 C<guestfs_inotify_files>.
3401 If this is passed as C<0>, then the kernel (or previously set)
3402 default is used.  For Linux 2.6.29 the default was 16384 events.
3403 Beyond this limit, the kernel throws away events, but records
3404 the fact that it threw them away by setting a flag
3405 C<IN_Q_OVERFLOW> in the returned structure list (see
3406 C<guestfs_inotify_read>).
3407
3408 Before any events are generated, you have to add some
3409 watches to the internal watch list.  See:
3410 C<guestfs_inotify_add_watch>,
3411 C<guestfs_inotify_rm_watch> and
3412 C<guestfs_inotify_watch_all>.
3413
3414 Queued up events should be read periodically by calling
3415 C<guestfs_inotify_read>
3416 (or C<guestfs_inotify_files> which is just a helpful
3417 wrapper around C<guestfs_inotify_read>).  If you don't
3418 read the events out often enough then you risk the internal
3419 queue overflowing.
3420
3421 The handle should be closed after use by calling
3422 C<guestfs_inotify_close>.  This also removes any
3423 watches automatically.
3424
3425 See also L<inotify(7)> for an overview of the inotify interface
3426 as exposed by the Linux kernel, which is roughly what we expose
3427 via libguestfs.  Note that there is one global inotify handle
3428 per libguestfs instance.");
3429
3430   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3431    [InitBasicFS, Always, TestOutputList (
3432       [["inotify_init"; "0"];
3433        ["inotify_add_watch"; "/"; "1073741823"];
3434        ["touch"; "/a"];
3435        ["touch"; "/b"];
3436        ["inotify_files"]], ["a"; "b"])],
3437    "add an inotify watch",
3438    "\
3439 Watch C<path> for the events listed in C<mask>.
3440
3441 Note that if C<path> is a directory then events within that
3442 directory are watched, but this does I<not> happen recursively
3443 (in subdirectories).
3444
3445 Note for non-C or non-Linux callers: the inotify events are
3446 defined by the Linux kernel ABI and are listed in
3447 C</usr/include/sys/inotify.h>.");
3448
3449   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3450    [],
3451    "remove an inotify watch",
3452    "\
3453 Remove a previously defined inotify watch.
3454 See C<guestfs_inotify_add_watch>.");
3455
3456   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3457    [],
3458    "return list of inotify events",
3459    "\
3460 Return the complete queue of events that have happened
3461 since the previous read call.
3462
3463 If no events have happened, this returns an empty list.
3464
3465 I<Note>: In order to make sure that all events have been
3466 read, you must call this function repeatedly until it
3467 returns an empty list.  The reason is that the call will
3468 read events up to the maximum appliance-to-host message
3469 size and leave remaining events in the queue.");
3470
3471   ("inotify_files", (RStringList "paths", []), 183, [],
3472    [],
3473    "return list of watched files that had events",
3474    "\
3475 This function is a helpful wrapper around C<guestfs_inotify_read>
3476 which just returns a list of pathnames of objects that were
3477 touched.  The returned pathnames are sorted and deduplicated.");
3478
3479   ("inotify_close", (RErr, []), 184, [],
3480    [],
3481    "close the inotify handle",
3482    "\
3483 This closes the inotify handle which was previously
3484 opened by inotify_init.  It removes all watches, throws
3485 away any pending events, and deallocates all resources.");
3486
3487   ("setcon", (RErr, [String "context"]), 185, [],
3488    [],
3489    "set SELinux security context",
3490    "\
3491 This sets the SELinux security context of the daemon
3492 to the string C<context>.
3493
3494 See the documentation about SELINUX in L<guestfs(3)>.");
3495
3496   ("getcon", (RString "context", []), 186, [],
3497    [],
3498    "get SELinux security context",
3499    "\
3500 This gets the SELinux security context of the daemon.
3501
3502 See the documentation about SELINUX in L<guestfs(3)>,
3503 and C<guestfs_setcon>");
3504
3505   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3506    [InitEmpty, Always, TestOutput (
3507       [["sfdiskM"; "/dev/sda"; ","];
3508        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3509        ["mount"; "/dev/sda1"; "/"];
3510        ["write_file"; "/new"; "new file contents"; "0"];
3511        ["cat"; "/new"]], "new file contents")],
3512    "make a filesystem with block size",
3513    "\
3514 This call is similar to C<guestfs_mkfs>, but it allows you to
3515 control the block size of the resulting filesystem.  Supported
3516 block sizes depend on the filesystem type, but typically they
3517 are C<1024>, C<2048> or C<4096> only.");
3518
3519   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3520    [InitEmpty, Always, TestOutput (
3521       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3522        ["mke2journal"; "4096"; "/dev/sda1"];
3523        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3524        ["mount"; "/dev/sda2"; "/"];
3525        ["write_file"; "/new"; "new file contents"; "0"];
3526        ["cat"; "/new"]], "new file contents")],
3527    "make ext2/3/4 external journal",
3528    "\
3529 This creates an ext2 external journal on C<device>.  It is equivalent
3530 to the command:
3531
3532  mke2fs -O journal_dev -b blocksize device");
3533
3534   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3535    [InitEmpty, Always, TestOutput (
3536       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3537        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3538        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3539        ["mount"; "/dev/sda2"; "/"];
3540        ["write_file"; "/new"; "new file contents"; "0"];
3541        ["cat"; "/new"]], "new file contents")],
3542    "make ext2/3/4 external journal with label",
3543    "\
3544 This creates an ext2 external journal on C<device> with label C<label>.");
3545
3546   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3547    (let uuid = uuidgen () in
3548     [InitEmpty, Always, TestOutput (
3549        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3550         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3551         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3552         ["mount"; "/dev/sda2"; "/"];
3553         ["write_file"; "/new"; "new file contents"; "0"];
3554         ["cat"; "/new"]], "new file contents")]),
3555    "make ext2/3/4 external journal with UUID",
3556    "\
3557 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3558
3559   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3560    [],
3561    "make ext2/3/4 filesystem with external journal",
3562    "\
3563 This creates an ext2/3/4 filesystem on C<device> with
3564 an external journal on C<journal>.  It is equivalent
3565 to the command:
3566
3567  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3568
3569 See also C<guestfs_mke2journal>.");
3570
3571   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3572    [],
3573    "make ext2/3/4 filesystem with external journal",
3574    "\
3575 This creates an ext2/3/4 filesystem on C<device> with
3576 an external journal on the journal labeled C<label>.
3577
3578 See also C<guestfs_mke2journal_L>.");
3579
3580   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3581    [],
3582    "make ext2/3/4 filesystem with external journal",
3583    "\
3584 This creates an ext2/3/4 filesystem on C<device> with
3585 an external journal on the journal with UUID C<uuid>.
3586
3587 See also C<guestfs_mke2journal_U>.");
3588
3589   ("modprobe", (RErr, [String "modulename"]), 194, [],
3590    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3591    "load a kernel module",
3592    "\
3593 This loads a kernel module in the appliance.
3594
3595 The kernel module must have been whitelisted when libguestfs
3596 was built (see C<appliance/kmod.whitelist.in> in the source).");
3597
3598   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3599    [InitNone, Always, TestOutput (
3600      [["echo_daemon"; "This is a test"]], "This is a test"
3601    )],
3602    "echo arguments back to the client",
3603    "\
3604 This command concatenate the list of C<words> passed with single spaces between
3605 them and returns the resulting string.
3606
3607 You can use this command to test the connection through to the daemon.
3608
3609 See also C<guestfs_ping_daemon>.");
3610
3611 ]
3612
3613 let all_functions = non_daemon_functions @ daemon_functions
3614
3615 (* In some places we want the functions to be displayed sorted
3616  * alphabetically, so this is useful:
3617  *)
3618 let all_functions_sorted =
3619   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3620                compare n1 n2) all_functions
3621
3622 (* Field types for structures. *)
3623 type field =
3624   | FChar                       (* C 'char' (really, a 7 bit byte). *)
3625   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
3626   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
3627   | FUInt32
3628   | FInt32
3629   | FUInt64
3630   | FInt64
3631   | FBytes                      (* Any int measure that counts bytes. *)
3632   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
3633   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
3634
3635 (* Because we generate extra parsing code for LVM command line tools,
3636  * we have to pull out the LVM columns separately here.
3637  *)
3638 let lvm_pv_cols = [
3639   "pv_name", FString;
3640   "pv_uuid", FUUID;
3641   "pv_fmt", FString;
3642   "pv_size", FBytes;
3643   "dev_size", FBytes;
3644   "pv_free", FBytes;
3645   "pv_used", FBytes;
3646   "pv_attr", FString (* XXX *);
3647   "pv_pe_count", FInt64;
3648   "pv_pe_alloc_count", FInt64;
3649   "pv_tags", FString;
3650   "pe_start", FBytes;
3651   "pv_mda_count", FInt64;
3652   "pv_mda_free", FBytes;
3653   (* Not in Fedora 10:
3654      "pv_mda_size", FBytes;
3655   *)
3656 ]
3657 let lvm_vg_cols = [
3658   "vg_name", FString;
3659   "vg_uuid", FUUID;
3660   "vg_fmt", FString;
3661   "vg_attr", FString (* XXX *);
3662   "vg_size", FBytes;
3663   "vg_free", FBytes;
3664   "vg_sysid", FString;
3665   "vg_extent_size", FBytes;
3666   "vg_extent_count", FInt64;
3667   "vg_free_count", FInt64;
3668   "max_lv", FInt64;
3669   "max_pv", FInt64;
3670   "pv_count", FInt64;
3671   "lv_count", FInt64;
3672   "snap_count", FInt64;
3673   "vg_seqno", FInt64;
3674   "vg_tags", FString;
3675   "vg_mda_count", FInt64;
3676   "vg_mda_free", FBytes;
3677   (* Not in Fedora 10:
3678      "vg_mda_size", FBytes;
3679   *)
3680 ]
3681 let lvm_lv_cols = [
3682   "lv_name", FString;
3683   "lv_uuid", FUUID;
3684   "lv_attr", FString (* XXX *);
3685   "lv_major", FInt64;
3686   "lv_minor", FInt64;
3687   "lv_kernel_major", FInt64;
3688   "lv_kernel_minor", FInt64;
3689   "lv_size", FBytes;
3690   "seg_count", FInt64;
3691   "origin", FString;
3692   "snap_percent", FOptPercent;
3693   "copy_percent", FOptPercent;
3694   "move_pv", FString;
3695   "lv_tags", FString;
3696   "mirror_log", FString;
3697   "modules", FString;
3698 ]
3699
3700 (* Names and fields in all structures (in RStruct and RStructList)
3701  * that we support.
3702  *)
3703 let structs = [
3704   (* The old RIntBool return type, only ever used for aug_defnode.  Do
3705    * not use this struct in any new code.
3706    *)
3707   "int_bool", [
3708     "i", FInt32;                (* for historical compatibility *)
3709     "b", FInt32;                (* for historical compatibility *)
3710   ];
3711
3712   (* LVM PVs, VGs, LVs. *)
3713   "lvm_pv", lvm_pv_cols;
3714   "lvm_vg", lvm_vg_cols;
3715   "lvm_lv", lvm_lv_cols;
3716
3717   (* Column names and types from stat structures.
3718    * NB. Can't use things like 'st_atime' because glibc header files
3719    * define some of these as macros.  Ugh.
3720    *)
3721   "stat", [
3722     "dev", FInt64;
3723     "ino", FInt64;
3724     "mode", FInt64;
3725     "nlink", FInt64;
3726     "uid", FInt64;
3727     "gid", FInt64;
3728     "rdev", FInt64;
3729     "size", FInt64;
3730     "blksize", FInt64;
3731     "blocks", FInt64;
3732     "atime", FInt64;
3733     "mtime", FInt64;
3734     "ctime", FInt64;
3735   ];
3736   "statvfs", [
3737     "bsize", FInt64;
3738     "frsize", FInt64;
3739     "blocks", FInt64;
3740     "bfree", FInt64;
3741     "bavail", FInt64;
3742     "files", FInt64;
3743     "ffree", FInt64;
3744     "favail", FInt64;
3745     "fsid", FInt64;
3746     "flag", FInt64;
3747     "namemax", FInt64;
3748   ];
3749
3750   (* Column names in dirent structure. *)
3751   "dirent", [
3752     "ino", FInt64;
3753     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
3754     "ftyp", FChar;
3755     "name", FString;
3756   ];
3757
3758   (* Version numbers. *)
3759   "version", [
3760     "major", FInt64;
3761     "minor", FInt64;
3762     "release", FInt64;
3763     "extra", FString;
3764   ];
3765
3766   (* Extended attribute. *)
3767   "xattr", [
3768     "attrname", FString;
3769     "attrval", FBuffer;
3770   ];
3771
3772   (* Inotify events. *)
3773   "inotify_event", [
3774     "in_wd", FInt64;
3775     "in_mask", FUInt32;
3776     "in_cookie", FUInt32;
3777     "in_name", FString;
3778   ];
3779 ] (* end of structs *)
3780
3781 (* Ugh, Java has to be different ..
3782  * These names are also used by the Haskell bindings.
3783  *)
3784 let java_structs = [
3785   "int_bool", "IntBool";
3786   "lvm_pv", "PV";
3787   "lvm_vg", "VG";
3788   "lvm_lv", "LV";
3789   "stat", "Stat";
3790   "statvfs", "StatVFS";
3791   "dirent", "Dirent";
3792   "version", "Version";
3793   "xattr", "XAttr";
3794   "inotify_event", "INotifyEvent";
3795 ]
3796
3797 (* What structs are actually returned. *)
3798 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
3799
3800 (* Returns a list of RStruct/RStructList structs that are returned
3801  * by any function.  Each element of returned list is a pair:
3802  *
3803  * (structname, RStructOnly)
3804  *    == there exists function which returns RStruct (_, structname)
3805  * (structname, RStructListOnly)
3806  *    == there exists function which returns RStructList (_, structname)
3807  * (structname, RStructAndList)
3808  *    == there are functions returning both RStruct (_, structname)
3809  *                                      and RStructList (_, structname)
3810  *)
3811 let rstructs_used =
3812   (* ||| is a "logical OR" for rstructs_used_t *)
3813   let (|||) a b =
3814     match a, b with
3815     | RStructAndList, _
3816     | _, RStructAndList -> RStructAndList
3817     | RStructOnly, RStructListOnly
3818     | RStructListOnly, RStructOnly -> RStructAndList
3819     | RStructOnly, RStructOnly -> RStructOnly
3820     | RStructListOnly, RStructListOnly -> RStructListOnly
3821   in
3822
3823   let h = Hashtbl.create 13 in
3824
3825   (* if elem->oldv exists, update entry using ||| operator,
3826    * else just add elem->newv to the hash
3827    *)
3828   let update elem newv =
3829     try  let oldv = Hashtbl.find h elem in
3830          Hashtbl.replace h elem (newv ||| oldv)
3831     with Not_found -> Hashtbl.add h elem newv
3832   in
3833
3834   List.iter (
3835     fun (_, style, _, _, _, _, _) ->
3836       match fst style with
3837       | RStruct (_, structname) -> update structname RStructOnly
3838       | RStructList (_, structname) -> update structname RStructListOnly
3839       | _ -> ()
3840   ) all_functions;
3841
3842   (* return key->values as a list of (key,value) *)
3843   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
3844
3845 (* debug:
3846 let () =
3847   List.iter (
3848     function
3849     | sn, RStructOnly -> printf "%s RStructOnly\n" sn
3850     | sn, RStructListOnly -> printf "%s RStructListOnly\n" sn
3851     | sn, RStructAndList -> printf "%s RStructAndList\n" sn
3852   ) rstructs_used
3853 *)
3854
3855 (* Used for testing language bindings. *)
3856 type callt =
3857   | CallString of string
3858   | CallOptString of string option
3859   | CallStringList of string list
3860   | CallInt of int
3861   | CallBool of bool
3862
3863 (* Used to memoize the result of pod2text. *)
3864 let pod2text_memo_filename = "src/.pod2text.data"
3865 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
3866   try
3867     let chan = open_in pod2text_memo_filename in
3868     let v = input_value chan in
3869     close_in chan;
3870     v
3871   with
3872     _ -> Hashtbl.create 13
3873 let pod2text_memo_updated () =
3874   let chan = open_out pod2text_memo_filename in
3875   output_value chan pod2text_memo;
3876   close_out chan
3877
3878 (* Useful functions.
3879  * Note we don't want to use any external OCaml libraries which
3880  * makes this a bit harder than it should be.
3881  *)
3882 let failwithf fs = ksprintf failwith fs
3883
3884 let replace_char s c1 c2 =
3885   let s2 = String.copy s in
3886   let r = ref false in
3887   for i = 0 to String.length s2 - 1 do
3888     if String.unsafe_get s2 i = c1 then (
3889       String.unsafe_set s2 i c2;
3890       r := true
3891     )
3892   done;
3893   if not !r then s else s2
3894
3895 let isspace c =
3896   c = ' '
3897   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
3898
3899 let triml ?(test = isspace) str =
3900   let i = ref 0 in
3901   let n = ref (String.length str) in
3902   while !n > 0 && test str.[!i]; do
3903     decr n;
3904     incr i
3905   done;
3906   if !i = 0 then str
3907   else String.sub str !i !n
3908
3909 let trimr ?(test = isspace) str =
3910   let n = ref (String.length str) in
3911   while !n > 0 && test str.[!n-1]; do
3912     decr n
3913   done;
3914   if !n = String.length str then str
3915   else String.sub str 0 !n
3916
3917 let trim ?(test = isspace) str =
3918   trimr ~test (triml ~test str)
3919
3920 let rec find s sub =
3921   let len = String.length s in
3922   let sublen = String.length sub in
3923   let rec loop i =
3924     if i <= len-sublen then (
3925       let rec loop2 j =
3926         if j < sublen then (
3927           if s.[i+j] = sub.[j] then loop2 (j+1)
3928           else -1
3929         ) else
3930           i (* found *)
3931       in
3932       let r = loop2 0 in
3933       if r = -1 then loop (i+1) else r
3934     ) else
3935       -1 (* not found *)
3936   in
3937   loop 0
3938
3939 let rec replace_str s s1 s2 =
3940   let len = String.length s in
3941   let sublen = String.length s1 in
3942   let i = find s s1 in
3943   if i = -1 then s
3944   else (
3945     let s' = String.sub s 0 i in
3946     let s'' = String.sub s (i+sublen) (len-i-sublen) in
3947     s' ^ s2 ^ replace_str s'' s1 s2
3948   )
3949
3950 let rec string_split sep str =
3951   let len = String.length str in
3952   let seplen = String.length sep in
3953   let i = find str sep in
3954   if i = -1 then [str]
3955   else (
3956     let s' = String.sub str 0 i in
3957     let s'' = String.sub str (i+seplen) (len-i-seplen) in
3958     s' :: string_split sep s''
3959   )
3960
3961 let files_equal n1 n2 =
3962   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
3963   match Sys.command cmd with
3964   | 0 -> true
3965   | 1 -> false
3966   | i -> failwithf "%s: failed with error code %d" cmd i
3967
3968 let rec filter_map f = function
3969   | [] -> []
3970   | x :: xs ->
3971       match f x with
3972       | Some y -> y :: filter_map f xs
3973       | None -> filter_map f xs
3974
3975 let rec find_map f = function
3976   | [] -> raise Not_found
3977   | x :: xs ->
3978       match f x with
3979       | Some y -> y
3980       | None -> find_map f xs
3981
3982 let iteri f xs =
3983   let rec loop i = function
3984     | [] -> ()
3985     | x :: xs -> f i x; loop (i+1) xs
3986   in
3987   loop 0 xs
3988
3989 let mapi f xs =
3990   let rec loop i = function
3991     | [] -> []
3992     | x :: xs -> let r = f i x in r :: loop (i+1) xs
3993   in
3994   loop 0 xs
3995
3996 let name_of_argt = function
3997   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
3998   | StringList n | DeviceList n | Bool n | Int n
3999   | FileIn n | FileOut n -> n
4000
4001 let java_name_of_struct typ =
4002   try List.assoc typ java_structs
4003   with Not_found ->
4004     failwithf
4005       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4006
4007 let cols_of_struct typ =
4008   try List.assoc typ structs
4009   with Not_found ->
4010     failwithf "cols_of_struct: unknown struct %s" typ
4011
4012 let seq_of_test = function
4013   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4014   | TestOutputListOfDevices (s, _)
4015   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4016   | TestOutputTrue s | TestOutputFalse s
4017   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4018   | TestOutputStruct (s, _)
4019   | TestLastFail s -> s
4020
4021 (* Handling for function flags. *)
4022 let protocol_limit_warning =
4023   "Because of the message protocol, there is a transfer limit
4024 of somewhere between 2MB and 4MB.  To transfer large files you should use
4025 FTP."
4026
4027 let danger_will_robinson =
4028   "B<This command is dangerous.  Without careful use you
4029 can easily destroy all your data>."
4030
4031 let deprecation_notice flags =
4032   try
4033     let alt =
4034       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4035     let txt =
4036       sprintf "This function is deprecated.
4037 In new code, use the C<%s> call instead.
4038
4039 Deprecated functions will not be removed from the API, but the
4040 fact that they are deprecated indicates that there are problems
4041 with correct use of these functions." alt in
4042     Some txt
4043   with
4044     Not_found -> None
4045
4046 (* Check function names etc. for consistency. *)
4047 let check_functions () =
4048   let contains_uppercase str =
4049     let len = String.length str in
4050     let rec loop i =
4051       if i >= len then false
4052       else (
4053         let c = str.[i] in
4054         if c >= 'A' && c <= 'Z' then true
4055         else loop (i+1)
4056       )
4057     in
4058     loop 0
4059   in
4060
4061   (* Check function names. *)
4062   List.iter (
4063     fun (name, _, _, _, _, _, _) ->
4064       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4065         failwithf "function name %s does not need 'guestfs' prefix" name;
4066       if name = "" then
4067         failwithf "function name is empty";
4068       if name.[0] < 'a' || name.[0] > 'z' then
4069         failwithf "function name %s must start with lowercase a-z" name;
4070       if String.contains name '-' then
4071         failwithf "function name %s should not contain '-', use '_' instead."
4072           name
4073   ) all_functions;
4074
4075   (* Check function parameter/return names. *)
4076   List.iter (
4077     fun (name, style, _, _, _, _, _) ->
4078       let check_arg_ret_name n =
4079         if contains_uppercase n then
4080           failwithf "%s param/ret %s should not contain uppercase chars"
4081             name n;
4082         if String.contains n '-' || String.contains n '_' then
4083           failwithf "%s param/ret %s should not contain '-' or '_'"
4084             name n;
4085         if n = "value" then
4086           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;
4087         if n = "int" || n = "char" || n = "short" || n = "long" then
4088           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4089         if n = "i" || n = "n" then
4090           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4091         if n = "argv" || n = "args" then
4092           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4093
4094         (* List Haskell, OCaml and C keywords here.
4095          * http://www.haskell.org/haskellwiki/Keywords
4096          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4097          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4098          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4099          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4100          * Omitting _-containing words, since they're handled above.
4101          * Omitting the OCaml reserved word, "val", is ok,
4102          * and saves us from renaming several parameters.
4103          *)
4104         let reserved = [
4105           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4106           "char"; "class"; "const"; "constraint"; "continue"; "data";
4107           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4108           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4109           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4110           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4111           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4112           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4113           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4114           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4115           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4116           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4117           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4118           "volatile"; "when"; "where"; "while";
4119           ] in
4120         if List.mem n reserved then
4121           failwithf "%s has param/ret using reserved word %s" name n;
4122       in
4123
4124       (match fst style with
4125        | RErr -> ()
4126        | RInt n | RInt64 n | RBool n
4127        | RConstString n | RConstOptString n | RString n
4128        | RStringList n | RStruct (n, _) | RStructList (n, _)
4129        | RHashtable n | RBufferOut n ->
4130            check_arg_ret_name n
4131       );
4132       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4133   ) all_functions;
4134
4135   (* Check short descriptions. *)
4136   List.iter (
4137     fun (name, _, _, _, _, shortdesc, _) ->
4138       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4139         failwithf "short description of %s should begin with lowercase." name;
4140       let c = shortdesc.[String.length shortdesc-1] in
4141       if c = '\n' || c = '.' then
4142         failwithf "short description of %s should not end with . or \\n." name
4143   ) all_functions;
4144
4145   (* Check long dscriptions. *)
4146   List.iter (
4147     fun (name, _, _, _, _, _, longdesc) ->
4148       if longdesc.[String.length longdesc-1] = '\n' then
4149         failwithf "long description of %s should not end with \\n." name
4150   ) all_functions;
4151
4152   (* Check proc_nrs. *)
4153   List.iter (
4154     fun (name, _, proc_nr, _, _, _, _) ->
4155       if proc_nr <= 0 then
4156         failwithf "daemon function %s should have proc_nr > 0" name
4157   ) daemon_functions;
4158
4159   List.iter (
4160     fun (name, _, proc_nr, _, _, _, _) ->
4161       if proc_nr <> -1 then
4162         failwithf "non-daemon function %s should have proc_nr -1" name
4163   ) non_daemon_functions;
4164
4165   let proc_nrs =
4166     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4167       daemon_functions in
4168   let proc_nrs =
4169     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4170   let rec loop = function
4171     | [] -> ()
4172     | [_] -> ()
4173     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4174         loop rest
4175     | (name1,nr1) :: (name2,nr2) :: _ ->
4176         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4177           name1 name2 nr1 nr2
4178   in
4179   loop proc_nrs;
4180
4181   (* Check tests. *)
4182   List.iter (
4183     function
4184       (* Ignore functions that have no tests.  We generate a
4185        * warning when the user does 'make check' instead.
4186        *)
4187     | name, _, _, _, [], _, _ -> ()
4188     | name, _, _, _, tests, _, _ ->
4189         let funcs =
4190           List.map (
4191             fun (_, _, test) ->
4192               match seq_of_test test with
4193               | [] ->
4194                   failwithf "%s has a test containing an empty sequence" name
4195               | cmds -> List.map List.hd cmds
4196           ) tests in
4197         let funcs = List.flatten funcs in
4198
4199         let tested = List.mem name funcs in
4200
4201         if not tested then
4202           failwithf "function %s has tests but does not test itself" name
4203   ) all_functions
4204
4205 (* 'pr' prints to the current output file. *)
4206 let chan = ref stdout
4207 let pr fs = ksprintf (output_string !chan) fs
4208
4209 (* Generate a header block in a number of standard styles. *)
4210 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4211 type license = GPLv2 | LGPLv2
4212
4213 let generate_header comment license =
4214   let c = match comment with
4215     | CStyle ->     pr "/* "; " *"
4216     | HashStyle ->  pr "# ";  "#"
4217     | OCamlStyle -> pr "(* "; " *"
4218     | HaskellStyle -> pr "{- "; "  " in
4219   pr "libguestfs generated file\n";
4220   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4221   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4222   pr "%s\n" c;
4223   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4224   pr "%s\n" c;
4225   (match license with
4226    | GPLv2 ->
4227        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4228        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4229        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4230        pr "%s (at your option) any later version.\n" c;
4231        pr "%s\n" c;
4232        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4233        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4234        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4235        pr "%s GNU General Public License for more details.\n" c;
4236        pr "%s\n" c;
4237        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4238        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4239        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4240
4241    | LGPLv2 ->
4242        pr "%s This library is free software; you can redistribute it and/or\n" c;
4243        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4244        pr "%s License as published by the Free Software Foundation; either\n" c;
4245        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4246        pr "%s\n" c;
4247        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4248        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4249        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4250        pr "%s Lesser General Public License for more details.\n" c;
4251        pr "%s\n" c;
4252        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4253        pr "%s License along with this library; if not, write to the Free Software\n" c;
4254        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4255   );
4256   (match comment with
4257    | CStyle -> pr " */\n"
4258    | HashStyle -> ()
4259    | OCamlStyle -> pr " *)\n"
4260    | HaskellStyle -> pr "-}\n"
4261   );
4262   pr "\n"
4263
4264 (* Start of main code generation functions below this line. *)
4265
4266 (* Generate the pod documentation for the C API. *)
4267 let rec generate_actions_pod () =
4268   List.iter (
4269     fun (shortname, style, _, flags, _, _, longdesc) ->
4270       if not (List.mem NotInDocs flags) then (
4271         let name = "guestfs_" ^ shortname in
4272         pr "=head2 %s\n\n" name;
4273         pr " ";
4274         generate_prototype ~extern:false ~handle:"handle" name style;
4275         pr "\n\n";
4276         pr "%s\n\n" longdesc;
4277         (match fst style with
4278          | RErr ->
4279              pr "This function returns 0 on success or -1 on error.\n\n"
4280          | RInt _ ->
4281              pr "On error this function returns -1.\n\n"
4282          | RInt64 _ ->
4283              pr "On error this function returns -1.\n\n"
4284          | RBool _ ->
4285              pr "This function returns a C truth value on success or -1 on error.\n\n"
4286          | RConstString _ ->
4287              pr "This function returns a string, or NULL on error.
4288 The string is owned by the guest handle and must I<not> be freed.\n\n"
4289          | RConstOptString _ ->
4290              pr "This function returns a string which may be NULL.
4291 There is way to return an error from this function.
4292 The string is owned by the guest handle and must I<not> be freed.\n\n"
4293          | RString _ ->
4294              pr "This function returns a string, or NULL on error.
4295 I<The caller must free the returned string after use>.\n\n"
4296          | RStringList _ ->
4297              pr "This function returns a NULL-terminated array of strings
4298 (like L<environ(3)>), or NULL if there was an error.
4299 I<The caller must free the strings and the array after use>.\n\n"
4300          | RStruct (_, typ) ->
4301              pr "This function returns a C<struct guestfs_%s *>,
4302 or NULL if there was an error.
4303 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4304          | RStructList (_, typ) ->
4305              pr "This function returns a C<struct guestfs_%s_list *>
4306 (see E<lt>guestfs-structs.hE<gt>),
4307 or NULL if there was an error.
4308 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4309          | RHashtable _ ->
4310              pr "This function returns a NULL-terminated array of
4311 strings, or NULL if there was an error.
4312 The array of strings will always have length C<2n+1>, where
4313 C<n> keys and values alternate, followed by the trailing NULL entry.
4314 I<The caller must free the strings and the array after use>.\n\n"
4315          | RBufferOut _ ->
4316              pr "This function returns a buffer, or NULL on error.
4317 The size of the returned buffer is written to C<*size_r>.
4318 I<The caller must free the returned buffer after use>.\n\n"
4319         );
4320         if List.mem ProtocolLimitWarning flags then
4321           pr "%s\n\n" protocol_limit_warning;
4322         if List.mem DangerWillRobinson flags then
4323           pr "%s\n\n" danger_will_robinson;
4324         match deprecation_notice flags with
4325         | None -> ()
4326         | Some txt -> pr "%s\n\n" txt
4327       )
4328   ) all_functions_sorted
4329
4330 and generate_structs_pod () =
4331   (* Structs documentation. *)
4332   List.iter (
4333     fun (typ, cols) ->
4334       pr "=head2 guestfs_%s\n" typ;
4335       pr "\n";
4336       pr " struct guestfs_%s {\n" typ;
4337       List.iter (
4338         function
4339         | name, FChar -> pr "   char %s;\n" name
4340         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4341         | name, FInt32 -> pr "   int32_t %s;\n" name
4342         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4343         | name, FInt64 -> pr "   int64_t %s;\n" name
4344         | name, FString -> pr "   char *%s;\n" name
4345         | name, FBuffer ->
4346             pr "   /* The next two fields describe a byte array. */\n";
4347             pr "   uint32_t %s_len;\n" name;
4348             pr "   char *%s;\n" name
4349         | name, FUUID ->
4350             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4351             pr "   char %s[32];\n" name
4352         | name, FOptPercent ->
4353             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4354             pr "   float %s;\n" name
4355       ) cols;
4356       pr " };\n";
4357       pr " \n";
4358       pr " struct guestfs_%s_list {\n" typ;
4359       pr "   uint32_t len; /* Number of elements in list. */\n";
4360       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4361       pr " };\n";
4362       pr " \n";
4363       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4364       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4365         typ typ;
4366       pr "\n"
4367   ) structs
4368
4369 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4370  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4371  *
4372  * We have to use an underscore instead of a dash because otherwise
4373  * rpcgen generates incorrect code.
4374  *
4375  * This header is NOT exported to clients, but see also generate_structs_h.
4376  *)
4377 and generate_xdr () =
4378   generate_header CStyle LGPLv2;
4379
4380   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4381   pr "typedef string str<>;\n";
4382   pr "\n";
4383
4384   (* Internal structures. *)
4385   List.iter (
4386     function
4387     | typ, cols ->
4388         pr "struct guestfs_int_%s {\n" typ;
4389         List.iter (function
4390                    | name, FChar -> pr "  char %s;\n" name
4391                    | name, FString -> pr "  string %s<>;\n" name
4392                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4393                    | name, FUUID -> pr "  opaque %s[32];\n" name
4394                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4395                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4396                    | name, FOptPercent -> pr "  float %s;\n" name
4397                   ) cols;
4398         pr "};\n";
4399         pr "\n";
4400         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4401         pr "\n";
4402   ) structs;
4403
4404   List.iter (
4405     fun (shortname, style, _, _, _, _, _) ->
4406       let name = "guestfs_" ^ shortname in
4407
4408       (match snd style with
4409        | [] -> ()
4410        | args ->
4411            pr "struct %s_args {\n" name;
4412            List.iter (
4413              function
4414              | Pathname n | Device n | Dev_or_Path n | String n -> pr "  string %s<>;\n" n
4415              | OptString n -> pr "  str *%s;\n" n
4416              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
4417              | Bool n -> pr "  bool %s;\n" n
4418              | Int n -> pr "  int %s;\n" n
4419              | FileIn _ | FileOut _ -> ()
4420            ) args;
4421            pr "};\n\n"
4422       );
4423       (match fst style with
4424        | RErr -> ()
4425        | RInt n ->
4426            pr "struct %s_ret {\n" name;
4427            pr "  int %s;\n" n;
4428            pr "};\n\n"
4429        | RInt64 n ->
4430            pr "struct %s_ret {\n" name;
4431            pr "  hyper %s;\n" n;
4432            pr "};\n\n"
4433        | RBool n ->
4434            pr "struct %s_ret {\n" name;
4435            pr "  bool %s;\n" n;
4436            pr "};\n\n"
4437        | RConstString _ | RConstOptString _ ->
4438            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4439        | RString n ->
4440            pr "struct %s_ret {\n" name;
4441            pr "  string %s<>;\n" n;
4442            pr "};\n\n"
4443        | RStringList n ->
4444            pr "struct %s_ret {\n" name;
4445            pr "  str %s<>;\n" n;
4446            pr "};\n\n"
4447        | RStruct (n, typ) ->
4448            pr "struct %s_ret {\n" name;
4449            pr "  guestfs_int_%s %s;\n" typ n;
4450            pr "};\n\n"
4451        | RStructList (n, typ) ->
4452            pr "struct %s_ret {\n" name;
4453            pr "  guestfs_int_%s_list %s;\n" typ n;
4454            pr "};\n\n"
4455        | RHashtable n ->
4456            pr "struct %s_ret {\n" name;
4457            pr "  str %s<>;\n" n;
4458            pr "};\n\n"
4459        | RBufferOut n ->
4460            pr "struct %s_ret {\n" name;
4461            pr "  opaque %s<>;\n" n;
4462            pr "};\n\n"
4463       );
4464   ) daemon_functions;
4465
4466   (* Table of procedure numbers. *)
4467   pr "enum guestfs_procedure {\n";
4468   List.iter (
4469     fun (shortname, _, proc_nr, _, _, _, _) ->
4470       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4471   ) daemon_functions;
4472   pr "  GUESTFS_PROC_NR_PROCS\n";
4473   pr "};\n";
4474   pr "\n";
4475
4476   (* Having to choose a maximum message size is annoying for several
4477    * reasons (it limits what we can do in the API), but it (a) makes
4478    * the protocol a lot simpler, and (b) provides a bound on the size
4479    * of the daemon which operates in limited memory space.  For large
4480    * file transfers you should use FTP.
4481    *)
4482   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4483   pr "\n";
4484
4485   (* Message header, etc. *)
4486   pr "\
4487 /* The communication protocol is now documented in the guestfs(3)
4488  * manpage.
4489  */
4490
4491 const GUESTFS_PROGRAM = 0x2000F5F5;
4492 const GUESTFS_PROTOCOL_VERSION = 1;
4493
4494 /* These constants must be larger than any possible message length. */
4495 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4496 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4497
4498 enum guestfs_message_direction {
4499   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
4500   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
4501 };
4502
4503 enum guestfs_message_status {
4504   GUESTFS_STATUS_OK = 0,
4505   GUESTFS_STATUS_ERROR = 1
4506 };
4507
4508 const GUESTFS_ERROR_LEN = 256;
4509
4510 struct guestfs_message_error {
4511   string error_message<GUESTFS_ERROR_LEN>;
4512 };
4513
4514 struct guestfs_message_header {
4515   unsigned prog;                     /* GUESTFS_PROGRAM */
4516   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
4517   guestfs_procedure proc;            /* GUESTFS_PROC_x */
4518   guestfs_message_direction direction;
4519   unsigned serial;                   /* message serial number */
4520   guestfs_message_status status;
4521 };
4522
4523 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4524
4525 struct guestfs_chunk {
4526   int cancel;                        /* if non-zero, transfer is cancelled */
4527   /* data size is 0 bytes if the transfer has finished successfully */
4528   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4529 };
4530 "
4531
4532 (* Generate the guestfs-structs.h file. *)
4533 and generate_structs_h () =
4534   generate_header CStyle LGPLv2;
4535
4536   (* This is a public exported header file containing various
4537    * structures.  The structures are carefully written to have
4538    * exactly the same in-memory format as the XDR structures that
4539    * we use on the wire to the daemon.  The reason for creating
4540    * copies of these structures here is just so we don't have to
4541    * export the whole of guestfs_protocol.h (which includes much
4542    * unrelated and XDR-dependent stuff that we don't want to be
4543    * public, or required by clients).
4544    *
4545    * To reiterate, we will pass these structures to and from the
4546    * client with a simple assignment or memcpy, so the format
4547    * must be identical to what rpcgen / the RFC defines.
4548    *)
4549
4550   (* Public structures. *)
4551   List.iter (
4552     fun (typ, cols) ->
4553       pr "struct guestfs_%s {\n" typ;
4554       List.iter (
4555         function
4556         | name, FChar -> pr "  char %s;\n" name
4557         | name, FString -> pr "  char *%s;\n" name
4558         | name, FBuffer ->
4559             pr "  uint32_t %s_len;\n" name;
4560             pr "  char *%s;\n" name
4561         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4562         | name, FUInt32 -> pr "  uint32_t %s;\n" name
4563         | name, FInt32 -> pr "  int32_t %s;\n" name
4564         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
4565         | name, FInt64 -> pr "  int64_t %s;\n" name
4566         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
4567       ) cols;
4568       pr "};\n";
4569       pr "\n";
4570       pr "struct guestfs_%s_list {\n" typ;
4571       pr "  uint32_t len;\n";
4572       pr "  struct guestfs_%s *val;\n" typ;
4573       pr "};\n";
4574       pr "\n";
4575       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4576       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4577       pr "\n"
4578   ) structs
4579
4580 (* Generate the guestfs-actions.h file. *)
4581 and generate_actions_h () =
4582   generate_header CStyle LGPLv2;
4583   List.iter (
4584     fun (shortname, style, _, _, _, _, _) ->
4585       let name = "guestfs_" ^ shortname in
4586       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4587         name style
4588   ) all_functions
4589
4590 (* Generate the guestfs-internal-actions.h file. *)
4591 and generate_internal_actions_h () =
4592   generate_header CStyle LGPLv2;
4593   List.iter (
4594     fun (shortname, style, _, _, _, _, _) ->
4595       let name = "guestfs__" ^ shortname in
4596       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4597         name style
4598   ) non_daemon_functions
4599
4600 (* Generate the client-side dispatch stubs. *)
4601 and generate_client_actions () =
4602   generate_header CStyle LGPLv2;
4603
4604   pr "\
4605 #include <stdio.h>
4606 #include <stdlib.h>
4607
4608 #include \"guestfs.h\"
4609 #include \"guestfs-internal-actions.h\"
4610 #include \"guestfs_protocol.h\"
4611
4612 #define error guestfs_error
4613 //#define perrorf guestfs_perrorf
4614 //#define safe_malloc guestfs_safe_malloc
4615 #define safe_realloc guestfs_safe_realloc
4616 //#define safe_strdup guestfs_safe_strdup
4617 #define safe_memdup guestfs_safe_memdup
4618
4619 /* Check the return message from a call for validity. */
4620 static int
4621 check_reply_header (guestfs_h *g,
4622                     const struct guestfs_message_header *hdr,
4623                     unsigned int proc_nr, unsigned int serial)
4624 {
4625   if (hdr->prog != GUESTFS_PROGRAM) {
4626     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4627     return -1;
4628   }
4629   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4630     error (g, \"wrong protocol version (%%d/%%d)\",
4631            hdr->vers, GUESTFS_PROTOCOL_VERSION);
4632     return -1;
4633   }
4634   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4635     error (g, \"unexpected message direction (%%d/%%d)\",
4636            hdr->direction, GUESTFS_DIRECTION_REPLY);
4637     return -1;
4638   }
4639   if (hdr->proc != proc_nr) {
4640     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4641     return -1;
4642   }
4643   if (hdr->serial != serial) {
4644     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4645     return -1;
4646   }
4647
4648   return 0;
4649 }
4650
4651 /* Check we are in the right state to run a high-level action. */
4652 static int
4653 check_state (guestfs_h *g, const char *caller)
4654 {
4655   if (!guestfs_is_ready (g)) {
4656     if (guestfs_is_config (g))
4657       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4658         caller);
4659     else if (guestfs_is_launching (g))
4660       error (g, \"%%s: call wait_ready() before using this function\",
4661         caller);
4662     else
4663       error (g, \"%%s called from the wrong state, %%d != READY\",
4664         caller, guestfs_get_state (g));
4665     return -1;
4666   }
4667   return 0;
4668 }
4669
4670 ";
4671
4672   (* Generate code to generate guestfish call traces. *)
4673   let trace_call shortname style =
4674     pr "  if (guestfs__get_trace (g)) {\n";
4675
4676     let needs_i =
4677       List.exists (function
4678                    | StringList _ | DeviceList _ -> true
4679                    | _ -> false) (snd style) in
4680     if needs_i then (
4681       pr "    int i;\n";
4682       pr "\n"
4683     );
4684
4685     pr "    printf (\"%s\");\n" shortname;
4686     List.iter (
4687       function
4688       | String n                        (* strings *)
4689       | Device n
4690       | Pathname n
4691       | Dev_or_Path n
4692       | FileIn n
4693       | FileOut n ->
4694           (* guestfish doesn't support string escaping, so neither do we *)
4695           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
4696       | OptString n ->                  (* string option *)
4697           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
4698           pr "    else printf (\" null\");\n"
4699       | StringList n
4700       | DeviceList n ->                 (* string list *)
4701           pr "    putchar (' ');\n";
4702           pr "    putchar ('\"');\n";
4703           pr "    for (i = 0; %s[i]; ++i) {\n" n;
4704           pr "      if (i > 0) putchar (' ');\n";
4705           pr "      fputs (%s[i], stdout);\n" n;
4706           pr "    }\n";
4707           pr "    putchar ('\"');\n";
4708       | Bool n ->                       (* boolean *)
4709           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
4710       | Int n ->                        (* int *)
4711           pr "    printf (\" %%d\", %s);\n" n
4712     ) (snd style);
4713     pr "    putchar ('\\n');\n";
4714     pr "  }\n";
4715     pr "\n";
4716   in
4717
4718   (* For non-daemon functions, generate a wrapper around each function. *)
4719   List.iter (
4720     fun (shortname, style, _, _, _, _, _) ->
4721       let name = "guestfs_" ^ shortname in
4722
4723       generate_prototype ~extern:false ~semicolon:false ~newline:true
4724         ~handle:"g" name style;
4725       pr "{\n";
4726       trace_call shortname style;
4727       pr "  return guestfs__%s " shortname;
4728       generate_c_call_args ~handle:"g" style;
4729       pr ";\n";
4730       pr "}\n";
4731       pr "\n"
4732   ) non_daemon_functions;
4733
4734   (* Client-side stubs for each function. *)
4735   List.iter (
4736     fun (shortname, style, _, _, _, _, _) ->
4737       let name = "guestfs_" ^ shortname in
4738
4739       (* Generate the context struct which stores the high-level
4740        * state between callback functions.
4741        *)
4742       pr "struct %s_ctx {\n" shortname;
4743       pr "  /* This flag is set by the callbacks, so we know we've done\n";
4744       pr "   * the callbacks as expected, and in the right sequence.\n";
4745       pr "   * 0 = not called, 1 = reply_cb called.\n";
4746       pr "   */\n";
4747       pr "  int cb_sequence;\n";
4748       pr "  struct guestfs_message_header hdr;\n";
4749       pr "  struct guestfs_message_error err;\n";
4750       (match fst style with
4751        | RErr -> ()
4752        | RConstString _ | RConstOptString _ ->
4753            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4754        | RInt _ | RInt64 _
4755        | RBool _ | RString _ | RStringList _
4756        | RStruct _ | RStructList _
4757        | RHashtable _ | RBufferOut _ ->
4758            pr "  struct %s_ret ret;\n" name
4759       );
4760       pr "};\n";
4761       pr "\n";
4762
4763       (* Generate the reply callback function. *)
4764       pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
4765       pr "{\n";
4766       pr "  guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4767       pr "  struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname;
4768       pr "\n";
4769       pr "  /* This should definitely not happen. */\n";
4770       pr "  if (ctx->cb_sequence != 0) {\n";
4771       pr "    ctx->cb_sequence = 9999;\n";
4772       pr "    error (g, \"%%s: internal error: reply callback called twice\", \"%s\");\n" name;
4773       pr "    return;\n";
4774       pr "  }\n";
4775       pr "\n";
4776       pr "  ml->main_loop_quit (ml, g);\n";
4777       pr "\n";
4778       pr "  if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n";
4779       pr "    error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name;
4780       pr "    return;\n";
4781       pr "  }\n";
4782       pr "  if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {\n";
4783       pr "    if (!xdr_guestfs_message_error (xdr, &ctx->err)) {\n";
4784       pr "      error (g, \"%%s: failed to parse reply error\", \"%s\");\n"
4785         name;
4786       pr "      return;\n";
4787       pr "    }\n";
4788       pr "    goto done;\n";
4789       pr "  }\n";
4790
4791       (match fst style with
4792        | RErr -> ()
4793        | RConstString _ | RConstOptString _ ->
4794            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4795        | RInt _ | RInt64 _
4796        | RBool _ | RString _ | RStringList _
4797        | RStruct _ | RStructList _
4798        | RHashtable _ | RBufferOut _ ->
4799            pr "  if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name;
4800            pr "    error (g, \"%%s: failed to parse reply\", \"%s\");\n" name;
4801            pr "    return;\n";
4802            pr "  }\n";
4803       );
4804
4805       pr " done:\n";
4806       pr "  ctx->cb_sequence = 1;\n";
4807       pr "}\n\n";
4808
4809       (* Generate the action stub. *)
4810       generate_prototype ~extern:false ~semicolon:false ~newline:true
4811         ~handle:"g" name style;
4812
4813       let error_code =
4814         match fst style with
4815         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4816         | RConstString _ | RConstOptString _ ->
4817             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4818         | RString _ | RStringList _
4819         | RStruct _ | RStructList _
4820         | RHashtable _ | RBufferOut _ ->
4821             "NULL" in
4822
4823       pr "{\n";
4824
4825       (match snd style with
4826        | [] -> ()
4827        | _ -> pr "  struct %s_args args;\n" name
4828       );
4829
4830       pr "  struct %s_ctx ctx;\n" shortname;
4831       pr "  guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4832       pr "  int serial;\n";
4833       pr "\n";
4834       trace_call shortname style;
4835       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4836       pr "  guestfs_set_busy (g);\n";
4837       pr "\n";
4838       pr "  memset (&ctx, 0, sizeof ctx);\n";
4839       pr "\n";
4840
4841       (* Send the main header and arguments. *)
4842       (match snd style with
4843        | [] ->
4844            pr "  serial = guestfs__send_sync (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4845              (String.uppercase shortname)
4846        | args ->
4847            List.iter (
4848              function
4849              | Pathname n | Device n | Dev_or_Path n | String n ->
4850                  pr "  args.%s = (char *) %s;\n" n n
4851              | OptString n ->
4852                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
4853              | StringList n | DeviceList n ->
4854                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
4855                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4856              | Bool n ->
4857                  pr "  args.%s = %s;\n" n n
4858              | Int n ->
4859                  pr "  args.%s = %s;\n" n n
4860              | FileIn _ | FileOut _ -> ()
4861            ) args;
4862            pr "  serial = guestfs__send_sync (g, GUESTFS_PROC_%s,\n"
4863              (String.uppercase shortname);
4864            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4865              name;
4866       );
4867       pr "  if (serial == -1) {\n";
4868       pr "    guestfs_end_busy (g);\n";
4869       pr "    return %s;\n" error_code;
4870       pr "  }\n";
4871       pr "\n";
4872
4873       (* Send any additional files (FileIn) requested. *)
4874       let need_read_reply_label = ref false in
4875       List.iter (
4876         function
4877         | FileIn n ->
4878             pr "  {\n";
4879             pr "    int r;\n";
4880             pr "\n";
4881             pr "    r = guestfs__send_file_sync (g, %s);\n" n;
4882             pr "    if (r == -1) {\n";
4883             pr "      guestfs_end_busy (g);\n";
4884             pr "      return %s;\n" error_code;
4885             pr "    }\n";
4886             pr "    if (r == -2) /* daemon cancelled */\n";
4887             pr "      goto read_reply;\n";
4888             need_read_reply_label := true;
4889             pr "  }\n";
4890             pr "\n";
4891         | _ -> ()
4892       ) (snd style);
4893
4894       (* Wait for the reply from the remote end. *)
4895       if !need_read_reply_label then pr " read_reply:\n";
4896       pr "  guestfs__switch_to_receiving (g);\n";
4897       pr "  ctx.cb_sequence = 0;\n";
4898       pr "  guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname;
4899       pr "  (void) ml->main_loop_run (ml, g);\n";
4900       pr "  guestfs_set_reply_callback (g, NULL, NULL);\n";
4901       pr "  if (ctx.cb_sequence != 1) {\n";
4902       pr "    error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name;
4903       pr "    guestfs_end_busy (g);\n";
4904       pr "    return %s;\n" error_code;
4905       pr "  }\n";
4906       pr "\n";
4907
4908       pr "  if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
4909         (String.uppercase shortname);
4910       pr "    guestfs_end_busy (g);\n";
4911       pr "    return %s;\n" error_code;
4912       pr "  }\n";
4913       pr "\n";
4914
4915       pr "  if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {\n";
4916       pr "    error (g, \"%%s\", ctx.err.error_message);\n";
4917       pr "    free (ctx.err.error_message);\n";
4918       pr "    guestfs_end_busy (g);\n";
4919       pr "    return %s;\n" error_code;
4920       pr "  }\n";
4921       pr "\n";
4922
4923       (* Expecting to receive further files (FileOut)? *)
4924       List.iter (
4925         function
4926         | FileOut n ->
4927             pr "  if (guestfs__receive_file_sync (g, %s) == -1) {\n" n;
4928             pr "    guestfs_end_busy (g);\n";
4929             pr "    return %s;\n" error_code;
4930             pr "  }\n";
4931             pr "\n";
4932         | _ -> ()
4933       ) (snd style);
4934
4935       pr "  guestfs_end_busy (g);\n";
4936
4937       (match fst style with
4938        | RErr -> pr "  return 0;\n"
4939        | RInt n | RInt64 n | RBool n ->
4940            pr "  return ctx.ret.%s;\n" n
4941        | RConstString _ | RConstOptString _ ->
4942            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4943        | RString n ->
4944            pr "  return ctx.ret.%s; /* caller will free */\n" n
4945        | RStringList n | RHashtable n ->
4946            pr "  /* caller will free this, but we need to add a NULL entry */\n";
4947            pr "  ctx.ret.%s.%s_val =\n" n n;
4948            pr "    safe_realloc (g, ctx.ret.%s.%s_val,\n" n n;
4949            pr "                  sizeof (char *) * (ctx.ret.%s.%s_len + 1));\n"
4950              n n;
4951            pr "  ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n;
4952            pr "  return ctx.ret.%s.%s_val;\n" n n
4953        | RStruct (n, _) ->
4954            pr "  /* caller will free this */\n";
4955            pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4956        | RStructList (n, _) ->
4957            pr "  /* caller will free this */\n";
4958            pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4959        | RBufferOut n ->
4960            pr "  *size_r = ctx.ret.%s.%s_len;\n" n n;
4961            pr "  return ctx.ret.%s.%s_val; /* caller will free */\n" n n
4962       );
4963
4964       pr "}\n\n"
4965   ) daemon_functions;
4966
4967   (* Functions to free structures. *)
4968   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
4969   pr " * structure format is identical to the XDR format.  See note in\n";
4970   pr " * generator.ml.\n";
4971   pr " */\n";
4972   pr "\n";
4973
4974   List.iter (
4975     fun (typ, _) ->
4976       pr "void\n";
4977       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
4978       pr "{\n";
4979       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
4980       pr "  free (x);\n";
4981       pr "}\n";
4982       pr "\n";
4983
4984       pr "void\n";
4985       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
4986       pr "{\n";
4987       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
4988       pr "  free (x);\n";
4989       pr "}\n";
4990       pr "\n";
4991
4992   ) structs;
4993
4994 (* Generate daemon/actions.h. *)
4995 and generate_daemon_actions_h () =
4996   generate_header CStyle GPLv2;
4997
4998   pr "#include \"../src/guestfs_protocol.h\"\n";
4999   pr "\n";
5000
5001   List.iter (
5002     fun (name, style, _, _, _, _, _) ->
5003       generate_prototype
5004         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5005         name style;
5006   ) daemon_functions
5007
5008 (* Generate the server-side stubs. *)
5009 and generate_daemon_actions () =
5010   generate_header CStyle GPLv2;
5011
5012   pr "#include <config.h>\n";
5013   pr "\n";
5014   pr "#include <stdio.h>\n";
5015   pr "#include <stdlib.h>\n";
5016   pr "#include <string.h>\n";
5017   pr "#include <inttypes.h>\n";
5018   pr "#include <ctype.h>\n";
5019   pr "#include <rpc/types.h>\n";
5020   pr "#include <rpc/xdr.h>\n";
5021   pr "\n";
5022   pr "#include \"daemon.h\"\n";
5023   pr "#include \"../src/guestfs_protocol.h\"\n";
5024   pr "#include \"actions.h\"\n";
5025   pr "\n";
5026
5027   List.iter (
5028     fun (name, style, _, _, _, _, _) ->
5029       (* Generate server-side stubs. *)
5030       pr "static void %s_stub (XDR *xdr_in)\n" name;
5031       pr "{\n";
5032       let error_code =
5033         match fst style with
5034         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5035         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5036         | RBool _ -> pr "  int r;\n"; "-1"
5037         | RConstString _ | RConstOptString _ ->
5038             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5039         | RString _ -> pr "  char *r;\n"; "NULL"
5040         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5041         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5042         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5043         | RBufferOut _ ->
5044             pr "  size_t size;\n";
5045             pr "  char *r;\n";
5046             "NULL" in
5047
5048       (match snd style with
5049        | [] -> ()
5050        | args ->
5051            pr "  struct guestfs_%s_args args;\n" name;
5052            List.iter (
5053              function
5054              | Device n | Dev_or_Path n
5055              | Pathname n
5056              | String n -> ()
5057              | OptString n -> pr "  char *%s;\n" n
5058              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5059              | Bool n -> pr "  int %s;\n" n
5060              | Int n -> pr "  int %s;\n" n
5061              | FileIn _ | FileOut _ -> ()
5062            ) args
5063       );
5064       pr "\n";
5065
5066       (match snd style with
5067        | [] -> ()
5068        | args ->
5069            pr "  memset (&args, 0, sizeof args);\n";
5070            pr "\n";
5071            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5072            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5073            pr "    return;\n";
5074            pr "  }\n";
5075            let pr_args n =
5076              pr "  char *%s = args.%s;\n" n n
5077            in
5078            let pr_list_handling_code n =
5079              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5080              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5081              pr "  if (%s == NULL) {\n" n;
5082              pr "    reply_with_perror (\"realloc\");\n";
5083              pr "    goto done;\n";
5084              pr "  }\n";
5085              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5086              pr "  args.%s.%s_val = %s;\n" n n n;
5087            in
5088            List.iter (
5089              function
5090              | Pathname n ->
5091                  pr_args n;
5092                  pr "  ABS_PATH (%s, goto done);\n" n;
5093              | Device n ->
5094                  pr_args n;
5095                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5096              | Dev_or_Path n ->
5097                  pr_args n;
5098                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5099              | String n -> pr_args n
5100              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5101              | StringList n ->
5102                  pr_list_handling_code n;
5103              | DeviceList n ->
5104                  pr_list_handling_code n;
5105                  pr "  /* Ensure that each is a device,\n";
5106                  pr "   * and perform device name translation. */\n";
5107                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5108                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5109                  pr "  }\n";
5110              | Bool n -> pr "  %s = args.%s;\n" n n
5111              | Int n -> pr "  %s = args.%s;\n" n n
5112              | FileIn _ | FileOut _ -> ()
5113            ) args;
5114            pr "\n"
5115       );
5116
5117
5118       (* this is used at least for do_equal *)
5119       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5120         (* Emit NEED_ROOT just once, even when there are two or
5121            more Pathname args *)
5122         pr "  NEED_ROOT (goto done);\n";
5123       );
5124
5125       (* Don't want to call the impl with any FileIn or FileOut
5126        * parameters, since these go "outside" the RPC protocol.
5127        *)
5128       let args' =
5129         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5130           (snd style) in
5131       pr "  r = do_%s " name;
5132       generate_c_call_args (fst style, args');
5133       pr ";\n";
5134
5135       pr "  if (r == %s)\n" error_code;
5136       pr "    /* do_%s has already called reply_with_error */\n" name;
5137       pr "    goto done;\n";
5138       pr "\n";
5139
5140       (* If there are any FileOut parameters, then the impl must
5141        * send its own reply.
5142        *)
5143       let no_reply =
5144         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5145       if no_reply then
5146         pr "  /* do_%s has already sent a reply */\n" name
5147       else (
5148         match fst style with
5149         | RErr -> pr "  reply (NULL, NULL);\n"
5150         | RInt n | RInt64 n | RBool n ->
5151             pr "  struct guestfs_%s_ret ret;\n" name;
5152             pr "  ret.%s = r;\n" n;
5153             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5154               name
5155         | RConstString _ | RConstOptString _ ->
5156             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5157         | RString n ->
5158             pr "  struct guestfs_%s_ret ret;\n" name;
5159             pr "  ret.%s = r;\n" n;
5160             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5161               name;
5162             pr "  free (r);\n"
5163         | RStringList n | RHashtable n ->
5164             pr "  struct guestfs_%s_ret ret;\n" name;
5165             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5166             pr "  ret.%s.%s_val = r;\n" n n;
5167             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5168               name;
5169             pr "  free_strings (r);\n"
5170         | RStruct (n, _) ->
5171             pr "  struct guestfs_%s_ret ret;\n" name;
5172             pr "  ret.%s = *r;\n" n;
5173             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5174               name;
5175             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5176               name
5177         | RStructList (n, _) ->
5178             pr "  struct guestfs_%s_ret ret;\n" name;
5179             pr "  ret.%s = *r;\n" n;
5180             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5181               name;
5182             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5183               name
5184         | RBufferOut n ->
5185             pr "  struct guestfs_%s_ret ret;\n" name;
5186             pr "  ret.%s.%s_val = r;\n" n n;
5187             pr "  ret.%s.%s_len = size;\n" n n;
5188             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5189               name;
5190             pr "  free (r);\n"
5191       );
5192
5193       (* Free the args. *)
5194       (match snd style with
5195        | [] ->
5196            pr "done: ;\n";
5197        | _ ->
5198            pr "done:\n";
5199            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5200              name
5201       );
5202
5203       pr "}\n\n";
5204   ) daemon_functions;
5205
5206   (* Dispatch function. *)
5207   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5208   pr "{\n";
5209   pr "  switch (proc_nr) {\n";
5210
5211   List.iter (
5212     fun (name, style, _, _, _, _, _) ->
5213       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5214       pr "      %s_stub (xdr_in);\n" name;
5215       pr "      break;\n"
5216   ) daemon_functions;
5217
5218   pr "    default:\n";
5219   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";
5220   pr "  }\n";
5221   pr "}\n";
5222   pr "\n";
5223
5224   (* LVM columns and tokenization functions. *)
5225   (* XXX This generates crap code.  We should rethink how we
5226    * do this parsing.
5227    *)
5228   List.iter (
5229     function
5230     | typ, cols ->
5231         pr "static const char *lvm_%s_cols = \"%s\";\n"
5232           typ (String.concat "," (List.map fst cols));
5233         pr "\n";
5234
5235         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5236         pr "{\n";
5237         pr "  char *tok, *p, *next;\n";
5238         pr "  int i, j;\n";
5239         pr "\n";
5240         (*
5241           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5242           pr "\n";
5243         *)
5244         pr "  if (!str) {\n";
5245         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5246         pr "    return -1;\n";
5247         pr "  }\n";
5248         pr "  if (!*str || isspace (*str)) {\n";
5249         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5250         pr "    return -1;\n";
5251         pr "  }\n";
5252         pr "  tok = str;\n";
5253         List.iter (
5254           fun (name, coltype) ->
5255             pr "  if (!tok) {\n";
5256             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5257             pr "    return -1;\n";
5258             pr "  }\n";
5259             pr "  p = strchrnul (tok, ',');\n";
5260             pr "  if (*p) next = p+1; else next = NULL;\n";
5261             pr "  *p = '\\0';\n";
5262             (match coltype with
5263              | FString ->
5264                  pr "  r->%s = strdup (tok);\n" name;
5265                  pr "  if (r->%s == NULL) {\n" name;
5266                  pr "    perror (\"strdup\");\n";
5267                  pr "    return -1;\n";
5268                  pr "  }\n"
5269              | FUUID ->
5270                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5271                  pr "    if (tok[j] == '\\0') {\n";
5272                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5273                  pr "      return -1;\n";
5274                  pr "    } else if (tok[j] != '-')\n";
5275                  pr "      r->%s[i++] = tok[j];\n" name;
5276                  pr "  }\n";
5277              | FBytes ->
5278                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5279                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5280                  pr "    return -1;\n";
5281                  pr "  }\n";
5282              | FInt64 ->
5283                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5284                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5285                  pr "    return -1;\n";
5286                  pr "  }\n";
5287              | FOptPercent ->
5288                  pr "  if (tok[0] == '\\0')\n";
5289                  pr "    r->%s = -1;\n" name;
5290                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5291                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5292                  pr "    return -1;\n";
5293                  pr "  }\n";
5294              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5295                  assert false (* can never be an LVM column *)
5296             );
5297             pr "  tok = next;\n";
5298         ) cols;
5299
5300         pr "  if (tok != NULL) {\n";
5301         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5302         pr "    return -1;\n";
5303         pr "  }\n";
5304         pr "  return 0;\n";
5305         pr "}\n";
5306         pr "\n";
5307
5308         pr "guestfs_int_lvm_%s_list *\n" typ;
5309         pr "parse_command_line_%ss (void)\n" typ;
5310         pr "{\n";
5311         pr "  char *out, *err;\n";
5312         pr "  char *p, *pend;\n";
5313         pr "  int r, i;\n";
5314         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5315         pr "  void *newp;\n";
5316         pr "\n";
5317         pr "  ret = malloc (sizeof *ret);\n";
5318         pr "  if (!ret) {\n";
5319         pr "    reply_with_perror (\"malloc\");\n";
5320         pr "    return NULL;\n";
5321         pr "  }\n";
5322         pr "\n";
5323         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5324         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5325         pr "\n";
5326         pr "  r = command (&out, &err,\n";
5327         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5328         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5329         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5330         pr "  if (r == -1) {\n";
5331         pr "    reply_with_error (\"%%s\", err);\n";
5332         pr "    free (out);\n";
5333         pr "    free (err);\n";
5334         pr "    free (ret);\n";
5335         pr "    return NULL;\n";
5336         pr "  }\n";
5337         pr "\n";
5338         pr "  free (err);\n";
5339         pr "\n";
5340         pr "  /* Tokenize each line of the output. */\n";
5341         pr "  p = out;\n";
5342         pr "  i = 0;\n";
5343         pr "  while (p) {\n";
5344         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5345         pr "    if (pend) {\n";
5346         pr "      *pend = '\\0';\n";
5347         pr "      pend++;\n";
5348         pr "    }\n";
5349         pr "\n";
5350         pr "    while (*p && isspace (*p))      /* Skip any leading whitespace. */\n";
5351         pr "      p++;\n";
5352         pr "\n";
5353         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5354         pr "      p = pend;\n";
5355         pr "      continue;\n";
5356         pr "    }\n";
5357         pr "\n";
5358         pr "    /* Allocate some space to store this next entry. */\n";
5359         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5360         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5361         pr "    if (newp == NULL) {\n";
5362         pr "      reply_with_perror (\"realloc\");\n";
5363         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5364         pr "      free (ret);\n";
5365         pr "      free (out);\n";
5366         pr "      return NULL;\n";
5367         pr "    }\n";
5368         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5369         pr "\n";
5370         pr "    /* Tokenize the next entry. */\n";
5371         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5372         pr "    if (r == -1) {\n";
5373         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5374         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5375         pr "      free (ret);\n";
5376         pr "      free (out);\n";
5377         pr "      return NULL;\n";
5378         pr "    }\n";
5379         pr "\n";
5380         pr "    ++i;\n";
5381         pr "    p = pend;\n";
5382         pr "  }\n";
5383         pr "\n";
5384         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5385         pr "\n";
5386         pr "  free (out);\n";
5387         pr "  return ret;\n";
5388         pr "}\n"
5389
5390   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5391
5392 (* Generate a list of function names, for debugging in the daemon.. *)
5393 and generate_daemon_names () =
5394   generate_header CStyle GPLv2;
5395
5396   pr "#include <config.h>\n";
5397   pr "\n";
5398   pr "#include \"daemon.h\"\n";
5399   pr "\n";
5400
5401   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5402   pr "const char *function_names[] = {\n";
5403   List.iter (
5404     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5405   ) daemon_functions;
5406   pr "};\n";
5407
5408 (* Generate the tests. *)
5409 and generate_tests () =
5410   generate_header CStyle GPLv2;
5411
5412   pr "\
5413 #include <stdio.h>
5414 #include <stdlib.h>
5415 #include <string.h>
5416 #include <unistd.h>
5417 #include <sys/types.h>
5418 #include <fcntl.h>
5419
5420 #include \"guestfs.h\"
5421
5422 static guestfs_h *g;
5423 static int suppress_error = 0;
5424
5425 static void print_error (guestfs_h *g, void *data, const char *msg)
5426 {
5427   if (!suppress_error)
5428     fprintf (stderr, \"%%s\\n\", msg);
5429 }
5430
5431 /* FIXME: nearly identical code appears in fish.c */
5432 static void print_strings (char *const *argv)
5433 {
5434   int argc;
5435
5436   for (argc = 0; argv[argc] != NULL; ++argc)
5437     printf (\"\\t%%s\\n\", argv[argc]);
5438 }
5439
5440 /*
5441 static void print_table (char const *const *argv)
5442 {
5443   int i;
5444
5445   for (i = 0; argv[i] != NULL; i += 2)
5446     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5447 }
5448 */
5449
5450 ";
5451
5452   (* Generate a list of commands which are not tested anywhere. *)
5453   pr "static void no_test_warnings (void)\n";
5454   pr "{\n";
5455
5456   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5457   List.iter (
5458     fun (_, _, _, _, tests, _, _) ->
5459       let tests = filter_map (
5460         function
5461         | (_, (Always|If _|Unless _), test) -> Some test
5462         | (_, Disabled, _) -> None
5463       ) tests in
5464       let seq = List.concat (List.map seq_of_test tests) in
5465       let cmds_tested = List.map List.hd seq in
5466       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5467   ) all_functions;
5468
5469   List.iter (
5470     fun (name, _, _, _, _, _, _) ->
5471       if not (Hashtbl.mem hash name) then
5472         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5473   ) all_functions;
5474
5475   pr "}\n";
5476   pr "\n";
5477
5478   (* Generate the actual tests.  Note that we generate the tests
5479    * in reverse order, deliberately, so that (in general) the
5480    * newest tests run first.  This makes it quicker and easier to
5481    * debug them.
5482    *)
5483   let test_names =
5484     List.map (
5485       fun (name, _, _, _, tests, _, _) ->
5486         mapi (generate_one_test name) tests
5487     ) (List.rev all_functions) in
5488   let test_names = List.concat test_names in
5489   let nr_tests = List.length test_names in
5490
5491   pr "\
5492 int main (int argc, char *argv[])
5493 {
5494   char c = 0;
5495   unsigned long int n_failed = 0;
5496   const char *filename;
5497   int fd;
5498   int nr_tests, test_num = 0;
5499
5500   setbuf (stdout, NULL);
5501
5502   no_test_warnings ();
5503
5504   g = guestfs_create ();
5505   if (g == NULL) {
5506     printf (\"guestfs_create FAILED\\n\");
5507     exit (1);
5508   }
5509
5510   guestfs_set_error_handler (g, print_error, NULL);
5511
5512   guestfs_set_path (g, \"../appliance\");
5513
5514   filename = \"test1.img\";
5515   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5516   if (fd == -1) {
5517     perror (filename);
5518     exit (1);
5519   }
5520   if (lseek (fd, %d, SEEK_SET) == -1) {
5521     perror (\"lseek\");
5522     close (fd);
5523     unlink (filename);
5524     exit (1);
5525   }
5526   if (write (fd, &c, 1) == -1) {
5527     perror (\"write\");
5528     close (fd);
5529     unlink (filename);
5530     exit (1);
5531   }
5532   if (close (fd) == -1) {
5533     perror (filename);
5534     unlink (filename);
5535     exit (1);
5536   }
5537   if (guestfs_add_drive (g, filename) == -1) {
5538     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5539     exit (1);
5540   }
5541
5542   filename = \"test2.img\";
5543   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5544   if (fd == -1) {
5545     perror (filename);
5546     exit (1);
5547   }
5548   if (lseek (fd, %d, SEEK_SET) == -1) {
5549     perror (\"lseek\");
5550     close (fd);
5551     unlink (filename);
5552     exit (1);
5553   }
5554   if (write (fd, &c, 1) == -1) {
5555     perror (\"write\");
5556     close (fd);
5557     unlink (filename);
5558     exit (1);
5559   }
5560   if (close (fd) == -1) {
5561     perror (filename);
5562     unlink (filename);
5563     exit (1);
5564   }
5565   if (guestfs_add_drive (g, filename) == -1) {
5566     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5567     exit (1);
5568   }
5569
5570   filename = \"test3.img\";
5571   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5572   if (fd == -1) {
5573     perror (filename);
5574     exit (1);
5575   }
5576   if (lseek (fd, %d, SEEK_SET) == -1) {
5577     perror (\"lseek\");
5578     close (fd);
5579     unlink (filename);
5580     exit (1);
5581   }
5582   if (write (fd, &c, 1) == -1) {
5583     perror (\"write\");
5584     close (fd);
5585     unlink (filename);
5586     exit (1);
5587   }
5588   if (close (fd) == -1) {
5589     perror (filename);
5590     unlink (filename);
5591     exit (1);
5592   }
5593   if (guestfs_add_drive (g, filename) == -1) {
5594     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5595     exit (1);
5596   }
5597
5598   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
5599     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
5600     exit (1);
5601   }
5602
5603   if (guestfs_launch (g) == -1) {
5604     printf (\"guestfs_launch FAILED\\n\");
5605     exit (1);
5606   }
5607
5608   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5609   alarm (600);
5610
5611   if (guestfs_wait_ready (g) == -1) {
5612     printf (\"guestfs_wait_ready FAILED\\n\");
5613     exit (1);
5614   }
5615
5616   /* Cancel previous alarm. */
5617   alarm (0);
5618
5619   nr_tests = %d;
5620
5621 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5622
5623   iteri (
5624     fun i test_name ->
5625       pr "  test_num++;\n";
5626       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5627       pr "  if (%s () == -1) {\n" test_name;
5628       pr "    printf (\"%s FAILED\\n\");\n" test_name;
5629       pr "    n_failed++;\n";
5630       pr "  }\n";
5631   ) test_names;
5632   pr "\n";
5633
5634   pr "  guestfs_close (g);\n";
5635   pr "  unlink (\"test1.img\");\n";
5636   pr "  unlink (\"test2.img\");\n";
5637   pr "  unlink (\"test3.img\");\n";
5638   pr "\n";
5639
5640   pr "  if (n_failed > 0) {\n";
5641   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
5642   pr "    exit (1);\n";
5643   pr "  }\n";
5644   pr "\n";
5645
5646   pr "  exit (0);\n";
5647   pr "}\n"
5648
5649 and generate_one_test name i (init, prereq, test) =
5650   let test_name = sprintf "test_%s_%d" name i in
5651
5652   pr "\
5653 static int %s_skip (void)
5654 {
5655   const char *str;
5656
5657   str = getenv (\"TEST_ONLY\");
5658   if (str)
5659     return strstr (str, \"%s\") == NULL;
5660   str = getenv (\"SKIP_%s\");
5661   if (str && strcmp (str, \"1\") == 0) return 1;
5662   str = getenv (\"SKIP_TEST_%s\");
5663   if (str && strcmp (str, \"1\") == 0) return 1;
5664   return 0;
5665 }
5666
5667 " test_name name (String.uppercase test_name) (String.uppercase name);
5668
5669   (match prereq with
5670    | Disabled | Always -> ()
5671    | If code | Unless code ->
5672        pr "static int %s_prereq (void)\n" test_name;
5673        pr "{\n";
5674        pr "  %s\n" code;
5675        pr "}\n";
5676        pr "\n";
5677   );
5678
5679   pr "\
5680 static int %s (void)
5681 {
5682   if (%s_skip ()) {
5683     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
5684     return 0;
5685   }
5686
5687 " test_name test_name test_name;
5688
5689   (match prereq with
5690    | Disabled ->
5691        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5692    | If _ ->
5693        pr "  if (! %s_prereq ()) {\n" test_name;
5694        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5695        pr "    return 0;\n";
5696        pr "  }\n";
5697        pr "\n";
5698        generate_one_test_body name i test_name init test;
5699    | Unless _ ->
5700        pr "  if (%s_prereq ()) {\n" test_name;
5701        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5702        pr "    return 0;\n";
5703        pr "  }\n";
5704        pr "\n";
5705        generate_one_test_body name i test_name init test;
5706    | Always ->
5707        generate_one_test_body name i test_name init test
5708   );
5709
5710   pr "  return 0;\n";
5711   pr "}\n";
5712   pr "\n";
5713   test_name
5714
5715 and generate_one_test_body name i test_name init test =
5716   (match init with
5717    | InitNone (* XXX at some point, InitNone and InitEmpty became
5718                * folded together as the same thing.  Really we should
5719                * make InitNone do nothing at all, but the tests may
5720                * need to be checked to make sure this is OK.
5721                *)
5722    | InitEmpty ->
5723        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
5724        List.iter (generate_test_command_call test_name)
5725          [["blockdev_setrw"; "/dev/sda"];
5726           ["umount_all"];
5727           ["lvm_remove_all"]]
5728    | InitPartition ->
5729        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5730        List.iter (generate_test_command_call test_name)
5731          [["blockdev_setrw"; "/dev/sda"];
5732           ["umount_all"];
5733           ["lvm_remove_all"];
5734           ["sfdiskM"; "/dev/sda"; ","]]
5735    | InitBasicFS ->
5736        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5737        List.iter (generate_test_command_call test_name)
5738          [["blockdev_setrw"; "/dev/sda"];
5739           ["umount_all"];
5740           ["lvm_remove_all"];
5741           ["sfdiskM"; "/dev/sda"; ","];
5742           ["mkfs"; "ext2"; "/dev/sda1"];
5743           ["mount"; "/dev/sda1"; "/"]]
5744    | InitBasicFSonLVM ->
5745        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5746          test_name;
5747        List.iter (generate_test_command_call test_name)
5748          [["blockdev_setrw"; "/dev/sda"];
5749           ["umount_all"];
5750           ["lvm_remove_all"];
5751           ["sfdiskM"; "/dev/sda"; ","];
5752           ["pvcreate"; "/dev/sda1"];
5753           ["vgcreate"; "VG"; "/dev/sda1"];
5754           ["lvcreate"; "LV"; "VG"; "8"];
5755           ["mkfs"; "ext2"; "/dev/VG/LV"];
5756           ["mount"; "/dev/VG/LV"; "/"]]
5757    | InitISOFS ->
5758        pr "  /* InitISOFS for %s */\n" test_name;
5759        List.iter (generate_test_command_call test_name)
5760          [["blockdev_setrw"; "/dev/sda"];
5761           ["umount_all"];
5762           ["lvm_remove_all"];
5763           ["mount_ro"; "/dev/sdd"; "/"]]
5764   );
5765
5766   let get_seq_last = function
5767     | [] ->
5768         failwithf "%s: you cannot use [] (empty list) when expecting a command"
5769           test_name
5770     | seq ->
5771         let seq = List.rev seq in
5772         List.rev (List.tl seq), List.hd seq
5773   in
5774
5775   match test with
5776   | TestRun seq ->
5777       pr "  /* TestRun for %s (%d) */\n" name i;
5778       List.iter (generate_test_command_call test_name) seq
5779   | TestOutput (seq, expected) ->
5780       pr "  /* TestOutput for %s (%d) */\n" name i;
5781       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5782       let seq, last = get_seq_last seq in
5783       let test () =
5784         pr "    if (strcmp (r, expected) != 0) {\n";
5785         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5786         pr "      return -1;\n";
5787         pr "    }\n"
5788       in
5789       List.iter (generate_test_command_call test_name) seq;
5790       generate_test_command_call ~test test_name last
5791   | TestOutputList (seq, expected) ->
5792       pr "  /* TestOutputList for %s (%d) */\n" name i;
5793       let seq, last = get_seq_last seq in
5794       let test () =
5795         iteri (
5796           fun i str ->
5797             pr "    if (!r[%d]) {\n" i;
5798             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5799             pr "      print_strings (r);\n";
5800             pr "      return -1;\n";
5801             pr "    }\n";
5802             pr "    {\n";
5803             pr "      const char *expected = \"%s\";\n" (c_quote str);
5804             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5805             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5806             pr "        return -1;\n";
5807             pr "      }\n";
5808             pr "    }\n"
5809         ) expected;
5810         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5811         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5812           test_name;
5813         pr "      print_strings (r);\n";
5814         pr "      return -1;\n";
5815         pr "    }\n"
5816       in
5817       List.iter (generate_test_command_call test_name) seq;
5818       generate_test_command_call ~test test_name last
5819   | TestOutputListOfDevices (seq, expected) ->
5820       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
5821       let seq, last = get_seq_last seq in
5822       let test () =
5823         iteri (
5824           fun i str ->
5825             pr "    if (!r[%d]) {\n" i;
5826             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5827             pr "      print_strings (r);\n";
5828             pr "      return -1;\n";
5829             pr "    }\n";
5830             pr "    {\n";
5831             pr "      const char *expected = \"%s\";\n" (c_quote str);
5832             pr "      r[%d][5] = 's';\n" i;
5833             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5834             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5835             pr "        return -1;\n";
5836             pr "      }\n";
5837             pr "    }\n"
5838         ) expected;
5839         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5840         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5841           test_name;
5842         pr "      print_strings (r);\n";
5843         pr "      return -1;\n";
5844         pr "    }\n"
5845       in
5846       List.iter (generate_test_command_call test_name) seq;
5847       generate_test_command_call ~test test_name last
5848   | TestOutputInt (seq, expected) ->
5849       pr "  /* TestOutputInt for %s (%d) */\n" name i;
5850       let seq, last = get_seq_last seq in
5851       let test () =
5852         pr "    if (r != %d) {\n" expected;
5853         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5854           test_name expected;
5855         pr "               (int) r);\n";
5856         pr "      return -1;\n";
5857         pr "    }\n"
5858       in
5859       List.iter (generate_test_command_call test_name) seq;
5860       generate_test_command_call ~test test_name last
5861   | TestOutputIntOp (seq, op, expected) ->
5862       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
5863       let seq, last = get_seq_last seq in
5864       let test () =
5865         pr "    if (! (r %s %d)) {\n" op expected;
5866         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5867           test_name op expected;
5868         pr "               (int) r);\n";
5869         pr "      return -1;\n";
5870         pr "    }\n"
5871       in
5872       List.iter (generate_test_command_call test_name) seq;
5873       generate_test_command_call ~test test_name last
5874   | TestOutputTrue seq ->
5875       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
5876       let seq, last = get_seq_last seq in
5877       let test () =
5878         pr "    if (!r) {\n";
5879         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5880           test_name;
5881         pr "      return -1;\n";
5882         pr "    }\n"
5883       in
5884       List.iter (generate_test_command_call test_name) seq;
5885       generate_test_command_call ~test test_name last
5886   | TestOutputFalse seq ->
5887       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
5888       let seq, last = get_seq_last seq in
5889       let test () =
5890         pr "    if (r) {\n";
5891         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
5892           test_name;
5893         pr "      return -1;\n";
5894         pr "    }\n"
5895       in
5896       List.iter (generate_test_command_call test_name) seq;
5897       generate_test_command_call ~test test_name last
5898   | TestOutputLength (seq, expected) ->
5899       pr "  /* TestOutputLength for %s (%d) */\n" name i;
5900       let seq, last = get_seq_last seq in
5901       let test () =
5902         pr "    int j;\n";
5903         pr "    for (j = 0; j < %d; ++j)\n" expected;
5904         pr "      if (r[j] == NULL) {\n";
5905         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
5906           test_name;
5907         pr "        print_strings (r);\n";
5908         pr "        return -1;\n";
5909         pr "      }\n";
5910         pr "    if (r[j] != NULL) {\n";
5911         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
5912           test_name;
5913         pr "      print_strings (r);\n";
5914         pr "      return -1;\n";
5915         pr "    }\n"
5916       in
5917       List.iter (generate_test_command_call test_name) seq;
5918       generate_test_command_call ~test test_name last
5919   | TestOutputBuffer (seq, expected) ->
5920       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
5921       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5922       let seq, last = get_seq_last seq in
5923       let len = String.length expected in
5924       let test () =
5925         pr "    if (size != %d) {\n" len;
5926         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
5927         pr "      return -1;\n";
5928         pr "    }\n";
5929         pr "    if (strncmp (r, expected, size) != 0) {\n";
5930         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5931         pr "      return -1;\n";
5932         pr "    }\n"
5933       in
5934       List.iter (generate_test_command_call test_name) seq;
5935       generate_test_command_call ~test test_name last
5936   | TestOutputStruct (seq, checks) ->
5937       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
5938       let seq, last = get_seq_last seq in
5939       let test () =
5940         List.iter (
5941           function
5942           | CompareWithInt (field, expected) ->
5943               pr "    if (r->%s != %d) {\n" field expected;
5944               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
5945                 test_name field expected;
5946               pr "               (int) r->%s);\n" field;
5947               pr "      return -1;\n";
5948               pr "    }\n"
5949           | CompareWithIntOp (field, op, expected) ->
5950               pr "    if (!(r->%s %s %d)) {\n" field op expected;
5951               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
5952                 test_name field op expected;
5953               pr "               (int) r->%s);\n" field;
5954               pr "      return -1;\n";
5955               pr "    }\n"
5956           | CompareWithString (field, expected) ->
5957               pr "    if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
5958               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
5959                 test_name field expected;
5960               pr "               r->%s);\n" field;
5961               pr "      return -1;\n";
5962               pr "    }\n"
5963           | CompareFieldsIntEq (field1, field2) ->
5964               pr "    if (r->%s != r->%s) {\n" field1 field2;
5965               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
5966                 test_name field1 field2;
5967               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
5968               pr "      return -1;\n";
5969               pr "    }\n"
5970           | CompareFieldsStrEq (field1, field2) ->
5971               pr "    if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
5972               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
5973                 test_name field1 field2;
5974               pr "               r->%s, r->%s);\n" field1 field2;
5975               pr "      return -1;\n";
5976               pr "    }\n"
5977         ) checks
5978       in
5979       List.iter (generate_test_command_call test_name) seq;
5980       generate_test_command_call ~test test_name last
5981   | TestLastFail seq ->
5982       pr "  /* TestLastFail for %s (%d) */\n" name i;
5983       let seq, last = get_seq_last seq in
5984       List.iter (generate_test_command_call test_name) seq;
5985       generate_test_command_call test_name ~expect_error:true last
5986
5987 (* Generate the code to run a command, leaving the result in 'r'.
5988  * If you expect to get an error then you should set expect_error:true.
5989  *)
5990 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
5991   match cmd with
5992   | [] -> assert false
5993   | name :: args ->
5994       (* Look up the command to find out what args/ret it has. *)
5995       let style =
5996         try
5997           let _, style, _, _, _, _, _ =
5998             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
5999           style
6000         with Not_found ->
6001           failwithf "%s: in test, command %s was not found" test_name name in
6002
6003       if List.length (snd style) <> List.length args then
6004         failwithf "%s: in test, wrong number of args given to %s"
6005           test_name name;
6006
6007       pr "  {\n";
6008
6009       List.iter (
6010         function
6011         | OptString n, "NULL" -> ()
6012         | Pathname n, arg
6013         | Device n, arg
6014         | Dev_or_Path n, arg
6015         | String n, arg
6016         | OptString n, arg ->
6017             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6018         | Int _, _
6019         | Bool _, _
6020         | FileIn _, _ | FileOut _, _ -> ()
6021         | StringList n, arg | DeviceList n, arg ->
6022             let strs = string_split " " arg in
6023             iteri (
6024               fun i str ->
6025                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6026             ) strs;
6027             pr "    const char *const %s[] = {\n" n;
6028             iteri (
6029               fun i _ -> pr "      %s_%d,\n" n i
6030             ) strs;
6031             pr "      NULL\n";
6032             pr "    };\n";
6033       ) (List.combine (snd style) args);
6034
6035       let error_code =
6036         match fst style with
6037         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6038         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6039         | RConstString _ | RConstOptString _ ->
6040             pr "    const char *r;\n"; "NULL"
6041         | RString _ -> pr "    char *r;\n"; "NULL"
6042         | RStringList _ | RHashtable _ ->
6043             pr "    char **r;\n";
6044             pr "    int i;\n";
6045             "NULL"
6046         | RStruct (_, typ) ->
6047             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6048         | RStructList (_, typ) ->
6049             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6050         | RBufferOut _ ->
6051             pr "    char *r;\n";
6052             pr "    size_t size;\n";
6053             "NULL" in
6054
6055       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6056       pr "    r = guestfs_%s (g" name;
6057
6058       (* Generate the parameters. *)
6059       List.iter (
6060         function
6061         | OptString _, "NULL" -> pr ", NULL"
6062         | Pathname n, _
6063         | Device n, _ | Dev_or_Path n, _
6064         | String n, _
6065         | OptString n, _ ->
6066             pr ", %s" n
6067         | FileIn _, arg | FileOut _, arg ->
6068             pr ", \"%s\"" (c_quote arg)
6069         | StringList n, _ | DeviceList n, _ ->
6070             pr ", (char **) %s" n
6071         | Int _, arg ->
6072             let i =
6073               try int_of_string arg
6074               with Failure "int_of_string" ->
6075                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6076             pr ", %d" i
6077         | Bool _, arg ->
6078             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6079       ) (List.combine (snd style) args);
6080
6081       (match fst style with
6082        | RBufferOut _ -> pr ", &size"
6083        | _ -> ()
6084       );
6085
6086       pr ");\n";
6087
6088       if not expect_error then
6089         pr "    if (r == %s)\n" error_code
6090       else
6091         pr "    if (r != %s)\n" error_code;
6092       pr "      return -1;\n";
6093
6094       (* Insert the test code. *)
6095       (match test with
6096        | None -> ()
6097        | Some f -> f ()
6098       );
6099
6100       (match fst style with
6101        | RErr | RInt _ | RInt64 _ | RBool _
6102        | RConstString _ | RConstOptString _ -> ()
6103        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6104        | RStringList _ | RHashtable _ ->
6105            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6106            pr "      free (r[i]);\n";
6107            pr "    free (r);\n"
6108        | RStruct (_, typ) ->
6109            pr "    guestfs_free_%s (r);\n" typ
6110        | RStructList (_, typ) ->
6111            pr "    guestfs_free_%s_list (r);\n" typ
6112       );
6113
6114       pr "  }\n"
6115
6116 and c_quote str =
6117   let str = replace_str str "\r" "\\r" in
6118   let str = replace_str str "\n" "\\n" in
6119   let str = replace_str str "\t" "\\t" in
6120   let str = replace_str str "\000" "\\0" in
6121   str
6122
6123 (* Generate a lot of different functions for guestfish. *)
6124 and generate_fish_cmds () =
6125   generate_header CStyle GPLv2;
6126
6127   let all_functions =
6128     List.filter (
6129       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6130     ) all_functions in
6131   let all_functions_sorted =
6132     List.filter (
6133       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6134     ) all_functions_sorted in
6135
6136   pr "#include <stdio.h>\n";
6137   pr "#include <stdlib.h>\n";
6138   pr "#include <string.h>\n";
6139   pr "#include <inttypes.h>\n";
6140   pr "#include <ctype.h>\n";
6141   pr "\n";
6142   pr "#include <guestfs.h>\n";
6143   pr "#include \"fish.h\"\n";
6144   pr "\n";
6145
6146   (* list_commands function, which implements guestfish -h *)
6147   pr "void list_commands (void)\n";
6148   pr "{\n";
6149   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6150   pr "  list_builtin_commands ();\n";
6151   List.iter (
6152     fun (name, _, _, flags, _, shortdesc, _) ->
6153       let name = replace_char name '_' '-' in
6154       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6155         name shortdesc
6156   ) all_functions_sorted;
6157   pr "  printf (\"    %%s\\n\",";
6158   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6159   pr "}\n";
6160   pr "\n";
6161
6162   (* display_command function, which implements guestfish -h cmd *)
6163   pr "void display_command (const char *cmd)\n";
6164   pr "{\n";
6165   List.iter (
6166     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6167       let name2 = replace_char name '_' '-' in
6168       let alias =
6169         try find_map (function FishAlias n -> Some n | _ -> None) flags
6170         with Not_found -> name in
6171       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6172       let synopsis =
6173         match snd style with
6174         | [] -> name2
6175         | args ->
6176             sprintf "%s <%s>"
6177               name2 (String.concat "> <" (List.map name_of_argt args)) in
6178
6179       let warnings =
6180         if List.mem ProtocolLimitWarning flags then
6181           ("\n\n" ^ protocol_limit_warning)
6182         else "" in
6183
6184       (* For DangerWillRobinson commands, we should probably have
6185        * guestfish prompt before allowing you to use them (especially
6186        * in interactive mode). XXX
6187        *)
6188       let warnings =
6189         warnings ^
6190           if List.mem DangerWillRobinson flags then
6191             ("\n\n" ^ danger_will_robinson)
6192           else "" in
6193
6194       let warnings =
6195         warnings ^
6196           match deprecation_notice flags with
6197           | None -> ""
6198           | Some txt -> "\n\n" ^ txt in
6199
6200       let describe_alias =
6201         if name <> alias then
6202           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6203         else "" in
6204
6205       pr "  if (";
6206       pr "strcasecmp (cmd, \"%s\") == 0" name;
6207       if name <> name2 then
6208         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6209       if name <> alias then
6210         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6211       pr ")\n";
6212       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6213         name2 shortdesc
6214         (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
6215       pr "  else\n"
6216   ) all_functions;
6217   pr "    display_builtin_command (cmd);\n";
6218   pr "}\n";
6219   pr "\n";
6220
6221   let emit_print_list_function typ =
6222     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6223       typ typ typ;
6224     pr "{\n";
6225     pr "  unsigned int i;\n";
6226     pr "\n";
6227     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6228     pr "    printf (\"[%%d] = {\\n\", i);\n";
6229     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6230     pr "    printf (\"}\\n\");\n";
6231     pr "  }\n";
6232     pr "}\n";
6233     pr "\n";
6234   in
6235
6236   (* print_* functions *)
6237   List.iter (
6238     fun (typ, cols) ->
6239       let needs_i =
6240         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6241
6242       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6243       pr "{\n";
6244       if needs_i then (
6245         pr "  unsigned int i;\n";
6246         pr "\n"
6247       );
6248       List.iter (
6249         function
6250         | name, FString ->
6251             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6252         | name, FUUID ->
6253             pr "  printf (\"%s: \");\n" name;
6254             pr "  for (i = 0; i < 32; ++i)\n";
6255             pr "    printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6256             pr "  printf (\"\\n\");\n"
6257         | name, FBuffer ->
6258             pr "  printf (\"%%s%s: \", indent);\n" name;
6259             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6260             pr "    if (isprint (%s->%s[i]))\n" typ name;
6261             pr "      printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6262             pr "    else\n";
6263             pr "      printf (\"%%s\\\\x%%02x\", indent, %s->%s[i]);\n" typ name;
6264             pr "  printf (\"\\n\");\n"
6265         | name, (FUInt64|FBytes) ->
6266             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6267               name typ name
6268         | name, FInt64 ->
6269             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6270               name typ name
6271         | name, FUInt32 ->
6272             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6273               name typ name
6274         | name, FInt32 ->
6275             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6276               name typ name
6277         | name, FChar ->
6278             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6279               name typ name
6280         | name, FOptPercent ->
6281             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6282               typ name name typ name;
6283             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6284       ) cols;
6285       pr "}\n";
6286       pr "\n";
6287   ) structs;
6288
6289   (* Emit a print_TYPE_list function definition only if that function is used. *)
6290   List.iter (
6291     function
6292     | typ, (RStructListOnly | RStructAndList) ->
6293         (* generate the function for typ *)
6294         emit_print_list_function typ
6295     | typ, _ -> () (* empty *)
6296   ) rstructs_used;
6297
6298   (* Emit a print_TYPE function definition only if that function is used. *)
6299   List.iter (
6300     function
6301     | typ, RStructOnly ->
6302         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6303         pr "{\n";
6304         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6305         pr "}\n";
6306         pr "\n";
6307     | typ, _ -> () (* empty *)
6308   ) rstructs_used;
6309
6310   (* run_<action> actions *)
6311   List.iter (
6312     fun (name, style, _, flags, _, _, _) ->
6313       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6314       pr "{\n";
6315       (match fst style with
6316        | RErr
6317        | RInt _
6318        | RBool _ -> pr "  int r;\n"
6319        | RInt64 _ -> pr "  int64_t r;\n"
6320        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6321        | RString _ -> pr "  char *r;\n"
6322        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6323        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6324        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6325        | RBufferOut _ ->
6326            pr "  char *r;\n";
6327            pr "  size_t size;\n";
6328       );
6329       List.iter (
6330         function
6331         | Pathname n
6332         | Device n | Dev_or_Path n
6333         | String n
6334         | OptString n
6335         | FileIn n
6336         | FileOut n -> pr "  const char *%s;\n" n
6337         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6338         | Bool n -> pr "  int %s;\n" n
6339         | Int n -> pr "  int %s;\n" n
6340       ) (snd style);
6341
6342       (* Check and convert parameters. *)
6343       let argc_expected = List.length (snd style) in
6344       pr "  if (argc != %d) {\n" argc_expected;
6345       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6346         argc_expected;
6347       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6348       pr "    return -1;\n";
6349       pr "  }\n";
6350       iteri (
6351         fun i ->
6352           function
6353           | Pathname name
6354           | Device name | Dev_or_Path name | String name -> pr "  %s = argv[%d];\n" name i
6355           | OptString name ->
6356               pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6357                 name i i
6358           | FileIn name ->
6359               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6360                 name i i
6361           | FileOut name ->
6362               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6363                 name i i
6364           | StringList name | DeviceList name ->
6365               pr "  %s = parse_string_list (argv[%d]);\n" name i;
6366               pr "  if (%s == NULL) return -1;\n" name;
6367           | Bool name ->
6368               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6369           | Int name ->
6370               pr "  %s = atoi (argv[%d]);\n" name i
6371       ) (snd style);
6372
6373       (* Call C API function. *)
6374       let fn =
6375         try find_map (function FishAction n -> Some n | _ -> None) flags
6376         with Not_found -> sprintf "guestfs_%s" name in
6377       pr "  r = %s " fn;
6378       generate_c_call_args ~handle:"g" style;
6379       pr ";\n";
6380
6381       List.iter (
6382         function
6383         | Pathname name | Device name | Dev_or_Path name | String name
6384         | OptString name | FileIn name | FileOut name | Bool name
6385         | Int name -> ()
6386         | StringList name | DeviceList name ->
6387             pr "  free_strings (%s);\n" name
6388       ) (snd style);
6389
6390       (* Check return value for errors and display command results. *)
6391       (match fst style with
6392        | RErr -> pr "  return r;\n"
6393        | RInt _ ->
6394            pr "  if (r == -1) return -1;\n";
6395            pr "  printf (\"%%d\\n\", r);\n";
6396            pr "  return 0;\n"
6397        | RInt64 _ ->
6398            pr "  if (r == -1) return -1;\n";
6399            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6400            pr "  return 0;\n"
6401        | RBool _ ->
6402            pr "  if (r == -1) return -1;\n";
6403            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6404            pr "  return 0;\n"
6405        | RConstString _ ->
6406            pr "  if (r == NULL) return -1;\n";
6407            pr "  printf (\"%%s\\n\", r);\n";
6408            pr "  return 0;\n"
6409        | RConstOptString _ ->
6410            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6411            pr "  return 0;\n"
6412        | RString _ ->
6413            pr "  if (r == NULL) return -1;\n";
6414            pr "  printf (\"%%s\\n\", r);\n";
6415            pr "  free (r);\n";
6416            pr "  return 0;\n"
6417        | RStringList _ ->
6418            pr "  if (r == NULL) return -1;\n";
6419            pr "  print_strings (r);\n";
6420            pr "  free_strings (r);\n";
6421            pr "  return 0;\n"
6422        | RStruct (_, typ) ->
6423            pr "  if (r == NULL) return -1;\n";
6424            pr "  print_%s (r);\n" typ;
6425            pr "  guestfs_free_%s (r);\n" typ;
6426            pr "  return 0;\n"
6427        | RStructList (_, typ) ->
6428            pr "  if (r == NULL) return -1;\n";
6429            pr "  print_%s_list (r);\n" typ;
6430            pr "  guestfs_free_%s_list (r);\n" typ;
6431            pr "  return 0;\n"
6432        | RHashtable _ ->
6433            pr "  if (r == NULL) return -1;\n";
6434            pr "  print_table (r);\n";
6435            pr "  free_strings (r);\n";
6436            pr "  return 0;\n"
6437        | RBufferOut _ ->
6438            pr "  if (r == NULL) return -1;\n";
6439            pr "  fwrite (r, size, 1, stdout);\n";
6440            pr "  free (r);\n";
6441            pr "  return 0;\n"
6442       );
6443       pr "}\n";
6444       pr "\n"
6445   ) all_functions;
6446
6447   (* run_action function *)
6448   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6449   pr "{\n";
6450   List.iter (
6451     fun (name, _, _, flags, _, _, _) ->
6452       let name2 = replace_char name '_' '-' in
6453       let alias =
6454         try find_map (function FishAlias n -> Some n | _ -> None) flags
6455         with Not_found -> name in
6456       pr "  if (";
6457       pr "strcasecmp (cmd, \"%s\") == 0" name;
6458       if name <> name2 then
6459         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6460       if name <> alias then
6461         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6462       pr ")\n";
6463       pr "    return run_%s (cmd, argc, argv);\n" name;
6464       pr "  else\n";
6465   ) all_functions;
6466   pr "    {\n";
6467   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6468   pr "      return -1;\n";
6469   pr "    }\n";
6470   pr "  return 0;\n";
6471   pr "}\n";
6472   pr "\n"
6473
6474 (* Readline completion for guestfish. *)
6475 and generate_fish_completion () =
6476   generate_header CStyle GPLv2;
6477
6478   let all_functions =
6479     List.filter (
6480       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6481     ) all_functions in
6482
6483   pr "\
6484 #include <config.h>
6485
6486 #include <stdio.h>
6487 #include <stdlib.h>
6488 #include <string.h>
6489
6490 #ifdef HAVE_LIBREADLINE
6491 #include <readline/readline.h>
6492 #endif
6493
6494 #include \"fish.h\"
6495
6496 #ifdef HAVE_LIBREADLINE
6497
6498 static const char *const commands[] = {
6499   BUILTIN_COMMANDS_FOR_COMPLETION,
6500 ";
6501
6502   (* Get the commands, including the aliases.  They don't need to be
6503    * sorted - the generator() function just does a dumb linear search.
6504    *)
6505   let commands =
6506     List.map (
6507       fun (name, _, _, flags, _, _, _) ->
6508         let name2 = replace_char name '_' '-' in
6509         let alias =
6510           try find_map (function FishAlias n -> Some n | _ -> None) flags
6511           with Not_found -> name in
6512
6513         if name <> alias then [name2; alias] else [name2]
6514     ) all_functions in
6515   let commands = List.flatten commands in
6516
6517   List.iter (pr "  \"%s\",\n") commands;
6518
6519   pr "  NULL
6520 };
6521
6522 static char *
6523 generator (const char *text, int state)
6524 {
6525   static int index, len;
6526   const char *name;
6527
6528   if (!state) {
6529     index = 0;
6530     len = strlen (text);
6531   }
6532
6533   rl_attempted_completion_over = 1;
6534
6535   while ((name = commands[index]) != NULL) {
6536     index++;
6537     if (strncasecmp (name, text, len) == 0)
6538       return strdup (name);
6539   }
6540
6541   return NULL;
6542 }
6543
6544 #endif /* HAVE_LIBREADLINE */
6545
6546 char **do_completion (const char *text, int start, int end)
6547 {
6548   char **matches = NULL;
6549
6550 #ifdef HAVE_LIBREADLINE
6551   rl_completion_append_character = ' ';
6552
6553   if (start == 0)
6554     matches = rl_completion_matches (text, generator);
6555   else if (complete_dest_paths)
6556     matches = rl_completion_matches (text, complete_dest_paths_generator);
6557 #endif
6558
6559   return matches;
6560 }
6561 ";
6562
6563 (* Generate the POD documentation for guestfish. *)
6564 and generate_fish_actions_pod () =
6565   let all_functions_sorted =
6566     List.filter (
6567       fun (_, _, _, flags, _, _, _) ->
6568         not (List.mem NotInFish flags || List.mem NotInDocs flags)
6569     ) all_functions_sorted in
6570
6571   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6572
6573   List.iter (
6574     fun (name, style, _, flags, _, _, longdesc) ->
6575       let longdesc =
6576         Str.global_substitute rex (
6577           fun s ->
6578             let sub =
6579               try Str.matched_group 1 s
6580               with Not_found ->
6581                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6582             "C<" ^ replace_char sub '_' '-' ^ ">"
6583         ) longdesc in
6584       let name = replace_char name '_' '-' in
6585       let alias =
6586         try find_map (function FishAlias n -> Some n | _ -> None) flags
6587         with Not_found -> name in
6588
6589       pr "=head2 %s" name;
6590       if name <> alias then
6591         pr " | %s" alias;
6592       pr "\n";
6593       pr "\n";
6594       pr " %s" name;
6595       List.iter (
6596         function
6597         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6598         | OptString n -> pr " %s" n
6599         | StringList n | DeviceList n -> pr " '%s ...'" n
6600         | Bool _ -> pr " true|false"
6601         | Int n -> pr " %s" n
6602         | FileIn n | FileOut n -> pr " (%s|-)" n
6603       ) (snd style);
6604       pr "\n";
6605       pr "\n";
6606       pr "%s\n\n" longdesc;
6607
6608       if List.exists (function FileIn _ | FileOut _ -> true
6609                       | _ -> false) (snd style) then
6610         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6611
6612       if List.mem ProtocolLimitWarning flags then
6613         pr "%s\n\n" protocol_limit_warning;
6614
6615       if List.mem DangerWillRobinson flags then
6616         pr "%s\n\n" danger_will_robinson;
6617
6618       match deprecation_notice flags with
6619       | None -> ()
6620       | Some txt -> pr "%s\n\n" txt
6621   ) all_functions_sorted
6622
6623 (* Generate a C function prototype. *)
6624 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6625     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6626     ?(prefix = "")
6627     ?handle name style =
6628   if extern then pr "extern ";
6629   if static then pr "static ";
6630   (match fst style with
6631    | RErr -> pr "int "
6632    | RInt _ -> pr "int "
6633    | RInt64 _ -> pr "int64_t "
6634    | RBool _ -> pr "int "
6635    | RConstString _ | RConstOptString _ -> pr "const char *"
6636    | RString _ | RBufferOut _ -> pr "char *"
6637    | RStringList _ | RHashtable _ -> pr "char **"
6638    | RStruct (_, typ) ->
6639        if not in_daemon then pr "struct guestfs_%s *" typ
6640        else pr "guestfs_int_%s *" typ
6641    | RStructList (_, typ) ->
6642        if not in_daemon then pr "struct guestfs_%s_list *" typ
6643        else pr "guestfs_int_%s_list *" typ
6644   );
6645   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6646   pr "%s%s (" prefix name;
6647   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6648     pr "void"
6649   else (
6650     let comma = ref false in
6651     (match handle with
6652      | None -> ()
6653      | Some handle -> pr "guestfs_h *%s" handle; comma := true
6654     );
6655     let next () =
6656       if !comma then (
6657         if single_line then pr ", " else pr ",\n\t\t"
6658       );
6659       comma := true
6660     in
6661     List.iter (
6662       function
6663       | Pathname n
6664       | Device n | Dev_or_Path n
6665       | String n
6666       | OptString n ->
6667           next ();
6668           pr "const char *%s" n
6669       | StringList n | DeviceList n ->
6670           next ();
6671           pr "char *const *%s" n
6672       | Bool n -> next (); pr "int %s" n
6673       | Int n -> next (); pr "int %s" n
6674       | FileIn n
6675       | FileOut n ->
6676           if not in_daemon then (next (); pr "const char *%s" n)
6677     ) (snd style);
6678     if is_RBufferOut then (next (); pr "size_t *size_r");
6679   );
6680   pr ")";
6681   if semicolon then pr ";";
6682   if newline then pr "\n"
6683
6684 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6685 and generate_c_call_args ?handle ?(decl = false) style =
6686   pr "(";
6687   let comma = ref false in
6688   let next () =
6689     if !comma then pr ", ";
6690     comma := true
6691   in
6692   (match handle with
6693    | None -> ()
6694    | Some handle -> pr "%s" handle; comma := true
6695   );
6696   List.iter (
6697     fun arg ->
6698       next ();
6699       pr "%s" (name_of_argt arg)
6700   ) (snd style);
6701   (* For RBufferOut calls, add implicit &size parameter. *)
6702   if not decl then (
6703     match fst style with
6704     | RBufferOut _ ->
6705         next ();
6706         pr "&size"
6707     | _ -> ()
6708   );
6709   pr ")"
6710
6711 (* Generate the OCaml bindings interface. *)
6712 and generate_ocaml_mli () =
6713   generate_header OCamlStyle LGPLv2;
6714
6715   pr "\
6716 (** For API documentation you should refer to the C API
6717     in the guestfs(3) manual page.  The OCaml API uses almost
6718     exactly the same calls. *)
6719
6720 type t
6721 (** A [guestfs_h] handle. *)
6722
6723 exception Error of string
6724 (** This exception is raised when there is an error. *)
6725
6726 val create : unit -> t
6727
6728 val close : t -> unit
6729 (** Handles are closed by the garbage collector when they become
6730     unreferenced, but callers can also call this in order to
6731     provide predictable cleanup. *)
6732
6733 ";
6734   generate_ocaml_structure_decls ();
6735
6736   (* The actions. *)
6737   List.iter (
6738     fun (name, style, _, _, _, shortdesc, _) ->
6739       generate_ocaml_prototype name style;
6740       pr "(** %s *)\n" shortdesc;
6741       pr "\n"
6742   ) all_functions
6743
6744 (* Generate the OCaml bindings implementation. *)
6745 and generate_ocaml_ml () =
6746   generate_header OCamlStyle LGPLv2;
6747
6748   pr "\
6749 type t
6750 exception Error of string
6751 external create : unit -> t = \"ocaml_guestfs_create\"
6752 external close : t -> unit = \"ocaml_guestfs_close\"
6753
6754 let () =
6755   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6756
6757 ";
6758
6759   generate_ocaml_structure_decls ();
6760
6761   (* The actions. *)
6762   List.iter (
6763     fun (name, style, _, _, _, shortdesc, _) ->
6764       generate_ocaml_prototype ~is_external:true name style;
6765   ) all_functions
6766
6767 (* Generate the OCaml bindings C implementation. *)
6768 and generate_ocaml_c () =
6769   generate_header CStyle LGPLv2;
6770
6771   pr "\
6772 #include <stdio.h>
6773 #include <stdlib.h>
6774 #include <string.h>
6775
6776 #include <caml/config.h>
6777 #include <caml/alloc.h>
6778 #include <caml/callback.h>
6779 #include <caml/fail.h>
6780 #include <caml/memory.h>
6781 #include <caml/mlvalues.h>
6782 #include <caml/signals.h>
6783
6784 #include <guestfs.h>
6785
6786 #include \"guestfs_c.h\"
6787
6788 /* Copy a hashtable of string pairs into an assoc-list.  We return
6789  * the list in reverse order, but hashtables aren't supposed to be
6790  * ordered anyway.
6791  */
6792 static CAMLprim value
6793 copy_table (char * const * argv)
6794 {
6795   CAMLparam0 ();
6796   CAMLlocal5 (rv, pairv, kv, vv, cons);
6797   int i;
6798
6799   rv = Val_int (0);
6800   for (i = 0; argv[i] != NULL; i += 2) {
6801     kv = caml_copy_string (argv[i]);
6802     vv = caml_copy_string (argv[i+1]);
6803     pairv = caml_alloc (2, 0);
6804     Store_field (pairv, 0, kv);
6805     Store_field (pairv, 1, vv);
6806     cons = caml_alloc (2, 0);
6807     Store_field (cons, 1, rv);
6808     rv = cons;
6809     Store_field (cons, 0, pairv);
6810   }
6811
6812   CAMLreturn (rv);
6813 }
6814
6815 ";
6816
6817   (* Struct copy functions. *)
6818
6819   let emit_ocaml_copy_list_function typ =
6820     pr "static CAMLprim value\n";
6821     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
6822     pr "{\n";
6823     pr "  CAMLparam0 ();\n";
6824     pr "  CAMLlocal2 (rv, v);\n";
6825     pr "  unsigned int i;\n";
6826     pr "\n";
6827     pr "  if (%ss->len == 0)\n" typ;
6828     pr "    CAMLreturn (Atom (0));\n";
6829     pr "  else {\n";
6830     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
6831     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
6832     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
6833     pr "      caml_modify (&Field (rv, i), v);\n";
6834     pr "    }\n";
6835     pr "    CAMLreturn (rv);\n";
6836     pr "  }\n";
6837     pr "}\n";
6838     pr "\n";
6839   in
6840
6841   List.iter (
6842     fun (typ, cols) ->
6843       let has_optpercent_col =
6844         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6845
6846       pr "static CAMLprim value\n";
6847       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6848       pr "{\n";
6849       pr "  CAMLparam0 ();\n";
6850       if has_optpercent_col then
6851         pr "  CAMLlocal3 (rv, v, v2);\n"
6852       else
6853         pr "  CAMLlocal2 (rv, v);\n";
6854       pr "\n";
6855       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
6856       iteri (
6857         fun i col ->
6858           (match col with
6859            | name, FString ->
6860                pr "  v = caml_copy_string (%s->%s);\n" typ name
6861            | name, FBuffer ->
6862                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
6863                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6864                  typ name typ name
6865            | name, FUUID ->
6866                pr "  v = caml_alloc_string (32);\n";
6867                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
6868            | name, (FBytes|FInt64|FUInt64) ->
6869                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
6870            | name, (FInt32|FUInt32) ->
6871                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
6872            | name, FOptPercent ->
6873                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
6874                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
6875                pr "    v = caml_alloc (1, 0);\n";
6876                pr "    Store_field (v, 0, v2);\n";
6877                pr "  } else /* None */\n";
6878                pr "    v = Val_int (0);\n";
6879            | name, FChar ->
6880                pr "  v = Val_int (%s->%s);\n" typ name
6881           );
6882           pr "  Store_field (rv, %d, v);\n" i
6883       ) cols;
6884       pr "  CAMLreturn (rv);\n";
6885       pr "}\n";
6886       pr "\n";
6887   ) structs;
6888
6889   (* Emit a copy_TYPE_list function definition only if that function is used. *)
6890   List.iter (
6891     function
6892     | typ, (RStructListOnly | RStructAndList) ->
6893         (* generate the function for typ *)
6894         emit_ocaml_copy_list_function typ
6895     | typ, _ -> () (* empty *)
6896   ) rstructs_used;
6897
6898   (* The wrappers. *)
6899   List.iter (
6900     fun (name, style, _, _, _, _, _) ->
6901       let params =
6902         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
6903
6904       let needs_extra_vs =
6905         match fst style with RConstOptString _ -> true | _ -> false in
6906
6907       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
6908       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
6909       List.iter (pr ", value %s") (List.tl params); pr ");\n";
6910
6911       pr "CAMLprim value\n";
6912       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
6913       List.iter (pr ", value %s") (List.tl params);
6914       pr ")\n";
6915       pr "{\n";
6916
6917       (match params with
6918        | [p1; p2; p3; p4; p5] ->
6919            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
6920        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
6921            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
6922            pr "  CAMLxparam%d (%s);\n"
6923              (List.length rest) (String.concat ", " rest)
6924        | ps ->
6925            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
6926       );
6927       if not needs_extra_vs then
6928         pr "  CAMLlocal1 (rv);\n"
6929       else
6930         pr "  CAMLlocal3 (rv, v, v2);\n";
6931       pr "\n";
6932
6933       pr "  guestfs_h *g = Guestfs_val (gv);\n";
6934       pr "  if (g == NULL)\n";
6935       pr "    caml_failwith (\"%s: used handle after closing it\");\n" name;
6936       pr "\n";
6937
6938       List.iter (
6939         function
6940         | Pathname n
6941         | Device n | Dev_or_Path n
6942         | String n
6943         | FileIn n
6944         | FileOut n ->
6945             pr "  const char *%s = String_val (%sv);\n" n n
6946         | OptString n ->
6947             pr "  const char *%s =\n" n;
6948             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
6949               n n
6950         | StringList n | DeviceList n ->
6951             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
6952         | Bool n ->
6953             pr "  int %s = Bool_val (%sv);\n" n n
6954         | Int n ->
6955             pr "  int %s = Int_val (%sv);\n" n n
6956       ) (snd style);
6957       let error_code =
6958         match fst style with
6959         | RErr -> pr "  int r;\n"; "-1"
6960         | RInt _ -> pr "  int r;\n"; "-1"
6961         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6962         | RBool _ -> pr "  int r;\n"; "-1"
6963         | RConstString _ | RConstOptString _ ->
6964             pr "  const char *r;\n"; "NULL"
6965         | RString _ -> pr "  char *r;\n"; "NULL"
6966         | RStringList _ ->
6967             pr "  int i;\n";
6968             pr "  char **r;\n";
6969             "NULL"
6970         | RStruct (_, typ) ->
6971             pr "  struct guestfs_%s *r;\n" typ; "NULL"
6972         | RStructList (_, typ) ->
6973             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
6974         | RHashtable _ ->
6975             pr "  int i;\n";
6976             pr "  char **r;\n";
6977             "NULL"
6978         | RBufferOut _ ->
6979             pr "  char *r;\n";
6980             pr "  size_t size;\n";
6981             "NULL" in
6982       pr "\n";
6983
6984       pr "  caml_enter_blocking_section ();\n";
6985       pr "  r = guestfs_%s " name;
6986       generate_c_call_args ~handle:"g" style;
6987       pr ";\n";
6988       pr "  caml_leave_blocking_section ();\n";
6989
6990       List.iter (
6991         function
6992         | StringList n | DeviceList n ->
6993             pr "  ocaml_guestfs_free_strings (%s);\n" n;
6994         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
6995         | FileIn _ | FileOut _ -> ()
6996       ) (snd style);
6997
6998       pr "  if (r == %s)\n" error_code;
6999       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7000       pr "\n";
7001
7002       (match fst style with
7003        | RErr -> pr "  rv = Val_unit;\n"
7004        | RInt _ -> pr "  rv = Val_int (r);\n"
7005        | RInt64 _ ->
7006            pr "  rv = caml_copy_int64 (r);\n"
7007        | RBool _ -> pr "  rv = Val_bool (r);\n"
7008        | RConstString _ ->
7009            pr "  rv = caml_copy_string (r);\n"
7010        | RConstOptString _ ->
7011            pr "  if (r) { /* Some string */\n";
7012            pr "    v = caml_alloc (1, 0);\n";
7013            pr "    v2 = caml_copy_string (r);\n";
7014            pr "    Store_field (v, 0, v2);\n";
7015            pr "  } else /* None */\n";
7016            pr "    v = Val_int (0);\n";
7017        | RString _ ->
7018            pr "  rv = caml_copy_string (r);\n";
7019            pr "  free (r);\n"
7020        | RStringList _ ->
7021            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7022            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7023            pr "  free (r);\n"
7024        | RStruct (_, typ) ->
7025            pr "  rv = copy_%s (r);\n" typ;
7026            pr "  guestfs_free_%s (r);\n" typ;
7027        | RStructList (_, typ) ->
7028            pr "  rv = copy_%s_list (r);\n" typ;
7029            pr "  guestfs_free_%s_list (r);\n" typ;
7030        | RHashtable _ ->
7031            pr "  rv = copy_table (r);\n";
7032            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7033            pr "  free (r);\n";
7034        | RBufferOut _ ->
7035            pr "  rv = caml_alloc_string (size);\n";
7036            pr "  memcpy (String_val (rv), r, size);\n";
7037       );
7038
7039       pr "  CAMLreturn (rv);\n";
7040       pr "}\n";
7041       pr "\n";
7042
7043       if List.length params > 5 then (
7044         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7045         pr "CAMLprim value ";
7046         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7047         pr "CAMLprim value\n";
7048         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7049         pr "{\n";
7050         pr "  return ocaml_guestfs_%s (argv[0]" name;
7051         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7052         pr ");\n";
7053         pr "}\n";
7054         pr "\n"
7055       )
7056   ) all_functions
7057
7058 and generate_ocaml_structure_decls () =
7059   List.iter (
7060     fun (typ, cols) ->
7061       pr "type %s = {\n" typ;
7062       List.iter (
7063         function
7064         | name, FString -> pr "  %s : string;\n" name
7065         | name, FBuffer -> pr "  %s : string;\n" name
7066         | name, FUUID -> pr "  %s : string;\n" name
7067         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7068         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7069         | name, FChar -> pr "  %s : char;\n" name
7070         | name, FOptPercent -> pr "  %s : float option;\n" name
7071       ) cols;
7072       pr "}\n";
7073       pr "\n"
7074   ) structs
7075
7076 and generate_ocaml_prototype ?(is_external = false) name style =
7077   if is_external then pr "external " else pr "val ";
7078   pr "%s : t -> " name;
7079   List.iter (
7080     function
7081     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7082     | OptString _ -> pr "string option -> "
7083     | StringList _ | DeviceList _ -> pr "string array -> "
7084     | Bool _ -> pr "bool -> "
7085     | Int _ -> pr "int -> "
7086   ) (snd style);
7087   (match fst style with
7088    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7089    | RInt _ -> pr "int"
7090    | RInt64 _ -> pr "int64"
7091    | RBool _ -> pr "bool"
7092    | RConstString _ -> pr "string"
7093    | RConstOptString _ -> pr "string option"
7094    | RString _ | RBufferOut _ -> pr "string"
7095    | RStringList _ -> pr "string array"
7096    | RStruct (_, typ) -> pr "%s" typ
7097    | RStructList (_, typ) -> pr "%s array" typ
7098    | RHashtable _ -> pr "(string * string) list"
7099   );
7100   if is_external then (
7101     pr " = ";
7102     if List.length (snd style) + 1 > 5 then
7103       pr "\"ocaml_guestfs_%s_byte\" " name;
7104     pr "\"ocaml_guestfs_%s\"" name
7105   );
7106   pr "\n"
7107
7108 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7109 and generate_perl_xs () =
7110   generate_header CStyle LGPLv2;
7111
7112   pr "\
7113 #include \"EXTERN.h\"
7114 #include \"perl.h\"
7115 #include \"XSUB.h\"
7116
7117 #include <guestfs.h>
7118
7119 #ifndef PRId64
7120 #define PRId64 \"lld\"
7121 #endif
7122
7123 static SV *
7124 my_newSVll(long long val) {
7125 #ifdef USE_64_BIT_ALL
7126   return newSViv(val);
7127 #else
7128   char buf[100];
7129   int len;
7130   len = snprintf(buf, 100, \"%%\" PRId64, val);
7131   return newSVpv(buf, len);
7132 #endif
7133 }
7134
7135 #ifndef PRIu64
7136 #define PRIu64 \"llu\"
7137 #endif
7138
7139 static SV *
7140 my_newSVull(unsigned long long val) {
7141 #ifdef USE_64_BIT_ALL
7142   return newSVuv(val);
7143 #else
7144   char buf[100];
7145   int len;
7146   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7147   return newSVpv(buf, len);
7148 #endif
7149 }
7150
7151 /* http://www.perlmonks.org/?node_id=680842 */
7152 static char **
7153 XS_unpack_charPtrPtr (SV *arg) {
7154   char **ret;
7155   AV *av;
7156   I32 i;
7157
7158   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7159     croak (\"array reference expected\");
7160
7161   av = (AV *)SvRV (arg);
7162   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7163   if (!ret)
7164     croak (\"malloc failed\");
7165
7166   for (i = 0; i <= av_len (av); i++) {
7167     SV **elem = av_fetch (av, i, 0);
7168
7169     if (!elem || !*elem)
7170       croak (\"missing element in list\");
7171
7172     ret[i] = SvPV_nolen (*elem);
7173   }
7174
7175   ret[i] = NULL;
7176
7177   return ret;
7178 }
7179
7180 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7181
7182 PROTOTYPES: ENABLE
7183
7184 guestfs_h *
7185 _create ()
7186    CODE:
7187       RETVAL = guestfs_create ();
7188       if (!RETVAL)
7189         croak (\"could not create guestfs handle\");
7190       guestfs_set_error_handler (RETVAL, NULL, NULL);
7191  OUTPUT:
7192       RETVAL
7193
7194 void
7195 DESTROY (g)
7196       guestfs_h *g;
7197  PPCODE:
7198       guestfs_close (g);
7199
7200 ";
7201
7202   List.iter (
7203     fun (name, style, _, _, _, _, _) ->
7204       (match fst style with
7205        | RErr -> pr "void\n"
7206        | RInt _ -> pr "SV *\n"
7207        | RInt64 _ -> pr "SV *\n"
7208        | RBool _ -> pr "SV *\n"
7209        | RConstString _ -> pr "SV *\n"
7210        | RConstOptString _ -> pr "SV *\n"
7211        | RString _ -> pr "SV *\n"
7212        | RBufferOut _ -> pr "SV *\n"
7213        | RStringList _
7214        | RStruct _ | RStructList _
7215        | RHashtable _ ->
7216            pr "void\n" (* all lists returned implictly on the stack *)
7217       );
7218       (* Call and arguments. *)
7219       pr "%s " name;
7220       generate_c_call_args ~handle:"g" ~decl:true style;
7221       pr "\n";
7222       pr "      guestfs_h *g;\n";
7223       iteri (
7224         fun i ->
7225           function
7226           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7227               pr "      char *%s;\n" n
7228           | OptString n ->
7229               (* http://www.perlmonks.org/?node_id=554277
7230                * Note that the implicit handle argument means we have
7231                * to add 1 to the ST(x) operator.
7232                *)
7233               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7234           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7235           | Bool n -> pr "      int %s;\n" n
7236           | Int n -> pr "      int %s;\n" n
7237       ) (snd style);
7238
7239       let do_cleanups () =
7240         List.iter (
7241           function
7242           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
7243           | FileIn _ | FileOut _ -> ()
7244           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7245         ) (snd style)
7246       in
7247
7248       (* Code. *)
7249       (match fst style with
7250        | RErr ->
7251            pr "PREINIT:\n";
7252            pr "      int r;\n";
7253            pr " PPCODE:\n";
7254            pr "      r = guestfs_%s " name;
7255            generate_c_call_args ~handle:"g" style;
7256            pr ";\n";
7257            do_cleanups ();
7258            pr "      if (r == -1)\n";
7259            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7260        | RInt n
7261        | RBool n ->
7262            pr "PREINIT:\n";
7263            pr "      int %s;\n" n;
7264            pr "   CODE:\n";
7265            pr "      %s = guestfs_%s " n name;
7266            generate_c_call_args ~handle:"g" style;
7267            pr ";\n";
7268            do_cleanups ();
7269            pr "      if (%s == -1)\n" n;
7270            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7271            pr "      RETVAL = newSViv (%s);\n" n;
7272            pr " OUTPUT:\n";
7273            pr "      RETVAL\n"
7274        | RInt64 n ->
7275            pr "PREINIT:\n";
7276            pr "      int64_t %s;\n" n;
7277            pr "   CODE:\n";
7278            pr "      %s = guestfs_%s " n name;
7279            generate_c_call_args ~handle:"g" style;
7280            pr ";\n";
7281            do_cleanups ();
7282            pr "      if (%s == -1)\n" n;
7283            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7284            pr "      RETVAL = my_newSVll (%s);\n" n;
7285            pr " OUTPUT:\n";
7286            pr "      RETVAL\n"
7287        | RConstString n ->
7288            pr "PREINIT:\n";
7289            pr "      const char *%s;\n" n;
7290            pr "   CODE:\n";
7291            pr "      %s = guestfs_%s " n name;
7292            generate_c_call_args ~handle:"g" style;
7293            pr ";\n";
7294            do_cleanups ();
7295            pr "      if (%s == NULL)\n" n;
7296            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7297            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7298            pr " OUTPUT:\n";
7299            pr "      RETVAL\n"
7300        | RConstOptString n ->
7301            pr "PREINIT:\n";
7302            pr "      const char *%s;\n" n;
7303            pr "   CODE:\n";
7304            pr "      %s = guestfs_%s " n name;
7305            generate_c_call_args ~handle:"g" style;
7306            pr ";\n";
7307            do_cleanups ();
7308            pr "      if (%s == NULL)\n" n;
7309            pr "        RETVAL = &PL_sv_undef;\n";
7310            pr "      else\n";
7311            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7312            pr " OUTPUT:\n";
7313            pr "      RETVAL\n"
7314        | RString n ->
7315            pr "PREINIT:\n";
7316            pr "      char *%s;\n" n;
7317            pr "   CODE:\n";
7318            pr "      %s = guestfs_%s " n name;
7319            generate_c_call_args ~handle:"g" style;
7320            pr ";\n";
7321            do_cleanups ();
7322            pr "      if (%s == NULL)\n" n;
7323            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7324            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7325            pr "      free (%s);\n" n;
7326            pr " OUTPUT:\n";
7327            pr "      RETVAL\n"
7328        | RStringList n | RHashtable n ->
7329            pr "PREINIT:\n";
7330            pr "      char **%s;\n" n;
7331            pr "      int i, n;\n";
7332            pr " PPCODE:\n";
7333            pr "      %s = guestfs_%s " n name;
7334            generate_c_call_args ~handle:"g" style;
7335            pr ";\n";
7336            do_cleanups ();
7337            pr "      if (%s == NULL)\n" n;
7338            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7339            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7340            pr "      EXTEND (SP, n);\n";
7341            pr "      for (i = 0; i < n; ++i) {\n";
7342            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7343            pr "        free (%s[i]);\n" n;
7344            pr "      }\n";
7345            pr "      free (%s);\n" n;
7346        | RStruct (n, typ) ->
7347            let cols = cols_of_struct typ in
7348            generate_perl_struct_code typ cols name style n do_cleanups
7349        | RStructList (n, typ) ->
7350            let cols = cols_of_struct typ in
7351            generate_perl_struct_list_code typ cols name style n do_cleanups
7352        | RBufferOut n ->
7353            pr "PREINIT:\n";
7354            pr "      char *%s;\n" n;
7355            pr "      size_t size;\n";
7356            pr "   CODE:\n";
7357            pr "      %s = guestfs_%s " n name;
7358            generate_c_call_args ~handle:"g" style;
7359            pr ";\n";
7360            do_cleanups ();
7361            pr "      if (%s == NULL)\n" n;
7362            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7363            pr "      RETVAL = newSVpv (%s, size);\n" n;
7364            pr "      free (%s);\n" n;
7365            pr " OUTPUT:\n";
7366            pr "      RETVAL\n"
7367       );
7368
7369       pr "\n"
7370   ) all_functions
7371
7372 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7373   pr "PREINIT:\n";
7374   pr "      struct guestfs_%s_list *%s;\n" typ n;
7375   pr "      int i;\n";
7376   pr "      HV *hv;\n";
7377   pr " PPCODE:\n";
7378   pr "      %s = guestfs_%s " n name;
7379   generate_c_call_args ~handle:"g" style;
7380   pr ";\n";
7381   do_cleanups ();
7382   pr "      if (%s == NULL)\n" n;
7383   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7384   pr "      EXTEND (SP, %s->len);\n" n;
7385   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7386   pr "        hv = newHV ();\n";
7387   List.iter (
7388     function
7389     | name, FString ->
7390         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7391           name (String.length name) n name
7392     | name, FUUID ->
7393         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7394           name (String.length name) n name
7395     | name, FBuffer ->
7396         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7397           name (String.length name) n name n name
7398     | name, (FBytes|FUInt64) ->
7399         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7400           name (String.length name) n name
7401     | name, FInt64 ->
7402         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7403           name (String.length name) n name
7404     | name, (FInt32|FUInt32) ->
7405         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7406           name (String.length name) n name
7407     | name, FChar ->
7408         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7409           name (String.length name) n name
7410     | name, FOptPercent ->
7411         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7412           name (String.length name) n name
7413   ) cols;
7414   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7415   pr "      }\n";
7416   pr "      guestfs_free_%s_list (%s);\n" typ n
7417
7418 and generate_perl_struct_code typ cols name style n do_cleanups =
7419   pr "PREINIT:\n";
7420   pr "      struct guestfs_%s *%s;\n" typ n;
7421   pr " PPCODE:\n";
7422   pr "      %s = guestfs_%s " n name;
7423   generate_c_call_args ~handle:"g" style;
7424   pr ";\n";
7425   do_cleanups ();
7426   pr "      if (%s == NULL)\n" n;
7427   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7428   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
7429   List.iter (
7430     fun ((name, _) as col) ->
7431       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7432
7433       match col with
7434       | name, FString ->
7435           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7436             n name
7437       | name, FBuffer ->
7438           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7439             n name n name
7440       | name, FUUID ->
7441           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7442             n name
7443       | name, (FBytes|FUInt64) ->
7444           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7445             n name
7446       | name, FInt64 ->
7447           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7448             n name
7449       | name, (FInt32|FUInt32) ->
7450           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7451             n name
7452       | name, FChar ->
7453           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7454             n name
7455       | name, FOptPercent ->
7456           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7457             n name
7458   ) cols;
7459   pr "      free (%s);\n" n
7460
7461 (* Generate Sys/Guestfs.pm. *)
7462 and generate_perl_pm () =
7463   generate_header HashStyle LGPLv2;
7464
7465   pr "\
7466 =pod
7467
7468 =head1 NAME
7469
7470 Sys::Guestfs - Perl bindings for libguestfs
7471
7472 =head1 SYNOPSIS
7473
7474  use Sys::Guestfs;
7475
7476  my $h = Sys::Guestfs->new ();
7477  $h->add_drive ('guest.img');
7478  $h->launch ();
7479  $h->wait_ready ();
7480  $h->mount ('/dev/sda1', '/');
7481  $h->touch ('/hello');
7482  $h->sync ();
7483
7484 =head1 DESCRIPTION
7485
7486 The C<Sys::Guestfs> module provides a Perl XS binding to the
7487 libguestfs API for examining and modifying virtual machine
7488 disk images.
7489
7490 Amongst the things this is good for: making batch configuration
7491 changes to guests, getting disk used/free statistics (see also:
7492 virt-df), migrating between virtualization systems (see also:
7493 virt-p2v), performing partial backups, performing partial guest
7494 clones, cloning guests and changing registry/UUID/hostname info, and
7495 much else besides.
7496
7497 Libguestfs uses Linux kernel and qemu code, and can access any type of
7498 guest filesystem that Linux and qemu can, including but not limited
7499 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7500 schemes, qcow, qcow2, vmdk.
7501
7502 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7503 LVs, what filesystem is in each LV, etc.).  It can also run commands
7504 in the context of the guest.  Also you can access filesystems over FTP.
7505
7506 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7507 functions for using libguestfs from Perl, including integration
7508 with libvirt.
7509
7510 =head1 ERRORS
7511
7512 All errors turn into calls to C<croak> (see L<Carp(3)>).
7513
7514 =head1 METHODS
7515
7516 =over 4
7517
7518 =cut
7519
7520 package Sys::Guestfs;
7521
7522 use strict;
7523 use warnings;
7524
7525 require XSLoader;
7526 XSLoader::load ('Sys::Guestfs');
7527
7528 =item $h = Sys::Guestfs->new ();
7529
7530 Create a new guestfs handle.
7531
7532 =cut
7533
7534 sub new {
7535   my $proto = shift;
7536   my $class = ref ($proto) || $proto;
7537
7538   my $self = Sys::Guestfs::_create ();
7539   bless $self, $class;
7540   return $self;
7541 }
7542
7543 ";
7544
7545   (* Actions.  We only need to print documentation for these as
7546    * they are pulled in from the XS code automatically.
7547    *)
7548   List.iter (
7549     fun (name, style, _, flags, _, _, longdesc) ->
7550       if not (List.mem NotInDocs flags) then (
7551         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7552         pr "=item ";
7553         generate_perl_prototype name style;
7554         pr "\n\n";
7555         pr "%s\n\n" longdesc;
7556         if List.mem ProtocolLimitWarning flags then
7557           pr "%s\n\n" protocol_limit_warning;
7558         if List.mem DangerWillRobinson flags then
7559           pr "%s\n\n" danger_will_robinson;
7560         match deprecation_notice flags with
7561         | None -> ()
7562         | Some txt -> pr "%s\n\n" txt
7563       )
7564   ) all_functions_sorted;
7565
7566   (* End of file. *)
7567   pr "\
7568 =cut
7569
7570 1;
7571
7572 =back
7573
7574 =head1 COPYRIGHT
7575
7576 Copyright (C) 2009 Red Hat Inc.
7577
7578 =head1 LICENSE
7579
7580 Please see the file COPYING.LIB for the full license.
7581
7582 =head1 SEE ALSO
7583
7584 L<guestfs(3)>,
7585 L<guestfish(1)>,
7586 L<http://libguestfs.org>,
7587 L<Sys::Guestfs::Lib(3)>.
7588
7589 =cut
7590 "
7591
7592 and generate_perl_prototype name style =
7593   (match fst style with
7594    | RErr -> ()
7595    | RBool n
7596    | RInt n
7597    | RInt64 n
7598    | RConstString n
7599    | RConstOptString n
7600    | RString n
7601    | RBufferOut n -> pr "$%s = " n
7602    | RStruct (n,_)
7603    | RHashtable n -> pr "%%%s = " n
7604    | RStringList n
7605    | RStructList (n,_) -> pr "@%s = " n
7606   );
7607   pr "$h->%s (" name;
7608   let comma = ref false in
7609   List.iter (
7610     fun arg ->
7611       if !comma then pr ", ";
7612       comma := true;
7613       match arg with
7614       | Pathname n | Device n | Dev_or_Path n | String n
7615       | OptString n | Bool n | Int n | FileIn n | FileOut n ->
7616           pr "$%s" n
7617       | StringList n | DeviceList n ->
7618           pr "\\@%s" n
7619   ) (snd style);
7620   pr ");"
7621
7622 (* Generate Python C module. *)
7623 and generate_python_c () =
7624   generate_header CStyle LGPLv2;
7625
7626   pr "\
7627 #include <Python.h>
7628
7629 #include <stdio.h>
7630 #include <stdlib.h>
7631 #include <assert.h>
7632
7633 #include \"guestfs.h\"
7634
7635 typedef struct {
7636   PyObject_HEAD
7637   guestfs_h *g;
7638 } Pyguestfs_Object;
7639
7640 static guestfs_h *
7641 get_handle (PyObject *obj)
7642 {
7643   assert (obj);
7644   assert (obj != Py_None);
7645   return ((Pyguestfs_Object *) obj)->g;
7646 }
7647
7648 static PyObject *
7649 put_handle (guestfs_h *g)
7650 {
7651   assert (g);
7652   return
7653     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7654 }
7655
7656 /* This list should be freed (but not the strings) after use. */
7657 static char **
7658 get_string_list (PyObject *obj)
7659 {
7660   int i, len;
7661   char **r;
7662
7663   assert (obj);
7664
7665   if (!PyList_Check (obj)) {
7666     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7667     return NULL;
7668   }
7669
7670   len = PyList_Size (obj);
7671   r = malloc (sizeof (char *) * (len+1));
7672   if (r == NULL) {
7673     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7674     return NULL;
7675   }
7676
7677   for (i = 0; i < len; ++i)
7678     r[i] = PyString_AsString (PyList_GetItem (obj, i));
7679   r[len] = NULL;
7680
7681   return r;
7682 }
7683
7684 static PyObject *
7685 put_string_list (char * const * const argv)
7686 {
7687   PyObject *list;
7688   int argc, i;
7689
7690   for (argc = 0; argv[argc] != NULL; ++argc)
7691     ;
7692
7693   list = PyList_New (argc);
7694   for (i = 0; i < argc; ++i)
7695     PyList_SetItem (list, i, PyString_FromString (argv[i]));
7696
7697   return list;
7698 }
7699
7700 static PyObject *
7701 put_table (char * const * const argv)
7702 {
7703   PyObject *list, *item;
7704   int argc, i;
7705
7706   for (argc = 0; argv[argc] != NULL; ++argc)
7707     ;
7708
7709   list = PyList_New (argc >> 1);
7710   for (i = 0; i < argc; i += 2) {
7711     item = PyTuple_New (2);
7712     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7713     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7714     PyList_SetItem (list, i >> 1, item);
7715   }
7716
7717   return list;
7718 }
7719
7720 static void
7721 free_strings (char **argv)
7722 {
7723   int argc;
7724
7725   for (argc = 0; argv[argc] != NULL; ++argc)
7726     free (argv[argc]);
7727   free (argv);
7728 }
7729
7730 static PyObject *
7731 py_guestfs_create (PyObject *self, PyObject *args)
7732 {
7733   guestfs_h *g;
7734
7735   g = guestfs_create ();
7736   if (g == NULL) {
7737     PyErr_SetString (PyExc_RuntimeError,
7738                      \"guestfs.create: failed to allocate handle\");
7739     return NULL;
7740   }
7741   guestfs_set_error_handler (g, NULL, NULL);
7742   return put_handle (g);
7743 }
7744
7745 static PyObject *
7746 py_guestfs_close (PyObject *self, PyObject *args)
7747 {
7748   PyObject *py_g;
7749   guestfs_h *g;
7750
7751   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7752     return NULL;
7753   g = get_handle (py_g);
7754
7755   guestfs_close (g);
7756
7757   Py_INCREF (Py_None);
7758   return Py_None;
7759 }
7760
7761 ";
7762
7763   let emit_put_list_function typ =
7764     pr "static PyObject *\n";
7765     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7766     pr "{\n";
7767     pr "  PyObject *list;\n";
7768     pr "  int i;\n";
7769     pr "\n";
7770     pr "  list = PyList_New (%ss->len);\n" typ;
7771     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
7772     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7773     pr "  return list;\n";
7774     pr "};\n";
7775     pr "\n"
7776   in
7777
7778   (* Structures, turned into Python dictionaries. *)
7779   List.iter (
7780     fun (typ, cols) ->
7781       pr "static PyObject *\n";
7782       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7783       pr "{\n";
7784       pr "  PyObject *dict;\n";
7785       pr "\n";
7786       pr "  dict = PyDict_New ();\n";
7787       List.iter (
7788         function
7789         | name, FString ->
7790             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7791             pr "                        PyString_FromString (%s->%s));\n"
7792               typ name
7793         | name, FBuffer ->
7794             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7795             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7796               typ name typ name
7797         | name, FUUID ->
7798             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7799             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
7800               typ name
7801         | name, (FBytes|FUInt64) ->
7802             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7803             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
7804               typ name
7805         | name, FInt64 ->
7806             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7807             pr "                        PyLong_FromLongLong (%s->%s));\n"
7808               typ name
7809         | name, FUInt32 ->
7810             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7811             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
7812               typ name
7813         | name, FInt32 ->
7814             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7815             pr "                        PyLong_FromLong (%s->%s));\n"
7816               typ name
7817         | name, FOptPercent ->
7818             pr "  if (%s->%s >= 0)\n" typ name;
7819             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
7820             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
7821               typ name;
7822             pr "  else {\n";
7823             pr "    Py_INCREF (Py_None);\n";
7824             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
7825             pr "  }\n"
7826         | name, FChar ->
7827             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7828             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7829       ) cols;
7830       pr "  return dict;\n";
7831       pr "};\n";
7832       pr "\n";
7833
7834   ) structs;
7835
7836   (* Emit a put_TYPE_list function definition only if that function is used. *)
7837   List.iter (
7838     function
7839     | typ, (RStructListOnly | RStructAndList) ->
7840         (* generate the function for typ *)
7841         emit_put_list_function typ
7842     | typ, _ -> () (* empty *)
7843   ) rstructs_used;
7844
7845   (* Python wrapper functions. *)
7846   List.iter (
7847     fun (name, style, _, _, _, _, _) ->
7848       pr "static PyObject *\n";
7849       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7850       pr "{\n";
7851
7852       pr "  PyObject *py_g;\n";
7853       pr "  guestfs_h *g;\n";
7854       pr "  PyObject *py_r;\n";
7855
7856       let error_code =
7857         match fst style with
7858         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
7859         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7860         | RConstString _ | RConstOptString _ ->
7861             pr "  const char *r;\n"; "NULL"
7862         | RString _ -> pr "  char *r;\n"; "NULL"
7863         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
7864         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
7865         | RStructList (_, typ) ->
7866             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7867         | RBufferOut _ ->
7868             pr "  char *r;\n";
7869             pr "  size_t size;\n";
7870             "NULL" in
7871
7872       List.iter (
7873         function
7874         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7875             pr "  const char *%s;\n" n
7876         | OptString n -> pr "  const char *%s;\n" n
7877         | StringList n | DeviceList n ->
7878             pr "  PyObject *py_%s;\n" n;
7879             pr "  char **%s;\n" n
7880         | Bool n -> pr "  int %s;\n" n
7881         | Int n -> pr "  int %s;\n" n
7882       ) (snd style);
7883
7884       pr "\n";
7885
7886       (* Convert the parameters. *)
7887       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
7888       List.iter (
7889         function
7890         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
7891         | OptString _ -> pr "z"
7892         | StringList _ | DeviceList _ -> pr "O"
7893         | Bool _ -> pr "i" (* XXX Python has booleans? *)
7894         | Int _ -> pr "i"
7895       ) (snd style);
7896       pr ":guestfs_%s\",\n" name;
7897       pr "                         &py_g";
7898       List.iter (
7899         function
7900         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
7901         | OptString n -> pr ", &%s" n
7902         | StringList n | DeviceList n -> pr ", &py_%s" n
7903         | Bool n -> pr ", &%s" n
7904         | Int n -> pr ", &%s" n
7905       ) (snd style);
7906
7907       pr "))\n";
7908       pr "    return NULL;\n";
7909
7910       pr "  g = get_handle (py_g);\n";
7911       List.iter (
7912         function
7913         | Pathname _ | Device _ | Dev_or_Path _ | String _
7914         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7915         | StringList n | DeviceList n ->
7916             pr "  %s = get_string_list (py_%s);\n" n n;
7917             pr "  if (!%s) return NULL;\n" n
7918       ) (snd style);
7919
7920       pr "\n";
7921
7922       pr "  r = guestfs_%s " name;
7923       generate_c_call_args ~handle:"g" style;
7924       pr ";\n";
7925
7926       List.iter (
7927         function
7928         | Pathname _ | Device _ | Dev_or_Path _ | String _
7929         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7930         | StringList n | DeviceList n ->
7931             pr "  free (%s);\n" n
7932       ) (snd style);
7933
7934       pr "  if (r == %s) {\n" error_code;
7935       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
7936       pr "    return NULL;\n";
7937       pr "  }\n";
7938       pr "\n";
7939
7940       (match fst style with
7941        | RErr ->
7942            pr "  Py_INCREF (Py_None);\n";
7943            pr "  py_r = Py_None;\n"
7944        | RInt _
7945        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
7946        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
7947        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
7948        | RConstOptString _ ->
7949            pr "  if (r)\n";
7950            pr "    py_r = PyString_FromString (r);\n";
7951            pr "  else {\n";
7952            pr "    Py_INCREF (Py_None);\n";
7953            pr "    py_r = Py_None;\n";
7954            pr "  }\n"
7955        | RString _ ->
7956            pr "  py_r = PyString_FromString (r);\n";
7957            pr "  free (r);\n"
7958        | RStringList _ ->
7959            pr "  py_r = put_string_list (r);\n";
7960            pr "  free_strings (r);\n"
7961        | RStruct (_, typ) ->
7962            pr "  py_r = put_%s (r);\n" typ;
7963            pr "  guestfs_free_%s (r);\n" typ
7964        | RStructList (_, typ) ->
7965            pr "  py_r = put_%s_list (r);\n" typ;
7966            pr "  guestfs_free_%s_list (r);\n" typ
7967        | RHashtable n ->
7968            pr "  py_r = put_table (r);\n";
7969            pr "  free_strings (r);\n"
7970        | RBufferOut _ ->
7971            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
7972            pr "  free (r);\n"
7973       );
7974
7975       pr "  return py_r;\n";
7976       pr "}\n";
7977       pr "\n"
7978   ) all_functions;
7979
7980   (* Table of functions. *)
7981   pr "static PyMethodDef methods[] = {\n";
7982   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
7983   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
7984   List.iter (
7985     fun (name, _, _, _, _, _, _) ->
7986       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
7987         name name
7988   ) all_functions;
7989   pr "  { NULL, NULL, 0, NULL }\n";
7990   pr "};\n";
7991   pr "\n";
7992
7993   (* Init function. *)
7994   pr "\
7995 void
7996 initlibguestfsmod (void)
7997 {
7998   static int initialized = 0;
7999
8000   if (initialized) return;
8001   Py_InitModule ((char *) \"libguestfsmod\", methods);
8002   initialized = 1;
8003 }
8004 "
8005
8006 (* Generate Python module. *)
8007 and generate_python_py () =
8008   generate_header HashStyle LGPLv2;
8009
8010   pr "\
8011 u\"\"\"Python bindings for libguestfs
8012
8013 import guestfs
8014 g = guestfs.GuestFS ()
8015 g.add_drive (\"guest.img\")
8016 g.launch ()
8017 g.wait_ready ()
8018 parts = g.list_partitions ()
8019
8020 The guestfs module provides a Python binding to the libguestfs API
8021 for examining and modifying virtual machine disk images.
8022
8023 Amongst the things this is good for: making batch configuration
8024 changes to guests, getting disk used/free statistics (see also:
8025 virt-df), migrating between virtualization systems (see also:
8026 virt-p2v), performing partial backups, performing partial guest
8027 clones, cloning guests and changing registry/UUID/hostname info, and
8028 much else besides.
8029
8030 Libguestfs uses Linux kernel and qemu code, and can access any type of
8031 guest filesystem that Linux and qemu can, including but not limited
8032 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8033 schemes, qcow, qcow2, vmdk.
8034
8035 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8036 LVs, what filesystem is in each LV, etc.).  It can also run commands
8037 in the context of the guest.  Also you can access filesystems over FTP.
8038
8039 Errors which happen while using the API are turned into Python
8040 RuntimeError exceptions.
8041
8042 To create a guestfs handle you usually have to perform the following
8043 sequence of calls:
8044
8045 # Create the handle, call add_drive at least once, and possibly
8046 # several times if the guest has multiple block devices:
8047 g = guestfs.GuestFS ()
8048 g.add_drive (\"guest.img\")
8049
8050 # Launch the qemu subprocess and wait for it to become ready:
8051 g.launch ()
8052 g.wait_ready ()
8053
8054 # Now you can issue commands, for example:
8055 logvols = g.lvs ()
8056
8057 \"\"\"
8058
8059 import libguestfsmod
8060
8061 class GuestFS:
8062     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8063
8064     def __init__ (self):
8065         \"\"\"Create a new libguestfs handle.\"\"\"
8066         self._o = libguestfsmod.create ()
8067
8068     def __del__ (self):
8069         libguestfsmod.close (self._o)
8070
8071 ";
8072
8073   List.iter (
8074     fun (name, style, _, flags, _, _, longdesc) ->
8075       pr "    def %s " name;
8076       generate_py_call_args ~handle:"self" (snd style);
8077       pr ":\n";
8078
8079       if not (List.mem NotInDocs flags) then (
8080         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8081         let doc =
8082           match fst style with
8083           | RErr | RInt _ | RInt64 _ | RBool _
8084           | RConstOptString _ | RConstString _
8085           | RString _ | RBufferOut _ -> doc
8086           | RStringList _ ->
8087               doc ^ "\n\nThis function returns a list of strings."
8088           | RStruct (_, typ) ->
8089               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8090           | RStructList (_, typ) ->
8091               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8092           | RHashtable _ ->
8093               doc ^ "\n\nThis function returns a dictionary." in
8094         let doc =
8095           if List.mem ProtocolLimitWarning flags then
8096             doc ^ "\n\n" ^ protocol_limit_warning
8097           else doc in
8098         let doc =
8099           if List.mem DangerWillRobinson flags then
8100             doc ^ "\n\n" ^ danger_will_robinson
8101           else doc in
8102         let doc =
8103           match deprecation_notice flags with
8104           | None -> doc
8105           | Some txt -> doc ^ "\n\n" ^ txt in
8106         let doc = pod2text ~width:60 name doc in
8107         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8108         let doc = String.concat "\n        " doc in
8109         pr "        u\"\"\"%s\"\"\"\n" doc;
8110       );
8111       pr "        return libguestfsmod.%s " name;
8112       generate_py_call_args ~handle:"self._o" (snd style);
8113       pr "\n";
8114       pr "\n";
8115   ) all_functions
8116
8117 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8118 and generate_py_call_args ~handle args =
8119   pr "(%s" handle;
8120   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8121   pr ")"
8122
8123 (* Useful if you need the longdesc POD text as plain text.  Returns a
8124  * list of lines.
8125  *
8126  * Because this is very slow (the slowest part of autogeneration),
8127  * we memoize the results.
8128  *)
8129 and pod2text ~width name longdesc =
8130   let key = width, name, longdesc in
8131   try Hashtbl.find pod2text_memo key
8132   with Not_found ->
8133     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8134     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8135     close_out chan;
8136     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8137     let chan = Unix.open_process_in cmd in
8138     let lines = ref [] in
8139     let rec loop i =
8140       let line = input_line chan in
8141       if i = 1 then             (* discard the first line of output *)
8142         loop (i+1)
8143       else (
8144         let line = triml line in
8145         lines := line :: !lines;
8146         loop (i+1)
8147       ) in
8148     let lines = try loop 1 with End_of_file -> List.rev !lines in
8149     Unix.unlink filename;
8150     (match Unix.close_process_in chan with
8151      | Unix.WEXITED 0 -> ()
8152      | Unix.WEXITED i ->
8153          failwithf "pod2text: process exited with non-zero status (%d)" i
8154      | Unix.WSIGNALED i | Unix.WSTOPPED i ->
8155          failwithf "pod2text: process signalled or stopped by signal %d" i
8156     );
8157     Hashtbl.add pod2text_memo key lines;
8158     pod2text_memo_updated ();
8159     lines
8160
8161 (* Generate ruby bindings. *)
8162 and generate_ruby_c () =
8163   generate_header CStyle LGPLv2;
8164
8165   pr "\
8166 #include <stdio.h>
8167 #include <stdlib.h>
8168
8169 #include <ruby.h>
8170
8171 #include \"guestfs.h\"
8172
8173 #include \"extconf.h\"
8174
8175 /* For Ruby < 1.9 */
8176 #ifndef RARRAY_LEN
8177 #define RARRAY_LEN(r) (RARRAY((r))->len)
8178 #endif
8179
8180 static VALUE m_guestfs;                 /* guestfs module */
8181 static VALUE c_guestfs;                 /* guestfs_h handle */
8182 static VALUE e_Error;                   /* used for all errors */
8183
8184 static void ruby_guestfs_free (void *p)
8185 {
8186   if (!p) return;
8187   guestfs_close ((guestfs_h *) p);
8188 }
8189
8190 static VALUE ruby_guestfs_create (VALUE m)
8191 {
8192   guestfs_h *g;
8193
8194   g = guestfs_create ();
8195   if (!g)
8196     rb_raise (e_Error, \"failed to create guestfs handle\");
8197
8198   /* Don't print error messages to stderr by default. */
8199   guestfs_set_error_handler (g, NULL, NULL);
8200
8201   /* Wrap it, and make sure the close function is called when the
8202    * handle goes away.
8203    */
8204   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8205 }
8206
8207 static VALUE ruby_guestfs_close (VALUE gv)
8208 {
8209   guestfs_h *g;
8210   Data_Get_Struct (gv, guestfs_h, g);
8211
8212   ruby_guestfs_free (g);
8213   DATA_PTR (gv) = NULL;
8214
8215   return Qnil;
8216 }
8217
8218 ";
8219
8220   List.iter (
8221     fun (name, style, _, _, _, _, _) ->
8222       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8223       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8224       pr ")\n";
8225       pr "{\n";
8226       pr "  guestfs_h *g;\n";
8227       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8228       pr "  if (!g)\n";
8229       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8230         name;
8231       pr "\n";
8232
8233       List.iter (
8234         function
8235         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8236             pr "  Check_Type (%sv, T_STRING);\n" n;
8237             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8238             pr "  if (!%s)\n" n;
8239             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8240             pr "              \"%s\", \"%s\");\n" n name
8241         | OptString n ->
8242             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8243         | StringList n | DeviceList n ->
8244             pr "  char **%s;\n" n;
8245             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8246             pr "  {\n";
8247             pr "    int i, len;\n";
8248             pr "    len = RARRAY_LEN (%sv);\n" n;
8249             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8250               n;
8251             pr "    for (i = 0; i < len; ++i) {\n";
8252             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8253             pr "      %s[i] = StringValueCStr (v);\n" n;
8254             pr "    }\n";
8255             pr "    %s[len] = NULL;\n" n;
8256             pr "  }\n";
8257         | Bool n ->
8258             pr "  int %s = RTEST (%sv);\n" n n
8259         | Int n ->
8260             pr "  int %s = NUM2INT (%sv);\n" n n
8261       ) (snd style);
8262       pr "\n";
8263
8264       let error_code =
8265         match fst style with
8266         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8267         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8268         | RConstString _ | RConstOptString _ ->
8269             pr "  const char *r;\n"; "NULL"
8270         | RString _ -> pr "  char *r;\n"; "NULL"
8271         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8272         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8273         | RStructList (_, typ) ->
8274             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8275         | RBufferOut _ ->
8276             pr "  char *r;\n";
8277             pr "  size_t size;\n";
8278             "NULL" in
8279       pr "\n";
8280
8281       pr "  r = guestfs_%s " name;
8282       generate_c_call_args ~handle:"g" style;
8283       pr ";\n";
8284
8285       List.iter (
8286         function
8287         | Pathname _ | Device _ | Dev_or_Path _ | String _
8288         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
8289         | StringList n | DeviceList n ->
8290             pr "  free (%s);\n" n
8291       ) (snd style);
8292
8293       pr "  if (r == %s)\n" error_code;
8294       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8295       pr "\n";
8296
8297       (match fst style with
8298        | RErr ->
8299            pr "  return Qnil;\n"
8300        | RInt _ | RBool _ ->
8301            pr "  return INT2NUM (r);\n"
8302        | RInt64 _ ->
8303            pr "  return ULL2NUM (r);\n"
8304        | RConstString _ ->
8305            pr "  return rb_str_new2 (r);\n";
8306        | RConstOptString _ ->
8307            pr "  if (r)\n";
8308            pr "    return rb_str_new2 (r);\n";
8309            pr "  else\n";
8310            pr "    return Qnil;\n";
8311        | RString _ ->
8312            pr "  VALUE rv = rb_str_new2 (r);\n";
8313            pr "  free (r);\n";
8314            pr "  return rv;\n";
8315        | RStringList _ ->
8316            pr "  int i, len = 0;\n";
8317            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8318            pr "  VALUE rv = rb_ary_new2 (len);\n";
8319            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8320            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8321            pr "    free (r[i]);\n";
8322            pr "  }\n";
8323            pr "  free (r);\n";
8324            pr "  return rv;\n"
8325        | RStruct (_, typ) ->
8326            let cols = cols_of_struct typ in
8327            generate_ruby_struct_code typ cols
8328        | RStructList (_, typ) ->
8329            let cols = cols_of_struct typ in
8330            generate_ruby_struct_list_code typ cols
8331        | RHashtable _ ->
8332            pr "  VALUE rv = rb_hash_new ();\n";
8333            pr "  int i;\n";
8334            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8335            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8336            pr "    free (r[i]);\n";
8337            pr "    free (r[i+1]);\n";
8338            pr "  }\n";
8339            pr "  free (r);\n";
8340            pr "  return rv;\n"
8341        | RBufferOut _ ->
8342            pr "  VALUE rv = rb_str_new (r, size);\n";
8343            pr "  free (r);\n";
8344            pr "  return rv;\n";
8345       );
8346
8347       pr "}\n";
8348       pr "\n"
8349   ) all_functions;
8350
8351   pr "\
8352 /* Initialize the module. */
8353 void Init__guestfs ()
8354 {
8355   m_guestfs = rb_define_module (\"Guestfs\");
8356   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8357   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8358
8359   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8360   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8361
8362 ";
8363   (* Define the rest of the methods. *)
8364   List.iter (
8365     fun (name, style, _, _, _, _, _) ->
8366       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8367       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8368   ) all_functions;
8369
8370   pr "}\n"
8371
8372 (* Ruby code to return a struct. *)
8373 and generate_ruby_struct_code typ cols =
8374   pr "  VALUE rv = rb_hash_new ();\n";
8375   List.iter (
8376     function
8377     | name, FString ->
8378         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8379     | name, FBuffer ->
8380         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8381     | name, FUUID ->
8382         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8383     | name, (FBytes|FUInt64) ->
8384         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8385     | name, FInt64 ->
8386         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8387     | name, FUInt32 ->
8388         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8389     | name, FInt32 ->
8390         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8391     | name, FOptPercent ->
8392         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8393     | name, FChar -> (* XXX wrong? *)
8394         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8395   ) cols;
8396   pr "  guestfs_free_%s (r);\n" typ;
8397   pr "  return rv;\n"
8398
8399 (* Ruby code to return a struct list. *)
8400 and generate_ruby_struct_list_code typ cols =
8401   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8402   pr "  int i;\n";
8403   pr "  for (i = 0; i < r->len; ++i) {\n";
8404   pr "    VALUE hv = rb_hash_new ();\n";
8405   List.iter (
8406     function
8407     | name, FString ->
8408         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8409     | name, FBuffer ->
8410         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
8411     | name, FUUID ->
8412         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8413     | name, (FBytes|FUInt64) ->
8414         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8415     | name, FInt64 ->
8416         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8417     | name, FUInt32 ->
8418         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8419     | name, FInt32 ->
8420         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8421     | name, FOptPercent ->
8422         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8423     | name, FChar -> (* XXX wrong? *)
8424         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8425   ) cols;
8426   pr "    rb_ary_push (rv, hv);\n";
8427   pr "  }\n";
8428   pr "  guestfs_free_%s_list (r);\n" typ;
8429   pr "  return rv;\n"
8430
8431 (* Generate Java bindings GuestFS.java file. *)
8432 and generate_java_java () =
8433   generate_header CStyle LGPLv2;
8434
8435   pr "\
8436 package com.redhat.et.libguestfs;
8437
8438 import java.util.HashMap;
8439 import com.redhat.et.libguestfs.LibGuestFSException;
8440 import com.redhat.et.libguestfs.PV;
8441 import com.redhat.et.libguestfs.VG;
8442 import com.redhat.et.libguestfs.LV;
8443 import com.redhat.et.libguestfs.Stat;
8444 import com.redhat.et.libguestfs.StatVFS;
8445 import com.redhat.et.libguestfs.IntBool;
8446 import com.redhat.et.libguestfs.Dirent;
8447
8448 /**
8449  * The GuestFS object is a libguestfs handle.
8450  *
8451  * @author rjones
8452  */
8453 public class GuestFS {
8454   // Load the native code.
8455   static {
8456     System.loadLibrary (\"guestfs_jni\");
8457   }
8458
8459   /**
8460    * The native guestfs_h pointer.
8461    */
8462   long g;
8463
8464   /**
8465    * Create a libguestfs handle.
8466    *
8467    * @throws LibGuestFSException
8468    */
8469   public GuestFS () throws LibGuestFSException
8470   {
8471     g = _create ();
8472   }
8473   private native long _create () throws LibGuestFSException;
8474
8475   /**
8476    * Close a libguestfs handle.
8477    *
8478    * You can also leave handles to be collected by the garbage
8479    * collector, but this method ensures that the resources used
8480    * by the handle are freed up immediately.  If you call any
8481    * other methods after closing the handle, you will get an
8482    * exception.
8483    *
8484    * @throws LibGuestFSException
8485    */
8486   public void close () throws LibGuestFSException
8487   {
8488     if (g != 0)
8489       _close (g);
8490     g = 0;
8491   }
8492   private native void _close (long g) throws LibGuestFSException;
8493
8494   public void finalize () throws LibGuestFSException
8495   {
8496     close ();
8497   }
8498
8499 ";
8500
8501   List.iter (
8502     fun (name, style, _, flags, _, shortdesc, longdesc) ->
8503       if not (List.mem NotInDocs flags); then (
8504         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8505         let doc =
8506           if List.mem ProtocolLimitWarning flags then
8507             doc ^ "\n\n" ^ protocol_limit_warning
8508           else doc in
8509         let doc =
8510           if List.mem DangerWillRobinson flags then
8511             doc ^ "\n\n" ^ danger_will_robinson
8512           else doc in
8513         let doc =
8514           match deprecation_notice flags with
8515           | None -> doc
8516           | Some txt -> doc ^ "\n\n" ^ txt in
8517         let doc = pod2text ~width:60 name doc in
8518         let doc = List.map (            (* RHBZ#501883 *)
8519           function
8520           | "" -> "<p>"
8521           | nonempty -> nonempty
8522         ) doc in
8523         let doc = String.concat "\n   * " doc in
8524
8525         pr "  /**\n";
8526         pr "   * %s\n" shortdesc;
8527         pr "   * <p>\n";
8528         pr "   * %s\n" doc;
8529         pr "   * @throws LibGuestFSException\n";
8530         pr "   */\n";
8531         pr "  ";
8532       );
8533       generate_java_prototype ~public:true ~semicolon:false name style;
8534       pr "\n";
8535       pr "  {\n";
8536       pr "    if (g == 0)\n";
8537       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
8538         name;
8539       pr "    ";
8540       if fst style <> RErr then pr "return ";
8541       pr "_%s " name;
8542       generate_java_call_args ~handle:"g" (snd style);
8543       pr ";\n";
8544       pr "  }\n";
8545       pr "  ";
8546       generate_java_prototype ~privat:true ~native:true name style;
8547       pr "\n";
8548       pr "\n";
8549   ) all_functions;
8550
8551   pr "}\n"
8552
8553 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8554 and generate_java_call_args ~handle args =
8555   pr "(%s" handle;
8556   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8557   pr ")"
8558
8559 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8560     ?(semicolon=true) name style =
8561   if privat then pr "private ";
8562   if public then pr "public ";
8563   if native then pr "native ";
8564
8565   (* return type *)
8566   (match fst style with
8567    | RErr -> pr "void ";
8568    | RInt _ -> pr "int ";
8569    | RInt64 _ -> pr "long ";
8570    | RBool _ -> pr "boolean ";
8571    | RConstString _ | RConstOptString _ | RString _
8572    | RBufferOut _ -> pr "String ";
8573    | RStringList _ -> pr "String[] ";
8574    | RStruct (_, typ) ->
8575        let name = java_name_of_struct typ in
8576        pr "%s " name;
8577    | RStructList (_, typ) ->
8578        let name = java_name_of_struct typ in
8579        pr "%s[] " name;
8580    | RHashtable _ -> pr "HashMap<String,String> ";
8581   );
8582
8583   if native then pr "_%s " name else pr "%s " name;
8584   pr "(";
8585   let needs_comma = ref false in
8586   if native then (
8587     pr "long g";
8588     needs_comma := true
8589   );
8590
8591   (* args *)
8592   List.iter (
8593     fun arg ->
8594       if !needs_comma then pr ", ";
8595       needs_comma := true;
8596
8597       match arg with
8598       | Pathname n
8599       | Device n | Dev_or_Path n
8600       | String n
8601       | OptString n
8602       | FileIn n
8603       | FileOut n ->
8604           pr "String %s" n
8605       | StringList n | DeviceList n ->
8606           pr "String[] %s" n
8607       | Bool n ->
8608           pr "boolean %s" n
8609       | Int n ->
8610           pr "int %s" n
8611   ) (snd style);
8612
8613   pr ")\n";
8614   pr "    throws LibGuestFSException";
8615   if semicolon then pr ";"
8616
8617 and generate_java_struct jtyp cols =
8618   generate_header CStyle LGPLv2;
8619
8620   pr "\
8621 package com.redhat.et.libguestfs;
8622
8623 /**
8624  * Libguestfs %s structure.
8625  *
8626  * @author rjones
8627  * @see GuestFS
8628  */
8629 public class %s {
8630 " jtyp jtyp;
8631
8632   List.iter (
8633     function
8634     | name, FString
8635     | name, FUUID
8636     | name, FBuffer -> pr "  public String %s;\n" name
8637     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
8638     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
8639     | name, FChar -> pr "  public char %s;\n" name
8640     | name, FOptPercent ->
8641         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
8642         pr "  public float %s;\n" name
8643   ) cols;
8644
8645   pr "}\n"
8646
8647 and generate_java_c () =
8648   generate_header CStyle LGPLv2;
8649
8650   pr "\
8651 #include <stdio.h>
8652 #include <stdlib.h>
8653 #include <string.h>
8654
8655 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8656 #include \"guestfs.h\"
8657
8658 /* Note that this function returns.  The exception is not thrown
8659  * until after the wrapper function returns.
8660  */
8661 static void
8662 throw_exception (JNIEnv *env, const char *msg)
8663 {
8664   jclass cl;
8665   cl = (*env)->FindClass (env,
8666                           \"com/redhat/et/libguestfs/LibGuestFSException\");
8667   (*env)->ThrowNew (env, cl, msg);
8668 }
8669
8670 JNIEXPORT jlong JNICALL
8671 Java_com_redhat_et_libguestfs_GuestFS__1create
8672   (JNIEnv *env, jobject obj)
8673 {
8674   guestfs_h *g;
8675
8676   g = guestfs_create ();
8677   if (g == NULL) {
8678     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8679     return 0;
8680   }
8681   guestfs_set_error_handler (g, NULL, NULL);
8682   return (jlong) (long) g;
8683 }
8684
8685 JNIEXPORT void JNICALL
8686 Java_com_redhat_et_libguestfs_GuestFS__1close
8687   (JNIEnv *env, jobject obj, jlong jg)
8688 {
8689   guestfs_h *g = (guestfs_h *) (long) jg;
8690   guestfs_close (g);
8691 }
8692
8693 ";
8694
8695   List.iter (
8696     fun (name, style, _, _, _, _, _) ->
8697       pr "JNIEXPORT ";
8698       (match fst style with
8699        | RErr -> pr "void ";
8700        | RInt _ -> pr "jint ";
8701        | RInt64 _ -> pr "jlong ";
8702        | RBool _ -> pr "jboolean ";
8703        | RConstString _ | RConstOptString _ | RString _
8704        | RBufferOut _ -> pr "jstring ";
8705        | RStruct _ | RHashtable _ ->
8706            pr "jobject ";
8707        | RStringList _ | RStructList _ ->
8708            pr "jobjectArray ";
8709       );
8710       pr "JNICALL\n";
8711       pr "Java_com_redhat_et_libguestfs_GuestFS_";
8712       pr "%s" (replace_str ("_" ^ name) "_" "_1");
8713       pr "\n";
8714       pr "  (JNIEnv *env, jobject obj, jlong jg";
8715       List.iter (
8716         function
8717         | Pathname n
8718         | Device n | Dev_or_Path n
8719         | String n
8720         | OptString n
8721         | FileIn n
8722         | FileOut n ->
8723             pr ", jstring j%s" n
8724         | StringList n | DeviceList n ->
8725             pr ", jobjectArray j%s" n
8726         | Bool n ->
8727             pr ", jboolean j%s" n
8728         | Int n ->
8729             pr ", jint j%s" n
8730       ) (snd style);
8731       pr ")\n";
8732       pr "{\n";
8733       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
8734       let error_code, no_ret =
8735         match fst style with
8736         | RErr -> pr "  int r;\n"; "-1", ""
8737         | RBool _
8738         | RInt _ -> pr "  int r;\n"; "-1", "0"
8739         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
8740         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8741         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8742         | RString _ ->
8743             pr "  jstring jr;\n";
8744             pr "  char *r;\n"; "NULL", "NULL"
8745         | RStringList _ ->
8746             pr "  jobjectArray jr;\n";
8747             pr "  int r_len;\n";
8748             pr "  jclass cl;\n";
8749             pr "  jstring jstr;\n";
8750             pr "  char **r;\n"; "NULL", "NULL"
8751         | RStruct (_, typ) ->
8752             pr "  jobject jr;\n";
8753             pr "  jclass cl;\n";
8754             pr "  jfieldID fl;\n";
8755             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8756         | RStructList (_, typ) ->
8757             pr "  jobjectArray jr;\n";
8758             pr "  jclass cl;\n";
8759             pr "  jfieldID fl;\n";
8760             pr "  jobject jfl;\n";
8761             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8762         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
8763         | RBufferOut _ ->
8764             pr "  jstring jr;\n";
8765             pr "  char *r;\n";
8766             pr "  size_t size;\n";
8767             "NULL", "NULL" in
8768       List.iter (
8769         function
8770         | Pathname n
8771         | Device n | Dev_or_Path n
8772         | String n
8773         | OptString n
8774         | FileIn n
8775         | FileOut n ->
8776             pr "  const char *%s;\n" n
8777         | StringList n | DeviceList n ->
8778             pr "  int %s_len;\n" n;
8779             pr "  const char **%s;\n" n
8780         | Bool n
8781         | Int n ->
8782             pr "  int %s;\n" n
8783       ) (snd style);
8784
8785       let needs_i =
8786         (match fst style with
8787          | RStringList _ | RStructList _ -> true
8788          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8789          | RConstOptString _
8790          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8791           List.exists (function
8792                        | StringList _ -> true
8793                        | DeviceList _ -> true
8794                        | _ -> false) (snd style) in
8795       if needs_i then
8796         pr "  int i;\n";
8797
8798       pr "\n";
8799
8800       (* Get the parameters. *)
8801       List.iter (
8802         function
8803         | Pathname n
8804         | Device n | Dev_or_Path n
8805         | String n
8806         | FileIn n
8807         | FileOut n ->
8808             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8809         | OptString n ->
8810             (* This is completely undocumented, but Java null becomes
8811              * a NULL parameter.
8812              *)
8813             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8814         | StringList n | DeviceList n ->
8815             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8816             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8817             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8818             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8819               n;
8820             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8821             pr "  }\n";
8822             pr "  %s[%s_len] = NULL;\n" n n;
8823         | Bool n
8824         | Int n ->
8825             pr "  %s = j%s;\n" n n
8826       ) (snd style);
8827
8828       (* Make the call. *)
8829       pr "  r = guestfs_%s " name;
8830       generate_c_call_args ~handle:"g" style;
8831       pr ";\n";
8832
8833       (* Release the parameters. *)
8834       List.iter (
8835         function
8836         | Pathname n
8837         | Device n | Dev_or_Path n
8838         | String n
8839         | FileIn n
8840         | FileOut n ->
8841             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8842         | OptString n ->
8843             pr "  if (j%s)\n" n;
8844             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8845         | StringList n | DeviceList n ->
8846             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8847             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8848               n;
8849             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8850             pr "  }\n";
8851             pr "  free (%s);\n" n
8852         | Bool n
8853         | Int n -> ()
8854       ) (snd style);
8855
8856       (* Check for errors. *)
8857       pr "  if (r == %s) {\n" error_code;
8858       pr "    throw_exception (env, guestfs_last_error (g));\n";
8859       pr "    return %s;\n" no_ret;
8860       pr "  }\n";
8861
8862       (* Return value. *)
8863       (match fst style with
8864        | RErr -> ()
8865        | RInt _ -> pr "  return (jint) r;\n"
8866        | RBool _ -> pr "  return (jboolean) r;\n"
8867        | RInt64 _ -> pr "  return (jlong) r;\n"
8868        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
8869        | RConstOptString _ ->
8870            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
8871        | RString _ ->
8872            pr "  jr = (*env)->NewStringUTF (env, r);\n";
8873            pr "  free (r);\n";
8874            pr "  return jr;\n"
8875        | RStringList _ ->
8876            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
8877            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
8878            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
8879            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
8880            pr "  for (i = 0; i < r_len; ++i) {\n";
8881            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
8882            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
8883            pr "    free (r[i]);\n";
8884            pr "  }\n";
8885            pr "  free (r);\n";
8886            pr "  return jr;\n"
8887        | RStruct (_, typ) ->
8888            let jtyp = java_name_of_struct typ in
8889            let cols = cols_of_struct typ in
8890            generate_java_struct_return typ jtyp cols
8891        | RStructList (_, typ) ->
8892            let jtyp = java_name_of_struct typ in
8893            let cols = cols_of_struct typ in
8894            generate_java_struct_list_return typ jtyp cols
8895        | RHashtable _ ->
8896            (* XXX *)
8897            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
8898            pr "  return NULL;\n"
8899        | RBufferOut _ ->
8900            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
8901            pr "  free (r);\n";
8902            pr "  return jr;\n"
8903       );
8904
8905       pr "}\n";
8906       pr "\n"
8907   ) all_functions
8908
8909 and generate_java_struct_return typ jtyp cols =
8910   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8911   pr "  jr = (*env)->AllocObject (env, cl);\n";
8912   List.iter (
8913     function
8914     | name, FString ->
8915         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8916         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
8917     | name, FUUID ->
8918         pr "  {\n";
8919         pr "    char s[33];\n";
8920         pr "    memcpy (s, r->%s, 32);\n" name;
8921         pr "    s[32] = 0;\n";
8922         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8923         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8924         pr "  }\n";
8925     | name, FBuffer ->
8926         pr "  {\n";
8927         pr "    int len = r->%s_len;\n" name;
8928         pr "    char s[len+1];\n";
8929         pr "    memcpy (s, r->%s, len);\n" name;
8930         pr "    s[len] = 0;\n";
8931         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8932         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8933         pr "  }\n";
8934     | name, (FBytes|FUInt64|FInt64) ->
8935         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8936         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8937     | name, (FUInt32|FInt32) ->
8938         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8939         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8940     | name, FOptPercent ->
8941         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8942         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
8943     | name, FChar ->
8944         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8945         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8946   ) cols;
8947   pr "  free (r);\n";
8948   pr "  return jr;\n"
8949
8950 and generate_java_struct_list_return typ jtyp cols =
8951   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8952   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
8953   pr "  for (i = 0; i < r->len; ++i) {\n";
8954   pr "    jfl = (*env)->AllocObject (env, cl);\n";
8955   List.iter (
8956     function
8957     | name, FString ->
8958         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8959         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
8960     | name, FUUID ->
8961         pr "    {\n";
8962         pr "      char s[33];\n";
8963         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
8964         pr "      s[32] = 0;\n";
8965         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8966         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8967         pr "    }\n";
8968     | name, FBuffer ->
8969         pr "    {\n";
8970         pr "      int len = r->val[i].%s_len;\n" name;
8971         pr "      char s[len+1];\n";
8972         pr "      memcpy (s, r->val[i].%s, len);\n" name;
8973         pr "      s[len] = 0;\n";
8974         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8975         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8976         pr "    }\n";
8977     | name, (FBytes|FUInt64|FInt64) ->
8978         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8979         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8980     | name, (FUInt32|FInt32) ->
8981         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8982         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8983     | name, FOptPercent ->
8984         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8985         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
8986     | name, FChar ->
8987         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8988         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8989   ) cols;
8990   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
8991   pr "  }\n";
8992   pr "  guestfs_free_%s_list (r);\n" typ;
8993   pr "  return jr;\n"
8994
8995 and generate_java_makefile_inc () =
8996   generate_header HashStyle GPLv2;
8997
8998   pr "java_built_sources = \\\n";
8999   List.iter (
9000     fun (typ, jtyp) ->
9001         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9002   ) java_structs;
9003   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9004
9005 and generate_haskell_hs () =
9006   generate_header HaskellStyle LGPLv2;
9007
9008   (* XXX We only know how to generate partial FFI for Haskell
9009    * at the moment.  Please help out!
9010    *)
9011   let can_generate style =
9012     match style with
9013     | RErr, _
9014     | RInt _, _
9015     | RInt64 _, _ -> true
9016     | RBool _, _
9017     | RConstString _, _
9018     | RConstOptString _, _
9019     | RString _, _
9020     | RStringList _, _
9021     | RStruct _, _
9022     | RStructList _, _
9023     | RHashtable _, _
9024     | RBufferOut _, _ -> false in
9025
9026   pr "\
9027 {-# INCLUDE <guestfs.h> #-}
9028 {-# LANGUAGE ForeignFunctionInterface #-}
9029
9030 module Guestfs (
9031   create";
9032
9033   (* List out the names of the actions we want to export. *)
9034   List.iter (
9035     fun (name, style, _, _, _, _, _) ->
9036       if can_generate style then pr ",\n  %s" name
9037   ) all_functions;
9038
9039   pr "
9040   ) where
9041 import Foreign
9042 import Foreign.C
9043 import Foreign.C.Types
9044 import IO
9045 import Control.Exception
9046 import Data.Typeable
9047
9048 data GuestfsS = GuestfsS            -- represents the opaque C struct
9049 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9050 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9051
9052 -- XXX define properly later XXX
9053 data PV = PV
9054 data VG = VG
9055 data LV = LV
9056 data IntBool = IntBool
9057 data Stat = Stat
9058 data StatVFS = StatVFS
9059 data Hashtable = Hashtable
9060
9061 foreign import ccall unsafe \"guestfs_create\" c_create
9062   :: IO GuestfsP
9063 foreign import ccall unsafe \"&guestfs_close\" c_close
9064   :: FunPtr (GuestfsP -> IO ())
9065 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9066   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9067
9068 create :: IO GuestfsH
9069 create = do
9070   p <- c_create
9071   c_set_error_handler p nullPtr nullPtr
9072   h <- newForeignPtr c_close p
9073   return h
9074
9075 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9076   :: GuestfsP -> IO CString
9077
9078 -- last_error :: GuestfsH -> IO (Maybe String)
9079 -- last_error h = do
9080 --   str <- withForeignPtr h (\\p -> c_last_error p)
9081 --   maybePeek peekCString str
9082
9083 last_error :: GuestfsH -> IO (String)
9084 last_error h = do
9085   str <- withForeignPtr h (\\p -> c_last_error p)
9086   if (str == nullPtr)
9087     then return \"no error\"
9088     else peekCString str
9089
9090 ";
9091
9092   (* Generate wrappers for each foreign function. *)
9093   List.iter (
9094     fun (name, style, _, _, _, _, _) ->
9095       if can_generate style then (
9096         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9097         pr "  :: ";
9098         generate_haskell_prototype ~handle:"GuestfsP" style;
9099         pr "\n";
9100         pr "\n";
9101         pr "%s :: " name;
9102         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9103         pr "\n";
9104         pr "%s %s = do\n" name
9105           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9106         pr "  r <- ";
9107         (* Convert pointer arguments using with* functions. *)
9108         List.iter (
9109           function
9110           | FileIn n
9111           | FileOut n
9112           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9113           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9114           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9115           | Bool _ | Int _ -> ()
9116         ) (snd style);
9117         (* Convert integer arguments. *)
9118         let args =
9119           List.map (
9120             function
9121             | Bool n -> sprintf "(fromBool %s)" n
9122             | Int n -> sprintf "(fromIntegral %s)" n
9123             | FileIn n | FileOut n
9124             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9125           ) (snd style) in
9126         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9127           (String.concat " " ("p" :: args));
9128         (match fst style with
9129          | RErr | RInt _ | RInt64 _ | RBool _ ->
9130              pr "  if (r == -1)\n";
9131              pr "    then do\n";
9132              pr "      err <- last_error h\n";
9133              pr "      fail err\n";
9134          | RConstString _ | RConstOptString _ | RString _
9135          | RStringList _ | RStruct _
9136          | RStructList _ | RHashtable _ | RBufferOut _ ->
9137              pr "  if (r == nullPtr)\n";
9138              pr "    then do\n";
9139              pr "      err <- last_error h\n";
9140              pr "      fail err\n";
9141         );
9142         (match fst style with
9143          | RErr ->
9144              pr "    else return ()\n"
9145          | RInt _ ->
9146              pr "    else return (fromIntegral r)\n"
9147          | RInt64 _ ->
9148              pr "    else return (fromIntegral r)\n"
9149          | RBool _ ->
9150              pr "    else return (toBool r)\n"
9151          | RConstString _
9152          | RConstOptString _
9153          | RString _
9154          | RStringList _
9155          | RStruct _
9156          | RStructList _
9157          | RHashtable _
9158          | RBufferOut _ ->
9159              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9160         );
9161         pr "\n";
9162       )
9163   ) all_functions
9164
9165 and generate_haskell_prototype ~handle ?(hs = false) style =
9166   pr "%s -> " handle;
9167   let string = if hs then "String" else "CString" in
9168   let int = if hs then "Int" else "CInt" in
9169   let bool = if hs then "Bool" else "CInt" in
9170   let int64 = if hs then "Integer" else "Int64" in
9171   List.iter (
9172     fun arg ->
9173       (match arg with
9174        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9175        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9176        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9177        | Bool _ -> pr "%s" bool
9178        | Int _ -> pr "%s" int
9179        | FileIn _ -> pr "%s" string
9180        | FileOut _ -> pr "%s" string
9181       );
9182       pr " -> ";
9183   ) (snd style);
9184   pr "IO (";
9185   (match fst style with
9186    | RErr -> if not hs then pr "CInt"
9187    | RInt _ -> pr "%s" int
9188    | RInt64 _ -> pr "%s" int64
9189    | RBool _ -> pr "%s" bool
9190    | RConstString _ -> pr "%s" string
9191    | RConstOptString _ -> pr "Maybe %s" string
9192    | RString _ -> pr "%s" string
9193    | RStringList _ -> pr "[%s]" string
9194    | RStruct (_, typ) ->
9195        let name = java_name_of_struct typ in
9196        pr "%s" name
9197    | RStructList (_, typ) ->
9198        let name = java_name_of_struct typ in
9199        pr "[%s]" name
9200    | RHashtable _ -> pr "Hashtable"
9201    | RBufferOut _ -> pr "%s" string
9202   );
9203   pr ")"
9204
9205 and generate_bindtests () =
9206   generate_header CStyle LGPLv2;
9207
9208   pr "\
9209 #include <stdio.h>
9210 #include <stdlib.h>
9211 #include <inttypes.h>
9212 #include <string.h>
9213
9214 #include \"guestfs.h\"
9215 #include \"guestfs-internal-actions.h\"
9216 #include \"guestfs_protocol.h\"
9217
9218 #define error guestfs_error
9219 #define safe_calloc guestfs_safe_calloc
9220 #define safe_malloc guestfs_safe_malloc
9221
9222 static void
9223 print_strings (char *const *argv)
9224 {
9225   int argc;
9226
9227   printf (\"[\");
9228   for (argc = 0; argv[argc] != NULL; ++argc) {
9229     if (argc > 0) printf (\", \");
9230     printf (\"\\\"%%s\\\"\", argv[argc]);
9231   }
9232   printf (\"]\\n\");
9233 }
9234
9235 /* The test0 function prints its parameters to stdout. */
9236 ";
9237
9238   let test0, tests =
9239     match test_functions with
9240     | [] -> assert false
9241     | test0 :: tests -> test0, tests in
9242
9243   let () =
9244     let (name, style, _, _, _, _, _) = test0 in
9245     generate_prototype ~extern:false ~semicolon:false ~newline:true
9246       ~handle:"g" ~prefix:"guestfs__" name style;
9247     pr "{\n";
9248     List.iter (
9249       function
9250       | Pathname n
9251       | Device n | Dev_or_Path n
9252       | String n
9253       | FileIn n
9254       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9255       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9256       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9257       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9258       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9259     ) (snd style);
9260     pr "  /* Java changes stdout line buffering so we need this: */\n";
9261     pr "  fflush (stdout);\n";
9262     pr "  return 0;\n";
9263     pr "}\n";
9264     pr "\n" in
9265
9266   List.iter (
9267     fun (name, style, _, _, _, _, _) ->
9268       if String.sub name (String.length name - 3) 3 <> "err" then (
9269         pr "/* Test normal return. */\n";
9270         generate_prototype ~extern:false ~semicolon:false ~newline:true
9271           ~handle:"g" ~prefix:"guestfs__" name style;
9272         pr "{\n";
9273         (match fst style with
9274          | RErr ->
9275              pr "  return 0;\n"
9276          | RInt _ ->
9277              pr "  int r;\n";
9278              pr "  sscanf (val, \"%%d\", &r);\n";
9279              pr "  return r;\n"
9280          | RInt64 _ ->
9281              pr "  int64_t r;\n";
9282              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9283              pr "  return r;\n"
9284          | RBool _ ->
9285              pr "  return strcmp (val, \"true\") == 0;\n"
9286          | RConstString _
9287          | RConstOptString _ ->
9288              (* Can't return the input string here.  Return a static
9289               * string so we ensure we get a segfault if the caller
9290               * tries to free it.
9291               *)
9292              pr "  return \"static string\";\n"
9293          | RString _ ->
9294              pr "  return strdup (val);\n"
9295          | RStringList _ ->
9296              pr "  char **strs;\n";
9297              pr "  int n, i;\n";
9298              pr "  sscanf (val, \"%%d\", &n);\n";
9299              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9300              pr "  for (i = 0; i < n; ++i) {\n";
9301              pr "    strs[i] = safe_malloc (g, 16);\n";
9302              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9303              pr "  }\n";
9304              pr "  strs[n] = NULL;\n";
9305              pr "  return strs;\n"
9306          | RStruct (_, typ) ->
9307              pr "  struct guestfs_%s *r;\n" typ;
9308              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9309              pr "  return r;\n"
9310          | RStructList (_, typ) ->
9311              pr "  struct guestfs_%s_list *r;\n" typ;
9312              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9313              pr "  sscanf (val, \"%%d\", &r->len);\n";
9314              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9315              pr "  return r;\n"
9316          | RHashtable _ ->
9317              pr "  char **strs;\n";
9318              pr "  int n, i;\n";
9319              pr "  sscanf (val, \"%%d\", &n);\n";
9320              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9321              pr "  for (i = 0; i < n; ++i) {\n";
9322              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9323              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9324              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9325              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9326              pr "  }\n";
9327              pr "  strs[n*2] = NULL;\n";
9328              pr "  return strs;\n"
9329          | RBufferOut _ ->
9330              pr "  return strdup (val);\n"
9331         );
9332         pr "}\n";
9333         pr "\n"
9334       ) else (
9335         pr "/* Test error return. */\n";
9336         generate_prototype ~extern:false ~semicolon:false ~newline:true
9337           ~handle:"g" ~prefix:"guestfs__" name style;
9338         pr "{\n";
9339         pr "  error (g, \"error\");\n";
9340         (match fst style with
9341          | RErr | RInt _ | RInt64 _ | RBool _ ->
9342              pr "  return -1;\n"
9343          | RConstString _ | RConstOptString _
9344          | RString _ | RStringList _ | RStruct _
9345          | RStructList _
9346          | RHashtable _
9347          | RBufferOut _ ->
9348              pr "  return NULL;\n"
9349         );
9350         pr "}\n";
9351         pr "\n"
9352       )
9353   ) tests
9354
9355 and generate_ocaml_bindtests () =
9356   generate_header OCamlStyle GPLv2;
9357
9358   pr "\
9359 let () =
9360   let g = Guestfs.create () in
9361 ";
9362
9363   let mkargs args =
9364     String.concat " " (
9365       List.map (
9366         function
9367         | CallString s -> "\"" ^ s ^ "\""
9368         | CallOptString None -> "None"
9369         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9370         | CallStringList xs ->
9371             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9372         | CallInt i when i >= 0 -> string_of_int i
9373         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9374         | CallBool b -> string_of_bool b
9375       ) args
9376     )
9377   in
9378
9379   generate_lang_bindtests (
9380     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9381   );
9382
9383   pr "print_endline \"EOF\"\n"
9384
9385 and generate_perl_bindtests () =
9386   pr "#!/usr/bin/perl -w\n";
9387   generate_header HashStyle GPLv2;
9388
9389   pr "\
9390 use strict;
9391
9392 use Sys::Guestfs;
9393
9394 my $g = Sys::Guestfs->new ();
9395 ";
9396
9397   let mkargs args =
9398     String.concat ", " (
9399       List.map (
9400         function
9401         | CallString s -> "\"" ^ s ^ "\""
9402         | CallOptString None -> "undef"
9403         | CallOptString (Some s) -> sprintf "\"%s\"" s
9404         | CallStringList xs ->
9405             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9406         | CallInt i -> string_of_int i
9407         | CallBool b -> if b then "1" else "0"
9408       ) args
9409     )
9410   in
9411
9412   generate_lang_bindtests (
9413     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9414   );
9415
9416   pr "print \"EOF\\n\"\n"
9417
9418 and generate_python_bindtests () =
9419   generate_header HashStyle GPLv2;
9420
9421   pr "\
9422 import guestfs
9423
9424 g = guestfs.GuestFS ()
9425 ";
9426
9427   let mkargs args =
9428     String.concat ", " (
9429       List.map (
9430         function
9431         | CallString s -> "\"" ^ s ^ "\""
9432         | CallOptString None -> "None"
9433         | CallOptString (Some s) -> sprintf "\"%s\"" s
9434         | CallStringList xs ->
9435             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9436         | CallInt i -> string_of_int i
9437         | CallBool b -> if b then "1" else "0"
9438       ) args
9439     )
9440   in
9441
9442   generate_lang_bindtests (
9443     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9444   );
9445
9446   pr "print \"EOF\"\n"
9447
9448 and generate_ruby_bindtests () =
9449   generate_header HashStyle GPLv2;
9450
9451   pr "\
9452 require 'guestfs'
9453
9454 g = Guestfs::create()
9455 ";
9456
9457   let mkargs args =
9458     String.concat ", " (
9459       List.map (
9460         function
9461         | CallString s -> "\"" ^ s ^ "\""
9462         | CallOptString None -> "nil"
9463         | CallOptString (Some s) -> sprintf "\"%s\"" s
9464         | CallStringList xs ->
9465             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9466         | CallInt i -> string_of_int i
9467         | CallBool b -> string_of_bool b
9468       ) args
9469     )
9470   in
9471
9472   generate_lang_bindtests (
9473     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9474   );
9475
9476   pr "print \"EOF\\n\"\n"
9477
9478 and generate_java_bindtests () =
9479   generate_header CStyle GPLv2;
9480
9481   pr "\
9482 import com.redhat.et.libguestfs.*;
9483
9484 public class Bindtests {
9485     public static void main (String[] argv)
9486     {
9487         try {
9488             GuestFS g = new GuestFS ();
9489 ";
9490
9491   let mkargs args =
9492     String.concat ", " (
9493       List.map (
9494         function
9495         | CallString s -> "\"" ^ s ^ "\""
9496         | CallOptString None -> "null"
9497         | CallOptString (Some s) -> sprintf "\"%s\"" s
9498         | CallStringList xs ->
9499             "new String[]{" ^
9500               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9501         | CallInt i -> string_of_int i
9502         | CallBool b -> string_of_bool b
9503       ) args
9504     )
9505   in
9506
9507   generate_lang_bindtests (
9508     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
9509   );
9510
9511   pr "
9512             System.out.println (\"EOF\");
9513         }
9514         catch (Exception exn) {
9515             System.err.println (exn);
9516             System.exit (1);
9517         }
9518     }
9519 }
9520 "
9521
9522 and generate_haskell_bindtests () =
9523   generate_header HaskellStyle GPLv2;
9524
9525   pr "\
9526 module Bindtests where
9527 import qualified Guestfs
9528
9529 main = do
9530   g <- Guestfs.create
9531 ";
9532
9533   let mkargs args =
9534     String.concat " " (
9535       List.map (
9536         function
9537         | CallString s -> "\"" ^ s ^ "\""
9538         | CallOptString None -> "Nothing"
9539         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9540         | CallStringList xs ->
9541             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9542         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9543         | CallInt i -> string_of_int i
9544         | CallBool true -> "True"
9545         | CallBool false -> "False"
9546       ) args
9547     )
9548   in
9549
9550   generate_lang_bindtests (
9551     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
9552   );
9553
9554   pr "  putStrLn \"EOF\"\n"
9555
9556 (* Language-independent bindings tests - we do it this way to
9557  * ensure there is parity in testing bindings across all languages.
9558  *)
9559 and generate_lang_bindtests call =
9560   call "test0" [CallString "abc"; CallOptString (Some "def");
9561                 CallStringList []; CallBool false;
9562                 CallInt 0; CallString "123"; CallString "456"];
9563   call "test0" [CallString "abc"; CallOptString None;
9564                 CallStringList []; CallBool false;
9565                 CallInt 0; CallString "123"; CallString "456"];
9566   call "test0" [CallString ""; CallOptString (Some "def");
9567                 CallStringList []; CallBool false;
9568                 CallInt 0; CallString "123"; CallString "456"];
9569   call "test0" [CallString ""; CallOptString (Some "");
9570                 CallStringList []; CallBool false;
9571                 CallInt 0; CallString "123"; CallString "456"];
9572   call "test0" [CallString "abc"; CallOptString (Some "def");
9573                 CallStringList ["1"]; CallBool false;
9574                 CallInt 0; CallString "123"; CallString "456"];
9575   call "test0" [CallString "abc"; CallOptString (Some "def");
9576                 CallStringList ["1"; "2"]; CallBool false;
9577                 CallInt 0; CallString "123"; CallString "456"];
9578   call "test0" [CallString "abc"; CallOptString (Some "def");
9579                 CallStringList ["1"]; CallBool true;
9580                 CallInt 0; CallString "123"; CallString "456"];
9581   call "test0" [CallString "abc"; CallOptString (Some "def");
9582                 CallStringList ["1"]; CallBool false;
9583                 CallInt (-1); CallString "123"; CallString "456"];
9584   call "test0" [CallString "abc"; CallOptString (Some "def");
9585                 CallStringList ["1"]; CallBool false;
9586                 CallInt (-2); CallString "123"; CallString "456"];
9587   call "test0" [CallString "abc"; CallOptString (Some "def");
9588                 CallStringList ["1"]; CallBool false;
9589                 CallInt 1; CallString "123"; CallString "456"];
9590   call "test0" [CallString "abc"; CallOptString (Some "def");
9591                 CallStringList ["1"]; CallBool false;
9592                 CallInt 2; CallString "123"; CallString "456"];
9593   call "test0" [CallString "abc"; CallOptString (Some "def");
9594                 CallStringList ["1"]; CallBool false;
9595                 CallInt 4095; CallString "123"; CallString "456"];
9596   call "test0" [CallString "abc"; CallOptString (Some "def");
9597                 CallStringList ["1"]; CallBool false;
9598                 CallInt 0; CallString ""; CallString ""]
9599
9600 (* XXX Add here tests of the return and error functions. *)
9601
9602 (* This is used to generate the src/MAX_PROC_NR file which
9603  * contains the maximum procedure number, a surrogate for the
9604  * ABI version number.  See src/Makefile.am for the details.
9605  *)
9606 and generate_max_proc_nr () =
9607   let proc_nrs = List.map (
9608     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9609   ) daemon_functions in
9610
9611   let max_proc_nr = List.fold_left max 0 proc_nrs in
9612
9613   pr "%d\n" max_proc_nr
9614
9615 let output_to filename =
9616   let filename_new = filename ^ ".new" in
9617   chan := open_out filename_new;
9618   let close () =
9619     close_out !chan;
9620     chan := stdout;
9621
9622     (* Is the new file different from the current file? *)
9623     if Sys.file_exists filename && files_equal filename filename_new then
9624       Unix.unlink filename_new          (* same, so skip it *)
9625     else (
9626       (* different, overwrite old one *)
9627       (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9628       Unix.rename filename_new filename;
9629       Unix.chmod filename 0o444;
9630       printf "written %s\n%!" filename;
9631     )
9632   in
9633   close
9634
9635 (* Main program. *)
9636 let () =
9637   check_functions ();
9638
9639   if not (Sys.file_exists "HACKING") then (
9640     eprintf "\
9641 You are probably running this from the wrong directory.
9642 Run it from the top source directory using the command
9643   src/generator.ml
9644 ";
9645     exit 1
9646   );
9647
9648   let close = output_to "src/guestfs_protocol.x" in
9649   generate_xdr ();
9650   close ();
9651
9652   let close = output_to "src/guestfs-structs.h" in
9653   generate_structs_h ();
9654   close ();
9655
9656   let close = output_to "src/guestfs-actions.h" in
9657   generate_actions_h ();
9658   close ();
9659
9660   let close = output_to "src/guestfs-internal-actions.h" in
9661   generate_internal_actions_h ();
9662   close ();
9663
9664   let close = output_to "src/guestfs-actions.c" in
9665   generate_client_actions ();
9666   close ();
9667
9668   let close = output_to "daemon/actions.h" in
9669   generate_daemon_actions_h ();
9670   close ();
9671
9672   let close = output_to "daemon/stubs.c" in
9673   generate_daemon_actions ();
9674   close ();
9675
9676   let close = output_to "daemon/names.c" in
9677   generate_daemon_names ();
9678   close ();
9679
9680   let close = output_to "capitests/tests.c" in
9681   generate_tests ();
9682   close ();
9683
9684   let close = output_to "src/guestfs-bindtests.c" in
9685   generate_bindtests ();
9686   close ();
9687
9688   let close = output_to "fish/cmds.c" in
9689   generate_fish_cmds ();
9690   close ();
9691
9692   let close = output_to "fish/completion.c" in
9693   generate_fish_completion ();
9694   close ();
9695
9696   let close = output_to "guestfs-structs.pod" in
9697   generate_structs_pod ();
9698   close ();
9699
9700   let close = output_to "guestfs-actions.pod" in
9701   generate_actions_pod ();
9702   close ();
9703
9704   let close = output_to "guestfish-actions.pod" in
9705   generate_fish_actions_pod ();
9706   close ();
9707
9708   let close = output_to "ocaml/guestfs.mli" in
9709   generate_ocaml_mli ();
9710   close ();
9711
9712   let close = output_to "ocaml/guestfs.ml" in
9713   generate_ocaml_ml ();
9714   close ();
9715
9716   let close = output_to "ocaml/guestfs_c_actions.c" in
9717   generate_ocaml_c ();
9718   close ();
9719
9720   let close = output_to "ocaml/bindtests.ml" in
9721   generate_ocaml_bindtests ();
9722   close ();
9723
9724   let close = output_to "perl/Guestfs.xs" in
9725   generate_perl_xs ();
9726   close ();
9727
9728   let close = output_to "perl/lib/Sys/Guestfs.pm" in
9729   generate_perl_pm ();
9730   close ();
9731
9732   let close = output_to "perl/bindtests.pl" in
9733   generate_perl_bindtests ();
9734   close ();
9735
9736   let close = output_to "python/guestfs-py.c" in
9737   generate_python_c ();
9738   close ();
9739
9740   let close = output_to "python/guestfs.py" in
9741   generate_python_py ();
9742   close ();
9743
9744   let close = output_to "python/bindtests.py" in
9745   generate_python_bindtests ();
9746   close ();
9747
9748   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9749   generate_ruby_c ();
9750   close ();
9751
9752   let close = output_to "ruby/bindtests.rb" in
9753   generate_ruby_bindtests ();
9754   close ();
9755
9756   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9757   generate_java_java ();
9758   close ();
9759
9760   List.iter (
9761     fun (typ, jtyp) ->
9762       let cols = cols_of_struct typ in
9763       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9764       let close = output_to filename in
9765       generate_java_struct jtyp cols;
9766       close ();
9767   ) java_structs;
9768
9769   let close = output_to "java/Makefile.inc" in
9770   generate_java_makefile_inc ();
9771   close ();
9772
9773   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9774   generate_java_c ();
9775   close ();
9776
9777   let close = output_to "java/Bindtests.java" in
9778   generate_java_bindtests ();
9779   close ();
9780
9781   let close = output_to "haskell/Guestfs.hs" in
9782   generate_haskell_hs ();
9783   close ();
9784
9785   let close = output_to "haskell/Bindtests.hs" in
9786   generate_haskell_bindtests ();
9787   close ();
9788
9789   let close = output_to "src/MAX_PROC_NR" in
9790   generate_max_proc_nr ();
9791   close ();
9792
9793   (* Always generate this file last, and unconditionally.  It's used
9794    * by the Makefile to know when we must re-run the generator.
9795    *)
9796   let chan = open_out "src/stamp-generator" in
9797   fprintf chan "1\n";
9798   close_out chan