Non-daemon actions indirect through generated code.
[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 ]
809
810 (* daemon_functions are any functions which cause some action
811  * to take place in the daemon.
812  *)
813
814 let daemon_functions = [
815   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
816    [InitEmpty, Always, TestOutput (
817       [["sfdiskM"; "/dev/sda"; ","];
818        ["mkfs"; "ext2"; "/dev/sda1"];
819        ["mount"; "/dev/sda1"; "/"];
820        ["write_file"; "/new"; "new file contents"; "0"];
821        ["cat"; "/new"]], "new file contents")],
822    "mount a guest disk at a position in the filesystem",
823    "\
824 Mount a guest disk at a position in the filesystem.  Block devices
825 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
826 the guest.  If those block devices contain partitions, they will have
827 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
828 names can be used.
829
830 The rules are the same as for L<mount(2)>:  A filesystem must
831 first be mounted on C</> before others can be mounted.  Other
832 filesystems can only be mounted on directories which already
833 exist.
834
835 The mounted filesystem is writable, if we have sufficient permissions
836 on the underlying device.
837
838 The filesystem options C<sync> and C<noatime> are set with this
839 call, in order to improve reliability.");
840
841   ("sync", (RErr, []), 2, [],
842    [ InitEmpty, Always, TestRun [["sync"]]],
843    "sync disks, writes are flushed through to the disk image",
844    "\
845 This syncs the disk, so that any writes are flushed through to the
846 underlying disk image.
847
848 You should always call this if you have modified a disk image, before
849 closing the handle.");
850
851   ("touch", (RErr, [Pathname "path"]), 3, [],
852    [InitBasicFS, Always, TestOutputTrue (
853       [["touch"; "/new"];
854        ["exists"; "/new"]])],
855    "update file timestamps or create a new file",
856    "\
857 Touch acts like the L<touch(1)> command.  It can be used to
858 update the timestamps on a file, or, if the file does not exist,
859 to create a new zero-length file.");
860
861   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
862    [InitISOFS, Always, TestOutput (
863       [["cat"; "/known-2"]], "abcdef\n")],
864    "list the contents of a file",
865    "\
866 Return the contents of the file named C<path>.
867
868 Note that this function cannot correctly handle binary files
869 (specifically, files containing C<\\0> character which is treated
870 as end of string).  For those you need to use the C<guestfs_read_file>
871 or C<guestfs_download> functions which have a more complex interface.");
872
873   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
874    [], (* XXX Tricky to test because it depends on the exact format
875         * of the 'ls -l' command, which changes between F10 and F11.
876         *)
877    "list the files in a directory (long format)",
878    "\
879 List the files in C<directory> (relative to the root directory,
880 there is no cwd) in the format of 'ls -la'.
881
882 This command is mostly useful for interactive sessions.  It
883 is I<not> intended that you try to parse the output string.");
884
885   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
886    [InitBasicFS, Always, TestOutputList (
887       [["touch"; "/new"];
888        ["touch"; "/newer"];
889        ["touch"; "/newest"];
890        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
891    "list the files in a directory",
892    "\
893 List the files in C<directory> (relative to the root directory,
894 there is no cwd).  The '.' and '..' entries are not returned, but
895 hidden files are shown.
896
897 This command is mostly useful for interactive sessions.  Programs
898 should probably use C<guestfs_readdir> instead.");
899
900   ("list_devices", (RStringList "devices", []), 7, [],
901    [InitEmpty, Always, TestOutputListOfDevices (
902       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
903    "list the block devices",
904    "\
905 List all the block devices.
906
907 The full block device names are returned, eg. C</dev/sda>");
908
909   ("list_partitions", (RStringList "partitions", []), 8, [],
910    [InitBasicFS, Always, TestOutputListOfDevices (
911       [["list_partitions"]], ["/dev/sda1"]);
912     InitEmpty, Always, TestOutputListOfDevices (
913       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
914        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
915    "list the partitions",
916    "\
917 List all the partitions detected on all block devices.
918
919 The full partition device names are returned, eg. C</dev/sda1>
920
921 This does not return logical volumes.  For that you will need to
922 call C<guestfs_lvs>.");
923
924   ("pvs", (RStringList "physvols", []), 9, [],
925    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
926       [["pvs"]], ["/dev/sda1"]);
927     InitEmpty, Always, TestOutputListOfDevices (
928       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
929        ["pvcreate"; "/dev/sda1"];
930        ["pvcreate"; "/dev/sda2"];
931        ["pvcreate"; "/dev/sda3"];
932        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
933    "list the LVM physical volumes (PVs)",
934    "\
935 List all the physical volumes detected.  This is the equivalent
936 of the L<pvs(8)> command.
937
938 This returns a list of just the device names that contain
939 PVs (eg. C</dev/sda2>).
940
941 See also C<guestfs_pvs_full>.");
942
943   ("vgs", (RStringList "volgroups", []), 10, [],
944    [InitBasicFSonLVM, Always, TestOutputList (
945       [["vgs"]], ["VG"]);
946     InitEmpty, Always, TestOutputList (
947       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
948        ["pvcreate"; "/dev/sda1"];
949        ["pvcreate"; "/dev/sda2"];
950        ["pvcreate"; "/dev/sda3"];
951        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
952        ["vgcreate"; "VG2"; "/dev/sda3"];
953        ["vgs"]], ["VG1"; "VG2"])],
954    "list the LVM volume groups (VGs)",
955    "\
956 List all the volumes groups detected.  This is the equivalent
957 of the L<vgs(8)> command.
958
959 This returns a list of just the volume group names that were
960 detected (eg. C<VolGroup00>).
961
962 See also C<guestfs_vgs_full>.");
963
964   ("lvs", (RStringList "logvols", []), 11, [],
965    [InitBasicFSonLVM, Always, TestOutputList (
966       [["lvs"]], ["/dev/VG/LV"]);
967     InitEmpty, Always, TestOutputList (
968       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
969        ["pvcreate"; "/dev/sda1"];
970        ["pvcreate"; "/dev/sda2"];
971        ["pvcreate"; "/dev/sda3"];
972        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
973        ["vgcreate"; "VG2"; "/dev/sda3"];
974        ["lvcreate"; "LV1"; "VG1"; "50"];
975        ["lvcreate"; "LV2"; "VG1"; "50"];
976        ["lvcreate"; "LV3"; "VG2"; "50"];
977        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
978    "list the LVM logical volumes (LVs)",
979    "\
980 List all the logical volumes detected.  This is the equivalent
981 of the L<lvs(8)> command.
982
983 This returns a list of the logical volume device names
984 (eg. C</dev/VolGroup00/LogVol00>).
985
986 See also C<guestfs_lvs_full>.");
987
988   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
989    [], (* XXX how to test? *)
990    "list the LVM physical volumes (PVs)",
991    "\
992 List all the physical volumes detected.  This is the equivalent
993 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
994
995   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
996    [], (* XXX how to test? *)
997    "list the LVM volume groups (VGs)",
998    "\
999 List all the volumes groups detected.  This is the equivalent
1000 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1001
1002   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1003    [], (* XXX how to test? *)
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.  The \"full\" version includes all fields.");
1008
1009   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1010    [InitISOFS, Always, TestOutputList (
1011       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1012     InitISOFS, Always, TestOutputList (
1013       [["read_lines"; "/empty"]], [])],
1014    "read file as lines",
1015    "\
1016 Return the contents of the file named C<path>.
1017
1018 The file contents are returned as a list of lines.  Trailing
1019 C<LF> and C<CRLF> character sequences are I<not> returned.
1020
1021 Note that this function cannot correctly handle binary files
1022 (specifically, files containing C<\\0> character which is treated
1023 as end of line).  For those you need to use the C<guestfs_read_file>
1024 function which has a more complex interface.");
1025
1026   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1027    [], (* XXX Augeas code needs tests. *)
1028    "create a new Augeas handle",
1029    "\
1030 Create a new Augeas handle for editing configuration files.
1031 If there was any previous Augeas handle associated with this
1032 guestfs session, then it is closed.
1033
1034 You must call this before using any other C<guestfs_aug_*>
1035 commands.
1036
1037 C<root> is the filesystem root.  C<root> must not be NULL,
1038 use C</> instead.
1039
1040 The flags are the same as the flags defined in
1041 E<lt>augeas.hE<gt>, the logical I<or> of the following
1042 integers:
1043
1044 =over 4
1045
1046 =item C<AUG_SAVE_BACKUP> = 1
1047
1048 Keep the original file with a C<.augsave> extension.
1049
1050 =item C<AUG_SAVE_NEWFILE> = 2
1051
1052 Save changes into a file with extension C<.augnew>, and
1053 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1054
1055 =item C<AUG_TYPE_CHECK> = 4
1056
1057 Typecheck lenses (can be expensive).
1058
1059 =item C<AUG_NO_STDINC> = 8
1060
1061 Do not use standard load path for modules.
1062
1063 =item C<AUG_SAVE_NOOP> = 16
1064
1065 Make save a no-op, just record what would have been changed.
1066
1067 =item C<AUG_NO_LOAD> = 32
1068
1069 Do not load the tree in C<guestfs_aug_init>.
1070
1071 =back
1072
1073 To close the handle, you can call C<guestfs_aug_close>.
1074
1075 To find out more about Augeas, see L<http://augeas.net/>.");
1076
1077   ("aug_close", (RErr, []), 26, [],
1078    [], (* XXX Augeas code needs tests. *)
1079    "close the current Augeas handle",
1080    "\
1081 Close the current Augeas handle and free up any resources
1082 used by it.  After calling this, you have to call
1083 C<guestfs_aug_init> again before you can use any other
1084 Augeas functions.");
1085
1086   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1087    [], (* XXX Augeas code needs tests. *)
1088    "define an Augeas variable",
1089    "\
1090 Defines an Augeas variable C<name> whose value is the result
1091 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1092 undefined.
1093
1094 On success this returns the number of nodes in C<expr>, or
1095 C<0> if C<expr> evaluates to something which is not a nodeset.");
1096
1097   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1098    [], (* XXX Augeas code needs tests. *)
1099    "define an Augeas node",
1100    "\
1101 Defines a variable C<name> whose value is the result of
1102 evaluating C<expr>.
1103
1104 If C<expr> evaluates to an empty nodeset, a node is created,
1105 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1106 C<name> will be the nodeset containing that single node.
1107
1108 On success this returns a pair containing the
1109 number of nodes in the nodeset, and a boolean flag
1110 if a node was created.");
1111
1112   ("aug_get", (RString "val", [String "augpath"]), 19, [],
1113    [], (* XXX Augeas code needs tests. *)
1114    "look up the value of an Augeas path",
1115    "\
1116 Look up the value associated with C<path>.  If C<path>
1117 matches exactly one node, the C<value> is returned.");
1118
1119   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1120    [], (* XXX Augeas code needs tests. *)
1121    "set Augeas path to value",
1122    "\
1123 Set the value associated with C<path> to C<value>.");
1124
1125   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1126    [], (* XXX Augeas code needs tests. *)
1127    "insert a sibling Augeas node",
1128    "\
1129 Create a new sibling C<label> for C<path>, inserting it into
1130 the tree before or after C<path> (depending on the boolean
1131 flag C<before>).
1132
1133 C<path> must match exactly one existing node in the tree, and
1134 C<label> must be a label, ie. not contain C</>, C<*> or end
1135 with a bracketed index C<[N]>.");
1136
1137   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1138    [], (* XXX Augeas code needs tests. *)
1139    "remove an Augeas path",
1140    "\
1141 Remove C<path> and all of its children.
1142
1143 On success this returns the number of entries which were removed.");
1144
1145   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1146    [], (* XXX Augeas code needs tests. *)
1147    "move Augeas node",
1148    "\
1149 Move the node C<src> to C<dest>.  C<src> must match exactly
1150 one node.  C<dest> is overwritten if it exists.");
1151
1152   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1153    [], (* XXX Augeas code needs tests. *)
1154    "return Augeas nodes which match augpath",
1155    "\
1156 Returns a list of paths which match the path expression C<path>.
1157 The returned paths are sufficiently qualified so that they match
1158 exactly one node in the current tree.");
1159
1160   ("aug_save", (RErr, []), 25, [],
1161    [], (* XXX Augeas code needs tests. *)
1162    "write all pending Augeas changes to disk",
1163    "\
1164 This writes all pending changes to disk.
1165
1166 The flags which were passed to C<guestfs_aug_init> affect exactly
1167 how files are saved.");
1168
1169   ("aug_load", (RErr, []), 27, [],
1170    [], (* XXX Augeas code needs tests. *)
1171    "load files into the tree",
1172    "\
1173 Load files into the tree.
1174
1175 See C<aug_load> in the Augeas documentation for the full gory
1176 details.");
1177
1178   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1179    [], (* XXX Augeas code needs tests. *)
1180    "list Augeas nodes under augpath",
1181    "\
1182 This is just a shortcut for listing C<guestfs_aug_match>
1183 C<path/*> and sorting the resulting nodes into alphabetical order.");
1184
1185   ("rm", (RErr, [Pathname "path"]), 29, [],
1186    [InitBasicFS, Always, TestRun
1187       [["touch"; "/new"];
1188        ["rm"; "/new"]];
1189     InitBasicFS, Always, TestLastFail
1190       [["rm"; "/new"]];
1191     InitBasicFS, Always, TestLastFail
1192       [["mkdir"; "/new"];
1193        ["rm"; "/new"]]],
1194    "remove a file",
1195    "\
1196 Remove the single file C<path>.");
1197
1198   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1199    [InitBasicFS, Always, TestRun
1200       [["mkdir"; "/new"];
1201        ["rmdir"; "/new"]];
1202     InitBasicFS, Always, TestLastFail
1203       [["rmdir"; "/new"]];
1204     InitBasicFS, Always, TestLastFail
1205       [["touch"; "/new"];
1206        ["rmdir"; "/new"]]],
1207    "remove a directory",
1208    "\
1209 Remove the single directory C<path>.");
1210
1211   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1212    [InitBasicFS, Always, TestOutputFalse
1213       [["mkdir"; "/new"];
1214        ["mkdir"; "/new/foo"];
1215        ["touch"; "/new/foo/bar"];
1216        ["rm_rf"; "/new"];
1217        ["exists"; "/new"]]],
1218    "remove a file or directory recursively",
1219    "\
1220 Remove the file or directory C<path>, recursively removing the
1221 contents if its a directory.  This is like the C<rm -rf> shell
1222 command.");
1223
1224   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1225    [InitBasicFS, Always, TestOutputTrue
1226       [["mkdir"; "/new"];
1227        ["is_dir"; "/new"]];
1228     InitBasicFS, Always, TestLastFail
1229       [["mkdir"; "/new/foo/bar"]]],
1230    "create a directory",
1231    "\
1232 Create a directory named C<path>.");
1233
1234   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1235    [InitBasicFS, Always, TestOutputTrue
1236       [["mkdir_p"; "/new/foo/bar"];
1237        ["is_dir"; "/new/foo/bar"]];
1238     InitBasicFS, Always, TestOutputTrue
1239       [["mkdir_p"; "/new/foo/bar"];
1240        ["is_dir"; "/new/foo"]];
1241     InitBasicFS, Always, TestOutputTrue
1242       [["mkdir_p"; "/new/foo/bar"];
1243        ["is_dir"; "/new"]];
1244     (* Regression tests for RHBZ#503133: *)
1245     InitBasicFS, Always, TestRun
1246       [["mkdir"; "/new"];
1247        ["mkdir_p"; "/new"]];
1248     InitBasicFS, Always, TestLastFail
1249       [["touch"; "/new"];
1250        ["mkdir_p"; "/new"]]],
1251    "create a directory and parents",
1252    "\
1253 Create a directory named C<path>, creating any parent directories
1254 as necessary.  This is like the C<mkdir -p> shell command.");
1255
1256   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1257    [], (* XXX Need stat command to test *)
1258    "change file mode",
1259    "\
1260 Change the mode (permissions) of C<path> to C<mode>.  Only
1261 numeric modes are supported.");
1262
1263   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1264    [], (* XXX Need stat command to test *)
1265    "change file owner and group",
1266    "\
1267 Change the file owner to C<owner> and group to C<group>.
1268
1269 Only numeric uid and gid are supported.  If you want to use
1270 names, you will need to locate and parse the password file
1271 yourself (Augeas support makes this relatively easy).");
1272
1273   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1274    [InitISOFS, Always, TestOutputTrue (
1275       [["exists"; "/empty"]]);
1276     InitISOFS, Always, TestOutputTrue (
1277       [["exists"; "/directory"]])],
1278    "test if file or directory exists",
1279    "\
1280 This returns C<true> if and only if there is a file, directory
1281 (or anything) with the given C<path> name.
1282
1283 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1284
1285   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1286    [InitISOFS, Always, TestOutputTrue (
1287       [["is_file"; "/known-1"]]);
1288     InitISOFS, Always, TestOutputFalse (
1289       [["is_file"; "/directory"]])],
1290    "test if file exists",
1291    "\
1292 This returns C<true> if and only if there is a file
1293 with the given C<path> name.  Note that it returns false for
1294 other objects like directories.
1295
1296 See also C<guestfs_stat>.");
1297
1298   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1299    [InitISOFS, Always, TestOutputFalse (
1300       [["is_dir"; "/known-3"]]);
1301     InitISOFS, Always, TestOutputTrue (
1302       [["is_dir"; "/directory"]])],
1303    "test if file exists",
1304    "\
1305 This returns C<true> if and only if there is a directory
1306 with the given C<path> name.  Note that it returns false for
1307 other objects like files.
1308
1309 See also C<guestfs_stat>.");
1310
1311   ("pvcreate", (RErr, [Device "device"]), 39, [],
1312    [InitEmpty, Always, TestOutputListOfDevices (
1313       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1314        ["pvcreate"; "/dev/sda1"];
1315        ["pvcreate"; "/dev/sda2"];
1316        ["pvcreate"; "/dev/sda3"];
1317        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1318    "create an LVM physical volume",
1319    "\
1320 This creates an LVM physical volume on the named C<device>,
1321 where C<device> should usually be a partition name such
1322 as C</dev/sda1>.");
1323
1324   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
1325    [InitEmpty, Always, TestOutputList (
1326       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1327        ["pvcreate"; "/dev/sda1"];
1328        ["pvcreate"; "/dev/sda2"];
1329        ["pvcreate"; "/dev/sda3"];
1330        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1331        ["vgcreate"; "VG2"; "/dev/sda3"];
1332        ["vgs"]], ["VG1"; "VG2"])],
1333    "create an LVM volume group",
1334    "\
1335 This creates an LVM volume group called C<volgroup>
1336 from the non-empty list of physical volumes C<physvols>.");
1337
1338   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1339    [InitEmpty, Always, TestOutputList (
1340       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1341        ["pvcreate"; "/dev/sda1"];
1342        ["pvcreate"; "/dev/sda2"];
1343        ["pvcreate"; "/dev/sda3"];
1344        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1345        ["vgcreate"; "VG2"; "/dev/sda3"];
1346        ["lvcreate"; "LV1"; "VG1"; "50"];
1347        ["lvcreate"; "LV2"; "VG1"; "50"];
1348        ["lvcreate"; "LV3"; "VG2"; "50"];
1349        ["lvcreate"; "LV4"; "VG2"; "50"];
1350        ["lvcreate"; "LV5"; "VG2"; "50"];
1351        ["lvs"]],
1352       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1353        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1354    "create an LVM volume group",
1355    "\
1356 This creates an LVM volume group called C<logvol>
1357 on the volume group C<volgroup>, with C<size> megabytes.");
1358
1359   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1360    [InitEmpty, Always, TestOutput (
1361       [["sfdiskM"; "/dev/sda"; ","];
1362        ["mkfs"; "ext2"; "/dev/sda1"];
1363        ["mount"; "/dev/sda1"; "/"];
1364        ["write_file"; "/new"; "new file contents"; "0"];
1365        ["cat"; "/new"]], "new file contents")],
1366    "make a filesystem",
1367    "\
1368 This creates a filesystem on C<device> (usually a partition
1369 or LVM logical volume).  The filesystem type is C<fstype>, for
1370 example C<ext3>.");
1371
1372   ("sfdisk", (RErr, [Device "device";
1373                      Int "cyls"; Int "heads"; Int "sectors";
1374                      StringList "lines"]), 43, [DangerWillRobinson],
1375    [],
1376    "create partitions on a block device",
1377    "\
1378 This is a direct interface to the L<sfdisk(8)> program for creating
1379 partitions on block devices.
1380
1381 C<device> should be a block device, for example C</dev/sda>.
1382
1383 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1384 and sectors on the device, which are passed directly to sfdisk as
1385 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1386 of these, then the corresponding parameter is omitted.  Usually for
1387 'large' disks, you can just pass C<0> for these, but for small
1388 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1389 out the right geometry and you will need to tell it.
1390
1391 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1392 information refer to the L<sfdisk(8)> manpage.
1393
1394 To create a single partition occupying the whole disk, you would
1395 pass C<lines> as a single element list, when the single element being
1396 the string C<,> (comma).
1397
1398 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1399
1400   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1401    [InitBasicFS, Always, TestOutput (
1402       [["write_file"; "/new"; "new file contents"; "0"];
1403        ["cat"; "/new"]], "new file contents");
1404     InitBasicFS, Always, TestOutput (
1405       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1406        ["cat"; "/new"]], "\nnew file contents\n");
1407     InitBasicFS, Always, TestOutput (
1408       [["write_file"; "/new"; "\n\n"; "0"];
1409        ["cat"; "/new"]], "\n\n");
1410     InitBasicFS, Always, TestOutput (
1411       [["write_file"; "/new"; ""; "0"];
1412        ["cat"; "/new"]], "");
1413     InitBasicFS, Always, TestOutput (
1414       [["write_file"; "/new"; "\n\n\n"; "0"];
1415        ["cat"; "/new"]], "\n\n\n");
1416     InitBasicFS, Always, TestOutput (
1417       [["write_file"; "/new"; "\n"; "0"];
1418        ["cat"; "/new"]], "\n")],
1419    "create a file",
1420    "\
1421 This call creates a file called C<path>.  The contents of the
1422 file is the string C<content> (which can contain any 8 bit data),
1423 with length C<size>.
1424
1425 As a special case, if C<size> is C<0>
1426 then the length is calculated using C<strlen> (so in this case
1427 the content cannot contain embedded ASCII NULs).
1428
1429 I<NB.> Owing to a bug, writing content containing ASCII NUL
1430 characters does I<not> work, even if the length is specified.
1431 We hope to resolve this bug in a future version.  In the meantime
1432 use C<guestfs_upload>.");
1433
1434   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1435    [InitEmpty, Always, TestOutputListOfDevices (
1436       [["sfdiskM"; "/dev/sda"; ","];
1437        ["mkfs"; "ext2"; "/dev/sda1"];
1438        ["mount"; "/dev/sda1"; "/"];
1439        ["mounts"]], ["/dev/sda1"]);
1440     InitEmpty, Always, TestOutputList (
1441       [["sfdiskM"; "/dev/sda"; ","];
1442        ["mkfs"; "ext2"; "/dev/sda1"];
1443        ["mount"; "/dev/sda1"; "/"];
1444        ["umount"; "/"];
1445        ["mounts"]], [])],
1446    "unmount a filesystem",
1447    "\
1448 This unmounts the given filesystem.  The filesystem may be
1449 specified either by its mountpoint (path) or the device which
1450 contains the filesystem.");
1451
1452   ("mounts", (RStringList "devices", []), 46, [],
1453    [InitBasicFS, Always, TestOutputListOfDevices (
1454       [["mounts"]], ["/dev/sda1"])],
1455    "show mounted filesystems",
1456    "\
1457 This returns the list of currently mounted filesystems.  It returns
1458 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1459
1460 Some internal mounts are not shown.
1461
1462 See also: C<guestfs_mountpoints>");
1463
1464   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1465    [InitBasicFS, Always, TestOutputList (
1466       [["umount_all"];
1467        ["mounts"]], []);
1468     (* check that umount_all can unmount nested mounts correctly: *)
1469     InitEmpty, Always, TestOutputList (
1470       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1471        ["mkfs"; "ext2"; "/dev/sda1"];
1472        ["mkfs"; "ext2"; "/dev/sda2"];
1473        ["mkfs"; "ext2"; "/dev/sda3"];
1474        ["mount"; "/dev/sda1"; "/"];
1475        ["mkdir"; "/mp1"];
1476        ["mount"; "/dev/sda2"; "/mp1"];
1477        ["mkdir"; "/mp1/mp2"];
1478        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1479        ["mkdir"; "/mp1/mp2/mp3"];
1480        ["umount_all"];
1481        ["mounts"]], [])],
1482    "unmount all filesystems",
1483    "\
1484 This unmounts all mounted filesystems.
1485
1486 Some internal mounts are not unmounted by this call.");
1487
1488   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1489    [],
1490    "remove all LVM LVs, VGs and PVs",
1491    "\
1492 This command removes all LVM logical volumes, volume groups
1493 and physical volumes.");
1494
1495   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1496    [InitISOFS, Always, TestOutput (
1497       [["file"; "/empty"]], "empty");
1498     InitISOFS, Always, TestOutput (
1499       [["file"; "/known-1"]], "ASCII text");
1500     InitISOFS, Always, TestLastFail (
1501       [["file"; "/notexists"]])],
1502    "determine file type",
1503    "\
1504 This call uses the standard L<file(1)> command to determine
1505 the type or contents of the file.  This also works on devices,
1506 for example to find out whether a partition contains a filesystem.
1507
1508 This call will also transparently look inside various types
1509 of compressed file.
1510
1511 The exact command which runs is C<file -zbsL path>.  Note in
1512 particular that the filename is not prepended to the output
1513 (the C<-b> option).");
1514
1515   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1516    [InitBasicFS, Always, TestOutput (
1517       [["upload"; "test-command"; "/test-command"];
1518        ["chmod"; "0o755"; "/test-command"];
1519        ["command"; "/test-command 1"]], "Result1");
1520     InitBasicFS, Always, TestOutput (
1521       [["upload"; "test-command"; "/test-command"];
1522        ["chmod"; "0o755"; "/test-command"];
1523        ["command"; "/test-command 2"]], "Result2\n");
1524     InitBasicFS, Always, TestOutput (
1525       [["upload"; "test-command"; "/test-command"];
1526        ["chmod"; "0o755"; "/test-command"];
1527        ["command"; "/test-command 3"]], "\nResult3");
1528     InitBasicFS, Always, TestOutput (
1529       [["upload"; "test-command"; "/test-command"];
1530        ["chmod"; "0o755"; "/test-command"];
1531        ["command"; "/test-command 4"]], "\nResult4\n");
1532     InitBasicFS, Always, TestOutput (
1533       [["upload"; "test-command"; "/test-command"];
1534        ["chmod"; "0o755"; "/test-command"];
1535        ["command"; "/test-command 5"]], "\nResult5\n\n");
1536     InitBasicFS, Always, TestOutput (
1537       [["upload"; "test-command"; "/test-command"];
1538        ["chmod"; "0o755"; "/test-command"];
1539        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1540     InitBasicFS, Always, TestOutput (
1541       [["upload"; "test-command"; "/test-command"];
1542        ["chmod"; "0o755"; "/test-command"];
1543        ["command"; "/test-command 7"]], "");
1544     InitBasicFS, Always, TestOutput (
1545       [["upload"; "test-command"; "/test-command"];
1546        ["chmod"; "0o755"; "/test-command"];
1547        ["command"; "/test-command 8"]], "\n");
1548     InitBasicFS, Always, TestOutput (
1549       [["upload"; "test-command"; "/test-command"];
1550        ["chmod"; "0o755"; "/test-command"];
1551        ["command"; "/test-command 9"]], "\n\n");
1552     InitBasicFS, Always, TestOutput (
1553       [["upload"; "test-command"; "/test-command"];
1554        ["chmod"; "0o755"; "/test-command"];
1555        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1556     InitBasicFS, Always, TestOutput (
1557       [["upload"; "test-command"; "/test-command"];
1558        ["chmod"; "0o755"; "/test-command"];
1559        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1560     InitBasicFS, Always, TestLastFail (
1561       [["upload"; "test-command"; "/test-command"];
1562        ["chmod"; "0o755"; "/test-command"];
1563        ["command"; "/test-command"]])],
1564    "run a command from the guest filesystem",
1565    "\
1566 This call runs a command from the guest filesystem.  The
1567 filesystem must be mounted, and must contain a compatible
1568 operating system (ie. something Linux, with the same
1569 or compatible processor architecture).
1570
1571 The single parameter is an argv-style list of arguments.
1572 The first element is the name of the program to run.
1573 Subsequent elements are parameters.  The list must be
1574 non-empty (ie. must contain a program name).  Note that
1575 the command runs directly, and is I<not> invoked via
1576 the shell (see C<guestfs_sh>).
1577
1578 The return value is anything printed to I<stdout> by
1579 the command.
1580
1581 If the command returns a non-zero exit status, then
1582 this function returns an error message.  The error message
1583 string is the content of I<stderr> from the command.
1584
1585 The C<$PATH> environment variable will contain at least
1586 C</usr/bin> and C</bin>.  If you require a program from
1587 another location, you should provide the full path in the
1588 first parameter.
1589
1590 Shared libraries and data files required by the program
1591 must be available on filesystems which are mounted in the
1592 correct places.  It is the caller's responsibility to ensure
1593 all filesystems that are needed are mounted at the right
1594 locations.");
1595
1596   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1597    [InitBasicFS, Always, TestOutputList (
1598       [["upload"; "test-command"; "/test-command"];
1599        ["chmod"; "0o755"; "/test-command"];
1600        ["command_lines"; "/test-command 1"]], ["Result1"]);
1601     InitBasicFS, Always, TestOutputList (
1602       [["upload"; "test-command"; "/test-command"];
1603        ["chmod"; "0o755"; "/test-command"];
1604        ["command_lines"; "/test-command 2"]], ["Result2"]);
1605     InitBasicFS, Always, TestOutputList (
1606       [["upload"; "test-command"; "/test-command"];
1607        ["chmod"; "0o755"; "/test-command"];
1608        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1609     InitBasicFS, Always, TestOutputList (
1610       [["upload"; "test-command"; "/test-command"];
1611        ["chmod"; "0o755"; "/test-command"];
1612        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1613     InitBasicFS, Always, TestOutputList (
1614       [["upload"; "test-command"; "/test-command"];
1615        ["chmod"; "0o755"; "/test-command"];
1616        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1617     InitBasicFS, Always, TestOutputList (
1618       [["upload"; "test-command"; "/test-command"];
1619        ["chmod"; "0o755"; "/test-command"];
1620        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1621     InitBasicFS, Always, TestOutputList (
1622       [["upload"; "test-command"; "/test-command"];
1623        ["chmod"; "0o755"; "/test-command"];
1624        ["command_lines"; "/test-command 7"]], []);
1625     InitBasicFS, Always, TestOutputList (
1626       [["upload"; "test-command"; "/test-command"];
1627        ["chmod"; "0o755"; "/test-command"];
1628        ["command_lines"; "/test-command 8"]], [""]);
1629     InitBasicFS, Always, TestOutputList (
1630       [["upload"; "test-command"; "/test-command"];
1631        ["chmod"; "0o755"; "/test-command"];
1632        ["command_lines"; "/test-command 9"]], ["";""]);
1633     InitBasicFS, Always, TestOutputList (
1634       [["upload"; "test-command"; "/test-command"];
1635        ["chmod"; "0o755"; "/test-command"];
1636        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1637     InitBasicFS, Always, TestOutputList (
1638       [["upload"; "test-command"; "/test-command"];
1639        ["chmod"; "0o755"; "/test-command"];
1640        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1641    "run a command, returning lines",
1642    "\
1643 This is the same as C<guestfs_command>, but splits the
1644 result into a list of lines.
1645
1646 See also: C<guestfs_sh_lines>");
1647
1648   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1649    [InitISOFS, Always, TestOutputStruct (
1650       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1651    "get file information",
1652    "\
1653 Returns file information for the given C<path>.
1654
1655 This is the same as the C<stat(2)> system call.");
1656
1657   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1658    [InitISOFS, Always, TestOutputStruct (
1659       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1660    "get file information for a symbolic link",
1661    "\
1662 Returns file information for the given C<path>.
1663
1664 This is the same as C<guestfs_stat> except that if C<path>
1665 is a symbolic link, then the link is stat-ed, not the file it
1666 refers to.
1667
1668 This is the same as the C<lstat(2)> system call.");
1669
1670   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1671    [InitISOFS, Always, TestOutputStruct (
1672       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1673    "get file system statistics",
1674    "\
1675 Returns file system statistics for any mounted file system.
1676 C<path> should be a file or directory in the mounted file system
1677 (typically it is the mount point itself, but it doesn't need to be).
1678
1679 This is the same as the C<statvfs(2)> system call.");
1680
1681   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1682    [], (* XXX test *)
1683    "get ext2/ext3/ext4 superblock details",
1684    "\
1685 This returns the contents of the ext2, ext3 or ext4 filesystem
1686 superblock on C<device>.
1687
1688 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1689 manpage for more details.  The list of fields returned isn't
1690 clearly defined, and depends on both the version of C<tune2fs>
1691 that libguestfs was built against, and the filesystem itself.");
1692
1693   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1694    [InitEmpty, Always, TestOutputTrue (
1695       [["blockdev_setro"; "/dev/sda"];
1696        ["blockdev_getro"; "/dev/sda"]])],
1697    "set block device to read-only",
1698    "\
1699 Sets the block device named C<device> to read-only.
1700
1701 This uses the L<blockdev(8)> command.");
1702
1703   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1704    [InitEmpty, Always, TestOutputFalse (
1705       [["blockdev_setrw"; "/dev/sda"];
1706        ["blockdev_getro"; "/dev/sda"]])],
1707    "set block device to read-write",
1708    "\
1709 Sets the block device named C<device> to read-write.
1710
1711 This uses the L<blockdev(8)> command.");
1712
1713   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1714    [InitEmpty, Always, TestOutputTrue (
1715       [["blockdev_setro"; "/dev/sda"];
1716        ["blockdev_getro"; "/dev/sda"]])],
1717    "is block device set to read-only",
1718    "\
1719 Returns a boolean indicating if the block device is read-only
1720 (true if read-only, false if not).
1721
1722 This uses the L<blockdev(8)> command.");
1723
1724   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1725    [InitEmpty, Always, TestOutputInt (
1726       [["blockdev_getss"; "/dev/sda"]], 512)],
1727    "get sectorsize of block device",
1728    "\
1729 This returns the size of sectors on a block device.
1730 Usually 512, but can be larger for modern devices.
1731
1732 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1733 for that).
1734
1735 This uses the L<blockdev(8)> command.");
1736
1737   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1738    [InitEmpty, Always, TestOutputInt (
1739       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1740    "get blocksize of block device",
1741    "\
1742 This returns the block size of a device.
1743
1744 (Note this is different from both I<size in blocks> and
1745 I<filesystem block size>).
1746
1747 This uses the L<blockdev(8)> command.");
1748
1749   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1750    [], (* XXX test *)
1751    "set blocksize of block device",
1752    "\
1753 This sets the block size of a device.
1754
1755 (Note this is different from both I<size in blocks> and
1756 I<filesystem block size>).
1757
1758 This uses the L<blockdev(8)> command.");
1759
1760   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1761    [InitEmpty, Always, TestOutputInt (
1762       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1763    "get total size of device in 512-byte sectors",
1764    "\
1765 This returns the size of the device in units of 512-byte sectors
1766 (even if the sectorsize isn't 512 bytes ... weird).
1767
1768 See also C<guestfs_blockdev_getss> for the real sector size of
1769 the device, and C<guestfs_blockdev_getsize64> for the more
1770 useful I<size in bytes>.
1771
1772 This uses the L<blockdev(8)> command.");
1773
1774   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1775    [InitEmpty, Always, TestOutputInt (
1776       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1777    "get total size of device in bytes",
1778    "\
1779 This returns the size of the device in bytes.
1780
1781 See also C<guestfs_blockdev_getsz>.
1782
1783 This uses the L<blockdev(8)> command.");
1784
1785   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1786    [InitEmpty, Always, TestRun
1787       [["blockdev_flushbufs"; "/dev/sda"]]],
1788    "flush device buffers",
1789    "\
1790 This tells the kernel to flush internal buffers associated
1791 with C<device>.
1792
1793 This uses the L<blockdev(8)> command.");
1794
1795   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1796    [InitEmpty, Always, TestRun
1797       [["blockdev_rereadpt"; "/dev/sda"]]],
1798    "reread partition table",
1799    "\
1800 Reread the partition table on C<device>.
1801
1802 This uses the L<blockdev(8)> command.");
1803
1804   ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1805    [InitBasicFS, Always, TestOutput (
1806       (* Pick a file from cwd which isn't likely to change. *)
1807       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1808        ["checksum"; "md5"; "/COPYING.LIB"]],
1809         Digest.to_hex (Digest.file "COPYING.LIB"))],
1810    "upload a file from the local machine",
1811    "\
1812 Upload local file C<filename> to C<remotefilename> on the
1813 filesystem.
1814
1815 C<filename> can also be a named pipe.
1816
1817 See also C<guestfs_download>.");
1818
1819   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1820    [InitBasicFS, Always, TestOutput (
1821       (* Pick a file from cwd which isn't likely to change. *)
1822       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1823        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1824        ["upload"; "testdownload.tmp"; "/upload"];
1825        ["checksum"; "md5"; "/upload"]],
1826         Digest.to_hex (Digest.file "COPYING.LIB"))],
1827    "download a file to the local machine",
1828    "\
1829 Download file C<remotefilename> and save it as C<filename>
1830 on the local machine.
1831
1832 C<filename> can also be a named pipe.
1833
1834 See also C<guestfs_upload>, C<guestfs_cat>.");
1835
1836   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1837    [InitISOFS, Always, TestOutput (
1838       [["checksum"; "crc"; "/known-3"]], "2891671662");
1839     InitISOFS, Always, TestLastFail (
1840       [["checksum"; "crc"; "/notexists"]]);
1841     InitISOFS, Always, TestOutput (
1842       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1843     InitISOFS, Always, TestOutput (
1844       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1845     InitISOFS, Always, TestOutput (
1846       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1847     InitISOFS, Always, TestOutput (
1848       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1849     InitISOFS, Always, TestOutput (
1850       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1851     InitISOFS, Always, TestOutput (
1852       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1853    "compute MD5, SHAx or CRC checksum of file",
1854    "\
1855 This call computes the MD5, SHAx or CRC checksum of the
1856 file named C<path>.
1857
1858 The type of checksum to compute is given by the C<csumtype>
1859 parameter which must have one of the following values:
1860
1861 =over 4
1862
1863 =item C<crc>
1864
1865 Compute the cyclic redundancy check (CRC) specified by POSIX
1866 for the C<cksum> command.
1867
1868 =item C<md5>
1869
1870 Compute the MD5 hash (using the C<md5sum> program).
1871
1872 =item C<sha1>
1873
1874 Compute the SHA1 hash (using the C<sha1sum> program).
1875
1876 =item C<sha224>
1877
1878 Compute the SHA224 hash (using the C<sha224sum> program).
1879
1880 =item C<sha256>
1881
1882 Compute the SHA256 hash (using the C<sha256sum> program).
1883
1884 =item C<sha384>
1885
1886 Compute the SHA384 hash (using the C<sha384sum> program).
1887
1888 =item C<sha512>
1889
1890 Compute the SHA512 hash (using the C<sha512sum> program).
1891
1892 =back
1893
1894 The checksum is returned as a printable string.");
1895
1896   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1897    [InitBasicFS, Always, TestOutput (
1898       [["tar_in"; "../images/helloworld.tar"; "/"];
1899        ["cat"; "/hello"]], "hello\n")],
1900    "unpack tarfile to directory",
1901    "\
1902 This command uploads and unpacks local file C<tarfile> (an
1903 I<uncompressed> tar file) into C<directory>.
1904
1905 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1906
1907   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1908    [],
1909    "pack directory into tarfile",
1910    "\
1911 This command packs the contents of C<directory> and downloads
1912 it to local file C<tarfile>.
1913
1914 To download a compressed tarball, use C<guestfs_tgz_out>.");
1915
1916   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1917    [InitBasicFS, Always, TestOutput (
1918       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1919        ["cat"; "/hello"]], "hello\n")],
1920    "unpack compressed tarball to directory",
1921    "\
1922 This command uploads and unpacks local file C<tarball> (a
1923 I<gzip compressed> tar file) into C<directory>.
1924
1925 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1926
1927   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1928    [],
1929    "pack directory into compressed tarball",
1930    "\
1931 This command packs the contents of C<directory> and downloads
1932 it to local file C<tarball>.
1933
1934 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1935
1936   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1937    [InitBasicFS, Always, TestLastFail (
1938       [["umount"; "/"];
1939        ["mount_ro"; "/dev/sda1"; "/"];
1940        ["touch"; "/new"]]);
1941     InitBasicFS, Always, TestOutput (
1942       [["write_file"; "/new"; "data"; "0"];
1943        ["umount"; "/"];
1944        ["mount_ro"; "/dev/sda1"; "/"];
1945        ["cat"; "/new"]], "data")],
1946    "mount a guest disk, read-only",
1947    "\
1948 This is the same as the C<guestfs_mount> command, but it
1949 mounts the filesystem with the read-only (I<-o ro>) flag.");
1950
1951   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
1952    [],
1953    "mount a guest disk with mount options",
1954    "\
1955 This is the same as the C<guestfs_mount> command, but it
1956 allows you to set the mount options as for the
1957 L<mount(8)> I<-o> flag.");
1958
1959   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
1960    [],
1961    "mount a guest disk with mount options and vfstype",
1962    "\
1963 This is the same as the C<guestfs_mount> command, but it
1964 allows you to set both the mount options and the vfstype
1965 as for the L<mount(8)> I<-o> and I<-t> flags.");
1966
1967   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1968    [],
1969    "debugging and internals",
1970    "\
1971 The C<guestfs_debug> command exposes some internals of
1972 C<guestfsd> (the guestfs daemon) that runs inside the
1973 qemu subprocess.
1974
1975 There is no comprehensive help for this command.  You have
1976 to look at the file C<daemon/debug.c> in the libguestfs source
1977 to find out what you can do.");
1978
1979   ("lvremove", (RErr, [Device "device"]), 77, [],
1980    [InitEmpty, Always, TestOutputList (
1981       [["sfdiskM"; "/dev/sda"; ","];
1982        ["pvcreate"; "/dev/sda1"];
1983        ["vgcreate"; "VG"; "/dev/sda1"];
1984        ["lvcreate"; "LV1"; "VG"; "50"];
1985        ["lvcreate"; "LV2"; "VG"; "50"];
1986        ["lvremove"; "/dev/VG/LV1"];
1987        ["lvs"]], ["/dev/VG/LV2"]);
1988     InitEmpty, Always, TestOutputList (
1989       [["sfdiskM"; "/dev/sda"; ","];
1990        ["pvcreate"; "/dev/sda1"];
1991        ["vgcreate"; "VG"; "/dev/sda1"];
1992        ["lvcreate"; "LV1"; "VG"; "50"];
1993        ["lvcreate"; "LV2"; "VG"; "50"];
1994        ["lvremove"; "/dev/VG"];
1995        ["lvs"]], []);
1996     InitEmpty, Always, TestOutputList (
1997       [["sfdiskM"; "/dev/sda"; ","];
1998        ["pvcreate"; "/dev/sda1"];
1999        ["vgcreate"; "VG"; "/dev/sda1"];
2000        ["lvcreate"; "LV1"; "VG"; "50"];
2001        ["lvcreate"; "LV2"; "VG"; "50"];
2002        ["lvremove"; "/dev/VG"];
2003        ["vgs"]], ["VG"])],
2004    "remove an LVM logical volume",
2005    "\
2006 Remove an LVM logical volume C<device>, where C<device> is
2007 the path to the LV, such as C</dev/VG/LV>.
2008
2009 You can also remove all LVs in a volume group by specifying
2010 the VG name, C</dev/VG>.");
2011
2012   ("vgremove", (RErr, [String "vgname"]), 78, [],
2013    [InitEmpty, Always, TestOutputList (
2014       [["sfdiskM"; "/dev/sda"; ","];
2015        ["pvcreate"; "/dev/sda1"];
2016        ["vgcreate"; "VG"; "/dev/sda1"];
2017        ["lvcreate"; "LV1"; "VG"; "50"];
2018        ["lvcreate"; "LV2"; "VG"; "50"];
2019        ["vgremove"; "VG"];
2020        ["lvs"]], []);
2021     InitEmpty, Always, TestOutputList (
2022       [["sfdiskM"; "/dev/sda"; ","];
2023        ["pvcreate"; "/dev/sda1"];
2024        ["vgcreate"; "VG"; "/dev/sda1"];
2025        ["lvcreate"; "LV1"; "VG"; "50"];
2026        ["lvcreate"; "LV2"; "VG"; "50"];
2027        ["vgremove"; "VG"];
2028        ["vgs"]], [])],
2029    "remove an LVM volume group",
2030    "\
2031 Remove an LVM volume group C<vgname>, (for example C<VG>).
2032
2033 This also forcibly removes all logical volumes in the volume
2034 group (if any).");
2035
2036   ("pvremove", (RErr, [Device "device"]), 79, [],
2037    [InitEmpty, Always, TestOutputListOfDevices (
2038       [["sfdiskM"; "/dev/sda"; ","];
2039        ["pvcreate"; "/dev/sda1"];
2040        ["vgcreate"; "VG"; "/dev/sda1"];
2041        ["lvcreate"; "LV1"; "VG"; "50"];
2042        ["lvcreate"; "LV2"; "VG"; "50"];
2043        ["vgremove"; "VG"];
2044        ["pvremove"; "/dev/sda1"];
2045        ["lvs"]], []);
2046     InitEmpty, Always, TestOutputListOfDevices (
2047       [["sfdiskM"; "/dev/sda"; ","];
2048        ["pvcreate"; "/dev/sda1"];
2049        ["vgcreate"; "VG"; "/dev/sda1"];
2050        ["lvcreate"; "LV1"; "VG"; "50"];
2051        ["lvcreate"; "LV2"; "VG"; "50"];
2052        ["vgremove"; "VG"];
2053        ["pvremove"; "/dev/sda1"];
2054        ["vgs"]], []);
2055     InitEmpty, Always, TestOutputListOfDevices (
2056       [["sfdiskM"; "/dev/sda"; ","];
2057        ["pvcreate"; "/dev/sda1"];
2058        ["vgcreate"; "VG"; "/dev/sda1"];
2059        ["lvcreate"; "LV1"; "VG"; "50"];
2060        ["lvcreate"; "LV2"; "VG"; "50"];
2061        ["vgremove"; "VG"];
2062        ["pvremove"; "/dev/sda1"];
2063        ["pvs"]], [])],
2064    "remove an LVM physical volume",
2065    "\
2066 This wipes a physical volume C<device> so that LVM will no longer
2067 recognise it.
2068
2069 The implementation uses the C<pvremove> command which refuses to
2070 wipe physical volumes that contain any volume groups, so you have
2071 to remove those first.");
2072
2073   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2074    [InitBasicFS, Always, TestOutput (
2075       [["set_e2label"; "/dev/sda1"; "testlabel"];
2076        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2077    "set the ext2/3/4 filesystem label",
2078    "\
2079 This sets the ext2/3/4 filesystem label of the filesystem on
2080 C<device> to C<label>.  Filesystem labels are limited to
2081 16 characters.
2082
2083 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2084 to return the existing label on a filesystem.");
2085
2086   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2087    [],
2088    "get the ext2/3/4 filesystem label",
2089    "\
2090 This returns the ext2/3/4 filesystem label of the filesystem on
2091 C<device>.");
2092
2093   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2094    (let uuid = uuidgen () in
2095     [InitBasicFS, Always, TestOutput (
2096        [["set_e2uuid"; "/dev/sda1"; uuid];
2097         ["get_e2uuid"; "/dev/sda1"]], uuid);
2098      InitBasicFS, Always, TestOutput (
2099        [["set_e2uuid"; "/dev/sda1"; "clear"];
2100         ["get_e2uuid"; "/dev/sda1"]], "");
2101      (* We can't predict what UUIDs will be, so just check the commands run. *)
2102      InitBasicFS, Always, TestRun (
2103        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2104      InitBasicFS, Always, TestRun (
2105        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2106    "set the ext2/3/4 filesystem UUID",
2107    "\
2108 This sets the ext2/3/4 filesystem UUID of the filesystem on
2109 C<device> to C<uuid>.  The format of the UUID and alternatives
2110 such as C<clear>, C<random> and C<time> are described in the
2111 L<tune2fs(8)> manpage.
2112
2113 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2114 to return the existing UUID of a filesystem.");
2115
2116   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2117    [],
2118    "get the ext2/3/4 filesystem UUID",
2119    "\
2120 This returns the ext2/3/4 filesystem UUID of the filesystem on
2121 C<device>.");
2122
2123   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2124    [InitBasicFS, Always, TestOutputInt (
2125       [["umount"; "/dev/sda1"];
2126        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2127     InitBasicFS, Always, TestOutputInt (
2128       [["umount"; "/dev/sda1"];
2129        ["zero"; "/dev/sda1"];
2130        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2131    "run the filesystem checker",
2132    "\
2133 This runs the filesystem checker (fsck) on C<device> which
2134 should have filesystem type C<fstype>.
2135
2136 The returned integer is the status.  See L<fsck(8)> for the
2137 list of status codes from C<fsck>.
2138
2139 Notes:
2140
2141 =over 4
2142
2143 =item *
2144
2145 Multiple status codes can be summed together.
2146
2147 =item *
2148
2149 A non-zero return code can mean \"success\", for example if
2150 errors have been corrected on the filesystem.
2151
2152 =item *
2153
2154 Checking or repairing NTFS volumes is not supported
2155 (by linux-ntfs).
2156
2157 =back
2158
2159 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2160
2161   ("zero", (RErr, [Device "device"]), 85, [],
2162    [InitBasicFS, Always, TestOutput (
2163       [["umount"; "/dev/sda1"];
2164        ["zero"; "/dev/sda1"];
2165        ["file"; "/dev/sda1"]], "data")],
2166    "write zeroes to the device",
2167    "\
2168 This command writes zeroes over the first few blocks of C<device>.
2169
2170 How many blocks are zeroed isn't specified (but it's I<not> enough
2171 to securely wipe the device).  It should be sufficient to remove
2172 any partition tables, filesystem superblocks and so on.
2173
2174 See also: C<guestfs_scrub_device>.");
2175
2176   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2177    (* Test disabled because grub-install incompatible with virtio-blk driver.
2178     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2179     *)
2180    [InitBasicFS, Disabled, TestOutputTrue (
2181       [["grub_install"; "/"; "/dev/sda1"];
2182        ["is_dir"; "/boot"]])],
2183    "install GRUB",
2184    "\
2185 This command installs GRUB (the Grand Unified Bootloader) on
2186 C<device>, with the root directory being C<root>.");
2187
2188   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2189    [InitBasicFS, Always, TestOutput (
2190       [["write_file"; "/old"; "file content"; "0"];
2191        ["cp"; "/old"; "/new"];
2192        ["cat"; "/new"]], "file content");
2193     InitBasicFS, Always, TestOutputTrue (
2194       [["write_file"; "/old"; "file content"; "0"];
2195        ["cp"; "/old"; "/new"];
2196        ["is_file"; "/old"]]);
2197     InitBasicFS, Always, TestOutput (
2198       [["write_file"; "/old"; "file content"; "0"];
2199        ["mkdir"; "/dir"];
2200        ["cp"; "/old"; "/dir/new"];
2201        ["cat"; "/dir/new"]], "file content")],
2202    "copy a file",
2203    "\
2204 This copies a file from C<src> to C<dest> where C<dest> is
2205 either a destination filename or destination directory.");
2206
2207   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2208    [InitBasicFS, Always, TestOutput (
2209       [["mkdir"; "/olddir"];
2210        ["mkdir"; "/newdir"];
2211        ["write_file"; "/olddir/file"; "file content"; "0"];
2212        ["cp_a"; "/olddir"; "/newdir"];
2213        ["cat"; "/newdir/olddir/file"]], "file content")],
2214    "copy a file or directory recursively",
2215    "\
2216 This copies a file or directory from C<src> to C<dest>
2217 recursively using the C<cp -a> command.");
2218
2219   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2220    [InitBasicFS, Always, TestOutput (
2221       [["write_file"; "/old"; "file content"; "0"];
2222        ["mv"; "/old"; "/new"];
2223        ["cat"; "/new"]], "file content");
2224     InitBasicFS, Always, TestOutputFalse (
2225       [["write_file"; "/old"; "file content"; "0"];
2226        ["mv"; "/old"; "/new"];
2227        ["is_file"; "/old"]])],
2228    "move a file",
2229    "\
2230 This moves a file from C<src> to C<dest> where C<dest> is
2231 either a destination filename or destination directory.");
2232
2233   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2234    [InitEmpty, Always, TestRun (
2235       [["drop_caches"; "3"]])],
2236    "drop kernel page cache, dentries and inodes",
2237    "\
2238 This instructs the guest kernel to drop its page cache,
2239 and/or dentries and inode caches.  The parameter C<whattodrop>
2240 tells the kernel what precisely to drop, see
2241 L<http://linux-mm.org/Drop_Caches>
2242
2243 Setting C<whattodrop> to 3 should drop everything.
2244
2245 This automatically calls L<sync(2)> before the operation,
2246 so that the maximum guest memory is freed.");
2247
2248   ("dmesg", (RString "kmsgs", []), 91, [],
2249    [InitEmpty, Always, TestRun (
2250       [["dmesg"]])],
2251    "return kernel messages",
2252    "\
2253 This returns the kernel messages (C<dmesg> output) from
2254 the guest kernel.  This is sometimes useful for extended
2255 debugging of problems.
2256
2257 Another way to get the same information is to enable
2258 verbose messages with C<guestfs_set_verbose> or by setting
2259 the environment variable C<LIBGUESTFS_DEBUG=1> before
2260 running the program.");
2261
2262   ("ping_daemon", (RErr, []), 92, [],
2263    [InitEmpty, Always, TestRun (
2264       [["ping_daemon"]])],
2265    "ping the guest daemon",
2266    "\
2267 This is a test probe into the guestfs daemon running inside
2268 the qemu subprocess.  Calling this function checks that the
2269 daemon responds to the ping message, without affecting the daemon
2270 or attached block device(s) in any other way.");
2271
2272   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2273    [InitBasicFS, Always, TestOutputTrue (
2274       [["write_file"; "/file1"; "contents of a file"; "0"];
2275        ["cp"; "/file1"; "/file2"];
2276        ["equal"; "/file1"; "/file2"]]);
2277     InitBasicFS, Always, TestOutputFalse (
2278       [["write_file"; "/file1"; "contents of a file"; "0"];
2279        ["write_file"; "/file2"; "contents of another file"; "0"];
2280        ["equal"; "/file1"; "/file2"]]);
2281     InitBasicFS, Always, TestLastFail (
2282       [["equal"; "/file1"; "/file2"]])],
2283    "test if two files have equal contents",
2284    "\
2285 This compares the two files C<file1> and C<file2> and returns
2286 true if their content is exactly equal, or false otherwise.
2287
2288 The external L<cmp(1)> program is used for the comparison.");
2289
2290   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2291    [InitISOFS, Always, TestOutputList (
2292       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2293     InitISOFS, Always, TestOutputList (
2294       [["strings"; "/empty"]], [])],
2295    "print the printable strings in a file",
2296    "\
2297 This runs the L<strings(1)> command on a file and returns
2298 the list of printable strings found.");
2299
2300   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2301    [InitISOFS, Always, TestOutputList (
2302       [["strings_e"; "b"; "/known-5"]], []);
2303     InitBasicFS, Disabled, TestOutputList (
2304       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2305        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2306    "print the printable strings in a file",
2307    "\
2308 This is like the C<guestfs_strings> command, but allows you to
2309 specify the encoding.
2310
2311 See the L<strings(1)> manpage for the full list of encodings.
2312
2313 Commonly useful encodings are C<l> (lower case L) which will
2314 show strings inside Windows/x86 files.
2315
2316 The returned strings are transcoded to UTF-8.");
2317
2318   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2319    [InitISOFS, Always, TestOutput (
2320       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2321     (* Test for RHBZ#501888c2 regression which caused large hexdump
2322      * commands to segfault.
2323      *)
2324     InitISOFS, Always, TestRun (
2325       [["hexdump"; "/100krandom"]])],
2326    "dump a file in hexadecimal",
2327    "\
2328 This runs C<hexdump -C> on the given C<path>.  The result is
2329 the human-readable, canonical hex dump of the file.");
2330
2331   ("zerofree", (RErr, [Device "device"]), 97, [],
2332    [InitNone, Always, TestOutput (
2333       [["sfdiskM"; "/dev/sda"; ","];
2334        ["mkfs"; "ext3"; "/dev/sda1"];
2335        ["mount"; "/dev/sda1"; "/"];
2336        ["write_file"; "/new"; "test file"; "0"];
2337        ["umount"; "/dev/sda1"];
2338        ["zerofree"; "/dev/sda1"];
2339        ["mount"; "/dev/sda1"; "/"];
2340        ["cat"; "/new"]], "test file")],
2341    "zero unused inodes and disk blocks on ext2/3 filesystem",
2342    "\
2343 This runs the I<zerofree> program on C<device>.  This program
2344 claims to zero unused inodes and disk blocks on an ext2/3
2345 filesystem, thus making it possible to compress the filesystem
2346 more effectively.
2347
2348 You should B<not> run this program if the filesystem is
2349 mounted.
2350
2351 It is possible that using this program can damage the filesystem
2352 or data on the filesystem.");
2353
2354   ("pvresize", (RErr, [Device "device"]), 98, [],
2355    [],
2356    "resize an LVM physical volume",
2357    "\
2358 This resizes (expands or shrinks) an existing LVM physical
2359 volume to match the new size of the underlying device.");
2360
2361   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2362                        Int "cyls"; Int "heads"; Int "sectors";
2363                        String "line"]), 99, [DangerWillRobinson],
2364    [],
2365    "modify a single partition on a block device",
2366    "\
2367 This runs L<sfdisk(8)> option to modify just the single
2368 partition C<n> (note: C<n> counts from 1).
2369
2370 For other parameters, see C<guestfs_sfdisk>.  You should usually
2371 pass C<0> for the cyls/heads/sectors parameters.");
2372
2373   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2374    [],
2375    "display the partition table",
2376    "\
2377 This displays the partition table on C<device>, in the
2378 human-readable output of the L<sfdisk(8)> command.  It is
2379 not intended to be parsed.");
2380
2381   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2382    [],
2383    "display the kernel geometry",
2384    "\
2385 This displays the kernel's idea of the geometry of C<device>.
2386
2387 The result is in human-readable format, and not designed to
2388 be parsed.");
2389
2390   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2391    [],
2392    "display the disk geometry from the partition table",
2393    "\
2394 This displays the disk geometry of C<device> read from the
2395 partition table.  Especially in the case where the underlying
2396 block device has been resized, this can be different from the
2397 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2398
2399 The result is in human-readable format, and not designed to
2400 be parsed.");
2401
2402   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2403    [],
2404    "activate or deactivate all volume groups",
2405    "\
2406 This command activates or (if C<activate> is false) deactivates
2407 all logical volumes in all volume groups.
2408 If activated, then they are made known to the
2409 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2410 then those devices disappear.
2411
2412 This command is the same as running C<vgchange -a y|n>");
2413
2414   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2415    [],
2416    "activate or deactivate some volume groups",
2417    "\
2418 This command activates or (if C<activate> is false) deactivates
2419 all logical volumes in the listed volume groups C<volgroups>.
2420 If activated, then they are made known to the
2421 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2422 then those devices disappear.
2423
2424 This command is the same as running C<vgchange -a y|n volgroups...>
2425
2426 Note that if C<volgroups> is an empty list then B<all> volume groups
2427 are activated or deactivated.");
2428
2429   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2430    [InitNone, Always, TestOutput (
2431       [["sfdiskM"; "/dev/sda"; ","];
2432        ["pvcreate"; "/dev/sda1"];
2433        ["vgcreate"; "VG"; "/dev/sda1"];
2434        ["lvcreate"; "LV"; "VG"; "10"];
2435        ["mkfs"; "ext2"; "/dev/VG/LV"];
2436        ["mount"; "/dev/VG/LV"; "/"];
2437        ["write_file"; "/new"; "test content"; "0"];
2438        ["umount"; "/"];
2439        ["lvresize"; "/dev/VG/LV"; "20"];
2440        ["e2fsck_f"; "/dev/VG/LV"];
2441        ["resize2fs"; "/dev/VG/LV"];
2442        ["mount"; "/dev/VG/LV"; "/"];
2443        ["cat"; "/new"]], "test content")],
2444    "resize an LVM logical volume",
2445    "\
2446 This resizes (expands or shrinks) an existing LVM logical
2447 volume to C<mbytes>.  When reducing, data in the reduced part
2448 is lost.");
2449
2450   ("resize2fs", (RErr, [Device "device"]), 106, [],
2451    [], (* lvresize tests this *)
2452    "resize an ext2/ext3 filesystem",
2453    "\
2454 This resizes an ext2 or ext3 filesystem to match the size of
2455 the underlying device.
2456
2457 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2458 on the C<device> before calling this command.  For unknown reasons
2459 C<resize2fs> sometimes gives an error about this and sometimes not.
2460 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2461 calling this function.");
2462
2463   ("find", (RStringList "names", [Pathname "directory"]), 107, [],
2464    [InitBasicFS, Always, TestOutputList (
2465       [["find"; "/"]], ["lost+found"]);
2466     InitBasicFS, Always, TestOutputList (
2467       [["touch"; "/a"];
2468        ["mkdir"; "/b"];
2469        ["touch"; "/b/c"];
2470        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2471     InitBasicFS, Always, TestOutputList (
2472       [["mkdir_p"; "/a/b/c"];
2473        ["touch"; "/a/b/c/d"];
2474        ["find"; "/a/b/"]], ["c"; "c/d"])],
2475    "find all files and directories",
2476    "\
2477 This command lists out all files and directories, recursively,
2478 starting at C<directory>.  It is essentially equivalent to
2479 running the shell command C<find directory -print> but some
2480 post-processing happens on the output, described below.
2481
2482 This returns a list of strings I<without any prefix>.  Thus
2483 if the directory structure was:
2484
2485  /tmp/a
2486  /tmp/b
2487  /tmp/c/d
2488
2489 then the returned list from C<guestfs_find> C</tmp> would be
2490 4 elements:
2491
2492  a
2493  b
2494  c
2495  c/d
2496
2497 If C<directory> is not a directory, then this command returns
2498 an error.
2499
2500 The returned list is sorted.");
2501
2502   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2503    [], (* lvresize tests this *)
2504    "check an ext2/ext3 filesystem",
2505    "\
2506 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2507 filesystem checker on C<device>, noninteractively (C<-p>),
2508 even if the filesystem appears to be clean (C<-f>).
2509
2510 This command is only needed because of C<guestfs_resize2fs>
2511 (q.v.).  Normally you should use C<guestfs_fsck>.");
2512
2513   ("sleep", (RErr, [Int "secs"]), 109, [],
2514    [InitNone, Always, TestRun (
2515       [["sleep"; "1"]])],
2516    "sleep for some seconds",
2517    "\
2518 Sleep for C<secs> seconds.");
2519
2520   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2521    [InitNone, Always, TestOutputInt (
2522       [["sfdiskM"; "/dev/sda"; ","];
2523        ["mkfs"; "ntfs"; "/dev/sda1"];
2524        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2525     InitNone, Always, TestOutputInt (
2526       [["sfdiskM"; "/dev/sda"; ","];
2527        ["mkfs"; "ext2"; "/dev/sda1"];
2528        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2529    "probe NTFS volume",
2530    "\
2531 This command runs the L<ntfs-3g.probe(8)> command which probes
2532 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2533 be mounted read-write, and some cannot be mounted at all).
2534
2535 C<rw> is a boolean flag.  Set it to true if you want to test
2536 if the volume can be mounted read-write.  Set it to false if
2537 you want to test if the volume can be mounted read-only.
2538
2539 The return value is an integer which C<0> if the operation
2540 would succeed, or some non-zero value documented in the
2541 L<ntfs-3g.probe(8)> manual page.");
2542
2543   ("sh", (RString "output", [String "command"]), 111, [],
2544    [], (* XXX needs tests *)
2545    "run a command via the shell",
2546    "\
2547 This call runs a command from the guest filesystem via the
2548 guest's C</bin/sh>.
2549
2550 This is like C<guestfs_command>, but passes the command to:
2551
2552  /bin/sh -c \"command\"
2553
2554 Depending on the guest's shell, this usually results in
2555 wildcards being expanded, shell expressions being interpolated
2556 and so on.
2557
2558 All the provisos about C<guestfs_command> apply to this call.");
2559
2560   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2561    [], (* XXX needs tests *)
2562    "run a command via the shell returning lines",
2563    "\
2564 This is the same as C<guestfs_sh>, but splits the result
2565 into a list of lines.
2566
2567 See also: C<guestfs_command_lines>");
2568
2569   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2570    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2571     * code in stubs.c, since all valid glob patterns must start with "/".
2572     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2573     *)
2574    [InitBasicFS, Always, TestOutputList (
2575       [["mkdir_p"; "/a/b/c"];
2576        ["touch"; "/a/b/c/d"];
2577        ["touch"; "/a/b/c/e"];
2578        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2579     InitBasicFS, Always, TestOutputList (
2580       [["mkdir_p"; "/a/b/c"];
2581        ["touch"; "/a/b/c/d"];
2582        ["touch"; "/a/b/c/e"];
2583        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2584     InitBasicFS, Always, TestOutputList (
2585       [["mkdir_p"; "/a/b/c"];
2586        ["touch"; "/a/b/c/d"];
2587        ["touch"; "/a/b/c/e"];
2588        ["glob_expand"; "/a/*/x/*"]], [])],
2589    "expand a wildcard path",
2590    "\
2591 This command searches for all the pathnames matching
2592 C<pattern> according to the wildcard expansion rules
2593 used by the shell.
2594
2595 If no paths match, then this returns an empty list
2596 (note: not an error).
2597
2598 It is just a wrapper around the C L<glob(3)> function
2599 with flags C<GLOB_MARK|GLOB_BRACE>.
2600 See that manual page for more details.");
2601
2602   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2603    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2604       [["scrub_device"; "/dev/sdc"]])],
2605    "scrub (securely wipe) a device",
2606    "\
2607 This command writes patterns over C<device> to make data retrieval
2608 more difficult.
2609
2610 It is an interface to the L<scrub(1)> program.  See that
2611 manual page for more details.");
2612
2613   ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2614    [InitBasicFS, Always, TestRun (
2615       [["write_file"; "/file"; "content"; "0"];
2616        ["scrub_file"; "/file"]])],
2617    "scrub (securely wipe) a file",
2618    "\
2619 This command writes patterns over a file to make data retrieval
2620 more difficult.
2621
2622 The file is I<removed> after scrubbing.
2623
2624 It is an interface to the L<scrub(1)> program.  See that
2625 manual page for more details.");
2626
2627   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2628    [], (* XXX needs testing *)
2629    "scrub (securely wipe) free space",
2630    "\
2631 This command creates the directory C<dir> and then fills it
2632 with files until the filesystem is full, and scrubs the files
2633 as for C<guestfs_scrub_file>, and deletes them.
2634 The intention is to scrub any free space on the partition
2635 containing C<dir>.
2636
2637 It is an interface to the L<scrub(1)> program.  See that
2638 manual page for more details.");
2639
2640   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2641    [InitBasicFS, Always, TestRun (
2642       [["mkdir"; "/tmp"];
2643        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2644    "create a temporary directory",
2645    "\
2646 This command creates a temporary directory.  The
2647 C<template> parameter should be a full pathname for the
2648 temporary directory name with the final six characters being
2649 \"XXXXXX\".
2650
2651 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2652 the second one being suitable for Windows filesystems.
2653
2654 The name of the temporary directory that was created
2655 is returned.
2656
2657 The temporary directory is created with mode 0700
2658 and is owned by root.
2659
2660 The caller is responsible for deleting the temporary
2661 directory and its contents after use.
2662
2663 See also: L<mkdtemp(3)>");
2664
2665   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2666    [InitISOFS, Always, TestOutputInt (
2667       [["wc_l"; "/10klines"]], 10000)],
2668    "count lines in a file",
2669    "\
2670 This command counts the lines in a file, using the
2671 C<wc -l> external command.");
2672
2673   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2674    [InitISOFS, Always, TestOutputInt (
2675       [["wc_w"; "/10klines"]], 10000)],
2676    "count words in a file",
2677    "\
2678 This command counts the words in a file, using the
2679 C<wc -w> external command.");
2680
2681   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2682    [InitISOFS, Always, TestOutputInt (
2683       [["wc_c"; "/100kallspaces"]], 102400)],
2684    "count characters in a file",
2685    "\
2686 This command counts the characters in a file, using the
2687 C<wc -c> external command.");
2688
2689   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2690    [InitISOFS, Always, TestOutputList (
2691       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2692    "return first 10 lines of a file",
2693    "\
2694 This command returns up to the first 10 lines of a file as
2695 a list of strings.");
2696
2697   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2698    [InitISOFS, Always, TestOutputList (
2699       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2700     InitISOFS, Always, TestOutputList (
2701       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2702     InitISOFS, Always, TestOutputList (
2703       [["head_n"; "0"; "/10klines"]], [])],
2704    "return first N lines of a file",
2705    "\
2706 If the parameter C<nrlines> is a positive number, this returns the first
2707 C<nrlines> lines of the file C<path>.
2708
2709 If the parameter C<nrlines> is a negative number, this returns lines
2710 from the file C<path>, excluding the last C<nrlines> lines.
2711
2712 If the parameter C<nrlines> is zero, this returns an empty list.");
2713
2714   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2715    [InitISOFS, Always, TestOutputList (
2716       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2717    "return last 10 lines of a file",
2718    "\
2719 This command returns up to the last 10 lines of a file as
2720 a list of strings.");
2721
2722   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2723    [InitISOFS, Always, TestOutputList (
2724       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2725     InitISOFS, Always, TestOutputList (
2726       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2727     InitISOFS, Always, TestOutputList (
2728       [["tail_n"; "0"; "/10klines"]], [])],
2729    "return last N lines of a file",
2730    "\
2731 If the parameter C<nrlines> is a positive number, this returns the last
2732 C<nrlines> lines of the file C<path>.
2733
2734 If the parameter C<nrlines> is a negative number, this returns lines
2735 from the file C<path>, starting with the C<-nrlines>th line.
2736
2737 If the parameter C<nrlines> is zero, this returns an empty list.");
2738
2739   ("df", (RString "output", []), 125, [],
2740    [], (* XXX Tricky to test because it depends on the exact format
2741         * of the 'df' command and other imponderables.
2742         *)
2743    "report file system disk space usage",
2744    "\
2745 This command runs the C<df> command to report disk space used.
2746
2747 This command is mostly useful for interactive sessions.  It
2748 is I<not> intended that you try to parse the output string.
2749 Use C<statvfs> from programs.");
2750
2751   ("df_h", (RString "output", []), 126, [],
2752    [], (* XXX Tricky to test because it depends on the exact format
2753         * of the 'df' command and other imponderables.
2754         *)
2755    "report file system disk space usage (human readable)",
2756    "\
2757 This command runs the C<df -h> command to report disk space used
2758 in human-readable format.
2759
2760 This command is mostly useful for interactive sessions.  It
2761 is I<not> intended that you try to parse the output string.
2762 Use C<statvfs> from programs.");
2763
2764   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2765    [InitISOFS, Always, TestOutputInt (
2766       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2767    "estimate file space usage",
2768    "\
2769 This command runs the C<du -s> command to estimate file space
2770 usage for C<path>.
2771
2772 C<path> can be a file or a directory.  If C<path> is a directory
2773 then the estimate includes the contents of the directory and all
2774 subdirectories (recursively).
2775
2776 The result is the estimated size in I<kilobytes>
2777 (ie. units of 1024 bytes).");
2778
2779   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2780    [InitISOFS, Always, TestOutputList (
2781       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2782    "list files in an initrd",
2783    "\
2784 This command lists out files contained in an initrd.
2785
2786 The files are listed without any initial C</> character.  The
2787 files are listed in the order they appear (not necessarily
2788 alphabetical).  Directory names are listed as separate items.
2789
2790 Old Linux kernels (2.4 and earlier) used a compressed ext2
2791 filesystem as initrd.  We I<only> support the newer initramfs
2792 format (compressed cpio files).");
2793
2794   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2795    [],
2796    "mount a file using the loop device",
2797    "\
2798 This command lets you mount C<file> (a filesystem image
2799 in a file) on a mount point.  It is entirely equivalent to
2800 the command C<mount -o loop file mountpoint>.");
2801
2802   ("mkswap", (RErr, [Device "device"]), 130, [],
2803    [InitEmpty, Always, TestRun (
2804       [["sfdiskM"; "/dev/sda"; ","];
2805        ["mkswap"; "/dev/sda1"]])],
2806    "create a swap partition",
2807    "\
2808 Create a swap partition on C<device>.");
2809
2810   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2811    [InitEmpty, Always, TestRun (
2812       [["sfdiskM"; "/dev/sda"; ","];
2813        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2814    "create a swap partition with a label",
2815    "\
2816 Create a swap partition on C<device> with label C<label>.
2817
2818 Note that you cannot attach a swap label to a block device
2819 (eg. C</dev/sda>), just to a partition.  This appears to be
2820 a limitation of the kernel or swap tools.");
2821
2822   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2823    (let uuid = uuidgen () in
2824     [InitEmpty, Always, TestRun (
2825        [["sfdiskM"; "/dev/sda"; ","];
2826         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2827    "create a swap partition with an explicit UUID",
2828    "\
2829 Create a swap partition on C<device> with UUID C<uuid>.");
2830
2831   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2832    [InitBasicFS, Always, TestOutputStruct (
2833       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2834        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2835        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2836     InitBasicFS, Always, TestOutputStruct (
2837       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2838        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2839    "make block, character or FIFO devices",
2840    "\
2841 This call creates block or character special devices, or
2842 named pipes (FIFOs).
2843
2844 The C<mode> parameter should be the mode, using the standard
2845 constants.  C<devmajor> and C<devminor> are the
2846 device major and minor numbers, only used when creating block
2847 and character special devices.");
2848
2849   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2850    [InitBasicFS, Always, TestOutputStruct (
2851       [["mkfifo"; "0o777"; "/node"];
2852        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2853    "make FIFO (named pipe)",
2854    "\
2855 This call creates a FIFO (named pipe) called C<path> with
2856 mode C<mode>.  It is just a convenient wrapper around
2857 C<guestfs_mknod>.");
2858
2859   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2860    [InitBasicFS, Always, TestOutputStruct (
2861       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2862        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2863    "make block device node",
2864    "\
2865 This call creates a block device node called C<path> with
2866 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2867 It is just a convenient wrapper around C<guestfs_mknod>.");
2868
2869   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2870    [InitBasicFS, Always, TestOutputStruct (
2871       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2872        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2873    "make char device node",
2874    "\
2875 This call creates a char device node called C<path> with
2876 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2877 It is just a convenient wrapper around C<guestfs_mknod>.");
2878
2879   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2880    [], (* XXX umask is one of those stateful things that we should
2881         * reset between each test.
2882         *)
2883    "set file mode creation mask (umask)",
2884    "\
2885 This function sets the mask used for creating new files and
2886 device nodes to C<mask & 0777>.
2887
2888 Typical umask values would be C<022> which creates new files
2889 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2890 C<002> which creates new files with permissions like
2891 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2892
2893 The default umask is C<022>.  This is important because it
2894 means that directories and device nodes will be created with
2895 C<0644> or C<0755> mode even if you specify C<0777>.
2896
2897 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2898
2899 This call returns the previous umask.");
2900
2901   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2902    [],
2903    "read directories entries",
2904    "\
2905 This returns the list of directory entries in directory C<dir>.
2906
2907 All entries in the directory are returned, including C<.> and
2908 C<..>.  The entries are I<not> sorted, but returned in the same
2909 order as the underlying filesystem.
2910
2911 Also this call returns basic file type information about each
2912 file.  The C<ftyp> field will contain one of the following characters:
2913
2914 =over 4
2915
2916 =item 'b'
2917
2918 Block special
2919
2920 =item 'c'
2921
2922 Char special
2923
2924 =item 'd'
2925
2926 Directory
2927
2928 =item 'f'
2929
2930 FIFO (named pipe)
2931
2932 =item 'l'
2933
2934 Symbolic link
2935
2936 =item 'r'
2937
2938 Regular file
2939
2940 =item 's'
2941
2942 Socket
2943
2944 =item 'u'
2945
2946 Unknown file type
2947
2948 =item '?'
2949
2950 The L<readdir(3)> returned a C<d_type> field with an
2951 unexpected value
2952
2953 =back
2954
2955 This function is primarily intended for use by programs.  To
2956 get a simple list of names, use C<guestfs_ls>.  To get a printable
2957 directory for human consumption, use C<guestfs_ll>.");
2958
2959   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
2960    [],
2961    "create partitions on a block device",
2962    "\
2963 This is a simplified interface to the C<guestfs_sfdisk>
2964 command, where partition sizes are specified in megabytes
2965 only (rounded to the nearest cylinder) and you don't need
2966 to specify the cyls, heads and sectors parameters which
2967 were rarely if ever used anyway.
2968
2969 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
2970
2971   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
2972    [],
2973    "determine file type inside a compressed file",
2974    "\
2975 This command runs C<file> after first decompressing C<path>
2976 using C<method>.
2977
2978 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
2979
2980 Since 1.0.63, use C<guestfs_file> instead which can now
2981 process compressed files.");
2982
2983   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
2984    [],
2985    "list extended attributes of a file or directory",
2986    "\
2987 This call lists the extended attributes of the file or directory
2988 C<path>.
2989
2990 At the system call level, this is a combination of the
2991 L<listxattr(2)> and L<getxattr(2)> calls.
2992
2993 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
2994
2995   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
2996    [],
2997    "list extended attributes of a file or directory",
2998    "\
2999 This is the same as C<guestfs_getxattrs>, but if C<path>
3000 is a symbolic link, then it returns the extended attributes
3001 of the link itself.");
3002
3003   ("setxattr", (RErr, [String "xattr";
3004                        String "val"; Int "vallen"; (* will be BufferIn *)
3005                        Pathname "path"]), 143, [],
3006    [],
3007    "set extended attribute of a file or directory",
3008    "\
3009 This call sets the extended attribute named C<xattr>
3010 of the file C<path> to the value C<val> (of length C<vallen>).
3011 The value is arbitrary 8 bit data.
3012
3013 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3014
3015   ("lsetxattr", (RErr, [String "xattr";
3016                         String "val"; Int "vallen"; (* will be BufferIn *)
3017                         Pathname "path"]), 144, [],
3018    [],
3019    "set extended attribute of a file or directory",
3020    "\
3021 This is the same as C<guestfs_setxattr>, but if C<path>
3022 is a symbolic link, then it sets an extended attribute
3023 of the link itself.");
3024
3025   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3026    [],
3027    "remove extended attribute of a file or directory",
3028    "\
3029 This call removes the extended attribute named C<xattr>
3030 of the file C<path>.
3031
3032 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3033
3034   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3035    [],
3036    "remove extended attribute of a file or directory",
3037    "\
3038 This is the same as C<guestfs_removexattr>, but if C<path>
3039 is a symbolic link, then it removes an extended attribute
3040 of the link itself.");
3041
3042   ("mountpoints", (RHashtable "mps", []), 147, [],
3043    [],
3044    "show mountpoints",
3045    "\
3046 This call is similar to C<guestfs_mounts>.  That call returns
3047 a list of devices.  This one returns a hash table (map) of
3048 device name to directory where the device is mounted.");
3049
3050   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3051   (* This is a special case: while you would expect a parameter
3052    * of type "Pathname", that doesn't work, because it implies
3053    * NEED_ROOT in the generated calling code in stubs.c, and
3054    * this function cannot use NEED_ROOT.
3055    *)
3056    [],
3057    "create a mountpoint",
3058    "\
3059 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3060 specialized calls that can be used to create extra mountpoints
3061 before mounting the first filesystem.
3062
3063 These calls are I<only> necessary in some very limited circumstances,
3064 mainly the case where you want to mount a mix of unrelated and/or
3065 read-only filesystems together.
3066
3067 For example, live CDs often contain a \"Russian doll\" nest of
3068 filesystems, an ISO outer layer, with a squashfs image inside, with
3069 an ext2/3 image inside that.  You can unpack this as follows
3070 in guestfish:
3071
3072  add-ro Fedora-11-i686-Live.iso
3073  run
3074  mkmountpoint /cd
3075  mkmountpoint /squash
3076  mkmountpoint /ext3
3077  mount /dev/sda /cd
3078  mount-loop /cd/LiveOS/squashfs.img /squash
3079  mount-loop /squash/LiveOS/ext3fs.img /ext3
3080
3081 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3082
3083   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3084    [],
3085    "remove a mountpoint",
3086    "\
3087 This calls removes a mountpoint that was previously created
3088 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3089 for full details.");
3090
3091   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3092    [InitISOFS, Always, TestOutputBuffer (
3093       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3094    "read a file",
3095    "\
3096 This calls returns the contents of the file C<path> as a
3097 buffer.
3098
3099 Unlike C<guestfs_cat>, this function can correctly
3100 handle files that contain embedded ASCII NUL characters.
3101 However unlike C<guestfs_download>, this function is limited
3102 in the total size of file that can be handled.");
3103
3104   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3105    [InitISOFS, Always, TestOutputList (
3106       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3107     InitISOFS, Always, TestOutputList (
3108       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3109    "return lines matching a pattern",
3110    "\
3111 This calls the external C<grep> program and returns the
3112 matching lines.");
3113
3114   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3115    [InitISOFS, Always, TestOutputList (
3116       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3117    "return lines matching a pattern",
3118    "\
3119 This calls the external C<egrep> program and returns the
3120 matching lines.");
3121
3122   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3123    [InitISOFS, Always, TestOutputList (
3124       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3125    "return lines matching a pattern",
3126    "\
3127 This calls the external C<fgrep> program and returns the
3128 matching lines.");
3129
3130   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3131    [InitISOFS, Always, TestOutputList (
3132       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3133    "return lines matching a pattern",
3134    "\
3135 This calls the external C<grep -i> program and returns the
3136 matching lines.");
3137
3138   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3139    [InitISOFS, Always, TestOutputList (
3140       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3141    "return lines matching a pattern",
3142    "\
3143 This calls the external C<egrep -i> program and returns the
3144 matching lines.");
3145
3146   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3147    [InitISOFS, Always, TestOutputList (
3148       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3149    "return lines matching a pattern",
3150    "\
3151 This calls the external C<fgrep -i> program and returns the
3152 matching lines.");
3153
3154   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3155    [InitISOFS, Always, TestOutputList (
3156       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3157    "return lines matching a pattern",
3158    "\
3159 This calls the external C<zgrep> program and returns the
3160 matching lines.");
3161
3162   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3163    [InitISOFS, Always, TestOutputList (
3164       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3165    "return lines matching a pattern",
3166    "\
3167 This calls the external C<zegrep> program and returns the
3168 matching lines.");
3169
3170   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3171    [InitISOFS, Always, TestOutputList (
3172       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3173    "return lines matching a pattern",
3174    "\
3175 This calls the external C<zfgrep> program and returns the
3176 matching lines.");
3177
3178   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3179    [InitISOFS, Always, TestOutputList (
3180       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3181    "return lines matching a pattern",
3182    "\
3183 This calls the external C<zgrep -i> program and returns the
3184 matching lines.");
3185
3186   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3187    [InitISOFS, Always, TestOutputList (
3188       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3189    "return lines matching a pattern",
3190    "\
3191 This calls the external C<zegrep -i> program and returns the
3192 matching lines.");
3193
3194   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3195    [InitISOFS, Always, TestOutputList (
3196       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3197    "return lines matching a pattern",
3198    "\
3199 This calls the external C<zfgrep -i> program and returns the
3200 matching lines.");
3201
3202   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3203    [InitISOFS, Always, TestOutput (
3204       [["realpath"; "/../directory"]], "/directory")],
3205    "canonicalized absolute pathname",
3206    "\
3207 Return the canonicalized absolute pathname of C<path>.  The
3208 returned path has no C<.>, C<..> or symbolic link path elements.");
3209
3210   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3211    [InitBasicFS, Always, TestOutputStruct (
3212       [["touch"; "/a"];
3213        ["ln"; "/a"; "/b"];
3214        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3215    "create a hard link",
3216    "\
3217 This command creates a hard link using the C<ln> command.");
3218
3219   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3220    [InitBasicFS, Always, TestOutputStruct (
3221       [["touch"; "/a"];
3222        ["touch"; "/b"];
3223        ["ln_f"; "/a"; "/b"];
3224        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3225    "create a hard link",
3226    "\
3227 This command creates a hard link using the C<ln -f> command.
3228 The C<-f> option removes the link (C<linkname>) if it exists already.");
3229
3230   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3231    [InitBasicFS, Always, TestOutputStruct (
3232       [["touch"; "/a"];
3233        ["ln_s"; "a"; "/b"];
3234        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3235    "create a symbolic link",
3236    "\
3237 This command creates a symbolic link using the C<ln -s> command.");
3238
3239   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3240    [InitBasicFS, Always, TestOutput (
3241       [["mkdir_p"; "/a/b"];
3242        ["touch"; "/a/b/c"];
3243        ["ln_sf"; "../d"; "/a/b/c"];
3244        ["readlink"; "/a/b/c"]], "../d")],
3245    "create a symbolic link",
3246    "\
3247 This command creates a symbolic link using the C<ln -sf> command,
3248 The C<-f> option removes the link (C<linkname>) if it exists already.");
3249
3250   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3251    [] (* XXX tested above *),
3252    "read the target of a symbolic link",
3253    "\
3254 This command reads the target of a symbolic link.");
3255
3256   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3257    [InitBasicFS, Always, TestOutputStruct (
3258       [["fallocate"; "/a"; "1000000"];
3259        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3260    "preallocate a file in the guest filesystem",
3261    "\
3262 This command preallocates a file (containing zero bytes) named
3263 C<path> of size C<len> bytes.  If the file exists already, it
3264 is overwritten.
3265
3266 Do not confuse this with the guestfish-specific
3267 C<alloc> command which allocates a file in the host and
3268 attaches it as a device.");
3269
3270   ("swapon_device", (RErr, [Device "device"]), 170, [],
3271    [InitPartition, Always, TestRun (
3272       [["mkswap"; "/dev/sda1"];
3273        ["swapon_device"; "/dev/sda1"];
3274        ["swapoff_device"; "/dev/sda1"]])],
3275    "enable swap on device",
3276    "\
3277 This command enables the libguestfs appliance to use the
3278 swap device or partition named C<device>.  The increased
3279 memory is made available for all commands, for example
3280 those run using C<guestfs_command> or C<guestfs_sh>.
3281
3282 Note that you should not swap to existing guest swap
3283 partitions unless you know what you are doing.  They may
3284 contain hibernation information, or other information that
3285 the guest doesn't want you to trash.  You also risk leaking
3286 information about the host to the guest this way.  Instead,
3287 attach a new host device to the guest and swap on that.");
3288
3289   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3290    [], (* XXX tested by swapon_device *)
3291    "disable swap on device",
3292    "\
3293 This command disables the libguestfs appliance swap
3294 device or partition named C<device>.
3295 See C<guestfs_swapon_device>.");
3296
3297   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3298    [InitBasicFS, Always, TestRun (
3299       [["fallocate"; "/swap"; "8388608"];
3300        ["mkswap_file"; "/swap"];
3301        ["swapon_file"; "/swap"];
3302        ["swapoff_file"; "/swap"]])],
3303    "enable swap on file",
3304    "\
3305 This command enables swap to a file.
3306 See C<guestfs_swapon_device> for other notes.");
3307
3308   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3309    [], (* XXX tested by swapon_file *)
3310    "disable swap on file",
3311    "\
3312 This command disables the libguestfs appliance swap on file.");
3313
3314   ("swapon_label", (RErr, [String "label"]), 174, [],
3315    [InitEmpty, Always, TestRun (
3316       [["sfdiskM"; "/dev/sdb"; ","];
3317        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3318        ["swapon_label"; "swapit"];
3319        ["swapoff_label"; "swapit"];
3320        ["zero"; "/dev/sdb"];
3321        ["blockdev_rereadpt"; "/dev/sdb"]])],
3322    "enable swap on labeled swap partition",
3323    "\
3324 This command enables swap to a labeled swap partition.
3325 See C<guestfs_swapon_device> for other notes.");
3326
3327   ("swapoff_label", (RErr, [String "label"]), 175, [],
3328    [], (* XXX tested by swapon_label *)
3329    "disable swap on labeled swap partition",
3330    "\
3331 This command disables the libguestfs appliance swap on
3332 labeled swap partition.");
3333
3334   ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3335    (let uuid = uuidgen () in
3336     [InitEmpty, Always, TestRun (
3337        [["mkswap_U"; uuid; "/dev/sdb"];
3338         ["swapon_uuid"; uuid];
3339         ["swapoff_uuid"; uuid]])]),
3340    "enable swap on swap partition by UUID",
3341    "\
3342 This command enables swap to a swap partition with the given UUID.
3343 See C<guestfs_swapon_device> for other notes.");
3344
3345   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3346    [], (* XXX tested by swapon_uuid *)
3347    "disable swap on swap partition by UUID",
3348    "\
3349 This command disables the libguestfs appliance swap partition
3350 with the given UUID.");
3351
3352   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3353    [InitBasicFS, Always, TestRun (
3354       [["fallocate"; "/swap"; "8388608"];
3355        ["mkswap_file"; "/swap"]])],
3356    "create a swap file",
3357    "\
3358 Create a swap file.
3359
3360 This command just writes a swap file signature to an existing
3361 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3362
3363   ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3364    [InitISOFS, Always, TestRun (
3365       [["inotify_init"; "0"]])],
3366    "create an inotify handle",
3367    "\
3368 This command creates a new inotify handle.
3369 The inotify subsystem can be used to notify events which happen to
3370 objects in the guest filesystem.
3371
3372 C<maxevents> is the maximum number of events which will be
3373 queued up between calls to C<guestfs_inotify_read> or
3374 C<guestfs_inotify_files>.
3375 If this is passed as C<0>, then the kernel (or previously set)
3376 default is used.  For Linux 2.6.29 the default was 16384 events.
3377 Beyond this limit, the kernel throws away events, but records
3378 the fact that it threw them away by setting a flag
3379 C<IN_Q_OVERFLOW> in the returned structure list (see
3380 C<guestfs_inotify_read>).
3381
3382 Before any events are generated, you have to add some
3383 watches to the internal watch list.  See:
3384 C<guestfs_inotify_add_watch>,
3385 C<guestfs_inotify_rm_watch> and
3386 C<guestfs_inotify_watch_all>.
3387
3388 Queued up events should be read periodically by calling
3389 C<guestfs_inotify_read>
3390 (or C<guestfs_inotify_files> which is just a helpful
3391 wrapper around C<guestfs_inotify_read>).  If you don't
3392 read the events out often enough then you risk the internal
3393 queue overflowing.
3394
3395 The handle should be closed after use by calling
3396 C<guestfs_inotify_close>.  This also removes any
3397 watches automatically.
3398
3399 See also L<inotify(7)> for an overview of the inotify interface
3400 as exposed by the Linux kernel, which is roughly what we expose
3401 via libguestfs.  Note that there is one global inotify handle
3402 per libguestfs instance.");
3403
3404   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3405    [InitBasicFS, Always, TestOutputList (
3406       [["inotify_init"; "0"];
3407        ["inotify_add_watch"; "/"; "1073741823"];
3408        ["touch"; "/a"];
3409        ["touch"; "/b"];
3410        ["inotify_files"]], ["a"; "b"])],
3411    "add an inotify watch",
3412    "\
3413 Watch C<path> for the events listed in C<mask>.
3414
3415 Note that if C<path> is a directory then events within that
3416 directory are watched, but this does I<not> happen recursively
3417 (in subdirectories).
3418
3419 Note for non-C or non-Linux callers: the inotify events are
3420 defined by the Linux kernel ABI and are listed in
3421 C</usr/include/sys/inotify.h>.");
3422
3423   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3424    [],
3425    "remove an inotify watch",
3426    "\
3427 Remove a previously defined inotify watch.
3428 See C<guestfs_inotify_add_watch>.");
3429
3430   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3431    [],
3432    "return list of inotify events",
3433    "\
3434 Return the complete queue of events that have happened
3435 since the previous read call.
3436
3437 If no events have happened, this returns an empty list.
3438
3439 I<Note>: In order to make sure that all events have been
3440 read, you must call this function repeatedly until it
3441 returns an empty list.  The reason is that the call will
3442 read events up to the maximum appliance-to-host message
3443 size and leave remaining events in the queue.");
3444
3445   ("inotify_files", (RStringList "paths", []), 183, [],
3446    [],
3447    "return list of watched files that had events",
3448    "\
3449 This function is a helpful wrapper around C<guestfs_inotify_read>
3450 which just returns a list of pathnames of objects that were
3451 touched.  The returned pathnames are sorted and deduplicated.");
3452
3453   ("inotify_close", (RErr, []), 184, [],
3454    [],
3455    "close the inotify handle",
3456    "\
3457 This closes the inotify handle which was previously
3458 opened by inotify_init.  It removes all watches, throws
3459 away any pending events, and deallocates all resources.");
3460
3461   ("setcon", (RErr, [String "context"]), 185, [],
3462    [],
3463    "set SELinux security context",
3464    "\
3465 This sets the SELinux security context of the daemon
3466 to the string C<context>.
3467
3468 See the documentation about SELINUX in L<guestfs(3)>.");
3469
3470   ("getcon", (RString "context", []), 186, [],
3471    [],
3472    "get SELinux security context",
3473    "\
3474 This gets the SELinux security context of the daemon.
3475
3476 See the documentation about SELINUX in L<guestfs(3)>,
3477 and C<guestfs_setcon>");
3478
3479   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3480    [InitEmpty, Always, TestOutput (
3481       [["sfdiskM"; "/dev/sda"; ","];
3482        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3483        ["mount"; "/dev/sda1"; "/"];
3484        ["write_file"; "/new"; "new file contents"; "0"];
3485        ["cat"; "/new"]], "new file contents")],
3486    "make a filesystem with block size",
3487    "\
3488 This call is similar to C<guestfs_mkfs>, but it allows you to
3489 control the block size of the resulting filesystem.  Supported
3490 block sizes depend on the filesystem type, but typically they
3491 are C<1024>, C<2048> or C<4096> only.");
3492
3493   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3494    [InitEmpty, Always, TestOutput (
3495       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3496        ["mke2journal"; "4096"; "/dev/sda1"];
3497        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3498        ["mount"; "/dev/sda2"; "/"];
3499        ["write_file"; "/new"; "new file contents"; "0"];
3500        ["cat"; "/new"]], "new file contents")],
3501    "make ext2/3/4 external journal",
3502    "\
3503 This creates an ext2 external journal on C<device>.  It is equivalent
3504 to the command:
3505
3506  mke2fs -O journal_dev -b blocksize device");
3507
3508   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3509    [InitEmpty, Always, TestOutput (
3510       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3511        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3512        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3513        ["mount"; "/dev/sda2"; "/"];
3514        ["write_file"; "/new"; "new file contents"; "0"];
3515        ["cat"; "/new"]], "new file contents")],
3516    "make ext2/3/4 external journal with label",
3517    "\
3518 This creates an ext2 external journal on C<device> with label C<label>.");
3519
3520   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3521    (let uuid = uuidgen () in
3522     [InitEmpty, Always, TestOutput (
3523        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3524         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3525         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3526         ["mount"; "/dev/sda2"; "/"];
3527         ["write_file"; "/new"; "new file contents"; "0"];
3528         ["cat"; "/new"]], "new file contents")]),
3529    "make ext2/3/4 external journal with UUID",
3530    "\
3531 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3532
3533   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3534    [],
3535    "make ext2/3/4 filesystem with external journal",
3536    "\
3537 This creates an ext2/3/4 filesystem on C<device> with
3538 an external journal on C<journal>.  It is equivalent
3539 to the command:
3540
3541  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3542
3543 See also C<guestfs_mke2journal>.");
3544
3545   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3546    [],
3547    "make ext2/3/4 filesystem with external journal",
3548    "\
3549 This creates an ext2/3/4 filesystem on C<device> with
3550 an external journal on the journal labeled C<label>.
3551
3552 See also C<guestfs_mke2journal_L>.");
3553
3554   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3555    [],
3556    "make ext2/3/4 filesystem with external journal",
3557    "\
3558 This creates an ext2/3/4 filesystem on C<device> with
3559 an external journal on the journal with UUID C<uuid>.
3560
3561 See also C<guestfs_mke2journal_U>.");
3562
3563   ("modprobe", (RErr, [String "modulename"]), 194, [],
3564    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3565    "load a kernel module",
3566    "\
3567 This loads a kernel module in the appliance.
3568
3569 The kernel module must have been whitelisted when libguestfs
3570 was built (see C<appliance/kmod.whitelist.in> in the source).");
3571
3572   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3573    [InitNone, Always, TestOutput (
3574      [["echo_daemon"; "This is a test"]], "This is a test"
3575    )],
3576    "echo arguments back to the client",
3577    "\
3578 This command concatenate the list of C<words> passed with single spaces between
3579 them and returns the resulting string.
3580
3581 You can use this command to test the connection through to the daemon.
3582
3583 See also C<guestfs_ping_daemon>.");
3584
3585 ]
3586
3587 let all_functions = non_daemon_functions @ daemon_functions
3588
3589 (* In some places we want the functions to be displayed sorted
3590  * alphabetically, so this is useful:
3591  *)
3592 let all_functions_sorted =
3593   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3594                compare n1 n2) all_functions
3595
3596 (* Field types for structures. *)
3597 type field =
3598   | FChar                       (* C 'char' (really, a 7 bit byte). *)
3599   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
3600   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
3601   | FUInt32
3602   | FInt32
3603   | FUInt64
3604   | FInt64
3605   | FBytes                      (* Any int measure that counts bytes. *)
3606   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
3607   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
3608
3609 (* Because we generate extra parsing code for LVM command line tools,
3610  * we have to pull out the LVM columns separately here.
3611  *)
3612 let lvm_pv_cols = [
3613   "pv_name", FString;
3614   "pv_uuid", FUUID;
3615   "pv_fmt", FString;
3616   "pv_size", FBytes;
3617   "dev_size", FBytes;
3618   "pv_free", FBytes;
3619   "pv_used", FBytes;
3620   "pv_attr", FString (* XXX *);
3621   "pv_pe_count", FInt64;
3622   "pv_pe_alloc_count", FInt64;
3623   "pv_tags", FString;
3624   "pe_start", FBytes;
3625   "pv_mda_count", FInt64;
3626   "pv_mda_free", FBytes;
3627   (* Not in Fedora 10:
3628      "pv_mda_size", FBytes;
3629   *)
3630 ]
3631 let lvm_vg_cols = [
3632   "vg_name", FString;
3633   "vg_uuid", FUUID;
3634   "vg_fmt", FString;
3635   "vg_attr", FString (* XXX *);
3636   "vg_size", FBytes;
3637   "vg_free", FBytes;
3638   "vg_sysid", FString;
3639   "vg_extent_size", FBytes;
3640   "vg_extent_count", FInt64;
3641   "vg_free_count", FInt64;
3642   "max_lv", FInt64;
3643   "max_pv", FInt64;
3644   "pv_count", FInt64;
3645   "lv_count", FInt64;
3646   "snap_count", FInt64;
3647   "vg_seqno", FInt64;
3648   "vg_tags", FString;
3649   "vg_mda_count", FInt64;
3650   "vg_mda_free", FBytes;
3651   (* Not in Fedora 10:
3652      "vg_mda_size", FBytes;
3653   *)
3654 ]
3655 let lvm_lv_cols = [
3656   "lv_name", FString;
3657   "lv_uuid", FUUID;
3658   "lv_attr", FString (* XXX *);
3659   "lv_major", FInt64;
3660   "lv_minor", FInt64;
3661   "lv_kernel_major", FInt64;
3662   "lv_kernel_minor", FInt64;
3663   "lv_size", FBytes;
3664   "seg_count", FInt64;
3665   "origin", FString;
3666   "snap_percent", FOptPercent;
3667   "copy_percent", FOptPercent;
3668   "move_pv", FString;
3669   "lv_tags", FString;
3670   "mirror_log", FString;
3671   "modules", FString;
3672 ]
3673
3674 (* Names and fields in all structures (in RStruct and RStructList)
3675  * that we support.
3676  *)
3677 let structs = [
3678   (* The old RIntBool return type, only ever used for aug_defnode.  Do
3679    * not use this struct in any new code.
3680    *)
3681   "int_bool", [
3682     "i", FInt32;                (* for historical compatibility *)
3683     "b", FInt32;                (* for historical compatibility *)
3684   ];
3685
3686   (* LVM PVs, VGs, LVs. *)
3687   "lvm_pv", lvm_pv_cols;
3688   "lvm_vg", lvm_vg_cols;
3689   "lvm_lv", lvm_lv_cols;
3690
3691   (* Column names and types from stat structures.
3692    * NB. Can't use things like 'st_atime' because glibc header files
3693    * define some of these as macros.  Ugh.
3694    *)
3695   "stat", [
3696     "dev", FInt64;
3697     "ino", FInt64;
3698     "mode", FInt64;
3699     "nlink", FInt64;
3700     "uid", FInt64;
3701     "gid", FInt64;
3702     "rdev", FInt64;
3703     "size", FInt64;
3704     "blksize", FInt64;
3705     "blocks", FInt64;
3706     "atime", FInt64;
3707     "mtime", FInt64;
3708     "ctime", FInt64;
3709   ];
3710   "statvfs", [
3711     "bsize", FInt64;
3712     "frsize", FInt64;
3713     "blocks", FInt64;
3714     "bfree", FInt64;
3715     "bavail", FInt64;
3716     "files", FInt64;
3717     "ffree", FInt64;
3718     "favail", FInt64;
3719     "fsid", FInt64;
3720     "flag", FInt64;
3721     "namemax", FInt64;
3722   ];
3723
3724   (* Column names in dirent structure. *)
3725   "dirent", [
3726     "ino", FInt64;
3727     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
3728     "ftyp", FChar;
3729     "name", FString;
3730   ];
3731
3732   (* Version numbers. *)
3733   "version", [
3734     "major", FInt64;
3735     "minor", FInt64;
3736     "release", FInt64;
3737     "extra", FString;
3738   ];
3739
3740   (* Extended attribute. *)
3741   "xattr", [
3742     "attrname", FString;
3743     "attrval", FBuffer;
3744   ];
3745
3746   (* Inotify events. *)
3747   "inotify_event", [
3748     "in_wd", FInt64;
3749     "in_mask", FUInt32;
3750     "in_cookie", FUInt32;
3751     "in_name", FString;
3752   ];
3753 ] (* end of structs *)
3754
3755 (* Ugh, Java has to be different ..
3756  * These names are also used by the Haskell bindings.
3757  *)
3758 let java_structs = [
3759   "int_bool", "IntBool";
3760   "lvm_pv", "PV";
3761   "lvm_vg", "VG";
3762   "lvm_lv", "LV";
3763   "stat", "Stat";
3764   "statvfs", "StatVFS";
3765   "dirent", "Dirent";
3766   "version", "Version";
3767   "xattr", "XAttr";
3768   "inotify_event", "INotifyEvent";
3769 ]
3770
3771 (* What structs are actually returned. *)
3772 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
3773
3774 (* Returns a list of RStruct/RStructList structs that are returned
3775  * by any function.  Each element of returned list is a pair:
3776  *
3777  * (structname, RStructOnly)
3778  *    == there exists function which returns RStruct (_, structname)
3779  * (structname, RStructListOnly)
3780  *    == there exists function which returns RStructList (_, structname)
3781  * (structname, RStructAndList)
3782  *    == there are functions returning both RStruct (_, structname)
3783  *                                      and RStructList (_, structname)
3784  *)
3785 let rstructs_used =
3786   (* ||| is a "logical OR" for rstructs_used_t *)
3787   let (|||) a b =
3788     match a, b with
3789     | RStructAndList, _
3790     | _, RStructAndList -> RStructAndList
3791     | RStructOnly, RStructListOnly
3792     | RStructListOnly, RStructOnly -> RStructAndList
3793     | RStructOnly, RStructOnly -> RStructOnly
3794     | RStructListOnly, RStructListOnly -> RStructListOnly
3795   in
3796
3797   let h = Hashtbl.create 13 in
3798
3799   (* if elem->oldv exists, update entry using ||| operator,
3800    * else just add elem->newv to the hash
3801    *)
3802   let update elem newv =
3803     try  let oldv = Hashtbl.find h elem in
3804          Hashtbl.replace h elem (newv ||| oldv)
3805     with Not_found -> Hashtbl.add h elem newv
3806   in
3807
3808   List.iter (
3809     fun (_, style, _, _, _, _, _) ->
3810       match fst style with
3811       | RStruct (_, structname) -> update structname RStructOnly
3812       | RStructList (_, structname) -> update structname RStructListOnly
3813       | _ -> ()
3814   ) all_functions;
3815
3816   (* return key->values as a list of (key,value) *)
3817   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
3818
3819 (* debug:
3820 let () =
3821   List.iter (
3822     function
3823     | sn, RStructOnly -> printf "%s RStructOnly\n" sn
3824     | sn, RStructListOnly -> printf "%s RStructListOnly\n" sn
3825     | sn, RStructAndList -> printf "%s RStructAndList\n" sn
3826   ) rstructs_used
3827 *)
3828
3829 (* Used for testing language bindings. *)
3830 type callt =
3831   | CallString of string
3832   | CallOptString of string option
3833   | CallStringList of string list
3834   | CallInt of int
3835   | CallBool of bool
3836
3837 (* Used to memoize the result of pod2text. *)
3838 let pod2text_memo_filename = "src/.pod2text.data"
3839 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
3840   try
3841     let chan = open_in pod2text_memo_filename in
3842     let v = input_value chan in
3843     close_in chan;
3844     v
3845   with
3846     _ -> Hashtbl.create 13
3847 let pod2text_memo_updated () =
3848   let chan = open_out pod2text_memo_filename in
3849   output_value chan pod2text_memo;
3850   close_out chan
3851
3852 (* Useful functions.
3853  * Note we don't want to use any external OCaml libraries which
3854  * makes this a bit harder than it should be.
3855  *)
3856 let failwithf fs = ksprintf failwith fs
3857
3858 let replace_char s c1 c2 =
3859   let s2 = String.copy s in
3860   let r = ref false in
3861   for i = 0 to String.length s2 - 1 do
3862     if String.unsafe_get s2 i = c1 then (
3863       String.unsafe_set s2 i c2;
3864       r := true
3865     )
3866   done;
3867   if not !r then s else s2
3868
3869 let isspace c =
3870   c = ' '
3871   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
3872
3873 let triml ?(test = isspace) str =
3874   let i = ref 0 in
3875   let n = ref (String.length str) in
3876   while !n > 0 && test str.[!i]; do
3877     decr n;
3878     incr i
3879   done;
3880   if !i = 0 then str
3881   else String.sub str !i !n
3882
3883 let trimr ?(test = isspace) str =
3884   let n = ref (String.length str) in
3885   while !n > 0 && test str.[!n-1]; do
3886     decr n
3887   done;
3888   if !n = String.length str then str
3889   else String.sub str 0 !n
3890
3891 let trim ?(test = isspace) str =
3892   trimr ~test (triml ~test str)
3893
3894 let rec find s sub =
3895   let len = String.length s in
3896   let sublen = String.length sub in
3897   let rec loop i =
3898     if i <= len-sublen then (
3899       let rec loop2 j =
3900         if j < sublen then (
3901           if s.[i+j] = sub.[j] then loop2 (j+1)
3902           else -1
3903         ) else
3904           i (* found *)
3905       in
3906       let r = loop2 0 in
3907       if r = -1 then loop (i+1) else r
3908     ) else
3909       -1 (* not found *)
3910   in
3911   loop 0
3912
3913 let rec replace_str s s1 s2 =
3914   let len = String.length s in
3915   let sublen = String.length s1 in
3916   let i = find s s1 in
3917   if i = -1 then s
3918   else (
3919     let s' = String.sub s 0 i in
3920     let s'' = String.sub s (i+sublen) (len-i-sublen) in
3921     s' ^ s2 ^ replace_str s'' s1 s2
3922   )
3923
3924 let rec string_split sep str =
3925   let len = String.length str in
3926   let seplen = String.length sep in
3927   let i = find str sep in
3928   if i = -1 then [str]
3929   else (
3930     let s' = String.sub str 0 i in
3931     let s'' = String.sub str (i+seplen) (len-i-seplen) in
3932     s' :: string_split sep s''
3933   )
3934
3935 let files_equal n1 n2 =
3936   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
3937   match Sys.command cmd with
3938   | 0 -> true
3939   | 1 -> false
3940   | i -> failwithf "%s: failed with error code %d" cmd i
3941
3942 let rec filter_map f = function
3943   | [] -> []
3944   | x :: xs ->
3945       match f x with
3946       | Some y -> y :: filter_map f xs
3947       | None -> filter_map f xs
3948
3949 let rec find_map f = function
3950   | [] -> raise Not_found
3951   | x :: xs ->
3952       match f x with
3953       | Some y -> y
3954       | None -> find_map f xs
3955
3956 let iteri f xs =
3957   let rec loop i = function
3958     | [] -> ()
3959     | x :: xs -> f i x; loop (i+1) xs
3960   in
3961   loop 0 xs
3962
3963 let mapi f xs =
3964   let rec loop i = function
3965     | [] -> []
3966     | x :: xs -> let r = f i x in r :: loop (i+1) xs
3967   in
3968   loop 0 xs
3969
3970 let name_of_argt = function
3971   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
3972   | StringList n | DeviceList n | Bool n | Int n
3973   | FileIn n | FileOut n -> n
3974
3975 let java_name_of_struct typ =
3976   try List.assoc typ java_structs
3977   with Not_found ->
3978     failwithf
3979       "java_name_of_struct: no java_structs entry corresponding to %s" typ
3980
3981 let cols_of_struct typ =
3982   try List.assoc typ structs
3983   with Not_found ->
3984     failwithf "cols_of_struct: unknown struct %s" typ
3985
3986 let seq_of_test = function
3987   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
3988   | TestOutputListOfDevices (s, _)
3989   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
3990   | TestOutputTrue s | TestOutputFalse s
3991   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
3992   | TestOutputStruct (s, _)
3993   | TestLastFail s -> s
3994
3995 (* Handling for function flags. *)
3996 let protocol_limit_warning =
3997   "Because of the message protocol, there is a transfer limit
3998 of somewhere between 2MB and 4MB.  To transfer large files you should use
3999 FTP."
4000
4001 let danger_will_robinson =
4002   "B<This command is dangerous.  Without careful use you
4003 can easily destroy all your data>."
4004
4005 let deprecation_notice flags =
4006   try
4007     let alt =
4008       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4009     let txt =
4010       sprintf "This function is deprecated.
4011 In new code, use the C<%s> call instead.
4012
4013 Deprecated functions will not be removed from the API, but the
4014 fact that they are deprecated indicates that there are problems
4015 with correct use of these functions." alt in
4016     Some txt
4017   with
4018     Not_found -> None
4019
4020 (* Check function names etc. for consistency. *)
4021 let check_functions () =
4022   let contains_uppercase str =
4023     let len = String.length str in
4024     let rec loop i =
4025       if i >= len then false
4026       else (
4027         let c = str.[i] in
4028         if c >= 'A' && c <= 'Z' then true
4029         else loop (i+1)
4030       )
4031     in
4032     loop 0
4033   in
4034
4035   (* Check function names. *)
4036   List.iter (
4037     fun (name, _, _, _, _, _, _) ->
4038       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4039         failwithf "function name %s does not need 'guestfs' prefix" name;
4040       if name = "" then
4041         failwithf "function name is empty";
4042       if name.[0] < 'a' || name.[0] > 'z' then
4043         failwithf "function name %s must start with lowercase a-z" name;
4044       if String.contains name '-' then
4045         failwithf "function name %s should not contain '-', use '_' instead."
4046           name
4047   ) all_functions;
4048
4049   (* Check function parameter/return names. *)
4050   List.iter (
4051     fun (name, style, _, _, _, _, _) ->
4052       let check_arg_ret_name n =
4053         if contains_uppercase n then
4054           failwithf "%s param/ret %s should not contain uppercase chars"
4055             name n;
4056         if String.contains n '-' || String.contains n '_' then
4057           failwithf "%s param/ret %s should not contain '-' or '_'"
4058             name n;
4059         if n = "value" then
4060           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;
4061         if n = "int" || n = "char" || n = "short" || n = "long" then
4062           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4063         if n = "i" || n = "n" then
4064           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4065         if n = "argv" || n = "args" then
4066           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4067
4068         (* List Haskell, OCaml and C keywords here.
4069          * http://www.haskell.org/haskellwiki/Keywords
4070          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4071          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4072          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4073          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4074          * Omitting _-containing words, since they're handled above.
4075          * Omitting the OCaml reserved word, "val", is ok,
4076          * and saves us from renaming several parameters.
4077          *)
4078         let reserved = [
4079           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4080           "char"; "class"; "const"; "constraint"; "continue"; "data";
4081           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4082           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4083           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4084           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4085           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4086           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4087           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4088           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4089           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4090           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4091           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4092           "volatile"; "when"; "where"; "while";
4093           ] in
4094         if List.mem n reserved then
4095           failwithf "%s has param/ret using reserved word %s" name n;
4096       in
4097
4098       (match fst style with
4099        | RErr -> ()
4100        | RInt n | RInt64 n | RBool n
4101        | RConstString n | RConstOptString n | RString n
4102        | RStringList n | RStruct (n, _) | RStructList (n, _)
4103        | RHashtable n | RBufferOut n ->
4104            check_arg_ret_name n
4105       );
4106       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4107   ) all_functions;
4108
4109   (* Check short descriptions. *)
4110   List.iter (
4111     fun (name, _, _, _, _, shortdesc, _) ->
4112       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4113         failwithf "short description of %s should begin with lowercase." name;
4114       let c = shortdesc.[String.length shortdesc-1] in
4115       if c = '\n' || c = '.' then
4116         failwithf "short description of %s should not end with . or \\n." name
4117   ) all_functions;
4118
4119   (* Check long dscriptions. *)
4120   List.iter (
4121     fun (name, _, _, _, _, _, longdesc) ->
4122       if longdesc.[String.length longdesc-1] = '\n' then
4123         failwithf "long description of %s should not end with \\n." name
4124   ) all_functions;
4125
4126   (* Check proc_nrs. *)
4127   List.iter (
4128     fun (name, _, proc_nr, _, _, _, _) ->
4129       if proc_nr <= 0 then
4130         failwithf "daemon function %s should have proc_nr > 0" name
4131   ) daemon_functions;
4132
4133   List.iter (
4134     fun (name, _, proc_nr, _, _, _, _) ->
4135       if proc_nr <> -1 then
4136         failwithf "non-daemon function %s should have proc_nr -1" name
4137   ) non_daemon_functions;
4138
4139   let proc_nrs =
4140     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4141       daemon_functions in
4142   let proc_nrs =
4143     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4144   let rec loop = function
4145     | [] -> ()
4146     | [_] -> ()
4147     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4148         loop rest
4149     | (name1,nr1) :: (name2,nr2) :: _ ->
4150         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4151           name1 name2 nr1 nr2
4152   in
4153   loop proc_nrs;
4154
4155   (* Check tests. *)
4156   List.iter (
4157     function
4158       (* Ignore functions that have no tests.  We generate a
4159        * warning when the user does 'make check' instead.
4160        *)
4161     | name, _, _, _, [], _, _ -> ()
4162     | name, _, _, _, tests, _, _ ->
4163         let funcs =
4164           List.map (
4165             fun (_, _, test) ->
4166               match seq_of_test test with
4167               | [] ->
4168                   failwithf "%s has a test containing an empty sequence" name
4169               | cmds -> List.map List.hd cmds
4170           ) tests in
4171         let funcs = List.flatten funcs in
4172
4173         let tested = List.mem name funcs in
4174
4175         if not tested then
4176           failwithf "function %s has tests but does not test itself" name
4177   ) all_functions
4178
4179 (* 'pr' prints to the current output file. *)
4180 let chan = ref stdout
4181 let pr fs = ksprintf (output_string !chan) fs
4182
4183 (* Generate a header block in a number of standard styles. *)
4184 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4185 type license = GPLv2 | LGPLv2
4186
4187 let generate_header comment license =
4188   let c = match comment with
4189     | CStyle ->     pr "/* "; " *"
4190     | HashStyle ->  pr "# ";  "#"
4191     | OCamlStyle -> pr "(* "; " *"
4192     | HaskellStyle -> pr "{- "; "  " in
4193   pr "libguestfs generated file\n";
4194   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4195   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4196   pr "%s\n" c;
4197   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4198   pr "%s\n" c;
4199   (match license with
4200    | GPLv2 ->
4201        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4202        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4203        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4204        pr "%s (at your option) any later version.\n" c;
4205        pr "%s\n" c;
4206        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4207        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4208        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4209        pr "%s GNU General Public License for more details.\n" c;
4210        pr "%s\n" c;
4211        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4212        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4213        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4214
4215    | LGPLv2 ->
4216        pr "%s This library is free software; you can redistribute it and/or\n" c;
4217        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4218        pr "%s License as published by the Free Software Foundation; either\n" c;
4219        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4220        pr "%s\n" c;
4221        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4222        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4223        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4224        pr "%s Lesser General Public License for more details.\n" c;
4225        pr "%s\n" c;
4226        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4227        pr "%s License along with this library; if not, write to the Free Software\n" c;
4228        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4229   );
4230   (match comment with
4231    | CStyle -> pr " */\n"
4232    | HashStyle -> ()
4233    | OCamlStyle -> pr " *)\n"
4234    | HaskellStyle -> pr "-}\n"
4235   );
4236   pr "\n"
4237
4238 (* Start of main code generation functions below this line. *)
4239
4240 (* Generate the pod documentation for the C API. *)
4241 let rec generate_actions_pod () =
4242   List.iter (
4243     fun (shortname, style, _, flags, _, _, longdesc) ->
4244       if not (List.mem NotInDocs flags) then (
4245         let name = "guestfs_" ^ shortname in
4246         pr "=head2 %s\n\n" name;
4247         pr " ";
4248         generate_prototype ~extern:false ~handle:"handle" name style;
4249         pr "\n\n";
4250         pr "%s\n\n" longdesc;
4251         (match fst style with
4252          | RErr ->
4253              pr "This function returns 0 on success or -1 on error.\n\n"
4254          | RInt _ ->
4255              pr "On error this function returns -1.\n\n"
4256          | RInt64 _ ->
4257              pr "On error this function returns -1.\n\n"
4258          | RBool _ ->
4259              pr "This function returns a C truth value on success or -1 on error.\n\n"
4260          | RConstString _ ->
4261              pr "This function returns a string, or NULL on error.
4262 The string is owned by the guest handle and must I<not> be freed.\n\n"
4263          | RConstOptString _ ->
4264              pr "This function returns a string which may be NULL.
4265 There is way to return an error from this function.
4266 The string is owned by the guest handle and must I<not> be freed.\n\n"
4267          | RString _ ->
4268              pr "This function returns a string, or NULL on error.
4269 I<The caller must free the returned string after use>.\n\n"
4270          | RStringList _ ->
4271              pr "This function returns a NULL-terminated array of strings
4272 (like L<environ(3)>), or NULL if there was an error.
4273 I<The caller must free the strings and the array after use>.\n\n"
4274          | RStruct (_, typ) ->
4275              pr "This function returns a C<struct guestfs_%s *>,
4276 or NULL if there was an error.
4277 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4278          | RStructList (_, typ) ->
4279              pr "This function returns a C<struct guestfs_%s_list *>
4280 (see E<lt>guestfs-structs.hE<gt>),
4281 or NULL if there was an error.
4282 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4283          | RHashtable _ ->
4284              pr "This function returns a NULL-terminated array of
4285 strings, or NULL if there was an error.
4286 The array of strings will always have length C<2n+1>, where
4287 C<n> keys and values alternate, followed by the trailing NULL entry.
4288 I<The caller must free the strings and the array after use>.\n\n"
4289          | RBufferOut _ ->
4290              pr "This function returns a buffer, or NULL on error.
4291 The size of the returned buffer is written to C<*size_r>.
4292 I<The caller must free the returned buffer after use>.\n\n"
4293         );
4294         if List.mem ProtocolLimitWarning flags then
4295           pr "%s\n\n" protocol_limit_warning;
4296         if List.mem DangerWillRobinson flags then
4297           pr "%s\n\n" danger_will_robinson;
4298         match deprecation_notice flags with
4299         | None -> ()
4300         | Some txt -> pr "%s\n\n" txt
4301       )
4302   ) all_functions_sorted
4303
4304 and generate_structs_pod () =
4305   (* Structs documentation. *)
4306   List.iter (
4307     fun (typ, cols) ->
4308       pr "=head2 guestfs_%s\n" typ;
4309       pr "\n";
4310       pr " struct guestfs_%s {\n" typ;
4311       List.iter (
4312         function
4313         | name, FChar -> pr "   char %s;\n" name
4314         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4315         | name, FInt32 -> pr "   int32_t %s;\n" name
4316         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4317         | name, FInt64 -> pr "   int64_t %s;\n" name
4318         | name, FString -> pr "   char *%s;\n" name
4319         | name, FBuffer ->
4320             pr "   /* The next two fields describe a byte array. */\n";
4321             pr "   uint32_t %s_len;\n" name;
4322             pr "   char *%s;\n" name
4323         | name, FUUID ->
4324             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4325             pr "   char %s[32];\n" name
4326         | name, FOptPercent ->
4327             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4328             pr "   float %s;\n" name
4329       ) cols;
4330       pr " };\n";
4331       pr " \n";
4332       pr " struct guestfs_%s_list {\n" typ;
4333       pr "   uint32_t len; /* Number of elements in list. */\n";
4334       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4335       pr " };\n";
4336       pr " \n";
4337       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4338       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4339         typ typ;
4340       pr "\n"
4341   ) structs
4342
4343 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4344  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4345  *
4346  * We have to use an underscore instead of a dash because otherwise
4347  * rpcgen generates incorrect code.
4348  *
4349  * This header is NOT exported to clients, but see also generate_structs_h.
4350  *)
4351 and generate_xdr () =
4352   generate_header CStyle LGPLv2;
4353
4354   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4355   pr "typedef string str<>;\n";
4356   pr "\n";
4357
4358   (* Internal structures. *)
4359   List.iter (
4360     function
4361     | typ, cols ->
4362         pr "struct guestfs_int_%s {\n" typ;
4363         List.iter (function
4364                    | name, FChar -> pr "  char %s;\n" name
4365                    | name, FString -> pr "  string %s<>;\n" name
4366                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4367                    | name, FUUID -> pr "  opaque %s[32];\n" name
4368                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4369                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4370                    | name, FOptPercent -> pr "  float %s;\n" name
4371                   ) cols;
4372         pr "};\n";
4373         pr "\n";
4374         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4375         pr "\n";
4376   ) structs;
4377
4378   List.iter (
4379     fun (shortname, style, _, _, _, _, _) ->
4380       let name = "guestfs_" ^ shortname in
4381
4382       (match snd style with
4383        | [] -> ()
4384        | args ->
4385            pr "struct %s_args {\n" name;
4386            List.iter (
4387              function
4388              | Pathname n | Device n | Dev_or_Path n | String n -> pr "  string %s<>;\n" n
4389              | OptString n -> pr "  str *%s;\n" n
4390              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
4391              | Bool n -> pr "  bool %s;\n" n
4392              | Int n -> pr "  int %s;\n" n
4393              | FileIn _ | FileOut _ -> ()
4394            ) args;
4395            pr "};\n\n"
4396       );
4397       (match fst style with
4398        | RErr -> ()
4399        | RInt n ->
4400            pr "struct %s_ret {\n" name;
4401            pr "  int %s;\n" n;
4402            pr "};\n\n"
4403        | RInt64 n ->
4404            pr "struct %s_ret {\n" name;
4405            pr "  hyper %s;\n" n;
4406            pr "};\n\n"
4407        | RBool n ->
4408            pr "struct %s_ret {\n" name;
4409            pr "  bool %s;\n" n;
4410            pr "};\n\n"
4411        | RConstString _ | RConstOptString _ ->
4412            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4413        | RString n ->
4414            pr "struct %s_ret {\n" name;
4415            pr "  string %s<>;\n" n;
4416            pr "};\n\n"
4417        | RStringList n ->
4418            pr "struct %s_ret {\n" name;
4419            pr "  str %s<>;\n" n;
4420            pr "};\n\n"
4421        | RStruct (n, typ) ->
4422            pr "struct %s_ret {\n" name;
4423            pr "  guestfs_int_%s %s;\n" typ n;
4424            pr "};\n\n"
4425        | RStructList (n, typ) ->
4426            pr "struct %s_ret {\n" name;
4427            pr "  guestfs_int_%s_list %s;\n" typ n;
4428            pr "};\n\n"
4429        | RHashtable n ->
4430            pr "struct %s_ret {\n" name;
4431            pr "  str %s<>;\n" n;
4432            pr "};\n\n"
4433        | RBufferOut n ->
4434            pr "struct %s_ret {\n" name;
4435            pr "  opaque %s<>;\n" n;
4436            pr "};\n\n"
4437       );
4438   ) daemon_functions;
4439
4440   (* Table of procedure numbers. *)
4441   pr "enum guestfs_procedure {\n";
4442   List.iter (
4443     fun (shortname, _, proc_nr, _, _, _, _) ->
4444       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4445   ) daemon_functions;
4446   pr "  GUESTFS_PROC_NR_PROCS\n";
4447   pr "};\n";
4448   pr "\n";
4449
4450   (* Having to choose a maximum message size is annoying for several
4451    * reasons (it limits what we can do in the API), but it (a) makes
4452    * the protocol a lot simpler, and (b) provides a bound on the size
4453    * of the daemon which operates in limited memory space.  For large
4454    * file transfers you should use FTP.
4455    *)
4456   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4457   pr "\n";
4458
4459   (* Message header, etc. *)
4460   pr "\
4461 /* The communication protocol is now documented in the guestfs(3)
4462  * manpage.
4463  */
4464
4465 const GUESTFS_PROGRAM = 0x2000F5F5;
4466 const GUESTFS_PROTOCOL_VERSION = 1;
4467
4468 /* These constants must be larger than any possible message length. */
4469 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4470 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4471
4472 enum guestfs_message_direction {
4473   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
4474   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
4475 };
4476
4477 enum guestfs_message_status {
4478   GUESTFS_STATUS_OK = 0,
4479   GUESTFS_STATUS_ERROR = 1
4480 };
4481
4482 const GUESTFS_ERROR_LEN = 256;
4483
4484 struct guestfs_message_error {
4485   string error_message<GUESTFS_ERROR_LEN>;
4486 };
4487
4488 struct guestfs_message_header {
4489   unsigned prog;                     /* GUESTFS_PROGRAM */
4490   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
4491   guestfs_procedure proc;            /* GUESTFS_PROC_x */
4492   guestfs_message_direction direction;
4493   unsigned serial;                   /* message serial number */
4494   guestfs_message_status status;
4495 };
4496
4497 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4498
4499 struct guestfs_chunk {
4500   int cancel;                        /* if non-zero, transfer is cancelled */
4501   /* data size is 0 bytes if the transfer has finished successfully */
4502   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4503 };
4504 "
4505
4506 (* Generate the guestfs-structs.h file. *)
4507 and generate_structs_h () =
4508   generate_header CStyle LGPLv2;
4509
4510   (* This is a public exported header file containing various
4511    * structures.  The structures are carefully written to have
4512    * exactly the same in-memory format as the XDR structures that
4513    * we use on the wire to the daemon.  The reason for creating
4514    * copies of these structures here is just so we don't have to
4515    * export the whole of guestfs_protocol.h (which includes much
4516    * unrelated and XDR-dependent stuff that we don't want to be
4517    * public, or required by clients).
4518    *
4519    * To reiterate, we will pass these structures to and from the
4520    * client with a simple assignment or memcpy, so the format
4521    * must be identical to what rpcgen / the RFC defines.
4522    *)
4523
4524   (* Public structures. *)
4525   List.iter (
4526     fun (typ, cols) ->
4527       pr "struct guestfs_%s {\n" typ;
4528       List.iter (
4529         function
4530         | name, FChar -> pr "  char %s;\n" name
4531         | name, FString -> pr "  char *%s;\n" name
4532         | name, FBuffer ->
4533             pr "  uint32_t %s_len;\n" name;
4534             pr "  char *%s;\n" name
4535         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4536         | name, FUInt32 -> pr "  uint32_t %s;\n" name
4537         | name, FInt32 -> pr "  int32_t %s;\n" name
4538         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
4539         | name, FInt64 -> pr "  int64_t %s;\n" name
4540         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
4541       ) cols;
4542       pr "};\n";
4543       pr "\n";
4544       pr "struct guestfs_%s_list {\n" typ;
4545       pr "  uint32_t len;\n";
4546       pr "  struct guestfs_%s *val;\n" typ;
4547       pr "};\n";
4548       pr "\n";
4549       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4550       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4551       pr "\n"
4552   ) structs
4553
4554 (* Generate the guestfs-actions.h file. *)
4555 and generate_actions_h () =
4556   generate_header CStyle LGPLv2;
4557   List.iter (
4558     fun (shortname, style, _, _, _, _, _) ->
4559       let name = "guestfs_" ^ shortname in
4560       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4561         name style
4562   ) all_functions
4563
4564 (* Generate the guestfs-internal-actions.h file. *)
4565 and generate_internal_actions_h () =
4566   generate_header CStyle LGPLv2;
4567   List.iter (
4568     fun (shortname, style, _, _, _, _, _) ->
4569       let name = "guestfs__" ^ shortname in
4570       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4571         name style
4572   ) non_daemon_functions
4573
4574 (* Generate the client-side dispatch stubs. *)
4575 and generate_client_actions () =
4576   generate_header CStyle LGPLv2;
4577
4578   pr "\
4579 #include <stdio.h>
4580 #include <stdlib.h>
4581
4582 #include \"guestfs.h\"
4583 #include \"guestfs-internal-actions.h\"
4584 #include \"guestfs_protocol.h\"
4585
4586 #define error guestfs_error
4587 //#define perrorf guestfs_perrorf
4588 //#define safe_malloc guestfs_safe_malloc
4589 #define safe_realloc guestfs_safe_realloc
4590 //#define safe_strdup guestfs_safe_strdup
4591 #define safe_memdup guestfs_safe_memdup
4592
4593 /* Check the return message from a call for validity. */
4594 static int
4595 check_reply_header (guestfs_h *g,
4596                     const struct guestfs_message_header *hdr,
4597                     unsigned int proc_nr, unsigned int serial)
4598 {
4599   if (hdr->prog != GUESTFS_PROGRAM) {
4600     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4601     return -1;
4602   }
4603   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4604     error (g, \"wrong protocol version (%%d/%%d)\",
4605            hdr->vers, GUESTFS_PROTOCOL_VERSION);
4606     return -1;
4607   }
4608   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4609     error (g, \"unexpected message direction (%%d/%%d)\",
4610            hdr->direction, GUESTFS_DIRECTION_REPLY);
4611     return -1;
4612   }
4613   if (hdr->proc != proc_nr) {
4614     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4615     return -1;
4616   }
4617   if (hdr->serial != serial) {
4618     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4619     return -1;
4620   }
4621
4622   return 0;
4623 }
4624
4625 /* Check we are in the right state to run a high-level action. */
4626 static int
4627 check_state (guestfs_h *g, const char *caller)
4628 {
4629   if (!guestfs_is_ready (g)) {
4630     if (guestfs_is_config (g))
4631       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4632         caller);
4633     else if (guestfs_is_launching (g))
4634       error (g, \"%%s: call wait_ready() before using this function\",
4635         caller);
4636     else
4637       error (g, \"%%s called from the wrong state, %%d != READY\",
4638         caller, guestfs_get_state (g));
4639     return -1;
4640   }
4641   return 0;
4642 }
4643
4644 ";
4645
4646   (* For non-daemon functions, generate a wrapper around each function. *)
4647   List.iter (
4648     fun (shortname, style, _, _, _, _, _) ->
4649       let name = "guestfs_" ^ shortname in
4650
4651       generate_prototype ~extern:false ~semicolon:false ~newline:true
4652         ~handle:"g" name style;
4653       pr "{\n";
4654       pr "  return guestfs__%s " shortname;
4655       generate_c_call_args ~handle:"g" style;
4656       pr ";\n";
4657       pr "}\n";
4658       pr "\n"
4659   ) non_daemon_functions;
4660
4661   (* Client-side stubs for each function. *)
4662   List.iter (
4663     fun (shortname, style, _, _, _, _, _) ->
4664       let name = "guestfs_" ^ shortname in
4665
4666       (* Generate the context struct which stores the high-level
4667        * state between callback functions.
4668        *)
4669       pr "struct %s_ctx {\n" shortname;
4670       pr "  /* This flag is set by the callbacks, so we know we've done\n";
4671       pr "   * the callbacks as expected, and in the right sequence.\n";
4672       pr "   * 0 = not called, 1 = reply_cb called.\n";
4673       pr "   */\n";
4674       pr "  int cb_sequence;\n";
4675       pr "  struct guestfs_message_header hdr;\n";
4676       pr "  struct guestfs_message_error err;\n";
4677       (match fst style with
4678        | RErr -> ()
4679        | RConstString _ | RConstOptString _ ->
4680            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4681        | RInt _ | RInt64 _
4682        | RBool _ | RString _ | RStringList _
4683        | RStruct _ | RStructList _
4684        | RHashtable _ | RBufferOut _ ->
4685            pr "  struct %s_ret ret;\n" name
4686       );
4687       pr "};\n";
4688       pr "\n";
4689
4690       (* Generate the reply callback function. *)
4691       pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
4692       pr "{\n";
4693       pr "  guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4694       pr "  struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname;
4695       pr "\n";
4696       pr "  /* This should definitely not happen. */\n";
4697       pr "  if (ctx->cb_sequence != 0) {\n";
4698       pr "    ctx->cb_sequence = 9999;\n";
4699       pr "    error (g, \"%%s: internal error: reply callback called twice\", \"%s\");\n" name;
4700       pr "    return;\n";
4701       pr "  }\n";
4702       pr "\n";
4703       pr "  ml->main_loop_quit (ml, g);\n";
4704       pr "\n";
4705       pr "  if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n";
4706       pr "    error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name;
4707       pr "    return;\n";
4708       pr "  }\n";
4709       pr "  if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {\n";
4710       pr "    if (!xdr_guestfs_message_error (xdr, &ctx->err)) {\n";
4711       pr "      error (g, \"%%s: failed to parse reply error\", \"%s\");\n"
4712         name;
4713       pr "      return;\n";
4714       pr "    }\n";
4715       pr "    goto done;\n";
4716       pr "  }\n";
4717
4718       (match fst style with
4719        | RErr -> ()
4720        | RConstString _ | RConstOptString _ ->
4721            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4722        | RInt _ | RInt64 _
4723        | RBool _ | RString _ | RStringList _
4724        | RStruct _ | RStructList _
4725        | RHashtable _ | RBufferOut _ ->
4726            pr "  if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name;
4727            pr "    error (g, \"%%s: failed to parse reply\", \"%s\");\n" name;
4728            pr "    return;\n";
4729            pr "  }\n";
4730       );
4731
4732       pr " done:\n";
4733       pr "  ctx->cb_sequence = 1;\n";
4734       pr "}\n\n";
4735
4736       (* Generate the action stub. *)
4737       generate_prototype ~extern:false ~semicolon:false ~newline:true
4738         ~handle:"g" name style;
4739
4740       let error_code =
4741         match fst style with
4742         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4743         | RConstString _ | RConstOptString _ ->
4744             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4745         | RString _ | RStringList _
4746         | RStruct _ | RStructList _
4747         | RHashtable _ | RBufferOut _ ->
4748             "NULL" in
4749
4750       pr "{\n";
4751
4752       (match snd style with
4753        | [] -> ()
4754        | _ -> pr "  struct %s_args args;\n" name
4755       );
4756
4757       pr "  struct %s_ctx ctx;\n" shortname;
4758       pr "  guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4759       pr "  int serial;\n";
4760       pr "\n";
4761       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4762       pr "  guestfs_set_busy (g);\n";
4763       pr "\n";
4764       pr "  memset (&ctx, 0, sizeof ctx);\n";
4765       pr "\n";
4766
4767       (* Send the main header and arguments. *)
4768       (match snd style with
4769        | [] ->
4770            pr "  serial = guestfs__send_sync (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4771              (String.uppercase shortname)
4772        | args ->
4773            List.iter (
4774              function
4775              | Pathname n | Device n | Dev_or_Path n | String n ->
4776                  pr "  args.%s = (char *) %s;\n" n n
4777              | OptString n ->
4778                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
4779              | StringList n | DeviceList n ->
4780                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
4781                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4782              | Bool n ->
4783                  pr "  args.%s = %s;\n" n n
4784              | Int n ->
4785                  pr "  args.%s = %s;\n" n n
4786              | FileIn _ | FileOut _ -> ()
4787            ) args;
4788            pr "  serial = guestfs__send_sync (g, GUESTFS_PROC_%s,\n"
4789              (String.uppercase shortname);
4790            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4791              name;
4792       );
4793       pr "  if (serial == -1) {\n";
4794       pr "    guestfs_end_busy (g);\n";
4795       pr "    return %s;\n" error_code;
4796       pr "  }\n";
4797       pr "\n";
4798
4799       (* Send any additional files (FileIn) requested. *)
4800       let need_read_reply_label = ref false in
4801       List.iter (
4802         function
4803         | FileIn n ->
4804             pr "  {\n";
4805             pr "    int r;\n";
4806             pr "\n";
4807             pr "    r = guestfs__send_file_sync (g, %s);\n" n;
4808             pr "    if (r == -1) {\n";
4809             pr "      guestfs_end_busy (g);\n";
4810             pr "      return %s;\n" error_code;
4811             pr "    }\n";
4812             pr "    if (r == -2) /* daemon cancelled */\n";
4813             pr "      goto read_reply;\n";
4814             need_read_reply_label := true;
4815             pr "  }\n";
4816             pr "\n";
4817         | _ -> ()
4818       ) (snd style);
4819
4820       (* Wait for the reply from the remote end. *)
4821       if !need_read_reply_label then pr " read_reply:\n";
4822       pr "  guestfs__switch_to_receiving (g);\n";
4823       pr "  ctx.cb_sequence = 0;\n";
4824       pr "  guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname;
4825       pr "  (void) ml->main_loop_run (ml, g);\n";
4826       pr "  guestfs_set_reply_callback (g, NULL, NULL);\n";
4827       pr "  if (ctx.cb_sequence != 1) {\n";
4828       pr "    error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name;
4829       pr "    guestfs_end_busy (g);\n";
4830       pr "    return %s;\n" error_code;
4831       pr "  }\n";
4832       pr "\n";
4833
4834       pr "  if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
4835         (String.uppercase shortname);
4836       pr "    guestfs_end_busy (g);\n";
4837       pr "    return %s;\n" error_code;
4838       pr "  }\n";
4839       pr "\n";
4840
4841       pr "  if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {\n";
4842       pr "    error (g, \"%%s\", ctx.err.error_message);\n";
4843       pr "    free (ctx.err.error_message);\n";
4844       pr "    guestfs_end_busy (g);\n";
4845       pr "    return %s;\n" error_code;
4846       pr "  }\n";
4847       pr "\n";
4848
4849       (* Expecting to receive further files (FileOut)? *)
4850       List.iter (
4851         function
4852         | FileOut n ->
4853             pr "  if (guestfs__receive_file_sync (g, %s) == -1) {\n" n;
4854             pr "    guestfs_end_busy (g);\n";
4855             pr "    return %s;\n" error_code;
4856             pr "  }\n";
4857             pr "\n";
4858         | _ -> ()
4859       ) (snd style);
4860
4861       pr "  guestfs_end_busy (g);\n";
4862
4863       (match fst style with
4864        | RErr -> pr "  return 0;\n"
4865        | RInt n | RInt64 n | RBool n ->
4866            pr "  return ctx.ret.%s;\n" n
4867        | RConstString _ | RConstOptString _ ->
4868            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4869        | RString n ->
4870            pr "  return ctx.ret.%s; /* caller will free */\n" n
4871        | RStringList n | RHashtable n ->
4872            pr "  /* caller will free this, but we need to add a NULL entry */\n";
4873            pr "  ctx.ret.%s.%s_val =\n" n n;
4874            pr "    safe_realloc (g, ctx.ret.%s.%s_val,\n" n n;
4875            pr "                  sizeof (char *) * (ctx.ret.%s.%s_len + 1));\n"
4876              n n;
4877            pr "  ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n;
4878            pr "  return ctx.ret.%s.%s_val;\n" n n
4879        | RStruct (n, _) ->
4880            pr "  /* caller will free this */\n";
4881            pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4882        | RStructList (n, _) ->
4883            pr "  /* caller will free this */\n";
4884            pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4885        | RBufferOut n ->
4886            pr "  *size_r = ctx.ret.%s.%s_len;\n" n n;
4887            pr "  return ctx.ret.%s.%s_val; /* caller will free */\n" n n
4888       );
4889
4890       pr "}\n\n"
4891   ) daemon_functions;
4892
4893   (* Functions to free structures. *)
4894   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
4895   pr " * structure format is identical to the XDR format.  See note in\n";
4896   pr " * generator.ml.\n";
4897   pr " */\n";
4898   pr "\n";
4899
4900   List.iter (
4901     fun (typ, _) ->
4902       pr "void\n";
4903       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
4904       pr "{\n";
4905       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
4906       pr "  free (x);\n";
4907       pr "}\n";
4908       pr "\n";
4909
4910       pr "void\n";
4911       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
4912       pr "{\n";
4913       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
4914       pr "  free (x);\n";
4915       pr "}\n";
4916       pr "\n";
4917
4918   ) structs;
4919
4920 (* Generate daemon/actions.h. *)
4921 and generate_daemon_actions_h () =
4922   generate_header CStyle GPLv2;
4923
4924   pr "#include \"../src/guestfs_protocol.h\"\n";
4925   pr "\n";
4926
4927   List.iter (
4928     fun (name, style, _, _, _, _, _) ->
4929       generate_prototype
4930         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
4931         name style;
4932   ) daemon_functions
4933
4934 (* Generate the server-side stubs. *)
4935 and generate_daemon_actions () =
4936   generate_header CStyle GPLv2;
4937
4938   pr "#include <config.h>\n";
4939   pr "\n";
4940   pr "#include <stdio.h>\n";
4941   pr "#include <stdlib.h>\n";
4942   pr "#include <string.h>\n";
4943   pr "#include <inttypes.h>\n";
4944   pr "#include <ctype.h>\n";
4945   pr "#include <rpc/types.h>\n";
4946   pr "#include <rpc/xdr.h>\n";
4947   pr "\n";
4948   pr "#include \"daemon.h\"\n";
4949   pr "#include \"../src/guestfs_protocol.h\"\n";
4950   pr "#include \"actions.h\"\n";
4951   pr "\n";
4952
4953   List.iter (
4954     fun (name, style, _, _, _, _, _) ->
4955       (* Generate server-side stubs. *)
4956       pr "static void %s_stub (XDR *xdr_in)\n" name;
4957       pr "{\n";
4958       let error_code =
4959         match fst style with
4960         | RErr | RInt _ -> pr "  int r;\n"; "-1"
4961         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
4962         | RBool _ -> pr "  int r;\n"; "-1"
4963         | RConstString _ | RConstOptString _ ->
4964             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4965         | RString _ -> pr "  char *r;\n"; "NULL"
4966         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
4967         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
4968         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
4969         | RBufferOut _ ->
4970             pr "  size_t size;\n";
4971             pr "  char *r;\n";
4972             "NULL" in
4973
4974       (match snd style with
4975        | [] -> ()
4976        | args ->
4977            pr "  struct guestfs_%s_args args;\n" name;
4978            List.iter (
4979              function
4980              | Device n | Dev_or_Path n
4981              | Pathname n
4982              | String n -> ()
4983              | OptString n -> pr "  char *%s;\n" n
4984              | StringList n | DeviceList n -> pr "  char **%s;\n" n
4985              | Bool n -> pr "  int %s;\n" n
4986              | Int n -> pr "  int %s;\n" n
4987              | FileIn _ | FileOut _ -> ()
4988            ) args
4989       );
4990       pr "\n";
4991
4992       (match snd style with
4993        | [] -> ()
4994        | args ->
4995            pr "  memset (&args, 0, sizeof args);\n";
4996            pr "\n";
4997            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
4998            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
4999            pr "    return;\n";
5000            pr "  }\n";
5001            let pr_args n =
5002              pr "  char *%s = args.%s;\n" n n
5003            in
5004            let pr_list_handling_code n =
5005              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5006              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5007              pr "  if (%s == NULL) {\n" n;
5008              pr "    reply_with_perror (\"realloc\");\n";
5009              pr "    goto done;\n";
5010              pr "  }\n";
5011              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5012              pr "  args.%s.%s_val = %s;\n" n n n;
5013            in
5014            List.iter (
5015              function
5016              | Pathname n ->
5017                  pr_args n;
5018                  pr "  ABS_PATH (%s, goto done);\n" n;
5019              | Device n ->
5020                  pr_args n;
5021                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5022              | Dev_or_Path n ->
5023                  pr_args n;
5024                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5025              | String n -> pr_args n
5026              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5027              | StringList n ->
5028                  pr_list_handling_code n;
5029              | DeviceList n ->
5030                  pr_list_handling_code n;
5031                  pr "  /* Ensure that each is a device,\n";
5032                  pr "   * and perform device name translation. */\n";
5033                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5034                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5035                  pr "  }\n";
5036              | Bool n -> pr "  %s = args.%s;\n" n n
5037              | Int n -> pr "  %s = args.%s;\n" n n
5038              | FileIn _ | FileOut _ -> ()
5039            ) args;
5040            pr "\n"
5041       );
5042
5043
5044       (* this is used at least for do_equal *)
5045       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5046         (* Emit NEED_ROOT just once, even when there are two or
5047            more Pathname args *)
5048         pr "  NEED_ROOT (goto done);\n";
5049       );
5050
5051       (* Don't want to call the impl with any FileIn or FileOut
5052        * parameters, since these go "outside" the RPC protocol.
5053        *)
5054       let args' =
5055         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5056           (snd style) in
5057       pr "  r = do_%s " name;
5058       generate_c_call_args (fst style, args');
5059       pr ";\n";
5060
5061       pr "  if (r == %s)\n" error_code;
5062       pr "    /* do_%s has already called reply_with_error */\n" name;
5063       pr "    goto done;\n";
5064       pr "\n";
5065
5066       (* If there are any FileOut parameters, then the impl must
5067        * send its own reply.
5068        *)
5069       let no_reply =
5070         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5071       if no_reply then
5072         pr "  /* do_%s has already sent a reply */\n" name
5073       else (
5074         match fst style with
5075         | RErr -> pr "  reply (NULL, NULL);\n"
5076         | RInt n | RInt64 n | RBool n ->
5077             pr "  struct guestfs_%s_ret ret;\n" name;
5078             pr "  ret.%s = r;\n" n;
5079             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5080               name
5081         | RConstString _ | RConstOptString _ ->
5082             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5083         | RString n ->
5084             pr "  struct guestfs_%s_ret ret;\n" name;
5085             pr "  ret.%s = r;\n" n;
5086             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5087               name;
5088             pr "  free (r);\n"
5089         | RStringList n | RHashtable n ->
5090             pr "  struct guestfs_%s_ret ret;\n" name;
5091             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5092             pr "  ret.%s.%s_val = r;\n" n n;
5093             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5094               name;
5095             pr "  free_strings (r);\n"
5096         | RStruct (n, _) ->
5097             pr "  struct guestfs_%s_ret ret;\n" name;
5098             pr "  ret.%s = *r;\n" n;
5099             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5100               name;
5101             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5102               name
5103         | RStructList (n, _) ->
5104             pr "  struct guestfs_%s_ret ret;\n" name;
5105             pr "  ret.%s = *r;\n" n;
5106             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5107               name;
5108             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5109               name
5110         | RBufferOut n ->
5111             pr "  struct guestfs_%s_ret ret;\n" name;
5112             pr "  ret.%s.%s_val = r;\n" n n;
5113             pr "  ret.%s.%s_len = size;\n" n n;
5114             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5115               name;
5116             pr "  free (r);\n"
5117       );
5118
5119       (* Free the args. *)
5120       (match snd style with
5121        | [] ->
5122            pr "done: ;\n";
5123        | _ ->
5124            pr "done:\n";
5125            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5126              name
5127       );
5128
5129       pr "}\n\n";
5130   ) daemon_functions;
5131
5132   (* Dispatch function. *)
5133   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5134   pr "{\n";
5135   pr "  switch (proc_nr) {\n";
5136
5137   List.iter (
5138     fun (name, style, _, _, _, _, _) ->
5139       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5140       pr "      %s_stub (xdr_in);\n" name;
5141       pr "      break;\n"
5142   ) daemon_functions;
5143
5144   pr "    default:\n";
5145   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";
5146   pr "  }\n";
5147   pr "}\n";
5148   pr "\n";
5149
5150   (* LVM columns and tokenization functions. *)
5151   (* XXX This generates crap code.  We should rethink how we
5152    * do this parsing.
5153    *)
5154   List.iter (
5155     function
5156     | typ, cols ->
5157         pr "static const char *lvm_%s_cols = \"%s\";\n"
5158           typ (String.concat "," (List.map fst cols));
5159         pr "\n";
5160
5161         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5162         pr "{\n";
5163         pr "  char *tok, *p, *next;\n";
5164         pr "  int i, j;\n";
5165         pr "\n";
5166         (*
5167           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5168           pr "\n";
5169         *)
5170         pr "  if (!str) {\n";
5171         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5172         pr "    return -1;\n";
5173         pr "  }\n";
5174         pr "  if (!*str || isspace (*str)) {\n";
5175         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5176         pr "    return -1;\n";
5177         pr "  }\n";
5178         pr "  tok = str;\n";
5179         List.iter (
5180           fun (name, coltype) ->
5181             pr "  if (!tok) {\n";
5182             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5183             pr "    return -1;\n";
5184             pr "  }\n";
5185             pr "  p = strchrnul (tok, ',');\n";
5186             pr "  if (*p) next = p+1; else next = NULL;\n";
5187             pr "  *p = '\\0';\n";
5188             (match coltype with
5189              | FString ->
5190                  pr "  r->%s = strdup (tok);\n" name;
5191                  pr "  if (r->%s == NULL) {\n" name;
5192                  pr "    perror (\"strdup\");\n";
5193                  pr "    return -1;\n";
5194                  pr "  }\n"
5195              | FUUID ->
5196                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5197                  pr "    if (tok[j] == '\\0') {\n";
5198                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5199                  pr "      return -1;\n";
5200                  pr "    } else if (tok[j] != '-')\n";
5201                  pr "      r->%s[i++] = tok[j];\n" name;
5202                  pr "  }\n";
5203              | FBytes ->
5204                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5205                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5206                  pr "    return -1;\n";
5207                  pr "  }\n";
5208              | FInt64 ->
5209                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5210                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5211                  pr "    return -1;\n";
5212                  pr "  }\n";
5213              | FOptPercent ->
5214                  pr "  if (tok[0] == '\\0')\n";
5215                  pr "    r->%s = -1;\n" name;
5216                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5217                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5218                  pr "    return -1;\n";
5219                  pr "  }\n";
5220              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5221                  assert false (* can never be an LVM column *)
5222             );
5223             pr "  tok = next;\n";
5224         ) cols;
5225
5226         pr "  if (tok != NULL) {\n";
5227         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5228         pr "    return -1;\n";
5229         pr "  }\n";
5230         pr "  return 0;\n";
5231         pr "}\n";
5232         pr "\n";
5233
5234         pr "guestfs_int_lvm_%s_list *\n" typ;
5235         pr "parse_command_line_%ss (void)\n" typ;
5236         pr "{\n";
5237         pr "  char *out, *err;\n";
5238         pr "  char *p, *pend;\n";
5239         pr "  int r, i;\n";
5240         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5241         pr "  void *newp;\n";
5242         pr "\n";
5243         pr "  ret = malloc (sizeof *ret);\n";
5244         pr "  if (!ret) {\n";
5245         pr "    reply_with_perror (\"malloc\");\n";
5246         pr "    return NULL;\n";
5247         pr "  }\n";
5248         pr "\n";
5249         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5250         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5251         pr "\n";
5252         pr "  r = command (&out, &err,\n";
5253         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5254         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5255         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5256         pr "  if (r == -1) {\n";
5257         pr "    reply_with_error (\"%%s\", err);\n";
5258         pr "    free (out);\n";
5259         pr "    free (err);\n";
5260         pr "    free (ret);\n";
5261         pr "    return NULL;\n";
5262         pr "  }\n";
5263         pr "\n";
5264         pr "  free (err);\n";
5265         pr "\n";
5266         pr "  /* Tokenize each line of the output. */\n";
5267         pr "  p = out;\n";
5268         pr "  i = 0;\n";
5269         pr "  while (p) {\n";
5270         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5271         pr "    if (pend) {\n";
5272         pr "      *pend = '\\0';\n";
5273         pr "      pend++;\n";
5274         pr "    }\n";
5275         pr "\n";
5276         pr "    while (*p && isspace (*p))      /* Skip any leading whitespace. */\n";
5277         pr "      p++;\n";
5278         pr "\n";
5279         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5280         pr "      p = pend;\n";
5281         pr "      continue;\n";
5282         pr "    }\n";
5283         pr "\n";
5284         pr "    /* Allocate some space to store this next entry. */\n";
5285         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5286         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5287         pr "    if (newp == NULL) {\n";
5288         pr "      reply_with_perror (\"realloc\");\n";
5289         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5290         pr "      free (ret);\n";
5291         pr "      free (out);\n";
5292         pr "      return NULL;\n";
5293         pr "    }\n";
5294         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5295         pr "\n";
5296         pr "    /* Tokenize the next entry. */\n";
5297         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5298         pr "    if (r == -1) {\n";
5299         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5300         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5301         pr "      free (ret);\n";
5302         pr "      free (out);\n";
5303         pr "      return NULL;\n";
5304         pr "    }\n";
5305         pr "\n";
5306         pr "    ++i;\n";
5307         pr "    p = pend;\n";
5308         pr "  }\n";
5309         pr "\n";
5310         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5311         pr "\n";
5312         pr "  free (out);\n";
5313         pr "  return ret;\n";
5314         pr "}\n"
5315
5316   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5317
5318 (* Generate a list of function names, for debugging in the daemon.. *)
5319 and generate_daemon_names () =
5320   generate_header CStyle GPLv2;
5321
5322   pr "#include <config.h>\n";
5323   pr "\n";
5324   pr "#include \"daemon.h\"\n";
5325   pr "\n";
5326
5327   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5328   pr "const char *function_names[] = {\n";
5329   List.iter (
5330     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5331   ) daemon_functions;
5332   pr "};\n";
5333
5334 (* Generate the tests. *)
5335 and generate_tests () =
5336   generate_header CStyle GPLv2;
5337
5338   pr "\
5339 #include <stdio.h>
5340 #include <stdlib.h>
5341 #include <string.h>
5342 #include <unistd.h>
5343 #include <sys/types.h>
5344 #include <fcntl.h>
5345
5346 #include \"guestfs.h\"
5347
5348 static guestfs_h *g;
5349 static int suppress_error = 0;
5350
5351 static void print_error (guestfs_h *g, void *data, const char *msg)
5352 {
5353   if (!suppress_error)
5354     fprintf (stderr, \"%%s\\n\", msg);
5355 }
5356
5357 /* FIXME: nearly identical code appears in fish.c */
5358 static void print_strings (char *const *argv)
5359 {
5360   int argc;
5361
5362   for (argc = 0; argv[argc] != NULL; ++argc)
5363     printf (\"\\t%%s\\n\", argv[argc]);
5364 }
5365
5366 /*
5367 static void print_table (char const *const *argv)
5368 {
5369   int i;
5370
5371   for (i = 0; argv[i] != NULL; i += 2)
5372     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5373 }
5374 */
5375
5376 ";
5377
5378   (* Generate a list of commands which are not tested anywhere. *)
5379   pr "static void no_test_warnings (void)\n";
5380   pr "{\n";
5381
5382   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5383   List.iter (
5384     fun (_, _, _, _, tests, _, _) ->
5385       let tests = filter_map (
5386         function
5387         | (_, (Always|If _|Unless _), test) -> Some test
5388         | (_, Disabled, _) -> None
5389       ) tests in
5390       let seq = List.concat (List.map seq_of_test tests) in
5391       let cmds_tested = List.map List.hd seq in
5392       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5393   ) all_functions;
5394
5395   List.iter (
5396     fun (name, _, _, _, _, _, _) ->
5397       if not (Hashtbl.mem hash name) then
5398         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5399   ) all_functions;
5400
5401   pr "}\n";
5402   pr "\n";
5403
5404   (* Generate the actual tests.  Note that we generate the tests
5405    * in reverse order, deliberately, so that (in general) the
5406    * newest tests run first.  This makes it quicker and easier to
5407    * debug them.
5408    *)
5409   let test_names =
5410     List.map (
5411       fun (name, _, _, _, tests, _, _) ->
5412         mapi (generate_one_test name) tests
5413     ) (List.rev all_functions) in
5414   let test_names = List.concat test_names in
5415   let nr_tests = List.length test_names in
5416
5417   pr "\
5418 int main (int argc, char *argv[])
5419 {
5420   char c = 0;
5421   unsigned long int n_failed = 0;
5422   const char *filename;
5423   int fd;
5424   int nr_tests, test_num = 0;
5425
5426   setbuf (stdout, NULL);
5427
5428   no_test_warnings ();
5429
5430   g = guestfs_create ();
5431   if (g == NULL) {
5432     printf (\"guestfs_create FAILED\\n\");
5433     exit (1);
5434   }
5435
5436   guestfs_set_error_handler (g, print_error, NULL);
5437
5438   guestfs_set_path (g, \"../appliance\");
5439
5440   filename = \"test1.img\";
5441   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5442   if (fd == -1) {
5443     perror (filename);
5444     exit (1);
5445   }
5446   if (lseek (fd, %d, SEEK_SET) == -1) {
5447     perror (\"lseek\");
5448     close (fd);
5449     unlink (filename);
5450     exit (1);
5451   }
5452   if (write (fd, &c, 1) == -1) {
5453     perror (\"write\");
5454     close (fd);
5455     unlink (filename);
5456     exit (1);
5457   }
5458   if (close (fd) == -1) {
5459     perror (filename);
5460     unlink (filename);
5461     exit (1);
5462   }
5463   if (guestfs_add_drive (g, filename) == -1) {
5464     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5465     exit (1);
5466   }
5467
5468   filename = \"test2.img\";
5469   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5470   if (fd == -1) {
5471     perror (filename);
5472     exit (1);
5473   }
5474   if (lseek (fd, %d, SEEK_SET) == -1) {
5475     perror (\"lseek\");
5476     close (fd);
5477     unlink (filename);
5478     exit (1);
5479   }
5480   if (write (fd, &c, 1) == -1) {
5481     perror (\"write\");
5482     close (fd);
5483     unlink (filename);
5484     exit (1);
5485   }
5486   if (close (fd) == -1) {
5487     perror (filename);
5488     unlink (filename);
5489     exit (1);
5490   }
5491   if (guestfs_add_drive (g, filename) == -1) {
5492     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5493     exit (1);
5494   }
5495
5496   filename = \"test3.img\";
5497   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5498   if (fd == -1) {
5499     perror (filename);
5500     exit (1);
5501   }
5502   if (lseek (fd, %d, SEEK_SET) == -1) {
5503     perror (\"lseek\");
5504     close (fd);
5505     unlink (filename);
5506     exit (1);
5507   }
5508   if (write (fd, &c, 1) == -1) {
5509     perror (\"write\");
5510     close (fd);
5511     unlink (filename);
5512     exit (1);
5513   }
5514   if (close (fd) == -1) {
5515     perror (filename);
5516     unlink (filename);
5517     exit (1);
5518   }
5519   if (guestfs_add_drive (g, filename) == -1) {
5520     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5521     exit (1);
5522   }
5523
5524   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
5525     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
5526     exit (1);
5527   }
5528
5529   if (guestfs_launch (g) == -1) {
5530     printf (\"guestfs_launch FAILED\\n\");
5531     exit (1);
5532   }
5533
5534   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5535   alarm (600);
5536
5537   if (guestfs_wait_ready (g) == -1) {
5538     printf (\"guestfs_wait_ready FAILED\\n\");
5539     exit (1);
5540   }
5541
5542   /* Cancel previous alarm. */
5543   alarm (0);
5544
5545   nr_tests = %d;
5546
5547 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5548
5549   iteri (
5550     fun i test_name ->
5551       pr "  test_num++;\n";
5552       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5553       pr "  if (%s () == -1) {\n" test_name;
5554       pr "    printf (\"%s FAILED\\n\");\n" test_name;
5555       pr "    n_failed++;\n";
5556       pr "  }\n";
5557   ) test_names;
5558   pr "\n";
5559
5560   pr "  guestfs_close (g);\n";
5561   pr "  unlink (\"test1.img\");\n";
5562   pr "  unlink (\"test2.img\");\n";
5563   pr "  unlink (\"test3.img\");\n";
5564   pr "\n";
5565
5566   pr "  if (n_failed > 0) {\n";
5567   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
5568   pr "    exit (1);\n";
5569   pr "  }\n";
5570   pr "\n";
5571
5572   pr "  exit (0);\n";
5573   pr "}\n"
5574
5575 and generate_one_test name i (init, prereq, test) =
5576   let test_name = sprintf "test_%s_%d" name i in
5577
5578   pr "\
5579 static int %s_skip (void)
5580 {
5581   const char *str;
5582
5583   str = getenv (\"TEST_ONLY\");
5584   if (str)
5585     return strstr (str, \"%s\") == NULL;
5586   str = getenv (\"SKIP_%s\");
5587   if (str && strcmp (str, \"1\") == 0) return 1;
5588   str = getenv (\"SKIP_TEST_%s\");
5589   if (str && strcmp (str, \"1\") == 0) return 1;
5590   return 0;
5591 }
5592
5593 " test_name name (String.uppercase test_name) (String.uppercase name);
5594
5595   (match prereq with
5596    | Disabled | Always -> ()
5597    | If code | Unless code ->
5598        pr "static int %s_prereq (void)\n" test_name;
5599        pr "{\n";
5600        pr "  %s\n" code;
5601        pr "}\n";
5602        pr "\n";
5603   );
5604
5605   pr "\
5606 static int %s (void)
5607 {
5608   if (%s_skip ()) {
5609     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
5610     return 0;
5611   }
5612
5613 " test_name test_name test_name;
5614
5615   (match prereq with
5616    | Disabled ->
5617        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5618    | If _ ->
5619        pr "  if (! %s_prereq ()) {\n" test_name;
5620        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5621        pr "    return 0;\n";
5622        pr "  }\n";
5623        pr "\n";
5624        generate_one_test_body name i test_name init test;
5625    | Unless _ ->
5626        pr "  if (%s_prereq ()) {\n" test_name;
5627        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5628        pr "    return 0;\n";
5629        pr "  }\n";
5630        pr "\n";
5631        generate_one_test_body name i test_name init test;
5632    | Always ->
5633        generate_one_test_body name i test_name init test
5634   );
5635
5636   pr "  return 0;\n";
5637   pr "}\n";
5638   pr "\n";
5639   test_name
5640
5641 and generate_one_test_body name i test_name init test =
5642   (match init with
5643    | InitNone (* XXX at some point, InitNone and InitEmpty became
5644                * folded together as the same thing.  Really we should
5645                * make InitNone do nothing at all, but the tests may
5646                * need to be checked to make sure this is OK.
5647                *)
5648    | InitEmpty ->
5649        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
5650        List.iter (generate_test_command_call test_name)
5651          [["blockdev_setrw"; "/dev/sda"];
5652           ["umount_all"];
5653           ["lvm_remove_all"]]
5654    | InitPartition ->
5655        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5656        List.iter (generate_test_command_call test_name)
5657          [["blockdev_setrw"; "/dev/sda"];
5658           ["umount_all"];
5659           ["lvm_remove_all"];
5660           ["sfdiskM"; "/dev/sda"; ","]]
5661    | InitBasicFS ->
5662        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5663        List.iter (generate_test_command_call test_name)
5664          [["blockdev_setrw"; "/dev/sda"];
5665           ["umount_all"];
5666           ["lvm_remove_all"];
5667           ["sfdiskM"; "/dev/sda"; ","];
5668           ["mkfs"; "ext2"; "/dev/sda1"];
5669           ["mount"; "/dev/sda1"; "/"]]
5670    | InitBasicFSonLVM ->
5671        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5672          test_name;
5673        List.iter (generate_test_command_call test_name)
5674          [["blockdev_setrw"; "/dev/sda"];
5675           ["umount_all"];
5676           ["lvm_remove_all"];
5677           ["sfdiskM"; "/dev/sda"; ","];
5678           ["pvcreate"; "/dev/sda1"];
5679           ["vgcreate"; "VG"; "/dev/sda1"];
5680           ["lvcreate"; "LV"; "VG"; "8"];
5681           ["mkfs"; "ext2"; "/dev/VG/LV"];
5682           ["mount"; "/dev/VG/LV"; "/"]]
5683    | InitISOFS ->
5684        pr "  /* InitISOFS for %s */\n" test_name;
5685        List.iter (generate_test_command_call test_name)
5686          [["blockdev_setrw"; "/dev/sda"];
5687           ["umount_all"];
5688           ["lvm_remove_all"];
5689           ["mount_ro"; "/dev/sdd"; "/"]]
5690   );
5691
5692   let get_seq_last = function
5693     | [] ->
5694         failwithf "%s: you cannot use [] (empty list) when expecting a command"
5695           test_name
5696     | seq ->
5697         let seq = List.rev seq in
5698         List.rev (List.tl seq), List.hd seq
5699   in
5700
5701   match test with
5702   | TestRun seq ->
5703       pr "  /* TestRun for %s (%d) */\n" name i;
5704       List.iter (generate_test_command_call test_name) seq
5705   | TestOutput (seq, expected) ->
5706       pr "  /* TestOutput for %s (%d) */\n" name i;
5707       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5708       let seq, last = get_seq_last seq in
5709       let test () =
5710         pr "    if (strcmp (r, expected) != 0) {\n";
5711         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5712         pr "      return -1;\n";
5713         pr "    }\n"
5714       in
5715       List.iter (generate_test_command_call test_name) seq;
5716       generate_test_command_call ~test test_name last
5717   | TestOutputList (seq, expected) ->
5718       pr "  /* TestOutputList for %s (%d) */\n" name i;
5719       let seq, last = get_seq_last seq in
5720       let test () =
5721         iteri (
5722           fun i str ->
5723             pr "    if (!r[%d]) {\n" i;
5724             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5725             pr "      print_strings (r);\n";
5726             pr "      return -1;\n";
5727             pr "    }\n";
5728             pr "    {\n";
5729             pr "      const char *expected = \"%s\";\n" (c_quote str);
5730             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5731             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5732             pr "        return -1;\n";
5733             pr "      }\n";
5734             pr "    }\n"
5735         ) expected;
5736         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5737         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5738           test_name;
5739         pr "      print_strings (r);\n";
5740         pr "      return -1;\n";
5741         pr "    }\n"
5742       in
5743       List.iter (generate_test_command_call test_name) seq;
5744       generate_test_command_call ~test test_name last
5745   | TestOutputListOfDevices (seq, expected) ->
5746       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
5747       let seq, last = get_seq_last seq in
5748       let test () =
5749         iteri (
5750           fun i str ->
5751             pr "    if (!r[%d]) {\n" i;
5752             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5753             pr "      print_strings (r);\n";
5754             pr "      return -1;\n";
5755             pr "    }\n";
5756             pr "    {\n";
5757             pr "      const char *expected = \"%s\";\n" (c_quote str);
5758             pr "      r[%d][5] = 's';\n" i;
5759             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5760             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5761             pr "        return -1;\n";
5762             pr "      }\n";
5763             pr "    }\n"
5764         ) expected;
5765         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5766         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5767           test_name;
5768         pr "      print_strings (r);\n";
5769         pr "      return -1;\n";
5770         pr "    }\n"
5771       in
5772       List.iter (generate_test_command_call test_name) seq;
5773       generate_test_command_call ~test test_name last
5774   | TestOutputInt (seq, expected) ->
5775       pr "  /* TestOutputInt for %s (%d) */\n" name i;
5776       let seq, last = get_seq_last seq in
5777       let test () =
5778         pr "    if (r != %d) {\n" expected;
5779         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5780           test_name expected;
5781         pr "               (int) r);\n";
5782         pr "      return -1;\n";
5783         pr "    }\n"
5784       in
5785       List.iter (generate_test_command_call test_name) seq;
5786       generate_test_command_call ~test test_name last
5787   | TestOutputIntOp (seq, op, expected) ->
5788       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
5789       let seq, last = get_seq_last seq in
5790       let test () =
5791         pr "    if (! (r %s %d)) {\n" op expected;
5792         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5793           test_name op expected;
5794         pr "               (int) r);\n";
5795         pr "      return -1;\n";
5796         pr "    }\n"
5797       in
5798       List.iter (generate_test_command_call test_name) seq;
5799       generate_test_command_call ~test test_name last
5800   | TestOutputTrue seq ->
5801       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
5802       let seq, last = get_seq_last seq in
5803       let test () =
5804         pr "    if (!r) {\n";
5805         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5806           test_name;
5807         pr "      return -1;\n";
5808         pr "    }\n"
5809       in
5810       List.iter (generate_test_command_call test_name) seq;
5811       generate_test_command_call ~test test_name last
5812   | TestOutputFalse seq ->
5813       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
5814       let seq, last = get_seq_last seq in
5815       let test () =
5816         pr "    if (r) {\n";
5817         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
5818           test_name;
5819         pr "      return -1;\n";
5820         pr "    }\n"
5821       in
5822       List.iter (generate_test_command_call test_name) seq;
5823       generate_test_command_call ~test test_name last
5824   | TestOutputLength (seq, expected) ->
5825       pr "  /* TestOutputLength for %s (%d) */\n" name i;
5826       let seq, last = get_seq_last seq in
5827       let test () =
5828         pr "    int j;\n";
5829         pr "    for (j = 0; j < %d; ++j)\n" expected;
5830         pr "      if (r[j] == NULL) {\n";
5831         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
5832           test_name;
5833         pr "        print_strings (r);\n";
5834         pr "        return -1;\n";
5835         pr "      }\n";
5836         pr "    if (r[j] != NULL) {\n";
5837         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
5838           test_name;
5839         pr "      print_strings (r);\n";
5840         pr "      return -1;\n";
5841         pr "    }\n"
5842       in
5843       List.iter (generate_test_command_call test_name) seq;
5844       generate_test_command_call ~test test_name last
5845   | TestOutputBuffer (seq, expected) ->
5846       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
5847       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5848       let seq, last = get_seq_last seq in
5849       let len = String.length expected in
5850       let test () =
5851         pr "    if (size != %d) {\n" len;
5852         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
5853         pr "      return -1;\n";
5854         pr "    }\n";
5855         pr "    if (strncmp (r, expected, size) != 0) {\n";
5856         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5857         pr "      return -1;\n";
5858         pr "    }\n"
5859       in
5860       List.iter (generate_test_command_call test_name) seq;
5861       generate_test_command_call ~test test_name last
5862   | TestOutputStruct (seq, checks) ->
5863       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
5864       let seq, last = get_seq_last seq in
5865       let test () =
5866         List.iter (
5867           function
5868           | CompareWithInt (field, expected) ->
5869               pr "    if (r->%s != %d) {\n" field expected;
5870               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
5871                 test_name field expected;
5872               pr "               (int) r->%s);\n" field;
5873               pr "      return -1;\n";
5874               pr "    }\n"
5875           | CompareWithIntOp (field, op, expected) ->
5876               pr "    if (!(r->%s %s %d)) {\n" field op expected;
5877               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
5878                 test_name field op expected;
5879               pr "               (int) r->%s);\n" field;
5880               pr "      return -1;\n";
5881               pr "    }\n"
5882           | CompareWithString (field, expected) ->
5883               pr "    if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
5884               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
5885                 test_name field expected;
5886               pr "               r->%s);\n" field;
5887               pr "      return -1;\n";
5888               pr "    }\n"
5889           | CompareFieldsIntEq (field1, field2) ->
5890               pr "    if (r->%s != r->%s) {\n" field1 field2;
5891               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
5892                 test_name field1 field2;
5893               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
5894               pr "      return -1;\n";
5895               pr "    }\n"
5896           | CompareFieldsStrEq (field1, field2) ->
5897               pr "    if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
5898               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
5899                 test_name field1 field2;
5900               pr "               r->%s, r->%s);\n" field1 field2;
5901               pr "      return -1;\n";
5902               pr "    }\n"
5903         ) checks
5904       in
5905       List.iter (generate_test_command_call test_name) seq;
5906       generate_test_command_call ~test test_name last
5907   | TestLastFail seq ->
5908       pr "  /* TestLastFail for %s (%d) */\n" name i;
5909       let seq, last = get_seq_last seq in
5910       List.iter (generate_test_command_call test_name) seq;
5911       generate_test_command_call test_name ~expect_error:true last
5912
5913 (* Generate the code to run a command, leaving the result in 'r'.
5914  * If you expect to get an error then you should set expect_error:true.
5915  *)
5916 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
5917   match cmd with
5918   | [] -> assert false
5919   | name :: args ->
5920       (* Look up the command to find out what args/ret it has. *)
5921       let style =
5922         try
5923           let _, style, _, _, _, _, _ =
5924             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
5925           style
5926         with Not_found ->
5927           failwithf "%s: in test, command %s was not found" test_name name in
5928
5929       if List.length (snd style) <> List.length args then
5930         failwithf "%s: in test, wrong number of args given to %s"
5931           test_name name;
5932
5933       pr "  {\n";
5934
5935       List.iter (
5936         function
5937         | OptString n, "NULL" -> ()
5938         | Pathname n, arg
5939         | Device n, arg
5940         | Dev_or_Path n, arg
5941         | String n, arg
5942         | OptString n, arg ->
5943             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
5944         | Int _, _
5945         | Bool _, _
5946         | FileIn _, _ | FileOut _, _ -> ()
5947         | StringList n, arg | DeviceList n, arg ->
5948             let strs = string_split " " arg in
5949             iteri (
5950               fun i str ->
5951                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
5952             ) strs;
5953             pr "    const char *const %s[] = {\n" n;
5954             iteri (
5955               fun i _ -> pr "      %s_%d,\n" n i
5956             ) strs;
5957             pr "      NULL\n";
5958             pr "    };\n";
5959       ) (List.combine (snd style) args);
5960
5961       let error_code =
5962         match fst style with
5963         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
5964         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
5965         | RConstString _ | RConstOptString _ ->
5966             pr "    const char *r;\n"; "NULL"
5967         | RString _ -> pr "    char *r;\n"; "NULL"
5968         | RStringList _ | RHashtable _ ->
5969             pr "    char **r;\n";
5970             pr "    int i;\n";
5971             "NULL"
5972         | RStruct (_, typ) ->
5973             pr "    struct guestfs_%s *r;\n" typ; "NULL"
5974         | RStructList (_, typ) ->
5975             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
5976         | RBufferOut _ ->
5977             pr "    char *r;\n";
5978             pr "    size_t size;\n";
5979             "NULL" in
5980
5981       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
5982       pr "    r = guestfs_%s (g" name;
5983
5984       (* Generate the parameters. *)
5985       List.iter (
5986         function
5987         | OptString _, "NULL" -> pr ", NULL"
5988         | Pathname n, _
5989         | Device n, _ | Dev_or_Path n, _
5990         | String n, _
5991         | OptString n, _ ->
5992             pr ", %s" n
5993         | FileIn _, arg | FileOut _, arg ->
5994             pr ", \"%s\"" (c_quote arg)
5995         | StringList n, _ | DeviceList n, _ ->
5996             pr ", (char **) %s" n
5997         | Int _, arg ->
5998             let i =
5999               try int_of_string arg
6000               with Failure "int_of_string" ->
6001                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6002             pr ", %d" i
6003         | Bool _, arg ->
6004             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6005       ) (List.combine (snd style) args);
6006
6007       (match fst style with
6008        | RBufferOut _ -> pr ", &size"
6009        | _ -> ()
6010       );
6011
6012       pr ");\n";
6013
6014       if not expect_error then
6015         pr "    if (r == %s)\n" error_code
6016       else
6017         pr "    if (r != %s)\n" error_code;
6018       pr "      return -1;\n";
6019
6020       (* Insert the test code. *)
6021       (match test with
6022        | None -> ()
6023        | Some f -> f ()
6024       );
6025
6026       (match fst style with
6027        | RErr | RInt _ | RInt64 _ | RBool _
6028        | RConstString _ | RConstOptString _ -> ()
6029        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6030        | RStringList _ | RHashtable _ ->
6031            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6032            pr "      free (r[i]);\n";
6033            pr "    free (r);\n"
6034        | RStruct (_, typ) ->
6035            pr "    guestfs_free_%s (r);\n" typ
6036        | RStructList (_, typ) ->
6037            pr "    guestfs_free_%s_list (r);\n" typ
6038       );
6039
6040       pr "  }\n"
6041
6042 and c_quote str =
6043   let str = replace_str str "\r" "\\r" in
6044   let str = replace_str str "\n" "\\n" in
6045   let str = replace_str str "\t" "\\t" in
6046   let str = replace_str str "\000" "\\0" in
6047   str
6048
6049 (* Generate a lot of different functions for guestfish. *)
6050 and generate_fish_cmds () =
6051   generate_header CStyle GPLv2;
6052
6053   let all_functions =
6054     List.filter (
6055       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6056     ) all_functions in
6057   let all_functions_sorted =
6058     List.filter (
6059       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6060     ) all_functions_sorted in
6061
6062   pr "#include <stdio.h>\n";
6063   pr "#include <stdlib.h>\n";
6064   pr "#include <string.h>\n";
6065   pr "#include <inttypes.h>\n";
6066   pr "#include <ctype.h>\n";
6067   pr "\n";
6068   pr "#include <guestfs.h>\n";
6069   pr "#include \"fish.h\"\n";
6070   pr "\n";
6071
6072   (* list_commands function, which implements guestfish -h *)
6073   pr "void list_commands (void)\n";
6074   pr "{\n";
6075   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6076   pr "  list_builtin_commands ();\n";
6077   List.iter (
6078     fun (name, _, _, flags, _, shortdesc, _) ->
6079       let name = replace_char name '_' '-' in
6080       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6081         name shortdesc
6082   ) all_functions_sorted;
6083   pr "  printf (\"    %%s\\n\",";
6084   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6085   pr "}\n";
6086   pr "\n";
6087
6088   (* display_command function, which implements guestfish -h cmd *)
6089   pr "void display_command (const char *cmd)\n";
6090   pr "{\n";
6091   List.iter (
6092     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6093       let name2 = replace_char name '_' '-' in
6094       let alias =
6095         try find_map (function FishAlias n -> Some n | _ -> None) flags
6096         with Not_found -> name in
6097       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6098       let synopsis =
6099         match snd style with
6100         | [] -> name2
6101         | args ->
6102             sprintf "%s <%s>"
6103               name2 (String.concat "> <" (List.map name_of_argt args)) in
6104
6105       let warnings =
6106         if List.mem ProtocolLimitWarning flags then
6107           ("\n\n" ^ protocol_limit_warning)
6108         else "" in
6109
6110       (* For DangerWillRobinson commands, we should probably have
6111        * guestfish prompt before allowing you to use them (especially
6112        * in interactive mode). XXX
6113        *)
6114       let warnings =
6115         warnings ^
6116           if List.mem DangerWillRobinson flags then
6117             ("\n\n" ^ danger_will_robinson)
6118           else "" in
6119
6120       let warnings =
6121         warnings ^
6122           match deprecation_notice flags with
6123           | None -> ""
6124           | Some txt -> "\n\n" ^ txt in
6125
6126       let describe_alias =
6127         if name <> alias then
6128           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6129         else "" in
6130
6131       pr "  if (";
6132       pr "strcasecmp (cmd, \"%s\") == 0" name;
6133       if name <> name2 then
6134         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6135       if name <> alias then
6136         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6137       pr ")\n";
6138       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6139         name2 shortdesc
6140         (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
6141       pr "  else\n"
6142   ) all_functions;
6143   pr "    display_builtin_command (cmd);\n";
6144   pr "}\n";
6145   pr "\n";
6146
6147   let emit_print_list_function typ =
6148     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6149       typ typ typ;
6150     pr "{\n";
6151     pr "  unsigned int i;\n";
6152     pr "\n";
6153     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6154     pr "    printf (\"[%%d] = {\\n\", i);\n";
6155     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6156     pr "    printf (\"}\\n\");\n";
6157     pr "  }\n";
6158     pr "}\n";
6159     pr "\n";
6160   in
6161
6162   (* print_* functions *)
6163   List.iter (
6164     fun (typ, cols) ->
6165       let needs_i =
6166         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6167
6168       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6169       pr "{\n";
6170       if needs_i then (
6171         pr "  unsigned int i;\n";
6172         pr "\n"
6173       );
6174       List.iter (
6175         function
6176         | name, FString ->
6177             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6178         | name, FUUID ->
6179             pr "  printf (\"%s: \");\n" name;
6180             pr "  for (i = 0; i < 32; ++i)\n";
6181             pr "    printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6182             pr "  printf (\"\\n\");\n"
6183         | name, FBuffer ->
6184             pr "  printf (\"%%s%s: \", indent);\n" name;
6185             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6186             pr "    if (isprint (%s->%s[i]))\n" typ name;
6187             pr "      printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6188             pr "    else\n";
6189             pr "      printf (\"%%s\\\\x%%02x\", indent, %s->%s[i]);\n" typ name;
6190             pr "  printf (\"\\n\");\n"
6191         | name, (FUInt64|FBytes) ->
6192             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6193               name typ name
6194         | name, FInt64 ->
6195             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6196               name typ name
6197         | name, FUInt32 ->
6198             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6199               name typ name
6200         | name, FInt32 ->
6201             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6202               name typ name
6203         | name, FChar ->
6204             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6205               name typ name
6206         | name, FOptPercent ->
6207             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6208               typ name name typ name;
6209             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6210       ) cols;
6211       pr "}\n";
6212       pr "\n";
6213   ) structs;
6214
6215   (* Emit a print_TYPE_list function definition only if that function is used. *)
6216   List.iter (
6217     function
6218     | typ, (RStructListOnly | RStructAndList) ->
6219         (* generate the function for typ *)
6220         emit_print_list_function typ
6221     | typ, _ -> () (* empty *)
6222   ) rstructs_used;
6223
6224   (* Emit a print_TYPE function definition only if that function is used. *)
6225   List.iter (
6226     function
6227     | typ, RStructOnly ->
6228         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6229         pr "{\n";
6230         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6231         pr "}\n";
6232         pr "\n";
6233     | typ, _ -> () (* empty *)
6234   ) rstructs_used;
6235
6236   (* run_<action> actions *)
6237   List.iter (
6238     fun (name, style, _, flags, _, _, _) ->
6239       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6240       pr "{\n";
6241       (match fst style with
6242        | RErr
6243        | RInt _
6244        | RBool _ -> pr "  int r;\n"
6245        | RInt64 _ -> pr "  int64_t r;\n"
6246        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6247        | RString _ -> pr "  char *r;\n"
6248        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6249        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6250        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6251        | RBufferOut _ ->
6252            pr "  char *r;\n";
6253            pr "  size_t size;\n";
6254       );
6255       List.iter (
6256         function
6257         | Pathname n
6258         | Device n | Dev_or_Path n
6259         | String n
6260         | OptString n
6261         | FileIn n
6262         | FileOut n -> pr "  const char *%s;\n" n
6263         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6264         | Bool n -> pr "  int %s;\n" n
6265         | Int n -> pr "  int %s;\n" n
6266       ) (snd style);
6267
6268       (* Check and convert parameters. *)
6269       let argc_expected = List.length (snd style) in
6270       pr "  if (argc != %d) {\n" argc_expected;
6271       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6272         argc_expected;
6273       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6274       pr "    return -1;\n";
6275       pr "  }\n";
6276       iteri (
6277         fun i ->
6278           function
6279           | Pathname name
6280           | Device name | Dev_or_Path name | String name -> pr "  %s = argv[%d];\n" name i
6281           | OptString name ->
6282               pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6283                 name i i
6284           | FileIn name ->
6285               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6286                 name i i
6287           | FileOut name ->
6288               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6289                 name i i
6290           | StringList name | DeviceList name ->
6291               pr "  %s = parse_string_list (argv[%d]);\n" name i
6292           | Bool name ->
6293               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6294           | Int name ->
6295               pr "  %s = atoi (argv[%d]);\n" name i
6296       ) (snd style);
6297
6298       (* Call C API function. *)
6299       let fn =
6300         try find_map (function FishAction n -> Some n | _ -> None) flags
6301         with Not_found -> sprintf "guestfs_%s" name in
6302       pr "  r = %s " fn;
6303       generate_c_call_args ~handle:"g" style;
6304       pr ";\n";
6305
6306       List.iter (
6307         function
6308         | Pathname name | Device name | Dev_or_Path name | String name
6309         | OptString name | FileIn name | FileOut name | Bool name
6310         | Int name -> ()
6311         | StringList name | DeviceList name ->
6312             pr "  free_strings (%s);\n" name
6313       ) (snd style);
6314
6315       (* Check return value for errors and display command results. *)
6316       (match fst style with
6317        | RErr -> pr "  return r;\n"
6318        | RInt _ ->
6319            pr "  if (r == -1) return -1;\n";
6320            pr "  printf (\"%%d\\n\", r);\n";
6321            pr "  return 0;\n"
6322        | RInt64 _ ->
6323            pr "  if (r == -1) return -1;\n";
6324            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6325            pr "  return 0;\n"
6326        | RBool _ ->
6327            pr "  if (r == -1) return -1;\n";
6328            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6329            pr "  return 0;\n"
6330        | RConstString _ ->
6331            pr "  if (r == NULL) return -1;\n";
6332            pr "  printf (\"%%s\\n\", r);\n";
6333            pr "  return 0;\n"
6334        | RConstOptString _ ->
6335            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6336            pr "  return 0;\n"
6337        | RString _ ->
6338            pr "  if (r == NULL) return -1;\n";
6339            pr "  printf (\"%%s\\n\", r);\n";
6340            pr "  free (r);\n";
6341            pr "  return 0;\n"
6342        | RStringList _ ->
6343            pr "  if (r == NULL) return -1;\n";
6344            pr "  print_strings (r);\n";
6345            pr "  free_strings (r);\n";
6346            pr "  return 0;\n"
6347        | RStruct (_, typ) ->
6348            pr "  if (r == NULL) return -1;\n";
6349            pr "  print_%s (r);\n" typ;
6350            pr "  guestfs_free_%s (r);\n" typ;
6351            pr "  return 0;\n"
6352        | RStructList (_, typ) ->
6353            pr "  if (r == NULL) return -1;\n";
6354            pr "  print_%s_list (r);\n" typ;
6355            pr "  guestfs_free_%s_list (r);\n" typ;
6356            pr "  return 0;\n"
6357        | RHashtable _ ->
6358            pr "  if (r == NULL) return -1;\n";
6359            pr "  print_table (r);\n";
6360            pr "  free_strings (r);\n";
6361            pr "  return 0;\n"
6362        | RBufferOut _ ->
6363            pr "  if (r == NULL) return -1;\n";
6364            pr "  fwrite (r, size, 1, stdout);\n";
6365            pr "  free (r);\n";
6366            pr "  return 0;\n"
6367       );
6368       pr "}\n";
6369       pr "\n"
6370   ) all_functions;
6371
6372   (* run_action function *)
6373   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6374   pr "{\n";
6375   List.iter (
6376     fun (name, _, _, flags, _, _, _) ->
6377       let name2 = replace_char name '_' '-' in
6378       let alias =
6379         try find_map (function FishAlias n -> Some n | _ -> None) flags
6380         with Not_found -> name in
6381       pr "  if (";
6382       pr "strcasecmp (cmd, \"%s\") == 0" name;
6383       if name <> name2 then
6384         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6385       if name <> alias then
6386         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6387       pr ")\n";
6388       pr "    return run_%s (cmd, argc, argv);\n" name;
6389       pr "  else\n";
6390   ) all_functions;
6391   pr "    {\n";
6392   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6393   pr "      return -1;\n";
6394   pr "    }\n";
6395   pr "  return 0;\n";
6396   pr "}\n";
6397   pr "\n"
6398
6399 (* Readline completion for guestfish. *)
6400 and generate_fish_completion () =
6401   generate_header CStyle GPLv2;
6402
6403   let all_functions =
6404     List.filter (
6405       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6406     ) all_functions in
6407
6408   pr "\
6409 #include <config.h>
6410
6411 #include <stdio.h>
6412 #include <stdlib.h>
6413 #include <string.h>
6414
6415 #ifdef HAVE_LIBREADLINE
6416 #include <readline/readline.h>
6417 #endif
6418
6419 #include \"fish.h\"
6420
6421 #ifdef HAVE_LIBREADLINE
6422
6423 static const char *const commands[] = {
6424   BUILTIN_COMMANDS_FOR_COMPLETION,
6425 ";
6426
6427   (* Get the commands, including the aliases.  They don't need to be
6428    * sorted - the generator() function just does a dumb linear search.
6429    *)
6430   let commands =
6431     List.map (
6432       fun (name, _, _, flags, _, _, _) ->
6433         let name2 = replace_char name '_' '-' in
6434         let alias =
6435           try find_map (function FishAlias n -> Some n | _ -> None) flags
6436           with Not_found -> name in
6437
6438         if name <> alias then [name2; alias] else [name2]
6439     ) all_functions in
6440   let commands = List.flatten commands in
6441
6442   List.iter (pr "  \"%s\",\n") commands;
6443
6444   pr "  NULL
6445 };
6446
6447 static char *
6448 generator (const char *text, int state)
6449 {
6450   static int index, len;
6451   const char *name;
6452
6453   if (!state) {
6454     index = 0;
6455     len = strlen (text);
6456   }
6457
6458   rl_attempted_completion_over = 1;
6459
6460   while ((name = commands[index]) != NULL) {
6461     index++;
6462     if (strncasecmp (name, text, len) == 0)
6463       return strdup (name);
6464   }
6465
6466   return NULL;
6467 }
6468
6469 #endif /* HAVE_LIBREADLINE */
6470
6471 char **do_completion (const char *text, int start, int end)
6472 {
6473   char **matches = NULL;
6474
6475 #ifdef HAVE_LIBREADLINE
6476   rl_completion_append_character = ' ';
6477
6478   if (start == 0)
6479     matches = rl_completion_matches (text, generator);
6480   else if (complete_dest_paths)
6481     matches = rl_completion_matches (text, complete_dest_paths_generator);
6482 #endif
6483
6484   return matches;
6485 }
6486 ";
6487
6488 (* Generate the POD documentation for guestfish. *)
6489 and generate_fish_actions_pod () =
6490   let all_functions_sorted =
6491     List.filter (
6492       fun (_, _, _, flags, _, _, _) ->
6493         not (List.mem NotInFish flags || List.mem NotInDocs flags)
6494     ) all_functions_sorted in
6495
6496   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6497
6498   List.iter (
6499     fun (name, style, _, flags, _, _, longdesc) ->
6500       let longdesc =
6501         Str.global_substitute rex (
6502           fun s ->
6503             let sub =
6504               try Str.matched_group 1 s
6505               with Not_found ->
6506                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6507             "C<" ^ replace_char sub '_' '-' ^ ">"
6508         ) longdesc in
6509       let name = replace_char name '_' '-' in
6510       let alias =
6511         try find_map (function FishAlias n -> Some n | _ -> None) flags
6512         with Not_found -> name in
6513
6514       pr "=head2 %s" name;
6515       if name <> alias then
6516         pr " | %s" alias;
6517       pr "\n";
6518       pr "\n";
6519       pr " %s" name;
6520       List.iter (
6521         function
6522         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6523         | OptString n -> pr " %s" n
6524         | StringList n | DeviceList n -> pr " '%s ...'" n
6525         | Bool _ -> pr " true|false"
6526         | Int n -> pr " %s" n
6527         | FileIn n | FileOut n -> pr " (%s|-)" n
6528       ) (snd style);
6529       pr "\n";
6530       pr "\n";
6531       pr "%s\n\n" longdesc;
6532
6533       if List.exists (function FileIn _ | FileOut _ -> true
6534                       | _ -> false) (snd style) then
6535         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6536
6537       if List.mem ProtocolLimitWarning flags then
6538         pr "%s\n\n" protocol_limit_warning;
6539
6540       if List.mem DangerWillRobinson flags then
6541         pr "%s\n\n" danger_will_robinson;
6542
6543       match deprecation_notice flags with
6544       | None -> ()
6545       | Some txt -> pr "%s\n\n" txt
6546   ) all_functions_sorted
6547
6548 (* Generate a C function prototype. *)
6549 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6550     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6551     ?(prefix = "")
6552     ?handle name style =
6553   if extern then pr "extern ";
6554   if static then pr "static ";
6555   (match fst style with
6556    | RErr -> pr "int "
6557    | RInt _ -> pr "int "
6558    | RInt64 _ -> pr "int64_t "
6559    | RBool _ -> pr "int "
6560    | RConstString _ | RConstOptString _ -> pr "const char *"
6561    | RString _ | RBufferOut _ -> pr "char *"
6562    | RStringList _ | RHashtable _ -> pr "char **"
6563    | RStruct (_, typ) ->
6564        if not in_daemon then pr "struct guestfs_%s *" typ
6565        else pr "guestfs_int_%s *" typ
6566    | RStructList (_, typ) ->
6567        if not in_daemon then pr "struct guestfs_%s_list *" typ
6568        else pr "guestfs_int_%s_list *" typ
6569   );
6570   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6571   pr "%s%s (" prefix name;
6572   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6573     pr "void"
6574   else (
6575     let comma = ref false in
6576     (match handle with
6577      | None -> ()
6578      | Some handle -> pr "guestfs_h *%s" handle; comma := true
6579     );
6580     let next () =
6581       if !comma then (
6582         if single_line then pr ", " else pr ",\n\t\t"
6583       );
6584       comma := true
6585     in
6586     List.iter (
6587       function
6588       | Pathname n
6589       | Device n | Dev_or_Path n
6590       | String n
6591       | OptString n ->
6592           next ();
6593           pr "const char *%s" n
6594       | StringList n | DeviceList n ->
6595           next ();
6596           pr "char *const *%s" n
6597       | Bool n -> next (); pr "int %s" n
6598       | Int n -> next (); pr "int %s" n
6599       | FileIn n
6600       | FileOut n ->
6601           if not in_daemon then (next (); pr "const char *%s" n)
6602     ) (snd style);
6603     if is_RBufferOut then (next (); pr "size_t *size_r");
6604   );
6605   pr ")";
6606   if semicolon then pr ";";
6607   if newline then pr "\n"
6608
6609 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6610 and generate_c_call_args ?handle ?(decl = false) style =
6611   pr "(";
6612   let comma = ref false in
6613   let next () =
6614     if !comma then pr ", ";
6615     comma := true
6616   in
6617   (match handle with
6618    | None -> ()
6619    | Some handle -> pr "%s" handle; comma := true
6620   );
6621   List.iter (
6622     fun arg ->
6623       next ();
6624       pr "%s" (name_of_argt arg)
6625   ) (snd style);
6626   (* For RBufferOut calls, add implicit &size parameter. *)
6627   if not decl then (
6628     match fst style with
6629     | RBufferOut _ ->
6630         next ();
6631         pr "&size"
6632     | _ -> ()
6633   );
6634   pr ")"
6635
6636 (* Generate the OCaml bindings interface. *)
6637 and generate_ocaml_mli () =
6638   generate_header OCamlStyle LGPLv2;
6639
6640   pr "\
6641 (** For API documentation you should refer to the C API
6642     in the guestfs(3) manual page.  The OCaml API uses almost
6643     exactly the same calls. *)
6644
6645 type t
6646 (** A [guestfs_h] handle. *)
6647
6648 exception Error of string
6649 (** This exception is raised when there is an error. *)
6650
6651 val create : unit -> t
6652
6653 val close : t -> unit
6654 (** Handles are closed by the garbage collector when they become
6655     unreferenced, but callers can also call this in order to
6656     provide predictable cleanup. *)
6657
6658 ";
6659   generate_ocaml_structure_decls ();
6660
6661   (* The actions. *)
6662   List.iter (
6663     fun (name, style, _, _, _, shortdesc, _) ->
6664       generate_ocaml_prototype name style;
6665       pr "(** %s *)\n" shortdesc;
6666       pr "\n"
6667   ) all_functions
6668
6669 (* Generate the OCaml bindings implementation. *)
6670 and generate_ocaml_ml () =
6671   generate_header OCamlStyle LGPLv2;
6672
6673   pr "\
6674 type t
6675 exception Error of string
6676 external create : unit -> t = \"ocaml_guestfs_create\"
6677 external close : t -> unit = \"ocaml_guestfs_close\"
6678
6679 let () =
6680   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6681
6682 ";
6683
6684   generate_ocaml_structure_decls ();
6685
6686   (* The actions. *)
6687   List.iter (
6688     fun (name, style, _, _, _, shortdesc, _) ->
6689       generate_ocaml_prototype ~is_external:true name style;
6690   ) all_functions
6691
6692 (* Generate the OCaml bindings C implementation. *)
6693 and generate_ocaml_c () =
6694   generate_header CStyle LGPLv2;
6695
6696   pr "\
6697 #include <stdio.h>
6698 #include <stdlib.h>
6699 #include <string.h>
6700
6701 #include <caml/config.h>
6702 #include <caml/alloc.h>
6703 #include <caml/callback.h>
6704 #include <caml/fail.h>
6705 #include <caml/memory.h>
6706 #include <caml/mlvalues.h>
6707 #include <caml/signals.h>
6708
6709 #include <guestfs.h>
6710
6711 #include \"guestfs_c.h\"
6712
6713 /* Copy a hashtable of string pairs into an assoc-list.  We return
6714  * the list in reverse order, but hashtables aren't supposed to be
6715  * ordered anyway.
6716  */
6717 static CAMLprim value
6718 copy_table (char * const * argv)
6719 {
6720   CAMLparam0 ();
6721   CAMLlocal5 (rv, pairv, kv, vv, cons);
6722   int i;
6723
6724   rv = Val_int (0);
6725   for (i = 0; argv[i] != NULL; i += 2) {
6726     kv = caml_copy_string (argv[i]);
6727     vv = caml_copy_string (argv[i+1]);
6728     pairv = caml_alloc (2, 0);
6729     Store_field (pairv, 0, kv);
6730     Store_field (pairv, 1, vv);
6731     cons = caml_alloc (2, 0);
6732     Store_field (cons, 1, rv);
6733     rv = cons;
6734     Store_field (cons, 0, pairv);
6735   }
6736
6737   CAMLreturn (rv);
6738 }
6739
6740 ";
6741
6742   (* Struct copy functions. *)
6743
6744   let emit_ocaml_copy_list_function typ =
6745     pr "static CAMLprim value\n";
6746     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
6747     pr "{\n";
6748     pr "  CAMLparam0 ();\n";
6749     pr "  CAMLlocal2 (rv, v);\n";
6750     pr "  unsigned int i;\n";
6751     pr "\n";
6752     pr "  if (%ss->len == 0)\n" typ;
6753     pr "    CAMLreturn (Atom (0));\n";
6754     pr "  else {\n";
6755     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
6756     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
6757     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
6758     pr "      caml_modify (&Field (rv, i), v);\n";
6759     pr "    }\n";
6760     pr "    CAMLreturn (rv);\n";
6761     pr "  }\n";
6762     pr "}\n";
6763     pr "\n";
6764   in
6765
6766   List.iter (
6767     fun (typ, cols) ->
6768       let has_optpercent_col =
6769         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6770
6771       pr "static CAMLprim value\n";
6772       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6773       pr "{\n";
6774       pr "  CAMLparam0 ();\n";
6775       if has_optpercent_col then
6776         pr "  CAMLlocal3 (rv, v, v2);\n"
6777       else
6778         pr "  CAMLlocal2 (rv, v);\n";
6779       pr "\n";
6780       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
6781       iteri (
6782         fun i col ->
6783           (match col with
6784            | name, FString ->
6785                pr "  v = caml_copy_string (%s->%s);\n" typ name
6786            | name, FBuffer ->
6787                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
6788                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6789                  typ name typ name
6790            | name, FUUID ->
6791                pr "  v = caml_alloc_string (32);\n";
6792                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
6793            | name, (FBytes|FInt64|FUInt64) ->
6794                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
6795            | name, (FInt32|FUInt32) ->
6796                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
6797            | name, FOptPercent ->
6798                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
6799                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
6800                pr "    v = caml_alloc (1, 0);\n";
6801                pr "    Store_field (v, 0, v2);\n";
6802                pr "  } else /* None */\n";
6803                pr "    v = Val_int (0);\n";
6804            | name, FChar ->
6805                pr "  v = Val_int (%s->%s);\n" typ name
6806           );
6807           pr "  Store_field (rv, %d, v);\n" i
6808       ) cols;
6809       pr "  CAMLreturn (rv);\n";
6810       pr "}\n";
6811       pr "\n";
6812   ) structs;
6813
6814   (* Emit a copy_TYPE_list function definition only if that function is used. *)
6815   List.iter (
6816     function
6817     | typ, (RStructListOnly | RStructAndList) ->
6818         (* generate the function for typ *)
6819         emit_ocaml_copy_list_function typ
6820     | typ, _ -> () (* empty *)
6821   ) rstructs_used;
6822
6823   (* The wrappers. *)
6824   List.iter (
6825     fun (name, style, _, _, _, _, _) ->
6826       let params =
6827         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
6828
6829       let needs_extra_vs =
6830         match fst style with RConstOptString _ -> true | _ -> false in
6831
6832       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
6833       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
6834       List.iter (pr ", value %s") (List.tl params); pr ");\n";
6835
6836       pr "CAMLprim value\n";
6837       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
6838       List.iter (pr ", value %s") (List.tl params);
6839       pr ")\n";
6840       pr "{\n";
6841
6842       (match params with
6843        | [p1; p2; p3; p4; p5] ->
6844            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
6845        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
6846            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
6847            pr "  CAMLxparam%d (%s);\n"
6848              (List.length rest) (String.concat ", " rest)
6849        | ps ->
6850            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
6851       );
6852       if not needs_extra_vs then
6853         pr "  CAMLlocal1 (rv);\n"
6854       else
6855         pr "  CAMLlocal3 (rv, v, v2);\n";
6856       pr "\n";
6857
6858       pr "  guestfs_h *g = Guestfs_val (gv);\n";
6859       pr "  if (g == NULL)\n";
6860       pr "    caml_failwith (\"%s: used handle after closing it\");\n" name;
6861       pr "\n";
6862
6863       List.iter (
6864         function
6865         | Pathname n
6866         | Device n | Dev_or_Path n
6867         | String n
6868         | FileIn n
6869         | FileOut n ->
6870             pr "  const char *%s = String_val (%sv);\n" n n
6871         | OptString n ->
6872             pr "  const char *%s =\n" n;
6873             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
6874               n n
6875         | StringList n | DeviceList n ->
6876             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
6877         | Bool n ->
6878             pr "  int %s = Bool_val (%sv);\n" n n
6879         | Int n ->
6880             pr "  int %s = Int_val (%sv);\n" n n
6881       ) (snd style);
6882       let error_code =
6883         match fst style with
6884         | RErr -> pr "  int r;\n"; "-1"
6885         | RInt _ -> pr "  int r;\n"; "-1"
6886         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6887         | RBool _ -> pr "  int r;\n"; "-1"
6888         | RConstString _ | RConstOptString _ ->
6889             pr "  const char *r;\n"; "NULL"
6890         | RString _ -> pr "  char *r;\n"; "NULL"
6891         | RStringList _ ->
6892             pr "  int i;\n";
6893             pr "  char **r;\n";
6894             "NULL"
6895         | RStruct (_, typ) ->
6896             pr "  struct guestfs_%s *r;\n" typ; "NULL"
6897         | RStructList (_, typ) ->
6898             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
6899         | RHashtable _ ->
6900             pr "  int i;\n";
6901             pr "  char **r;\n";
6902             "NULL"
6903         | RBufferOut _ ->
6904             pr "  char *r;\n";
6905             pr "  size_t size;\n";
6906             "NULL" in
6907       pr "\n";
6908
6909       pr "  caml_enter_blocking_section ();\n";
6910       pr "  r = guestfs_%s " name;
6911       generate_c_call_args ~handle:"g" style;
6912       pr ";\n";
6913       pr "  caml_leave_blocking_section ();\n";
6914
6915       List.iter (
6916         function
6917         | StringList n | DeviceList n ->
6918             pr "  ocaml_guestfs_free_strings (%s);\n" n;
6919         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
6920         | FileIn _ | FileOut _ -> ()
6921       ) (snd style);
6922
6923       pr "  if (r == %s)\n" error_code;
6924       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
6925       pr "\n";
6926
6927       (match fst style with
6928        | RErr -> pr "  rv = Val_unit;\n"
6929        | RInt _ -> pr "  rv = Val_int (r);\n"
6930        | RInt64 _ ->
6931            pr "  rv = caml_copy_int64 (r);\n"
6932        | RBool _ -> pr "  rv = Val_bool (r);\n"
6933        | RConstString _ ->
6934            pr "  rv = caml_copy_string (r);\n"
6935        | RConstOptString _ ->
6936            pr "  if (r) { /* Some string */\n";
6937            pr "    v = caml_alloc (1, 0);\n";
6938            pr "    v2 = caml_copy_string (r);\n";
6939            pr "    Store_field (v, 0, v2);\n";
6940            pr "  } else /* None */\n";
6941            pr "    v = Val_int (0);\n";
6942        | RString _ ->
6943            pr "  rv = caml_copy_string (r);\n";
6944            pr "  free (r);\n"
6945        | RStringList _ ->
6946            pr "  rv = caml_copy_string_array ((const char **) r);\n";
6947            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6948            pr "  free (r);\n"
6949        | RStruct (_, typ) ->
6950            pr "  rv = copy_%s (r);\n" typ;
6951            pr "  guestfs_free_%s (r);\n" typ;
6952        | RStructList (_, typ) ->
6953            pr "  rv = copy_%s_list (r);\n" typ;
6954            pr "  guestfs_free_%s_list (r);\n" typ;
6955        | RHashtable _ ->
6956            pr "  rv = copy_table (r);\n";
6957            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6958            pr "  free (r);\n";
6959        | RBufferOut _ ->
6960            pr "  rv = caml_alloc_string (size);\n";
6961            pr "  memcpy (String_val (rv), r, size);\n";
6962       );
6963
6964       pr "  CAMLreturn (rv);\n";
6965       pr "}\n";
6966       pr "\n";
6967
6968       if List.length params > 5 then (
6969         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
6970         pr "CAMLprim value ";
6971         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
6972         pr "CAMLprim value\n";
6973         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
6974         pr "{\n";
6975         pr "  return ocaml_guestfs_%s (argv[0]" name;
6976         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
6977         pr ");\n";
6978         pr "}\n";
6979         pr "\n"
6980       )
6981   ) all_functions
6982
6983 and generate_ocaml_structure_decls () =
6984   List.iter (
6985     fun (typ, cols) ->
6986       pr "type %s = {\n" typ;
6987       List.iter (
6988         function
6989         | name, FString -> pr "  %s : string;\n" name
6990         | name, FBuffer -> pr "  %s : string;\n" name
6991         | name, FUUID -> pr "  %s : string;\n" name
6992         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
6993         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
6994         | name, FChar -> pr "  %s : char;\n" name
6995         | name, FOptPercent -> pr "  %s : float option;\n" name
6996       ) cols;
6997       pr "}\n";
6998       pr "\n"
6999   ) structs
7000
7001 and generate_ocaml_prototype ?(is_external = false) name style =
7002   if is_external then pr "external " else pr "val ";
7003   pr "%s : t -> " name;
7004   List.iter (
7005     function
7006     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7007     | OptString _ -> pr "string option -> "
7008     | StringList _ | DeviceList _ -> pr "string array -> "
7009     | Bool _ -> pr "bool -> "
7010     | Int _ -> pr "int -> "
7011   ) (snd style);
7012   (match fst style with
7013    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7014    | RInt _ -> pr "int"
7015    | RInt64 _ -> pr "int64"
7016    | RBool _ -> pr "bool"
7017    | RConstString _ -> pr "string"
7018    | RConstOptString _ -> pr "string option"
7019    | RString _ | RBufferOut _ -> pr "string"
7020    | RStringList _ -> pr "string array"
7021    | RStruct (_, typ) -> pr "%s" typ
7022    | RStructList (_, typ) -> pr "%s array" typ
7023    | RHashtable _ -> pr "(string * string) list"
7024   );
7025   if is_external then (
7026     pr " = ";
7027     if List.length (snd style) + 1 > 5 then
7028       pr "\"ocaml_guestfs_%s_byte\" " name;
7029     pr "\"ocaml_guestfs_%s\"" name
7030   );
7031   pr "\n"
7032
7033 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7034 and generate_perl_xs () =
7035   generate_header CStyle LGPLv2;
7036
7037   pr "\
7038 #include \"EXTERN.h\"
7039 #include \"perl.h\"
7040 #include \"XSUB.h\"
7041
7042 #include <guestfs.h>
7043
7044 #ifndef PRId64
7045 #define PRId64 \"lld\"
7046 #endif
7047
7048 static SV *
7049 my_newSVll(long long val) {
7050 #ifdef USE_64_BIT_ALL
7051   return newSViv(val);
7052 #else
7053   char buf[100];
7054   int len;
7055   len = snprintf(buf, 100, \"%%\" PRId64, val);
7056   return newSVpv(buf, len);
7057 #endif
7058 }
7059
7060 #ifndef PRIu64
7061 #define PRIu64 \"llu\"
7062 #endif
7063
7064 static SV *
7065 my_newSVull(unsigned long long val) {
7066 #ifdef USE_64_BIT_ALL
7067   return newSVuv(val);
7068 #else
7069   char buf[100];
7070   int len;
7071   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7072   return newSVpv(buf, len);
7073 #endif
7074 }
7075
7076 /* http://www.perlmonks.org/?node_id=680842 */
7077 static char **
7078 XS_unpack_charPtrPtr (SV *arg) {
7079   char **ret;
7080   AV *av;
7081   I32 i;
7082
7083   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7084     croak (\"array reference expected\");
7085
7086   av = (AV *)SvRV (arg);
7087   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7088   if (!ret)
7089     croak (\"malloc failed\");
7090
7091   for (i = 0; i <= av_len (av); i++) {
7092     SV **elem = av_fetch (av, i, 0);
7093
7094     if (!elem || !*elem)
7095       croak (\"missing element in list\");
7096
7097     ret[i] = SvPV_nolen (*elem);
7098   }
7099
7100   ret[i] = NULL;
7101
7102   return ret;
7103 }
7104
7105 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7106
7107 PROTOTYPES: ENABLE
7108
7109 guestfs_h *
7110 _create ()
7111    CODE:
7112       RETVAL = guestfs_create ();
7113       if (!RETVAL)
7114         croak (\"could not create guestfs handle\");
7115       guestfs_set_error_handler (RETVAL, NULL, NULL);
7116  OUTPUT:
7117       RETVAL
7118
7119 void
7120 DESTROY (g)
7121       guestfs_h *g;
7122  PPCODE:
7123       guestfs_close (g);
7124
7125 ";
7126
7127   List.iter (
7128     fun (name, style, _, _, _, _, _) ->
7129       (match fst style with
7130        | RErr -> pr "void\n"
7131        | RInt _ -> pr "SV *\n"
7132        | RInt64 _ -> pr "SV *\n"
7133        | RBool _ -> pr "SV *\n"
7134        | RConstString _ -> pr "SV *\n"
7135        | RConstOptString _ -> pr "SV *\n"
7136        | RString _ -> pr "SV *\n"
7137        | RBufferOut _ -> pr "SV *\n"
7138        | RStringList _
7139        | RStruct _ | RStructList _
7140        | RHashtable _ ->
7141            pr "void\n" (* all lists returned implictly on the stack *)
7142       );
7143       (* Call and arguments. *)
7144       pr "%s " name;
7145       generate_c_call_args ~handle:"g" ~decl:true style;
7146       pr "\n";
7147       pr "      guestfs_h *g;\n";
7148       iteri (
7149         fun i ->
7150           function
7151           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7152               pr "      char *%s;\n" n
7153           | OptString n ->
7154               (* http://www.perlmonks.org/?node_id=554277
7155                * Note that the implicit handle argument means we have
7156                * to add 1 to the ST(x) operator.
7157                *)
7158               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7159           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7160           | Bool n -> pr "      int %s;\n" n
7161           | Int n -> pr "      int %s;\n" n
7162       ) (snd style);
7163
7164       let do_cleanups () =
7165         List.iter (
7166           function
7167           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
7168           | FileIn _ | FileOut _ -> ()
7169           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7170         ) (snd style)
7171       in
7172
7173       (* Code. *)
7174       (match fst style with
7175        | RErr ->
7176            pr "PREINIT:\n";
7177            pr "      int r;\n";
7178            pr " PPCODE:\n";
7179            pr "      r = guestfs_%s " name;
7180            generate_c_call_args ~handle:"g" style;
7181            pr ";\n";
7182            do_cleanups ();
7183            pr "      if (r == -1)\n";
7184            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7185        | RInt n
7186        | RBool n ->
7187            pr "PREINIT:\n";
7188            pr "      int %s;\n" n;
7189            pr "   CODE:\n";
7190            pr "      %s = guestfs_%s " n name;
7191            generate_c_call_args ~handle:"g" style;
7192            pr ";\n";
7193            do_cleanups ();
7194            pr "      if (%s == -1)\n" n;
7195            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7196            pr "      RETVAL = newSViv (%s);\n" n;
7197            pr " OUTPUT:\n";
7198            pr "      RETVAL\n"
7199        | RInt64 n ->
7200            pr "PREINIT:\n";
7201            pr "      int64_t %s;\n" n;
7202            pr "   CODE:\n";
7203            pr "      %s = guestfs_%s " n name;
7204            generate_c_call_args ~handle:"g" style;
7205            pr ";\n";
7206            do_cleanups ();
7207            pr "      if (%s == -1)\n" n;
7208            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7209            pr "      RETVAL = my_newSVll (%s);\n" n;
7210            pr " OUTPUT:\n";
7211            pr "      RETVAL\n"
7212        | RConstString n ->
7213            pr "PREINIT:\n";
7214            pr "      const char *%s;\n" n;
7215            pr "   CODE:\n";
7216            pr "      %s = guestfs_%s " n name;
7217            generate_c_call_args ~handle:"g" style;
7218            pr ";\n";
7219            do_cleanups ();
7220            pr "      if (%s == NULL)\n" n;
7221            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7222            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7223            pr " OUTPUT:\n";
7224            pr "      RETVAL\n"
7225        | RConstOptString n ->
7226            pr "PREINIT:\n";
7227            pr "      const char *%s;\n" n;
7228            pr "   CODE:\n";
7229            pr "      %s = guestfs_%s " n name;
7230            generate_c_call_args ~handle:"g" style;
7231            pr ";\n";
7232            do_cleanups ();
7233            pr "      if (%s == NULL)\n" n;
7234            pr "        RETVAL = &PL_sv_undef;\n";
7235            pr "      else\n";
7236            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7237            pr " OUTPUT:\n";
7238            pr "      RETVAL\n"
7239        | RString n ->
7240            pr "PREINIT:\n";
7241            pr "      char *%s;\n" n;
7242            pr "   CODE:\n";
7243            pr "      %s = guestfs_%s " n name;
7244            generate_c_call_args ~handle:"g" style;
7245            pr ";\n";
7246            do_cleanups ();
7247            pr "      if (%s == NULL)\n" n;
7248            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7249            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7250            pr "      free (%s);\n" n;
7251            pr " OUTPUT:\n";
7252            pr "      RETVAL\n"
7253        | RStringList n | RHashtable n ->
7254            pr "PREINIT:\n";
7255            pr "      char **%s;\n" n;
7256            pr "      int i, n;\n";
7257            pr " PPCODE:\n";
7258            pr "      %s = guestfs_%s " n name;
7259            generate_c_call_args ~handle:"g" style;
7260            pr ";\n";
7261            do_cleanups ();
7262            pr "      if (%s == NULL)\n" n;
7263            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7264            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7265            pr "      EXTEND (SP, n);\n";
7266            pr "      for (i = 0; i < n; ++i) {\n";
7267            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7268            pr "        free (%s[i]);\n" n;
7269            pr "      }\n";
7270            pr "      free (%s);\n" n;
7271        | RStruct (n, typ) ->
7272            let cols = cols_of_struct typ in
7273            generate_perl_struct_code typ cols name style n do_cleanups
7274        | RStructList (n, typ) ->
7275            let cols = cols_of_struct typ in
7276            generate_perl_struct_list_code typ cols name style n do_cleanups
7277        | RBufferOut n ->
7278            pr "PREINIT:\n";
7279            pr "      char *%s;\n" n;
7280            pr "      size_t size;\n";
7281            pr "   CODE:\n";
7282            pr "      %s = guestfs_%s " n name;
7283            generate_c_call_args ~handle:"g" style;
7284            pr ";\n";
7285            do_cleanups ();
7286            pr "      if (%s == NULL)\n" n;
7287            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7288            pr "      RETVAL = newSVpv (%s, size);\n" n;
7289            pr "      free (%s);\n" n;
7290            pr " OUTPUT:\n";
7291            pr "      RETVAL\n"
7292       );
7293
7294       pr "\n"
7295   ) all_functions
7296
7297 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7298   pr "PREINIT:\n";
7299   pr "      struct guestfs_%s_list *%s;\n" typ n;
7300   pr "      int i;\n";
7301   pr "      HV *hv;\n";
7302   pr " PPCODE:\n";
7303   pr "      %s = guestfs_%s " n name;
7304   generate_c_call_args ~handle:"g" style;
7305   pr ";\n";
7306   do_cleanups ();
7307   pr "      if (%s == NULL)\n" n;
7308   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7309   pr "      EXTEND (SP, %s->len);\n" n;
7310   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7311   pr "        hv = newHV ();\n";
7312   List.iter (
7313     function
7314     | name, FString ->
7315         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7316           name (String.length name) n name
7317     | name, FUUID ->
7318         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7319           name (String.length name) n name
7320     | name, FBuffer ->
7321         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7322           name (String.length name) n name n name
7323     | name, (FBytes|FUInt64) ->
7324         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7325           name (String.length name) n name
7326     | name, FInt64 ->
7327         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7328           name (String.length name) n name
7329     | name, (FInt32|FUInt32) ->
7330         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7331           name (String.length name) n name
7332     | name, FChar ->
7333         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7334           name (String.length name) n name
7335     | name, FOptPercent ->
7336         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7337           name (String.length name) n name
7338   ) cols;
7339   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7340   pr "      }\n";
7341   pr "      guestfs_free_%s_list (%s);\n" typ n
7342
7343 and generate_perl_struct_code typ cols name style n do_cleanups =
7344   pr "PREINIT:\n";
7345   pr "      struct guestfs_%s *%s;\n" typ n;
7346   pr " PPCODE:\n";
7347   pr "      %s = guestfs_%s " n name;
7348   generate_c_call_args ~handle:"g" style;
7349   pr ";\n";
7350   do_cleanups ();
7351   pr "      if (%s == NULL)\n" n;
7352   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7353   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
7354   List.iter (
7355     fun ((name, _) as col) ->
7356       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7357
7358       match col with
7359       | name, FString ->
7360           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7361             n name
7362       | name, FBuffer ->
7363           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7364             n name n name
7365       | name, FUUID ->
7366           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7367             n name
7368       | name, (FBytes|FUInt64) ->
7369           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7370             n name
7371       | name, FInt64 ->
7372           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7373             n name
7374       | name, (FInt32|FUInt32) ->
7375           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7376             n name
7377       | name, FChar ->
7378           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7379             n name
7380       | name, FOptPercent ->
7381           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7382             n name
7383   ) cols;
7384   pr "      free (%s);\n" n
7385
7386 (* Generate Sys/Guestfs.pm. *)
7387 and generate_perl_pm () =
7388   generate_header HashStyle LGPLv2;
7389
7390   pr "\
7391 =pod
7392
7393 =head1 NAME
7394
7395 Sys::Guestfs - Perl bindings for libguestfs
7396
7397 =head1 SYNOPSIS
7398
7399  use Sys::Guestfs;
7400
7401  my $h = Sys::Guestfs->new ();
7402  $h->add_drive ('guest.img');
7403  $h->launch ();
7404  $h->wait_ready ();
7405  $h->mount ('/dev/sda1', '/');
7406  $h->touch ('/hello');
7407  $h->sync ();
7408
7409 =head1 DESCRIPTION
7410
7411 The C<Sys::Guestfs> module provides a Perl XS binding to the
7412 libguestfs API for examining and modifying virtual machine
7413 disk images.
7414
7415 Amongst the things this is good for: making batch configuration
7416 changes to guests, getting disk used/free statistics (see also:
7417 virt-df), migrating between virtualization systems (see also:
7418 virt-p2v), performing partial backups, performing partial guest
7419 clones, cloning guests and changing registry/UUID/hostname info, and
7420 much else besides.
7421
7422 Libguestfs uses Linux kernel and qemu code, and can access any type of
7423 guest filesystem that Linux and qemu can, including but not limited
7424 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7425 schemes, qcow, qcow2, vmdk.
7426
7427 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7428 LVs, what filesystem is in each LV, etc.).  It can also run commands
7429 in the context of the guest.  Also you can access filesystems over FTP.
7430
7431 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7432 functions for using libguestfs from Perl, including integration
7433 with libvirt.
7434
7435 =head1 ERRORS
7436
7437 All errors turn into calls to C<croak> (see L<Carp(3)>).
7438
7439 =head1 METHODS
7440
7441 =over 4
7442
7443 =cut
7444
7445 package Sys::Guestfs;
7446
7447 use strict;
7448 use warnings;
7449
7450 require XSLoader;
7451 XSLoader::load ('Sys::Guestfs');
7452
7453 =item $h = Sys::Guestfs->new ();
7454
7455 Create a new guestfs handle.
7456
7457 =cut
7458
7459 sub new {
7460   my $proto = shift;
7461   my $class = ref ($proto) || $proto;
7462
7463   my $self = Sys::Guestfs::_create ();
7464   bless $self, $class;
7465   return $self;
7466 }
7467
7468 ";
7469
7470   (* Actions.  We only need to print documentation for these as
7471    * they are pulled in from the XS code automatically.
7472    *)
7473   List.iter (
7474     fun (name, style, _, flags, _, _, longdesc) ->
7475       if not (List.mem NotInDocs flags) then (
7476         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7477         pr "=item ";
7478         generate_perl_prototype name style;
7479         pr "\n\n";
7480         pr "%s\n\n" longdesc;
7481         if List.mem ProtocolLimitWarning flags then
7482           pr "%s\n\n" protocol_limit_warning;
7483         if List.mem DangerWillRobinson flags then
7484           pr "%s\n\n" danger_will_robinson;
7485         match deprecation_notice flags with
7486         | None -> ()
7487         | Some txt -> pr "%s\n\n" txt
7488       )
7489   ) all_functions_sorted;
7490
7491   (* End of file. *)
7492   pr "\
7493 =cut
7494
7495 1;
7496
7497 =back
7498
7499 =head1 COPYRIGHT
7500
7501 Copyright (C) 2009 Red Hat Inc.
7502
7503 =head1 LICENSE
7504
7505 Please see the file COPYING.LIB for the full license.
7506
7507 =head1 SEE ALSO
7508
7509 L<guestfs(3)>,
7510 L<guestfish(1)>,
7511 L<http://libguestfs.org>,
7512 L<Sys::Guestfs::Lib(3)>.
7513
7514 =cut
7515 "
7516
7517 and generate_perl_prototype name style =
7518   (match fst style with
7519    | RErr -> ()
7520    | RBool n
7521    | RInt n
7522    | RInt64 n
7523    | RConstString n
7524    | RConstOptString n
7525    | RString n
7526    | RBufferOut n -> pr "$%s = " n
7527    | RStruct (n,_)
7528    | RHashtable n -> pr "%%%s = " n
7529    | RStringList n
7530    | RStructList (n,_) -> pr "@%s = " n
7531   );
7532   pr "$h->%s (" name;
7533   let comma = ref false in
7534   List.iter (
7535     fun arg ->
7536       if !comma then pr ", ";
7537       comma := true;
7538       match arg with
7539       | Pathname n | Device n | Dev_or_Path n | String n
7540       | OptString n | Bool n | Int n | FileIn n | FileOut n ->
7541           pr "$%s" n
7542       | StringList n | DeviceList n ->
7543           pr "\\@%s" n
7544   ) (snd style);
7545   pr ");"
7546
7547 (* Generate Python C module. *)
7548 and generate_python_c () =
7549   generate_header CStyle LGPLv2;
7550
7551   pr "\
7552 #include <Python.h>
7553
7554 #include <stdio.h>
7555 #include <stdlib.h>
7556 #include <assert.h>
7557
7558 #include \"guestfs.h\"
7559
7560 typedef struct {
7561   PyObject_HEAD
7562   guestfs_h *g;
7563 } Pyguestfs_Object;
7564
7565 static guestfs_h *
7566 get_handle (PyObject *obj)
7567 {
7568   assert (obj);
7569   assert (obj != Py_None);
7570   return ((Pyguestfs_Object *) obj)->g;
7571 }
7572
7573 static PyObject *
7574 put_handle (guestfs_h *g)
7575 {
7576   assert (g);
7577   return
7578     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7579 }
7580
7581 /* This list should be freed (but not the strings) after use. */
7582 static char **
7583 get_string_list (PyObject *obj)
7584 {
7585   int i, len;
7586   char **r;
7587
7588   assert (obj);
7589
7590   if (!PyList_Check (obj)) {
7591     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7592     return NULL;
7593   }
7594
7595   len = PyList_Size (obj);
7596   r = malloc (sizeof (char *) * (len+1));
7597   if (r == NULL) {
7598     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7599     return NULL;
7600   }
7601
7602   for (i = 0; i < len; ++i)
7603     r[i] = PyString_AsString (PyList_GetItem (obj, i));
7604   r[len] = NULL;
7605
7606   return r;
7607 }
7608
7609 static PyObject *
7610 put_string_list (char * const * const argv)
7611 {
7612   PyObject *list;
7613   int argc, i;
7614
7615   for (argc = 0; argv[argc] != NULL; ++argc)
7616     ;
7617
7618   list = PyList_New (argc);
7619   for (i = 0; i < argc; ++i)
7620     PyList_SetItem (list, i, PyString_FromString (argv[i]));
7621
7622   return list;
7623 }
7624
7625 static PyObject *
7626 put_table (char * const * const argv)
7627 {
7628   PyObject *list, *item;
7629   int argc, i;
7630
7631   for (argc = 0; argv[argc] != NULL; ++argc)
7632     ;
7633
7634   list = PyList_New (argc >> 1);
7635   for (i = 0; i < argc; i += 2) {
7636     item = PyTuple_New (2);
7637     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7638     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7639     PyList_SetItem (list, i >> 1, item);
7640   }
7641
7642   return list;
7643 }
7644
7645 static void
7646 free_strings (char **argv)
7647 {
7648   int argc;
7649
7650   for (argc = 0; argv[argc] != NULL; ++argc)
7651     free (argv[argc]);
7652   free (argv);
7653 }
7654
7655 static PyObject *
7656 py_guestfs_create (PyObject *self, PyObject *args)
7657 {
7658   guestfs_h *g;
7659
7660   g = guestfs_create ();
7661   if (g == NULL) {
7662     PyErr_SetString (PyExc_RuntimeError,
7663                      \"guestfs.create: failed to allocate handle\");
7664     return NULL;
7665   }
7666   guestfs_set_error_handler (g, NULL, NULL);
7667   return put_handle (g);
7668 }
7669
7670 static PyObject *
7671 py_guestfs_close (PyObject *self, PyObject *args)
7672 {
7673   PyObject *py_g;
7674   guestfs_h *g;
7675
7676   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7677     return NULL;
7678   g = get_handle (py_g);
7679
7680   guestfs_close (g);
7681
7682   Py_INCREF (Py_None);
7683   return Py_None;
7684 }
7685
7686 ";
7687
7688   let emit_put_list_function typ =
7689     pr "static PyObject *\n";
7690     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7691     pr "{\n";
7692     pr "  PyObject *list;\n";
7693     pr "  int i;\n";
7694     pr "\n";
7695     pr "  list = PyList_New (%ss->len);\n" typ;
7696     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
7697     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7698     pr "  return list;\n";
7699     pr "};\n";
7700     pr "\n"
7701   in
7702
7703   (* Structures, turned into Python dictionaries. *)
7704   List.iter (
7705     fun (typ, cols) ->
7706       pr "static PyObject *\n";
7707       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7708       pr "{\n";
7709       pr "  PyObject *dict;\n";
7710       pr "\n";
7711       pr "  dict = PyDict_New ();\n";
7712       List.iter (
7713         function
7714         | name, FString ->
7715             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7716             pr "                        PyString_FromString (%s->%s));\n"
7717               typ name
7718         | name, FBuffer ->
7719             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7720             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7721               typ name typ name
7722         | name, FUUID ->
7723             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7724             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
7725               typ name
7726         | name, (FBytes|FUInt64) ->
7727             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7728             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
7729               typ name
7730         | name, FInt64 ->
7731             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7732             pr "                        PyLong_FromLongLong (%s->%s));\n"
7733               typ name
7734         | name, FUInt32 ->
7735             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7736             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
7737               typ name
7738         | name, FInt32 ->
7739             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7740             pr "                        PyLong_FromLong (%s->%s));\n"
7741               typ name
7742         | name, FOptPercent ->
7743             pr "  if (%s->%s >= 0)\n" typ name;
7744             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
7745             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
7746               typ name;
7747             pr "  else {\n";
7748             pr "    Py_INCREF (Py_None);\n";
7749             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
7750             pr "  }\n"
7751         | name, FChar ->
7752             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7753             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7754       ) cols;
7755       pr "  return dict;\n";
7756       pr "};\n";
7757       pr "\n";
7758
7759   ) structs;
7760
7761   (* Emit a put_TYPE_list function definition only if that function is used. *)
7762   List.iter (
7763     function
7764     | typ, (RStructListOnly | RStructAndList) ->
7765         (* generate the function for typ *)
7766         emit_put_list_function typ
7767     | typ, _ -> () (* empty *)
7768   ) rstructs_used;
7769
7770   (* Python wrapper functions. *)
7771   List.iter (
7772     fun (name, style, _, _, _, _, _) ->
7773       pr "static PyObject *\n";
7774       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7775       pr "{\n";
7776
7777       pr "  PyObject *py_g;\n";
7778       pr "  guestfs_h *g;\n";
7779       pr "  PyObject *py_r;\n";
7780
7781       let error_code =
7782         match fst style with
7783         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
7784         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7785         | RConstString _ | RConstOptString _ ->
7786             pr "  const char *r;\n"; "NULL"
7787         | RString _ -> pr "  char *r;\n"; "NULL"
7788         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
7789         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
7790         | RStructList (_, typ) ->
7791             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7792         | RBufferOut _ ->
7793             pr "  char *r;\n";
7794             pr "  size_t size;\n";
7795             "NULL" in
7796
7797       List.iter (
7798         function
7799         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7800             pr "  const char *%s;\n" n
7801         | OptString n -> pr "  const char *%s;\n" n
7802         | StringList n | DeviceList n ->
7803             pr "  PyObject *py_%s;\n" n;
7804             pr "  char **%s;\n" n
7805         | Bool n -> pr "  int %s;\n" n
7806         | Int n -> pr "  int %s;\n" n
7807       ) (snd style);
7808
7809       pr "\n";
7810
7811       (* Convert the parameters. *)
7812       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
7813       List.iter (
7814         function
7815         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
7816         | OptString _ -> pr "z"
7817         | StringList _ | DeviceList _ -> pr "O"
7818         | Bool _ -> pr "i" (* XXX Python has booleans? *)
7819         | Int _ -> pr "i"
7820       ) (snd style);
7821       pr ":guestfs_%s\",\n" name;
7822       pr "                         &py_g";
7823       List.iter (
7824         function
7825         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
7826         | OptString n -> pr ", &%s" n
7827         | StringList n | DeviceList n -> pr ", &py_%s" n
7828         | Bool n -> pr ", &%s" n
7829         | Int n -> pr ", &%s" n
7830       ) (snd style);
7831
7832       pr "))\n";
7833       pr "    return NULL;\n";
7834
7835       pr "  g = get_handle (py_g);\n";
7836       List.iter (
7837         function
7838         | Pathname _ | Device _ | Dev_or_Path _ | String _
7839         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7840         | StringList n | DeviceList n ->
7841             pr "  %s = get_string_list (py_%s);\n" n n;
7842             pr "  if (!%s) return NULL;\n" n
7843       ) (snd style);
7844
7845       pr "\n";
7846
7847       pr "  r = guestfs_%s " name;
7848       generate_c_call_args ~handle:"g" style;
7849       pr ";\n";
7850
7851       List.iter (
7852         function
7853         | Pathname _ | Device _ | Dev_or_Path _ | String _
7854         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7855         | StringList n | DeviceList n ->
7856             pr "  free (%s);\n" n
7857       ) (snd style);
7858
7859       pr "  if (r == %s) {\n" error_code;
7860       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
7861       pr "    return NULL;\n";
7862       pr "  }\n";
7863       pr "\n";
7864
7865       (match fst style with
7866        | RErr ->
7867            pr "  Py_INCREF (Py_None);\n";
7868            pr "  py_r = Py_None;\n"
7869        | RInt _
7870        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
7871        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
7872        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
7873        | RConstOptString _ ->
7874            pr "  if (r)\n";
7875            pr "    py_r = PyString_FromString (r);\n";
7876            pr "  else {\n";
7877            pr "    Py_INCREF (Py_None);\n";
7878            pr "    py_r = Py_None;\n";
7879            pr "  }\n"
7880        | RString _ ->
7881            pr "  py_r = PyString_FromString (r);\n";
7882            pr "  free (r);\n"
7883        | RStringList _ ->
7884            pr "  py_r = put_string_list (r);\n";
7885            pr "  free_strings (r);\n"
7886        | RStruct (_, typ) ->
7887            pr "  py_r = put_%s (r);\n" typ;
7888            pr "  guestfs_free_%s (r);\n" typ
7889        | RStructList (_, typ) ->
7890            pr "  py_r = put_%s_list (r);\n" typ;
7891            pr "  guestfs_free_%s_list (r);\n" typ
7892        | RHashtable n ->
7893            pr "  py_r = put_table (r);\n";
7894            pr "  free_strings (r);\n"
7895        | RBufferOut _ ->
7896            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
7897            pr "  free (r);\n"
7898       );
7899
7900       pr "  return py_r;\n";
7901       pr "}\n";
7902       pr "\n"
7903   ) all_functions;
7904
7905   (* Table of functions. *)
7906   pr "static PyMethodDef methods[] = {\n";
7907   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
7908   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
7909   List.iter (
7910     fun (name, _, _, _, _, _, _) ->
7911       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
7912         name name
7913   ) all_functions;
7914   pr "  { NULL, NULL, 0, NULL }\n";
7915   pr "};\n";
7916   pr "\n";
7917
7918   (* Init function. *)
7919   pr "\
7920 void
7921 initlibguestfsmod (void)
7922 {
7923   static int initialized = 0;
7924
7925   if (initialized) return;
7926   Py_InitModule ((char *) \"libguestfsmod\", methods);
7927   initialized = 1;
7928 }
7929 "
7930
7931 (* Generate Python module. *)
7932 and generate_python_py () =
7933   generate_header HashStyle LGPLv2;
7934
7935   pr "\
7936 u\"\"\"Python bindings for libguestfs
7937
7938 import guestfs
7939 g = guestfs.GuestFS ()
7940 g.add_drive (\"guest.img\")
7941 g.launch ()
7942 g.wait_ready ()
7943 parts = g.list_partitions ()
7944
7945 The guestfs module provides a Python binding to the libguestfs API
7946 for examining and modifying virtual machine disk images.
7947
7948 Amongst the things this is good for: making batch configuration
7949 changes to guests, getting disk used/free statistics (see also:
7950 virt-df), migrating between virtualization systems (see also:
7951 virt-p2v), performing partial backups, performing partial guest
7952 clones, cloning guests and changing registry/UUID/hostname info, and
7953 much else besides.
7954
7955 Libguestfs uses Linux kernel and qemu code, and can access any type of
7956 guest filesystem that Linux and qemu can, including but not limited
7957 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7958 schemes, qcow, qcow2, vmdk.
7959
7960 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7961 LVs, what filesystem is in each LV, etc.).  It can also run commands
7962 in the context of the guest.  Also you can access filesystems over FTP.
7963
7964 Errors which happen while using the API are turned into Python
7965 RuntimeError exceptions.
7966
7967 To create a guestfs handle you usually have to perform the following
7968 sequence of calls:
7969
7970 # Create the handle, call add_drive at least once, and possibly
7971 # several times if the guest has multiple block devices:
7972 g = guestfs.GuestFS ()
7973 g.add_drive (\"guest.img\")
7974
7975 # Launch the qemu subprocess and wait for it to become ready:
7976 g.launch ()
7977 g.wait_ready ()
7978
7979 # Now you can issue commands, for example:
7980 logvols = g.lvs ()
7981
7982 \"\"\"
7983
7984 import libguestfsmod
7985
7986 class GuestFS:
7987     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
7988
7989     def __init__ (self):
7990         \"\"\"Create a new libguestfs handle.\"\"\"
7991         self._o = libguestfsmod.create ()
7992
7993     def __del__ (self):
7994         libguestfsmod.close (self._o)
7995
7996 ";
7997
7998   List.iter (
7999     fun (name, style, _, flags, _, _, longdesc) ->
8000       pr "    def %s " name;
8001       generate_py_call_args ~handle:"self" (snd style);
8002       pr ":\n";
8003
8004       if not (List.mem NotInDocs flags) then (
8005         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8006         let doc =
8007           match fst style with
8008           | RErr | RInt _ | RInt64 _ | RBool _
8009           | RConstOptString _ | RConstString _
8010           | RString _ | RBufferOut _ -> doc
8011           | RStringList _ ->
8012               doc ^ "\n\nThis function returns a list of strings."
8013           | RStruct (_, typ) ->
8014               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8015           | RStructList (_, typ) ->
8016               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8017           | RHashtable _ ->
8018               doc ^ "\n\nThis function returns a dictionary." in
8019         let doc =
8020           if List.mem ProtocolLimitWarning flags then
8021             doc ^ "\n\n" ^ protocol_limit_warning
8022           else doc in
8023         let doc =
8024           if List.mem DangerWillRobinson flags then
8025             doc ^ "\n\n" ^ danger_will_robinson
8026           else doc in
8027         let doc =
8028           match deprecation_notice flags with
8029           | None -> doc
8030           | Some txt -> doc ^ "\n\n" ^ txt in
8031         let doc = pod2text ~width:60 name doc in
8032         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8033         let doc = String.concat "\n        " doc in
8034         pr "        u\"\"\"%s\"\"\"\n" doc;
8035       );
8036       pr "        return libguestfsmod.%s " name;
8037       generate_py_call_args ~handle:"self._o" (snd style);
8038       pr "\n";
8039       pr "\n";
8040   ) all_functions
8041
8042 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8043 and generate_py_call_args ~handle args =
8044   pr "(%s" handle;
8045   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8046   pr ")"
8047
8048 (* Useful if you need the longdesc POD text as plain text.  Returns a
8049  * list of lines.
8050  *
8051  * Because this is very slow (the slowest part of autogeneration),
8052  * we memoize the results.
8053  *)
8054 and pod2text ~width name longdesc =
8055   let key = width, name, longdesc in
8056   try Hashtbl.find pod2text_memo key
8057   with Not_found ->
8058     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8059     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8060     close_out chan;
8061     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8062     let chan = Unix.open_process_in cmd in
8063     let lines = ref [] in
8064     let rec loop i =
8065       let line = input_line chan in
8066       if i = 1 then             (* discard the first line of output *)
8067         loop (i+1)
8068       else (
8069         let line = triml line in
8070         lines := line :: !lines;
8071         loop (i+1)
8072       ) in
8073     let lines = try loop 1 with End_of_file -> List.rev !lines in
8074     Unix.unlink filename;
8075     (match Unix.close_process_in chan with
8076      | Unix.WEXITED 0 -> ()
8077      | Unix.WEXITED i ->
8078          failwithf "pod2text: process exited with non-zero status (%d)" i
8079      | Unix.WSIGNALED i | Unix.WSTOPPED i ->
8080          failwithf "pod2text: process signalled or stopped by signal %d" i
8081     );
8082     Hashtbl.add pod2text_memo key lines;
8083     pod2text_memo_updated ();
8084     lines
8085
8086 (* Generate ruby bindings. *)
8087 and generate_ruby_c () =
8088   generate_header CStyle LGPLv2;
8089
8090   pr "\
8091 #include <stdio.h>
8092 #include <stdlib.h>
8093
8094 #include <ruby.h>
8095
8096 #include \"guestfs.h\"
8097
8098 #include \"extconf.h\"
8099
8100 /* For Ruby < 1.9 */
8101 #ifndef RARRAY_LEN
8102 #define RARRAY_LEN(r) (RARRAY((r))->len)
8103 #endif
8104
8105 static VALUE m_guestfs;                 /* guestfs module */
8106 static VALUE c_guestfs;                 /* guestfs_h handle */
8107 static VALUE e_Error;                   /* used for all errors */
8108
8109 static void ruby_guestfs_free (void *p)
8110 {
8111   if (!p) return;
8112   guestfs_close ((guestfs_h *) p);
8113 }
8114
8115 static VALUE ruby_guestfs_create (VALUE m)
8116 {
8117   guestfs_h *g;
8118
8119   g = guestfs_create ();
8120   if (!g)
8121     rb_raise (e_Error, \"failed to create guestfs handle\");
8122
8123   /* Don't print error messages to stderr by default. */
8124   guestfs_set_error_handler (g, NULL, NULL);
8125
8126   /* Wrap it, and make sure the close function is called when the
8127    * handle goes away.
8128    */
8129   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8130 }
8131
8132 static VALUE ruby_guestfs_close (VALUE gv)
8133 {
8134   guestfs_h *g;
8135   Data_Get_Struct (gv, guestfs_h, g);
8136
8137   ruby_guestfs_free (g);
8138   DATA_PTR (gv) = NULL;
8139
8140   return Qnil;
8141 }
8142
8143 ";
8144
8145   List.iter (
8146     fun (name, style, _, _, _, _, _) ->
8147       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8148       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8149       pr ")\n";
8150       pr "{\n";
8151       pr "  guestfs_h *g;\n";
8152       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8153       pr "  if (!g)\n";
8154       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8155         name;
8156       pr "\n";
8157
8158       List.iter (
8159         function
8160         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8161             pr "  Check_Type (%sv, T_STRING);\n" n;
8162             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8163             pr "  if (!%s)\n" n;
8164             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8165             pr "              \"%s\", \"%s\");\n" n name
8166         | OptString n ->
8167             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8168         | StringList n | DeviceList n ->
8169             pr "  char **%s;\n" n;
8170             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8171             pr "  {\n";
8172             pr "    int i, len;\n";
8173             pr "    len = RARRAY_LEN (%sv);\n" n;
8174             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8175               n;
8176             pr "    for (i = 0; i < len; ++i) {\n";
8177             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8178             pr "      %s[i] = StringValueCStr (v);\n" n;
8179             pr "    }\n";
8180             pr "    %s[len] = NULL;\n" n;
8181             pr "  }\n";
8182         | Bool n ->
8183             pr "  int %s = RTEST (%sv);\n" n n
8184         | Int n ->
8185             pr "  int %s = NUM2INT (%sv);\n" n n
8186       ) (snd style);
8187       pr "\n";
8188
8189       let error_code =
8190         match fst style with
8191         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8192         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8193         | RConstString _ | RConstOptString _ ->
8194             pr "  const char *r;\n"; "NULL"
8195         | RString _ -> pr "  char *r;\n"; "NULL"
8196         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8197         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8198         | RStructList (_, typ) ->
8199             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8200         | RBufferOut _ ->
8201             pr "  char *r;\n";
8202             pr "  size_t size;\n";
8203             "NULL" in
8204       pr "\n";
8205
8206       pr "  r = guestfs_%s " name;
8207       generate_c_call_args ~handle:"g" style;
8208       pr ";\n";
8209
8210       List.iter (
8211         function
8212         | Pathname _ | Device _ | Dev_or_Path _ | String _
8213         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
8214         | StringList n | DeviceList n ->
8215             pr "  free (%s);\n" n
8216       ) (snd style);
8217
8218       pr "  if (r == %s)\n" error_code;
8219       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8220       pr "\n";
8221
8222       (match fst style with
8223        | RErr ->
8224            pr "  return Qnil;\n"
8225        | RInt _ | RBool _ ->
8226            pr "  return INT2NUM (r);\n"
8227        | RInt64 _ ->
8228            pr "  return ULL2NUM (r);\n"
8229        | RConstString _ ->
8230            pr "  return rb_str_new2 (r);\n";
8231        | RConstOptString _ ->
8232            pr "  if (r)\n";
8233            pr "    return rb_str_new2 (r);\n";
8234            pr "  else\n";
8235            pr "    return Qnil;\n";
8236        | RString _ ->
8237            pr "  VALUE rv = rb_str_new2 (r);\n";
8238            pr "  free (r);\n";
8239            pr "  return rv;\n";
8240        | RStringList _ ->
8241            pr "  int i, len = 0;\n";
8242            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8243            pr "  VALUE rv = rb_ary_new2 (len);\n";
8244            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8245            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8246            pr "    free (r[i]);\n";
8247            pr "  }\n";
8248            pr "  free (r);\n";
8249            pr "  return rv;\n"
8250        | RStruct (_, typ) ->
8251            let cols = cols_of_struct typ in
8252            generate_ruby_struct_code typ cols
8253        | RStructList (_, typ) ->
8254            let cols = cols_of_struct typ in
8255            generate_ruby_struct_list_code typ cols
8256        | RHashtable _ ->
8257            pr "  VALUE rv = rb_hash_new ();\n";
8258            pr "  int i;\n";
8259            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8260            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8261            pr "    free (r[i]);\n";
8262            pr "    free (r[i+1]);\n";
8263            pr "  }\n";
8264            pr "  free (r);\n";
8265            pr "  return rv;\n"
8266        | RBufferOut _ ->
8267            pr "  VALUE rv = rb_str_new (r, size);\n";
8268            pr "  free (r);\n";
8269            pr "  return rv;\n";
8270       );
8271
8272       pr "}\n";
8273       pr "\n"
8274   ) all_functions;
8275
8276   pr "\
8277 /* Initialize the module. */
8278 void Init__guestfs ()
8279 {
8280   m_guestfs = rb_define_module (\"Guestfs\");
8281   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8282   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8283
8284   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8285   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8286
8287 ";
8288   (* Define the rest of the methods. *)
8289   List.iter (
8290     fun (name, style, _, _, _, _, _) ->
8291       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8292       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8293   ) all_functions;
8294
8295   pr "}\n"
8296
8297 (* Ruby code to return a struct. *)
8298 and generate_ruby_struct_code typ cols =
8299   pr "  VALUE rv = rb_hash_new ();\n";
8300   List.iter (
8301     function
8302     | name, FString ->
8303         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8304     | name, FBuffer ->
8305         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8306     | name, FUUID ->
8307         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8308     | name, (FBytes|FUInt64) ->
8309         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8310     | name, FInt64 ->
8311         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8312     | name, FUInt32 ->
8313         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8314     | name, FInt32 ->
8315         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8316     | name, FOptPercent ->
8317         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8318     | name, FChar -> (* XXX wrong? *)
8319         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8320   ) cols;
8321   pr "  guestfs_free_%s (r);\n" typ;
8322   pr "  return rv;\n"
8323
8324 (* Ruby code to return a struct list. *)
8325 and generate_ruby_struct_list_code typ cols =
8326   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8327   pr "  int i;\n";
8328   pr "  for (i = 0; i < r->len; ++i) {\n";
8329   pr "    VALUE hv = rb_hash_new ();\n";
8330   List.iter (
8331     function
8332     | name, FString ->
8333         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8334     | name, FBuffer ->
8335         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
8336     | name, FUUID ->
8337         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8338     | name, (FBytes|FUInt64) ->
8339         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8340     | name, FInt64 ->
8341         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8342     | name, FUInt32 ->
8343         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8344     | name, FInt32 ->
8345         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8346     | name, FOptPercent ->
8347         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8348     | name, FChar -> (* XXX wrong? *)
8349         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8350   ) cols;
8351   pr "    rb_ary_push (rv, hv);\n";
8352   pr "  }\n";
8353   pr "  guestfs_free_%s_list (r);\n" typ;
8354   pr "  return rv;\n"
8355
8356 (* Generate Java bindings GuestFS.java file. *)
8357 and generate_java_java () =
8358   generate_header CStyle LGPLv2;
8359
8360   pr "\
8361 package com.redhat.et.libguestfs;
8362
8363 import java.util.HashMap;
8364 import com.redhat.et.libguestfs.LibGuestFSException;
8365 import com.redhat.et.libguestfs.PV;
8366 import com.redhat.et.libguestfs.VG;
8367 import com.redhat.et.libguestfs.LV;
8368 import com.redhat.et.libguestfs.Stat;
8369 import com.redhat.et.libguestfs.StatVFS;
8370 import com.redhat.et.libguestfs.IntBool;
8371 import com.redhat.et.libguestfs.Dirent;
8372
8373 /**
8374  * The GuestFS object is a libguestfs handle.
8375  *
8376  * @author rjones
8377  */
8378 public class GuestFS {
8379   // Load the native code.
8380   static {
8381     System.loadLibrary (\"guestfs_jni\");
8382   }
8383
8384   /**
8385    * The native guestfs_h pointer.
8386    */
8387   long g;
8388
8389   /**
8390    * Create a libguestfs handle.
8391    *
8392    * @throws LibGuestFSException
8393    */
8394   public GuestFS () throws LibGuestFSException
8395   {
8396     g = _create ();
8397   }
8398   private native long _create () throws LibGuestFSException;
8399
8400   /**
8401    * Close a libguestfs handle.
8402    *
8403    * You can also leave handles to be collected by the garbage
8404    * collector, but this method ensures that the resources used
8405    * by the handle are freed up immediately.  If you call any
8406    * other methods after closing the handle, you will get an
8407    * exception.
8408    *
8409    * @throws LibGuestFSException
8410    */
8411   public void close () throws LibGuestFSException
8412   {
8413     if (g != 0)
8414       _close (g);
8415     g = 0;
8416   }
8417   private native void _close (long g) throws LibGuestFSException;
8418
8419   public void finalize () throws LibGuestFSException
8420   {
8421     close ();
8422   }
8423
8424 ";
8425
8426   List.iter (
8427     fun (name, style, _, flags, _, shortdesc, longdesc) ->
8428       if not (List.mem NotInDocs flags); then (
8429         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8430         let doc =
8431           if List.mem ProtocolLimitWarning flags then
8432             doc ^ "\n\n" ^ protocol_limit_warning
8433           else doc in
8434         let doc =
8435           if List.mem DangerWillRobinson flags then
8436             doc ^ "\n\n" ^ danger_will_robinson
8437           else doc in
8438         let doc =
8439           match deprecation_notice flags with
8440           | None -> doc
8441           | Some txt -> doc ^ "\n\n" ^ txt in
8442         let doc = pod2text ~width:60 name doc in
8443         let doc = List.map (            (* RHBZ#501883 *)
8444           function
8445           | "" -> "<p>"
8446           | nonempty -> nonempty
8447         ) doc in
8448         let doc = String.concat "\n   * " doc in
8449
8450         pr "  /**\n";
8451         pr "   * %s\n" shortdesc;
8452         pr "   * <p>\n";
8453         pr "   * %s\n" doc;
8454         pr "   * @throws LibGuestFSException\n";
8455         pr "   */\n";
8456         pr "  ";
8457       );
8458       generate_java_prototype ~public:true ~semicolon:false name style;
8459       pr "\n";
8460       pr "  {\n";
8461       pr "    if (g == 0)\n";
8462       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
8463         name;
8464       pr "    ";
8465       if fst style <> RErr then pr "return ";
8466       pr "_%s " name;
8467       generate_java_call_args ~handle:"g" (snd style);
8468       pr ";\n";
8469       pr "  }\n";
8470       pr "  ";
8471       generate_java_prototype ~privat:true ~native:true name style;
8472       pr "\n";
8473       pr "\n";
8474   ) all_functions;
8475
8476   pr "}\n"
8477
8478 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8479 and generate_java_call_args ~handle args =
8480   pr "(%s" handle;
8481   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8482   pr ")"
8483
8484 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8485     ?(semicolon=true) name style =
8486   if privat then pr "private ";
8487   if public then pr "public ";
8488   if native then pr "native ";
8489
8490   (* return type *)
8491   (match fst style with
8492    | RErr -> pr "void ";
8493    | RInt _ -> pr "int ";
8494    | RInt64 _ -> pr "long ";
8495    | RBool _ -> pr "boolean ";
8496    | RConstString _ | RConstOptString _ | RString _
8497    | RBufferOut _ -> pr "String ";
8498    | RStringList _ -> pr "String[] ";
8499    | RStruct (_, typ) ->
8500        let name = java_name_of_struct typ in
8501        pr "%s " name;
8502    | RStructList (_, typ) ->
8503        let name = java_name_of_struct typ in
8504        pr "%s[] " name;
8505    | RHashtable _ -> pr "HashMap<String,String> ";
8506   );
8507
8508   if native then pr "_%s " name else pr "%s " name;
8509   pr "(";
8510   let needs_comma = ref false in
8511   if native then (
8512     pr "long g";
8513     needs_comma := true
8514   );
8515
8516   (* args *)
8517   List.iter (
8518     fun arg ->
8519       if !needs_comma then pr ", ";
8520       needs_comma := true;
8521
8522       match arg with
8523       | Pathname n
8524       | Device n | Dev_or_Path n
8525       | String n
8526       | OptString n
8527       | FileIn n
8528       | FileOut n ->
8529           pr "String %s" n
8530       | StringList n | DeviceList n ->
8531           pr "String[] %s" n
8532       | Bool n ->
8533           pr "boolean %s" n
8534       | Int n ->
8535           pr "int %s" n
8536   ) (snd style);
8537
8538   pr ")\n";
8539   pr "    throws LibGuestFSException";
8540   if semicolon then pr ";"
8541
8542 and generate_java_struct jtyp cols =
8543   generate_header CStyle LGPLv2;
8544
8545   pr "\
8546 package com.redhat.et.libguestfs;
8547
8548 /**
8549  * Libguestfs %s structure.
8550  *
8551  * @author rjones
8552  * @see GuestFS
8553  */
8554 public class %s {
8555 " jtyp jtyp;
8556
8557   List.iter (
8558     function
8559     | name, FString
8560     | name, FUUID
8561     | name, FBuffer -> pr "  public String %s;\n" name
8562     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
8563     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
8564     | name, FChar -> pr "  public char %s;\n" name
8565     | name, FOptPercent ->
8566         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
8567         pr "  public float %s;\n" name
8568   ) cols;
8569
8570   pr "}\n"
8571
8572 and generate_java_c () =
8573   generate_header CStyle LGPLv2;
8574
8575   pr "\
8576 #include <stdio.h>
8577 #include <stdlib.h>
8578 #include <string.h>
8579
8580 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8581 #include \"guestfs.h\"
8582
8583 /* Note that this function returns.  The exception is not thrown
8584  * until after the wrapper function returns.
8585  */
8586 static void
8587 throw_exception (JNIEnv *env, const char *msg)
8588 {
8589   jclass cl;
8590   cl = (*env)->FindClass (env,
8591                           \"com/redhat/et/libguestfs/LibGuestFSException\");
8592   (*env)->ThrowNew (env, cl, msg);
8593 }
8594
8595 JNIEXPORT jlong JNICALL
8596 Java_com_redhat_et_libguestfs_GuestFS__1create
8597   (JNIEnv *env, jobject obj)
8598 {
8599   guestfs_h *g;
8600
8601   g = guestfs_create ();
8602   if (g == NULL) {
8603     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8604     return 0;
8605   }
8606   guestfs_set_error_handler (g, NULL, NULL);
8607   return (jlong) (long) g;
8608 }
8609
8610 JNIEXPORT void JNICALL
8611 Java_com_redhat_et_libguestfs_GuestFS__1close
8612   (JNIEnv *env, jobject obj, jlong jg)
8613 {
8614   guestfs_h *g = (guestfs_h *) (long) jg;
8615   guestfs_close (g);
8616 }
8617
8618 ";
8619
8620   List.iter (
8621     fun (name, style, _, _, _, _, _) ->
8622       pr "JNIEXPORT ";
8623       (match fst style with
8624        | RErr -> pr "void ";
8625        | RInt _ -> pr "jint ";
8626        | RInt64 _ -> pr "jlong ";
8627        | RBool _ -> pr "jboolean ";
8628        | RConstString _ | RConstOptString _ | RString _
8629        | RBufferOut _ -> pr "jstring ";
8630        | RStruct _ | RHashtable _ ->
8631            pr "jobject ";
8632        | RStringList _ | RStructList _ ->
8633            pr "jobjectArray ";
8634       );
8635       pr "JNICALL\n";
8636       pr "Java_com_redhat_et_libguestfs_GuestFS_";
8637       pr "%s" (replace_str ("_" ^ name) "_" "_1");
8638       pr "\n";
8639       pr "  (JNIEnv *env, jobject obj, jlong jg";
8640       List.iter (
8641         function
8642         | Pathname n
8643         | Device n | Dev_or_Path n
8644         | String n
8645         | OptString n
8646         | FileIn n
8647         | FileOut n ->
8648             pr ", jstring j%s" n
8649         | StringList n | DeviceList n ->
8650             pr ", jobjectArray j%s" n
8651         | Bool n ->
8652             pr ", jboolean j%s" n
8653         | Int n ->
8654             pr ", jint j%s" n
8655       ) (snd style);
8656       pr ")\n";
8657       pr "{\n";
8658       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
8659       let error_code, no_ret =
8660         match fst style with
8661         | RErr -> pr "  int r;\n"; "-1", ""
8662         | RBool _
8663         | RInt _ -> pr "  int r;\n"; "-1", "0"
8664         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
8665         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8666         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8667         | RString _ ->
8668             pr "  jstring jr;\n";
8669             pr "  char *r;\n"; "NULL", "NULL"
8670         | RStringList _ ->
8671             pr "  jobjectArray jr;\n";
8672             pr "  int r_len;\n";
8673             pr "  jclass cl;\n";
8674             pr "  jstring jstr;\n";
8675             pr "  char **r;\n"; "NULL", "NULL"
8676         | RStruct (_, typ) ->
8677             pr "  jobject jr;\n";
8678             pr "  jclass cl;\n";
8679             pr "  jfieldID fl;\n";
8680             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8681         | RStructList (_, typ) ->
8682             pr "  jobjectArray jr;\n";
8683             pr "  jclass cl;\n";
8684             pr "  jfieldID fl;\n";
8685             pr "  jobject jfl;\n";
8686             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8687         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
8688         | RBufferOut _ ->
8689             pr "  jstring jr;\n";
8690             pr "  char *r;\n";
8691             pr "  size_t size;\n";
8692             "NULL", "NULL" in
8693       List.iter (
8694         function
8695         | Pathname n
8696         | Device n | Dev_or_Path n
8697         | String n
8698         | OptString n
8699         | FileIn n
8700         | FileOut n ->
8701             pr "  const char *%s;\n" n
8702         | StringList n | DeviceList n ->
8703             pr "  int %s_len;\n" n;
8704             pr "  const char **%s;\n" n
8705         | Bool n
8706         | Int n ->
8707             pr "  int %s;\n" n
8708       ) (snd style);
8709
8710       let needs_i =
8711         (match fst style with
8712          | RStringList _ | RStructList _ -> true
8713          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8714          | RConstOptString _
8715          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8716           List.exists (function
8717                        | StringList _ -> true
8718                        | DeviceList _ -> true
8719                        | _ -> false) (snd style) in
8720       if needs_i then
8721         pr "  int i;\n";
8722
8723       pr "\n";
8724
8725       (* Get the parameters. *)
8726       List.iter (
8727         function
8728         | Pathname n
8729         | Device n | Dev_or_Path n
8730         | String n
8731         | FileIn n
8732         | FileOut n ->
8733             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8734         | OptString n ->
8735             (* This is completely undocumented, but Java null becomes
8736              * a NULL parameter.
8737              *)
8738             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8739         | StringList n | DeviceList n ->
8740             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8741             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8742             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8743             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8744               n;
8745             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8746             pr "  }\n";
8747             pr "  %s[%s_len] = NULL;\n" n n;
8748         | Bool n
8749         | Int n ->
8750             pr "  %s = j%s;\n" n n
8751       ) (snd style);
8752
8753       (* Make the call. *)
8754       pr "  r = guestfs_%s " name;
8755       generate_c_call_args ~handle:"g" style;
8756       pr ";\n";
8757
8758       (* Release the parameters. *)
8759       List.iter (
8760         function
8761         | Pathname n
8762         | Device n | Dev_or_Path n
8763         | String n
8764         | FileIn n
8765         | FileOut n ->
8766             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8767         | OptString n ->
8768             pr "  if (j%s)\n" n;
8769             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8770         | StringList n | DeviceList n ->
8771             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8772             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8773               n;
8774             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8775             pr "  }\n";
8776             pr "  free (%s);\n" n
8777         | Bool n
8778         | Int n -> ()
8779       ) (snd style);
8780
8781       (* Check for errors. *)
8782       pr "  if (r == %s) {\n" error_code;
8783       pr "    throw_exception (env, guestfs_last_error (g));\n";
8784       pr "    return %s;\n" no_ret;
8785       pr "  }\n";
8786
8787       (* Return value. *)
8788       (match fst style with
8789        | RErr -> ()
8790        | RInt _ -> pr "  return (jint) r;\n"
8791        | RBool _ -> pr "  return (jboolean) r;\n"
8792        | RInt64 _ -> pr "  return (jlong) r;\n"
8793        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
8794        | RConstOptString _ ->
8795            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
8796        | RString _ ->
8797            pr "  jr = (*env)->NewStringUTF (env, r);\n";
8798            pr "  free (r);\n";
8799            pr "  return jr;\n"
8800        | RStringList _ ->
8801            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
8802            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
8803            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
8804            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
8805            pr "  for (i = 0; i < r_len; ++i) {\n";
8806            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
8807            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
8808            pr "    free (r[i]);\n";
8809            pr "  }\n";
8810            pr "  free (r);\n";
8811            pr "  return jr;\n"
8812        | RStruct (_, typ) ->
8813            let jtyp = java_name_of_struct typ in
8814            let cols = cols_of_struct typ in
8815            generate_java_struct_return typ jtyp cols
8816        | RStructList (_, typ) ->
8817            let jtyp = java_name_of_struct typ in
8818            let cols = cols_of_struct typ in
8819            generate_java_struct_list_return typ jtyp cols
8820        | RHashtable _ ->
8821            (* XXX *)
8822            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
8823            pr "  return NULL;\n"
8824        | RBufferOut _ ->
8825            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
8826            pr "  free (r);\n";
8827            pr "  return jr;\n"
8828       );
8829
8830       pr "}\n";
8831       pr "\n"
8832   ) all_functions
8833
8834 and generate_java_struct_return typ jtyp cols =
8835   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8836   pr "  jr = (*env)->AllocObject (env, cl);\n";
8837   List.iter (
8838     function
8839     | name, FString ->
8840         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8841         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
8842     | name, FUUID ->
8843         pr "  {\n";
8844         pr "    char s[33];\n";
8845         pr "    memcpy (s, r->%s, 32);\n" name;
8846         pr "    s[32] = 0;\n";
8847         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8848         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8849         pr "  }\n";
8850     | name, FBuffer ->
8851         pr "  {\n";
8852         pr "    int len = r->%s_len;\n" name;
8853         pr "    char s[len+1];\n";
8854         pr "    memcpy (s, r->%s, len);\n" name;
8855         pr "    s[len] = 0;\n";
8856         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8857         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8858         pr "  }\n";
8859     | name, (FBytes|FUInt64|FInt64) ->
8860         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8861         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8862     | name, (FUInt32|FInt32) ->
8863         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8864         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8865     | name, FOptPercent ->
8866         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8867         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
8868     | name, FChar ->
8869         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8870         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8871   ) cols;
8872   pr "  free (r);\n";
8873   pr "  return jr;\n"
8874
8875 and generate_java_struct_list_return typ jtyp cols =
8876   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8877   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
8878   pr "  for (i = 0; i < r->len; ++i) {\n";
8879   pr "    jfl = (*env)->AllocObject (env, cl);\n";
8880   List.iter (
8881     function
8882     | name, FString ->
8883         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8884         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
8885     | name, FUUID ->
8886         pr "    {\n";
8887         pr "      char s[33];\n";
8888         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
8889         pr "      s[32] = 0;\n";
8890         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8891         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8892         pr "    }\n";
8893     | name, FBuffer ->
8894         pr "    {\n";
8895         pr "      int len = r->val[i].%s_len;\n" name;
8896         pr "      char s[len+1];\n";
8897         pr "      memcpy (s, r->val[i].%s, len);\n" name;
8898         pr "      s[len] = 0;\n";
8899         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8900         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8901         pr "    }\n";
8902     | name, (FBytes|FUInt64|FInt64) ->
8903         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8904         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8905     | name, (FUInt32|FInt32) ->
8906         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8907         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8908     | name, FOptPercent ->
8909         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8910         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
8911     | name, FChar ->
8912         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8913         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8914   ) cols;
8915   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
8916   pr "  }\n";
8917   pr "  guestfs_free_%s_list (r);\n" typ;
8918   pr "  return jr;\n"
8919
8920 and generate_java_makefile_inc () =
8921   generate_header HashStyle GPLv2;
8922
8923   pr "java_built_sources = \\\n";
8924   List.iter (
8925     fun (typ, jtyp) ->
8926         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
8927   ) java_structs;
8928   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
8929
8930 and generate_haskell_hs () =
8931   generate_header HaskellStyle LGPLv2;
8932
8933   (* XXX We only know how to generate partial FFI for Haskell
8934    * at the moment.  Please help out!
8935    *)
8936   let can_generate style =
8937     match style with
8938     | RErr, _
8939     | RInt _, _
8940     | RInt64 _, _ -> true
8941     | RBool _, _
8942     | RConstString _, _
8943     | RConstOptString _, _
8944     | RString _, _
8945     | RStringList _, _
8946     | RStruct _, _
8947     | RStructList _, _
8948     | RHashtable _, _
8949     | RBufferOut _, _ -> false in
8950
8951   pr "\
8952 {-# INCLUDE <guestfs.h> #-}
8953 {-# LANGUAGE ForeignFunctionInterface #-}
8954
8955 module Guestfs (
8956   create";
8957
8958   (* List out the names of the actions we want to export. *)
8959   List.iter (
8960     fun (name, style, _, _, _, _, _) ->
8961       if can_generate style then pr ",\n  %s" name
8962   ) all_functions;
8963
8964   pr "
8965   ) where
8966 import Foreign
8967 import Foreign.C
8968 import Foreign.C.Types
8969 import IO
8970 import Control.Exception
8971 import Data.Typeable
8972
8973 data GuestfsS = GuestfsS            -- represents the opaque C struct
8974 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
8975 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
8976
8977 -- XXX define properly later XXX
8978 data PV = PV
8979 data VG = VG
8980 data LV = LV
8981 data IntBool = IntBool
8982 data Stat = Stat
8983 data StatVFS = StatVFS
8984 data Hashtable = Hashtable
8985
8986 foreign import ccall unsafe \"guestfs_create\" c_create
8987   :: IO GuestfsP
8988 foreign import ccall unsafe \"&guestfs_close\" c_close
8989   :: FunPtr (GuestfsP -> IO ())
8990 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
8991   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
8992
8993 create :: IO GuestfsH
8994 create = do
8995   p <- c_create
8996   c_set_error_handler p nullPtr nullPtr
8997   h <- newForeignPtr c_close p
8998   return h
8999
9000 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9001   :: GuestfsP -> IO CString
9002
9003 -- last_error :: GuestfsH -> IO (Maybe String)
9004 -- last_error h = do
9005 --   str <- withForeignPtr h (\\p -> c_last_error p)
9006 --   maybePeek peekCString str
9007
9008 last_error :: GuestfsH -> IO (String)
9009 last_error h = do
9010   str <- withForeignPtr h (\\p -> c_last_error p)
9011   if (str == nullPtr)
9012     then return \"no error\"
9013     else peekCString str
9014
9015 ";
9016
9017   (* Generate wrappers for each foreign function. *)
9018   List.iter (
9019     fun (name, style, _, _, _, _, _) ->
9020       if can_generate style then (
9021         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9022         pr "  :: ";
9023         generate_haskell_prototype ~handle:"GuestfsP" style;
9024         pr "\n";
9025         pr "\n";
9026         pr "%s :: " name;
9027         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9028         pr "\n";
9029         pr "%s %s = do\n" name
9030           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9031         pr "  r <- ";
9032         (* Convert pointer arguments using with* functions. *)
9033         List.iter (
9034           function
9035           | FileIn n
9036           | FileOut n
9037           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9038           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9039           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9040           | Bool _ | Int _ -> ()
9041         ) (snd style);
9042         (* Convert integer arguments. *)
9043         let args =
9044           List.map (
9045             function
9046             | Bool n -> sprintf "(fromBool %s)" n
9047             | Int n -> sprintf "(fromIntegral %s)" n
9048             | FileIn n | FileOut n
9049             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9050           ) (snd style) in
9051         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9052           (String.concat " " ("p" :: args));
9053         (match fst style with
9054          | RErr | RInt _ | RInt64 _ | RBool _ ->
9055              pr "  if (r == -1)\n";
9056              pr "    then do\n";
9057              pr "      err <- last_error h\n";
9058              pr "      fail err\n";
9059          | RConstString _ | RConstOptString _ | RString _
9060          | RStringList _ | RStruct _
9061          | RStructList _ | RHashtable _ | RBufferOut _ ->
9062              pr "  if (r == nullPtr)\n";
9063              pr "    then do\n";
9064              pr "      err <- last_error h\n";
9065              pr "      fail err\n";
9066         );
9067         (match fst style with
9068          | RErr ->
9069              pr "    else return ()\n"
9070          | RInt _ ->
9071              pr "    else return (fromIntegral r)\n"
9072          | RInt64 _ ->
9073              pr "    else return (fromIntegral r)\n"
9074          | RBool _ ->
9075              pr "    else return (toBool r)\n"
9076          | RConstString _
9077          | RConstOptString _
9078          | RString _
9079          | RStringList _
9080          | RStruct _
9081          | RStructList _
9082          | RHashtable _
9083          | RBufferOut _ ->
9084              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9085         );
9086         pr "\n";
9087       )
9088   ) all_functions
9089
9090 and generate_haskell_prototype ~handle ?(hs = false) style =
9091   pr "%s -> " handle;
9092   let string = if hs then "String" else "CString" in
9093   let int = if hs then "Int" else "CInt" in
9094   let bool = if hs then "Bool" else "CInt" in
9095   let int64 = if hs then "Integer" else "Int64" in
9096   List.iter (
9097     fun arg ->
9098       (match arg with
9099        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9100        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9101        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9102        | Bool _ -> pr "%s" bool
9103        | Int _ -> pr "%s" int
9104        | FileIn _ -> pr "%s" string
9105        | FileOut _ -> pr "%s" string
9106       );
9107       pr " -> ";
9108   ) (snd style);
9109   pr "IO (";
9110   (match fst style with
9111    | RErr -> if not hs then pr "CInt"
9112    | RInt _ -> pr "%s" int
9113    | RInt64 _ -> pr "%s" int64
9114    | RBool _ -> pr "%s" bool
9115    | RConstString _ -> pr "%s" string
9116    | RConstOptString _ -> pr "Maybe %s" string
9117    | RString _ -> pr "%s" string
9118    | RStringList _ -> pr "[%s]" string
9119    | RStruct (_, typ) ->
9120        let name = java_name_of_struct typ in
9121        pr "%s" name
9122    | RStructList (_, typ) ->
9123        let name = java_name_of_struct typ in
9124        pr "[%s]" name
9125    | RHashtable _ -> pr "Hashtable"
9126    | RBufferOut _ -> pr "%s" string
9127   );
9128   pr ")"
9129
9130 and generate_bindtests () =
9131   generate_header CStyle LGPLv2;
9132
9133   pr "\
9134 #include <stdio.h>
9135 #include <stdlib.h>
9136 #include <inttypes.h>
9137 #include <string.h>
9138
9139 #include \"guestfs.h\"
9140 #include \"guestfs-internal-actions.h\"
9141 #include \"guestfs_protocol.h\"
9142
9143 #define error guestfs_error
9144 #define safe_calloc guestfs_safe_calloc
9145 #define safe_malloc guestfs_safe_malloc
9146
9147 static void
9148 print_strings (char *const *argv)
9149 {
9150   int argc;
9151
9152   printf (\"[\");
9153   for (argc = 0; argv[argc] != NULL; ++argc) {
9154     if (argc > 0) printf (\", \");
9155     printf (\"\\\"%%s\\\"\", argv[argc]);
9156   }
9157   printf (\"]\\n\");
9158 }
9159
9160 /* The test0 function prints its parameters to stdout. */
9161 ";
9162
9163   let test0, tests =
9164     match test_functions with
9165     | [] -> assert false
9166     | test0 :: tests -> test0, tests in
9167
9168   let () =
9169     let (name, style, _, _, _, _, _) = test0 in
9170     generate_prototype ~extern:false ~semicolon:false ~newline:true
9171       ~handle:"g" ~prefix:"guestfs__" name style;
9172     pr "{\n";
9173     List.iter (
9174       function
9175       | Pathname n
9176       | Device n | Dev_or_Path n
9177       | String n
9178       | FileIn n
9179       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9180       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9181       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9182       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9183       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9184     ) (snd style);
9185     pr "  /* Java changes stdout line buffering so we need this: */\n";
9186     pr "  fflush (stdout);\n";
9187     pr "  return 0;\n";
9188     pr "}\n";
9189     pr "\n" in
9190
9191   List.iter (
9192     fun (name, style, _, _, _, _, _) ->
9193       if String.sub name (String.length name - 3) 3 <> "err" then (
9194         pr "/* Test normal return. */\n";
9195         generate_prototype ~extern:false ~semicolon:false ~newline:true
9196           ~handle:"g" ~prefix:"guestfs__" name style;
9197         pr "{\n";
9198         (match fst style with
9199          | RErr ->
9200              pr "  return 0;\n"
9201          | RInt _ ->
9202              pr "  int r;\n";
9203              pr "  sscanf (val, \"%%d\", &r);\n";
9204              pr "  return r;\n"
9205          | RInt64 _ ->
9206              pr "  int64_t r;\n";
9207              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9208              pr "  return r;\n"
9209          | RBool _ ->
9210              pr "  return strcmp (val, \"true\") == 0;\n"
9211          | RConstString _
9212          | RConstOptString _ ->
9213              (* Can't return the input string here.  Return a static
9214               * string so we ensure we get a segfault if the caller
9215               * tries to free it.
9216               *)
9217              pr "  return \"static string\";\n"
9218          | RString _ ->
9219              pr "  return strdup (val);\n"
9220          | RStringList _ ->
9221              pr "  char **strs;\n";
9222              pr "  int n, i;\n";
9223              pr "  sscanf (val, \"%%d\", &n);\n";
9224              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9225              pr "  for (i = 0; i < n; ++i) {\n";
9226              pr "    strs[i] = safe_malloc (g, 16);\n";
9227              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9228              pr "  }\n";
9229              pr "  strs[n] = NULL;\n";
9230              pr "  return strs;\n"
9231          | RStruct (_, typ) ->
9232              pr "  struct guestfs_%s *r;\n" typ;
9233              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9234              pr "  return r;\n"
9235          | RStructList (_, typ) ->
9236              pr "  struct guestfs_%s_list *r;\n" typ;
9237              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9238              pr "  sscanf (val, \"%%d\", &r->len);\n";
9239              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9240              pr "  return r;\n"
9241          | RHashtable _ ->
9242              pr "  char **strs;\n";
9243              pr "  int n, i;\n";
9244              pr "  sscanf (val, \"%%d\", &n);\n";
9245              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9246              pr "  for (i = 0; i < n; ++i) {\n";
9247              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9248              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9249              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9250              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9251              pr "  }\n";
9252              pr "  strs[n*2] = NULL;\n";
9253              pr "  return strs;\n"
9254          | RBufferOut _ ->
9255              pr "  return strdup (val);\n"
9256         );
9257         pr "}\n";
9258         pr "\n"
9259       ) else (
9260         pr "/* Test error return. */\n";
9261         generate_prototype ~extern:false ~semicolon:false ~newline:true
9262           ~handle:"g" ~prefix:"guestfs__" name style;
9263         pr "{\n";
9264         pr "  error (g, \"error\");\n";
9265         (match fst style with
9266          | RErr | RInt _ | RInt64 _ | RBool _ ->
9267              pr "  return -1;\n"
9268          | RConstString _ | RConstOptString _
9269          | RString _ | RStringList _ | RStruct _
9270          | RStructList _
9271          | RHashtable _
9272          | RBufferOut _ ->
9273              pr "  return NULL;\n"
9274         );
9275         pr "}\n";
9276         pr "\n"
9277       )
9278   ) tests
9279
9280 and generate_ocaml_bindtests () =
9281   generate_header OCamlStyle GPLv2;
9282
9283   pr "\
9284 let () =
9285   let g = Guestfs.create () in
9286 ";
9287
9288   let mkargs args =
9289     String.concat " " (
9290       List.map (
9291         function
9292         | CallString s -> "\"" ^ s ^ "\""
9293         | CallOptString None -> "None"
9294         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9295         | CallStringList xs ->
9296             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9297         | CallInt i when i >= 0 -> string_of_int i
9298         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9299         | CallBool b -> string_of_bool b
9300       ) args
9301     )
9302   in
9303
9304   generate_lang_bindtests (
9305     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9306   );
9307
9308   pr "print_endline \"EOF\"\n"
9309
9310 and generate_perl_bindtests () =
9311   pr "#!/usr/bin/perl -w\n";
9312   generate_header HashStyle GPLv2;
9313
9314   pr "\
9315 use strict;
9316
9317 use Sys::Guestfs;
9318
9319 my $g = Sys::Guestfs->new ();
9320 ";
9321
9322   let mkargs args =
9323     String.concat ", " (
9324       List.map (
9325         function
9326         | CallString s -> "\"" ^ s ^ "\""
9327         | CallOptString None -> "undef"
9328         | CallOptString (Some s) -> sprintf "\"%s\"" s
9329         | CallStringList xs ->
9330             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9331         | CallInt i -> string_of_int i
9332         | CallBool b -> if b then "1" else "0"
9333       ) args
9334     )
9335   in
9336
9337   generate_lang_bindtests (
9338     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9339   );
9340
9341   pr "print \"EOF\\n\"\n"
9342
9343 and generate_python_bindtests () =
9344   generate_header HashStyle GPLv2;
9345
9346   pr "\
9347 import guestfs
9348
9349 g = guestfs.GuestFS ()
9350 ";
9351
9352   let mkargs args =
9353     String.concat ", " (
9354       List.map (
9355         function
9356         | CallString s -> "\"" ^ s ^ "\""
9357         | CallOptString None -> "None"
9358         | CallOptString (Some s) -> sprintf "\"%s\"" s
9359         | CallStringList xs ->
9360             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9361         | CallInt i -> string_of_int i
9362         | CallBool b -> if b then "1" else "0"
9363       ) args
9364     )
9365   in
9366
9367   generate_lang_bindtests (
9368     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9369   );
9370
9371   pr "print \"EOF\"\n"
9372
9373 and generate_ruby_bindtests () =
9374   generate_header HashStyle GPLv2;
9375
9376   pr "\
9377 require 'guestfs'
9378
9379 g = Guestfs::create()
9380 ";
9381
9382   let mkargs args =
9383     String.concat ", " (
9384       List.map (
9385         function
9386         | CallString s -> "\"" ^ s ^ "\""
9387         | CallOptString None -> "nil"
9388         | CallOptString (Some s) -> sprintf "\"%s\"" s
9389         | CallStringList xs ->
9390             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9391         | CallInt i -> string_of_int i
9392         | CallBool b -> string_of_bool b
9393       ) args
9394     )
9395   in
9396
9397   generate_lang_bindtests (
9398     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9399   );
9400
9401   pr "print \"EOF\\n\"\n"
9402
9403 and generate_java_bindtests () =
9404   generate_header CStyle GPLv2;
9405
9406   pr "\
9407 import com.redhat.et.libguestfs.*;
9408
9409 public class Bindtests {
9410     public static void main (String[] argv)
9411     {
9412         try {
9413             GuestFS g = new GuestFS ();
9414 ";
9415
9416   let mkargs args =
9417     String.concat ", " (
9418       List.map (
9419         function
9420         | CallString s -> "\"" ^ s ^ "\""
9421         | CallOptString None -> "null"
9422         | CallOptString (Some s) -> sprintf "\"%s\"" s
9423         | CallStringList xs ->
9424             "new String[]{" ^
9425               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9426         | CallInt i -> string_of_int i
9427         | CallBool b -> string_of_bool b
9428       ) args
9429     )
9430   in
9431
9432   generate_lang_bindtests (
9433     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
9434   );
9435
9436   pr "
9437             System.out.println (\"EOF\");
9438         }
9439         catch (Exception exn) {
9440             System.err.println (exn);
9441             System.exit (1);
9442         }
9443     }
9444 }
9445 "
9446
9447 and generate_haskell_bindtests () =
9448   generate_header HaskellStyle GPLv2;
9449
9450   pr "\
9451 module Bindtests where
9452 import qualified Guestfs
9453
9454 main = do
9455   g <- Guestfs.create
9456 ";
9457
9458   let mkargs args =
9459     String.concat " " (
9460       List.map (
9461         function
9462         | CallString s -> "\"" ^ s ^ "\""
9463         | CallOptString None -> "Nothing"
9464         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9465         | CallStringList xs ->
9466             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9467         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9468         | CallInt i -> string_of_int i
9469         | CallBool true -> "True"
9470         | CallBool false -> "False"
9471       ) args
9472     )
9473   in
9474
9475   generate_lang_bindtests (
9476     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
9477   );
9478
9479   pr "  putStrLn \"EOF\"\n"
9480
9481 (* Language-independent bindings tests - we do it this way to
9482  * ensure there is parity in testing bindings across all languages.
9483  *)
9484 and generate_lang_bindtests call =
9485   call "test0" [CallString "abc"; CallOptString (Some "def");
9486                 CallStringList []; CallBool false;
9487                 CallInt 0; CallString "123"; CallString "456"];
9488   call "test0" [CallString "abc"; CallOptString None;
9489                 CallStringList []; CallBool false;
9490                 CallInt 0; CallString "123"; CallString "456"];
9491   call "test0" [CallString ""; CallOptString (Some "def");
9492                 CallStringList []; CallBool false;
9493                 CallInt 0; CallString "123"; CallString "456"];
9494   call "test0" [CallString ""; CallOptString (Some "");
9495                 CallStringList []; CallBool false;
9496                 CallInt 0; CallString "123"; CallString "456"];
9497   call "test0" [CallString "abc"; CallOptString (Some "def");
9498                 CallStringList ["1"]; CallBool false;
9499                 CallInt 0; CallString "123"; CallString "456"];
9500   call "test0" [CallString "abc"; CallOptString (Some "def");
9501                 CallStringList ["1"; "2"]; CallBool false;
9502                 CallInt 0; CallString "123"; CallString "456"];
9503   call "test0" [CallString "abc"; CallOptString (Some "def");
9504                 CallStringList ["1"]; CallBool true;
9505                 CallInt 0; CallString "123"; CallString "456"];
9506   call "test0" [CallString "abc"; CallOptString (Some "def");
9507                 CallStringList ["1"]; CallBool false;
9508                 CallInt (-1); CallString "123"; CallString "456"];
9509   call "test0" [CallString "abc"; CallOptString (Some "def");
9510                 CallStringList ["1"]; CallBool false;
9511                 CallInt (-2); CallString "123"; CallString "456"];
9512   call "test0" [CallString "abc"; CallOptString (Some "def");
9513                 CallStringList ["1"]; CallBool false;
9514                 CallInt 1; CallString "123"; CallString "456"];
9515   call "test0" [CallString "abc"; CallOptString (Some "def");
9516                 CallStringList ["1"]; CallBool false;
9517                 CallInt 2; CallString "123"; CallString "456"];
9518   call "test0" [CallString "abc"; CallOptString (Some "def");
9519                 CallStringList ["1"]; CallBool false;
9520                 CallInt 4095; CallString "123"; CallString "456"];
9521   call "test0" [CallString "abc"; CallOptString (Some "def");
9522                 CallStringList ["1"]; CallBool false;
9523                 CallInt 0; CallString ""; CallString ""]
9524
9525 (* XXX Add here tests of the return and error functions. *)
9526
9527 (* This is used to generate the src/MAX_PROC_NR file which
9528  * contains the maximum procedure number, a surrogate for the
9529  * ABI version number.  See src/Makefile.am for the details.
9530  *)
9531 and generate_max_proc_nr () =
9532   let proc_nrs = List.map (
9533     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9534   ) daemon_functions in
9535
9536   let max_proc_nr = List.fold_left max 0 proc_nrs in
9537
9538   pr "%d\n" max_proc_nr
9539
9540 let output_to filename =
9541   let filename_new = filename ^ ".new" in
9542   chan := open_out filename_new;
9543   let close () =
9544     close_out !chan;
9545     chan := stdout;
9546
9547     (* Is the new file different from the current file? *)
9548     if Sys.file_exists filename && files_equal filename filename_new then
9549       Unix.unlink filename_new          (* same, so skip it *)
9550     else (
9551       (* different, overwrite old one *)
9552       (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9553       Unix.rename filename_new filename;
9554       Unix.chmod filename 0o444;
9555       printf "written %s\n%!" filename;
9556     )
9557   in
9558   close
9559
9560 (* Main program. *)
9561 let () =
9562   check_functions ();
9563
9564   if not (Sys.file_exists "HACKING") then (
9565     eprintf "\
9566 You are probably running this from the wrong directory.
9567 Run it from the top source directory using the command
9568   src/generator.ml
9569 ";
9570     exit 1
9571   );
9572
9573   let close = output_to "src/guestfs_protocol.x" in
9574   generate_xdr ();
9575   close ();
9576
9577   let close = output_to "src/guestfs-structs.h" in
9578   generate_structs_h ();
9579   close ();
9580
9581   let close = output_to "src/guestfs-actions.h" in
9582   generate_actions_h ();
9583   close ();
9584
9585   let close = output_to "src/guestfs-internal-actions.h" in
9586   generate_internal_actions_h ();
9587   close ();
9588
9589   let close = output_to "src/guestfs-actions.c" in
9590   generate_client_actions ();
9591   close ();
9592
9593   let close = output_to "daemon/actions.h" in
9594   generate_daemon_actions_h ();
9595   close ();
9596
9597   let close = output_to "daemon/stubs.c" in
9598   generate_daemon_actions ();
9599   close ();
9600
9601   let close = output_to "daemon/names.c" in
9602   generate_daemon_names ();
9603   close ();
9604
9605   let close = output_to "capitests/tests.c" in
9606   generate_tests ();
9607   close ();
9608
9609   let close = output_to "src/guestfs-bindtests.c" in
9610   generate_bindtests ();
9611   close ();
9612
9613   let close = output_to "fish/cmds.c" in
9614   generate_fish_cmds ();
9615   close ();
9616
9617   let close = output_to "fish/completion.c" in
9618   generate_fish_completion ();
9619   close ();
9620
9621   let close = output_to "guestfs-structs.pod" in
9622   generate_structs_pod ();
9623   close ();
9624
9625   let close = output_to "guestfs-actions.pod" in
9626   generate_actions_pod ();
9627   close ();
9628
9629   let close = output_to "guestfish-actions.pod" in
9630   generate_fish_actions_pod ();
9631   close ();
9632
9633   let close = output_to "ocaml/guestfs.mli" in
9634   generate_ocaml_mli ();
9635   close ();
9636
9637   let close = output_to "ocaml/guestfs.ml" in
9638   generate_ocaml_ml ();
9639   close ();
9640
9641   let close = output_to "ocaml/guestfs_c_actions.c" in
9642   generate_ocaml_c ();
9643   close ();
9644
9645   let close = output_to "ocaml/bindtests.ml" in
9646   generate_ocaml_bindtests ();
9647   close ();
9648
9649   let close = output_to "perl/Guestfs.xs" in
9650   generate_perl_xs ();
9651   close ();
9652
9653   let close = output_to "perl/lib/Sys/Guestfs.pm" in
9654   generate_perl_pm ();
9655   close ();
9656
9657   let close = output_to "perl/bindtests.pl" in
9658   generate_perl_bindtests ();
9659   close ();
9660
9661   let close = output_to "python/guestfs-py.c" in
9662   generate_python_c ();
9663   close ();
9664
9665   let close = output_to "python/guestfs.py" in
9666   generate_python_py ();
9667   close ();
9668
9669   let close = output_to "python/bindtests.py" in
9670   generate_python_bindtests ();
9671   close ();
9672
9673   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9674   generate_ruby_c ();
9675   close ();
9676
9677   let close = output_to "ruby/bindtests.rb" in
9678   generate_ruby_bindtests ();
9679   close ();
9680
9681   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9682   generate_java_java ();
9683   close ();
9684
9685   List.iter (
9686     fun (typ, jtyp) ->
9687       let cols = cols_of_struct typ in
9688       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9689       let close = output_to filename in
9690       generate_java_struct jtyp cols;
9691       close ();
9692   ) java_structs;
9693
9694   let close = output_to "java/Makefile.inc" in
9695   generate_java_makefile_inc ();
9696   close ();
9697
9698   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9699   generate_java_c ();
9700   close ();
9701
9702   let close = output_to "java/Bindtests.java" in
9703   generate_java_bindtests ();
9704   close ();
9705
9706   let close = output_to "haskell/Guestfs.hs" in
9707   generate_haskell_hs ();
9708   close ();
9709
9710   let close = output_to "haskell/Bindtests.hs" in
9711   generate_haskell_bindtests ();
9712   close ();
9713
9714   let close = output_to "src/MAX_PROC_NR" in
9715   generate_max_proc_nr ();
9716   close ();
9717
9718   (* Always generate this file last, and unconditionally.  It's used
9719    * by the Makefile to know when we must re-run the generator.
9720    *)
9721   let chan = open_out "src/stamp-generator" in
9722   fprintf chan "1\n";
9723   close_out chan