Add echo_daemon command
[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 client-side dispatch stubs. *)
4565 and generate_client_actions () =
4566   generate_header CStyle LGPLv2;
4567
4568   pr "\
4569 #include <stdio.h>
4570 #include <stdlib.h>
4571
4572 #include \"guestfs.h\"
4573 #include \"guestfs_protocol.h\"
4574
4575 #define error guestfs_error
4576 //#define perrorf guestfs_perrorf
4577 //#define safe_malloc guestfs_safe_malloc
4578 #define safe_realloc guestfs_safe_realloc
4579 //#define safe_strdup guestfs_safe_strdup
4580 #define safe_memdup guestfs_safe_memdup
4581
4582 /* Check the return message from a call for validity. */
4583 static int
4584 check_reply_header (guestfs_h *g,
4585                     const struct guestfs_message_header *hdr,
4586                     unsigned int proc_nr, unsigned int serial)
4587 {
4588   if (hdr->prog != GUESTFS_PROGRAM) {
4589     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4590     return -1;
4591   }
4592   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4593     error (g, \"wrong protocol version (%%d/%%d)\",
4594            hdr->vers, GUESTFS_PROTOCOL_VERSION);
4595     return -1;
4596   }
4597   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4598     error (g, \"unexpected message direction (%%d/%%d)\",
4599            hdr->direction, GUESTFS_DIRECTION_REPLY);
4600     return -1;
4601   }
4602   if (hdr->proc != proc_nr) {
4603     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4604     return -1;
4605   }
4606   if (hdr->serial != serial) {
4607     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4608     return -1;
4609   }
4610
4611   return 0;
4612 }
4613
4614 /* Check we are in the right state to run a high-level action. */
4615 static int
4616 check_state (guestfs_h *g, const char *caller)
4617 {
4618   if (!guestfs_is_ready (g)) {
4619     if (guestfs_is_config (g))
4620       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4621         caller);
4622     else if (guestfs_is_launching (g))
4623       error (g, \"%%s: call wait_ready() before using this function\",
4624         caller);
4625     else
4626       error (g, \"%%s called from the wrong state, %%d != READY\",
4627         caller, guestfs_get_state (g));
4628     return -1;
4629   }
4630   return 0;
4631 }
4632
4633 ";
4634
4635   (* Client-side stubs for each function. *)
4636   List.iter (
4637     fun (shortname, style, _, _, _, _, _) ->
4638       let name = "guestfs_" ^ shortname in
4639
4640       (* Generate the context struct which stores the high-level
4641        * state between callback functions.
4642        *)
4643       pr "struct %s_ctx {\n" shortname;
4644       pr "  /* This flag is set by the callbacks, so we know we've done\n";
4645       pr "   * the callbacks as expected, and in the right sequence.\n";
4646       pr "   * 0 = not called, 1 = reply_cb called.\n";
4647       pr "   */\n";
4648       pr "  int cb_sequence;\n";
4649       pr "  struct guestfs_message_header hdr;\n";
4650       pr "  struct guestfs_message_error err;\n";
4651       (match fst style with
4652        | RErr -> ()
4653        | RConstString _ | RConstOptString _ ->
4654            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4655        | RInt _ | RInt64 _
4656        | RBool _ | RString _ | RStringList _
4657        | RStruct _ | RStructList _
4658        | RHashtable _ | RBufferOut _ ->
4659            pr "  struct %s_ret ret;\n" name
4660       );
4661       pr "};\n";
4662       pr "\n";
4663
4664       (* Generate the reply callback function. *)
4665       pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
4666       pr "{\n";
4667       pr "  guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4668       pr "  struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname;
4669       pr "\n";
4670       pr "  /* This should definitely not happen. */\n";
4671       pr "  if (ctx->cb_sequence != 0) {\n";
4672       pr "    ctx->cb_sequence = 9999;\n";
4673       pr "    error (g, \"%%s: internal error: reply callback called twice\", \"%s\");\n" name;
4674       pr "    return;\n";
4675       pr "  }\n";
4676       pr "\n";
4677       pr "  ml->main_loop_quit (ml, g);\n";
4678       pr "\n";
4679       pr "  if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n";
4680       pr "    error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name;
4681       pr "    return;\n";
4682       pr "  }\n";
4683       pr "  if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {\n";
4684       pr "    if (!xdr_guestfs_message_error (xdr, &ctx->err)) {\n";
4685       pr "      error (g, \"%%s: failed to parse reply error\", \"%s\");\n"
4686         name;
4687       pr "      return;\n";
4688       pr "    }\n";
4689       pr "    goto done;\n";
4690       pr "  }\n";
4691
4692       (match fst style with
4693        | RErr -> ()
4694        | RConstString _ | RConstOptString _ ->
4695            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4696        | RInt _ | RInt64 _
4697        | RBool _ | RString _ | RStringList _
4698        | RStruct _ | RStructList _
4699        | RHashtable _ | RBufferOut _ ->
4700            pr "  if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name;
4701            pr "    error (g, \"%%s: failed to parse reply\", \"%s\");\n" name;
4702            pr "    return;\n";
4703            pr "  }\n";
4704       );
4705
4706       pr " done:\n";
4707       pr "  ctx->cb_sequence = 1;\n";
4708       pr "}\n\n";
4709
4710       (* Generate the action stub. *)
4711       generate_prototype ~extern:false ~semicolon:false ~newline:true
4712         ~handle:"g" name style;
4713
4714       let error_code =
4715         match fst style with
4716         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4717         | RConstString _ | RConstOptString _ ->
4718             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4719         | RString _ | RStringList _
4720         | RStruct _ | RStructList _
4721         | RHashtable _ | RBufferOut _ ->
4722             "NULL" in
4723
4724       pr "{\n";
4725
4726       (match snd style with
4727        | [] -> ()
4728        | _ -> pr "  struct %s_args args;\n" name
4729       );
4730
4731       pr "  struct %s_ctx ctx;\n" shortname;
4732       pr "  guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4733       pr "  int serial;\n";
4734       pr "\n";
4735       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4736       pr "  guestfs_set_busy (g);\n";
4737       pr "\n";
4738       pr "  memset (&ctx, 0, sizeof ctx);\n";
4739       pr "\n";
4740
4741       (* Send the main header and arguments. *)
4742       (match snd style with
4743        | [] ->
4744            pr "  serial = guestfs__send_sync (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4745              (String.uppercase shortname)
4746        | args ->
4747            List.iter (
4748              function
4749              | Pathname n | Device n | Dev_or_Path n | String n ->
4750                  pr "  args.%s = (char *) %s;\n" n n
4751              | OptString n ->
4752                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
4753              | StringList n | DeviceList n ->
4754                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
4755                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4756              | Bool n ->
4757                  pr "  args.%s = %s;\n" n n
4758              | Int n ->
4759                  pr "  args.%s = %s;\n" n n
4760              | FileIn _ | FileOut _ -> ()
4761            ) args;
4762            pr "  serial = guestfs__send_sync (g, GUESTFS_PROC_%s,\n"
4763              (String.uppercase shortname);
4764            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4765              name;
4766       );
4767       pr "  if (serial == -1) {\n";
4768       pr "    guestfs_end_busy (g);\n";
4769       pr "    return %s;\n" error_code;
4770       pr "  }\n";
4771       pr "\n";
4772
4773       (* Send any additional files (FileIn) requested. *)
4774       let need_read_reply_label = ref false in
4775       List.iter (
4776         function
4777         | FileIn n ->
4778             pr "  {\n";
4779             pr "    int r;\n";
4780             pr "\n";
4781             pr "    r = guestfs__send_file_sync (g, %s);\n" n;
4782             pr "    if (r == -1) {\n";
4783             pr "      guestfs_end_busy (g);\n";
4784             pr "      return %s;\n" error_code;
4785             pr "    }\n";
4786             pr "    if (r == -2) /* daemon cancelled */\n";
4787             pr "      goto read_reply;\n";
4788             need_read_reply_label := true;
4789             pr "  }\n";
4790             pr "\n";
4791         | _ -> ()
4792       ) (snd style);
4793
4794       (* Wait for the reply from the remote end. *)
4795       if !need_read_reply_label then pr " read_reply:\n";
4796       pr "  guestfs__switch_to_receiving (g);\n";
4797       pr "  ctx.cb_sequence = 0;\n";
4798       pr "  guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname;
4799       pr "  (void) ml->main_loop_run (ml, g);\n";
4800       pr "  guestfs_set_reply_callback (g, NULL, NULL);\n";
4801       pr "  if (ctx.cb_sequence != 1) {\n";
4802       pr "    error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name;
4803       pr "    guestfs_end_busy (g);\n";
4804       pr "    return %s;\n" error_code;
4805       pr "  }\n";
4806       pr "\n";
4807
4808       pr "  if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
4809         (String.uppercase shortname);
4810       pr "    guestfs_end_busy (g);\n";
4811       pr "    return %s;\n" error_code;
4812       pr "  }\n";
4813       pr "\n";
4814
4815       pr "  if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {\n";
4816       pr "    error (g, \"%%s\", ctx.err.error_message);\n";
4817       pr "    free (ctx.err.error_message);\n";
4818       pr "    guestfs_end_busy (g);\n";
4819       pr "    return %s;\n" error_code;
4820       pr "  }\n";
4821       pr "\n";
4822
4823       (* Expecting to receive further files (FileOut)? *)
4824       List.iter (
4825         function
4826         | FileOut n ->
4827             pr "  if (guestfs__receive_file_sync (g, %s) == -1) {\n" n;
4828             pr "    guestfs_end_busy (g);\n";
4829             pr "    return %s;\n" error_code;
4830             pr "  }\n";
4831             pr "\n";
4832         | _ -> ()
4833       ) (snd style);
4834
4835       pr "  guestfs_end_busy (g);\n";
4836
4837       (match fst style with
4838        | RErr -> pr "  return 0;\n"
4839        | RInt n | RInt64 n | RBool n ->
4840            pr "  return ctx.ret.%s;\n" n
4841        | RConstString _ | RConstOptString _ ->
4842            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4843        | RString n ->
4844            pr "  return ctx.ret.%s; /* caller will free */\n" n
4845        | RStringList n | RHashtable n ->
4846            pr "  /* caller will free this, but we need to add a NULL entry */\n";
4847            pr "  ctx.ret.%s.%s_val =\n" n n;
4848            pr "    safe_realloc (g, ctx.ret.%s.%s_val,\n" n n;
4849            pr "                  sizeof (char *) * (ctx.ret.%s.%s_len + 1));\n"
4850              n n;
4851            pr "  ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n;
4852            pr "  return ctx.ret.%s.%s_val;\n" n n
4853        | RStruct (n, _) ->
4854            pr "  /* caller will free this */\n";
4855            pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4856        | RStructList (n, _) ->
4857            pr "  /* caller will free this */\n";
4858            pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4859        | RBufferOut n ->
4860            pr "  *size_r = ctx.ret.%s.%s_len;\n" n n;
4861            pr "  return ctx.ret.%s.%s_val; /* caller will free */\n" n n
4862       );
4863
4864       pr "}\n\n"
4865   ) daemon_functions;
4866
4867   (* Functions to free structures. *)
4868   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
4869   pr " * structure format is identical to the XDR format.  See note in\n";
4870   pr " * generator.ml.\n";
4871   pr " */\n";
4872   pr "\n";
4873
4874   List.iter (
4875     fun (typ, _) ->
4876       pr "void\n";
4877       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
4878       pr "{\n";
4879       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
4880       pr "  free (x);\n";
4881       pr "}\n";
4882       pr "\n";
4883
4884       pr "void\n";
4885       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
4886       pr "{\n";
4887       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
4888       pr "  free (x);\n";
4889       pr "}\n";
4890       pr "\n";
4891
4892   ) structs;
4893
4894 (* Generate daemon/actions.h. *)
4895 and generate_daemon_actions_h () =
4896   generate_header CStyle GPLv2;
4897
4898   pr "#include \"../src/guestfs_protocol.h\"\n";
4899   pr "\n";
4900
4901   List.iter (
4902     fun (name, style, _, _, _, _, _) ->
4903       generate_prototype
4904         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
4905         name style;
4906   ) daemon_functions
4907
4908 (* Generate the server-side stubs. *)
4909 and generate_daemon_actions () =
4910   generate_header CStyle GPLv2;
4911
4912   pr "#include <config.h>\n";
4913   pr "\n";
4914   pr "#include <stdio.h>\n";
4915   pr "#include <stdlib.h>\n";
4916   pr "#include <string.h>\n";
4917   pr "#include <inttypes.h>\n";
4918   pr "#include <ctype.h>\n";
4919   pr "#include <rpc/types.h>\n";
4920   pr "#include <rpc/xdr.h>\n";
4921   pr "\n";
4922   pr "#include \"daemon.h\"\n";
4923   pr "#include \"../src/guestfs_protocol.h\"\n";
4924   pr "#include \"actions.h\"\n";
4925   pr "\n";
4926
4927   List.iter (
4928     fun (name, style, _, _, _, _, _) ->
4929       (* Generate server-side stubs. *)
4930       pr "static void %s_stub (XDR *xdr_in)\n" name;
4931       pr "{\n";
4932       let error_code =
4933         match fst style with
4934         | RErr | RInt _ -> pr "  int r;\n"; "-1"
4935         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
4936         | RBool _ -> pr "  int r;\n"; "-1"
4937         | RConstString _ | RConstOptString _ ->
4938             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4939         | RString _ -> pr "  char *r;\n"; "NULL"
4940         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
4941         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
4942         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
4943         | RBufferOut _ ->
4944             pr "  size_t size;\n";
4945             pr "  char *r;\n";
4946             "NULL" in
4947
4948       (match snd style with
4949        | [] -> ()
4950        | args ->
4951            pr "  struct guestfs_%s_args args;\n" name;
4952            List.iter (
4953              function
4954              | Device n | Dev_or_Path n
4955              | Pathname n
4956              | String n -> ()
4957              | OptString n -> pr "  char *%s;\n" n
4958              | StringList n | DeviceList n -> pr "  char **%s;\n" n
4959              | Bool n -> pr "  int %s;\n" n
4960              | Int n -> pr "  int %s;\n" n
4961              | FileIn _ | FileOut _ -> ()
4962            ) args
4963       );
4964       pr "\n";
4965
4966       (match snd style with
4967        | [] -> ()
4968        | args ->
4969            pr "  memset (&args, 0, sizeof args);\n";
4970            pr "\n";
4971            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
4972            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
4973            pr "    return;\n";
4974            pr "  }\n";
4975            let pr_args n =
4976              pr "  char *%s = args.%s;\n" n n
4977            in
4978            let pr_list_handling_code n =
4979              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
4980              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
4981              pr "  if (%s == NULL) {\n" n;
4982              pr "    reply_with_perror (\"realloc\");\n";
4983              pr "    goto done;\n";
4984              pr "  }\n";
4985              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
4986              pr "  args.%s.%s_val = %s;\n" n n n;
4987            in
4988            List.iter (
4989              function
4990              | Pathname n ->
4991                  pr_args n;
4992                  pr "  ABS_PATH (%s, goto done);\n" n;
4993              | Device n ->
4994                  pr_args n;
4995                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
4996              | Dev_or_Path n ->
4997                  pr_args n;
4998                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
4999              | String n -> pr_args n
5000              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5001              | StringList n ->
5002                  pr_list_handling_code n;
5003              | DeviceList n ->
5004                  pr_list_handling_code n;
5005                  pr "  /* Ensure that each is a device,\n";
5006                  pr "   * and perform device name translation. */\n";
5007                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5008                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5009                  pr "  }\n";
5010              | Bool n -> pr "  %s = args.%s;\n" n n
5011              | Int n -> pr "  %s = args.%s;\n" n n
5012              | FileIn _ | FileOut _ -> ()
5013            ) args;
5014            pr "\n"
5015       );
5016
5017
5018       (* this is used at least for do_equal *)
5019       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5020         (* Emit NEED_ROOT just once, even when there are two or
5021            more Pathname args *)
5022         pr "  NEED_ROOT (goto done);\n";
5023       );
5024
5025       (* Don't want to call the impl with any FileIn or FileOut
5026        * parameters, since these go "outside" the RPC protocol.
5027        *)
5028       let args' =
5029         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5030           (snd style) in
5031       pr "  r = do_%s " name;
5032       generate_c_call_args (fst style, args');
5033       pr ";\n";
5034
5035       pr "  if (r == %s)\n" error_code;
5036       pr "    /* do_%s has already called reply_with_error */\n" name;
5037       pr "    goto done;\n";
5038       pr "\n";
5039
5040       (* If there are any FileOut parameters, then the impl must
5041        * send its own reply.
5042        *)
5043       let no_reply =
5044         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5045       if no_reply then
5046         pr "  /* do_%s has already sent a reply */\n" name
5047       else (
5048         match fst style with
5049         | RErr -> pr "  reply (NULL, NULL);\n"
5050         | RInt n | RInt64 n | RBool n ->
5051             pr "  struct guestfs_%s_ret ret;\n" name;
5052             pr "  ret.%s = r;\n" n;
5053             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5054               name
5055         | RConstString _ | RConstOptString _ ->
5056             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5057         | RString n ->
5058             pr "  struct guestfs_%s_ret ret;\n" name;
5059             pr "  ret.%s = r;\n" n;
5060             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5061               name;
5062             pr "  free (r);\n"
5063         | RStringList n | RHashtable n ->
5064             pr "  struct guestfs_%s_ret ret;\n" name;
5065             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5066             pr "  ret.%s.%s_val = r;\n" n n;
5067             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5068               name;
5069             pr "  free_strings (r);\n"
5070         | RStruct (n, _) ->
5071             pr "  struct guestfs_%s_ret ret;\n" name;
5072             pr "  ret.%s = *r;\n" n;
5073             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5074               name;
5075             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5076               name
5077         | RStructList (n, _) ->
5078             pr "  struct guestfs_%s_ret ret;\n" name;
5079             pr "  ret.%s = *r;\n" n;
5080             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5081               name;
5082             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5083               name
5084         | RBufferOut n ->
5085             pr "  struct guestfs_%s_ret ret;\n" name;
5086             pr "  ret.%s.%s_val = r;\n" n n;
5087             pr "  ret.%s.%s_len = size;\n" n n;
5088             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5089               name;
5090             pr "  free (r);\n"
5091       );
5092
5093       (* Free the args. *)
5094       (match snd style with
5095        | [] ->
5096            pr "done: ;\n";
5097        | _ ->
5098            pr "done:\n";
5099            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5100              name
5101       );
5102
5103       pr "}\n\n";
5104   ) daemon_functions;
5105
5106   (* Dispatch function. *)
5107   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5108   pr "{\n";
5109   pr "  switch (proc_nr) {\n";
5110
5111   List.iter (
5112     fun (name, style, _, _, _, _, _) ->
5113       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5114       pr "      %s_stub (xdr_in);\n" name;
5115       pr "      break;\n"
5116   ) daemon_functions;
5117
5118   pr "    default:\n";
5119   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";
5120   pr "  }\n";
5121   pr "}\n";
5122   pr "\n";
5123
5124   (* LVM columns and tokenization functions. *)
5125   (* XXX This generates crap code.  We should rethink how we
5126    * do this parsing.
5127    *)
5128   List.iter (
5129     function
5130     | typ, cols ->
5131         pr "static const char *lvm_%s_cols = \"%s\";\n"
5132           typ (String.concat "," (List.map fst cols));
5133         pr "\n";
5134
5135         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5136         pr "{\n";
5137         pr "  char *tok, *p, *next;\n";
5138         pr "  int i, j;\n";
5139         pr "\n";
5140         (*
5141           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5142           pr "\n";
5143         *)
5144         pr "  if (!str) {\n";
5145         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5146         pr "    return -1;\n";
5147         pr "  }\n";
5148         pr "  if (!*str || isspace (*str)) {\n";
5149         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5150         pr "    return -1;\n";
5151         pr "  }\n";
5152         pr "  tok = str;\n";
5153         List.iter (
5154           fun (name, coltype) ->
5155             pr "  if (!tok) {\n";
5156             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5157             pr "    return -1;\n";
5158             pr "  }\n";
5159             pr "  p = strchrnul (tok, ',');\n";
5160             pr "  if (*p) next = p+1; else next = NULL;\n";
5161             pr "  *p = '\\0';\n";
5162             (match coltype with
5163              | FString ->
5164                  pr "  r->%s = strdup (tok);\n" name;
5165                  pr "  if (r->%s == NULL) {\n" name;
5166                  pr "    perror (\"strdup\");\n";
5167                  pr "    return -1;\n";
5168                  pr "  }\n"
5169              | FUUID ->
5170                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5171                  pr "    if (tok[j] == '\\0') {\n";
5172                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5173                  pr "      return -1;\n";
5174                  pr "    } else if (tok[j] != '-')\n";
5175                  pr "      r->%s[i++] = tok[j];\n" name;
5176                  pr "  }\n";
5177              | FBytes ->
5178                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5179                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5180                  pr "    return -1;\n";
5181                  pr "  }\n";
5182              | FInt64 ->
5183                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5184                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5185                  pr "    return -1;\n";
5186                  pr "  }\n";
5187              | FOptPercent ->
5188                  pr "  if (tok[0] == '\\0')\n";
5189                  pr "    r->%s = -1;\n" name;
5190                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5191                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5192                  pr "    return -1;\n";
5193                  pr "  }\n";
5194              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5195                  assert false (* can never be an LVM column *)
5196             );
5197             pr "  tok = next;\n";
5198         ) cols;
5199
5200         pr "  if (tok != NULL) {\n";
5201         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5202         pr "    return -1;\n";
5203         pr "  }\n";
5204         pr "  return 0;\n";
5205         pr "}\n";
5206         pr "\n";
5207
5208         pr "guestfs_int_lvm_%s_list *\n" typ;
5209         pr "parse_command_line_%ss (void)\n" typ;
5210         pr "{\n";
5211         pr "  char *out, *err;\n";
5212         pr "  char *p, *pend;\n";
5213         pr "  int r, i;\n";
5214         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5215         pr "  void *newp;\n";
5216         pr "\n";
5217         pr "  ret = malloc (sizeof *ret);\n";
5218         pr "  if (!ret) {\n";
5219         pr "    reply_with_perror (\"malloc\");\n";
5220         pr "    return NULL;\n";
5221         pr "  }\n";
5222         pr "\n";
5223         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5224         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5225         pr "\n";
5226         pr "  r = command (&out, &err,\n";
5227         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5228         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5229         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5230         pr "  if (r == -1) {\n";
5231         pr "    reply_with_error (\"%%s\", err);\n";
5232         pr "    free (out);\n";
5233         pr "    free (err);\n";
5234         pr "    free (ret);\n";
5235         pr "    return NULL;\n";
5236         pr "  }\n";
5237         pr "\n";
5238         pr "  free (err);\n";
5239         pr "\n";
5240         pr "  /* Tokenize each line of the output. */\n";
5241         pr "  p = out;\n";
5242         pr "  i = 0;\n";
5243         pr "  while (p) {\n";
5244         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5245         pr "    if (pend) {\n";
5246         pr "      *pend = '\\0';\n";
5247         pr "      pend++;\n";
5248         pr "    }\n";
5249         pr "\n";
5250         pr "    while (*p && isspace (*p))      /* Skip any leading whitespace. */\n";
5251         pr "      p++;\n";
5252         pr "\n";
5253         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5254         pr "      p = pend;\n";
5255         pr "      continue;\n";
5256         pr "    }\n";
5257         pr "\n";
5258         pr "    /* Allocate some space to store this next entry. */\n";
5259         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5260         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5261         pr "    if (newp == NULL) {\n";
5262         pr "      reply_with_perror (\"realloc\");\n";
5263         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5264         pr "      free (ret);\n";
5265         pr "      free (out);\n";
5266         pr "      return NULL;\n";
5267         pr "    }\n";
5268         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5269         pr "\n";
5270         pr "    /* Tokenize the next entry. */\n";
5271         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5272         pr "    if (r == -1) {\n";
5273         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5274         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5275         pr "      free (ret);\n";
5276         pr "      free (out);\n";
5277         pr "      return NULL;\n";
5278         pr "    }\n";
5279         pr "\n";
5280         pr "    ++i;\n";
5281         pr "    p = pend;\n";
5282         pr "  }\n";
5283         pr "\n";
5284         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5285         pr "\n";
5286         pr "  free (out);\n";
5287         pr "  return ret;\n";
5288         pr "}\n"
5289
5290   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5291
5292 (* Generate a list of function names, for debugging in the daemon.. *)
5293 and generate_daemon_names () =
5294   generate_header CStyle GPLv2;
5295
5296   pr "#include <config.h>\n";
5297   pr "\n";
5298   pr "#include \"daemon.h\"\n";
5299   pr "\n";
5300
5301   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5302   pr "const char *function_names[] = {\n";
5303   List.iter (
5304     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5305   ) daemon_functions;
5306   pr "};\n";
5307
5308 (* Generate the tests. *)
5309 and generate_tests () =
5310   generate_header CStyle GPLv2;
5311
5312   pr "\
5313 #include <stdio.h>
5314 #include <stdlib.h>
5315 #include <string.h>
5316 #include <unistd.h>
5317 #include <sys/types.h>
5318 #include <fcntl.h>
5319
5320 #include \"guestfs.h\"
5321
5322 static guestfs_h *g;
5323 static int suppress_error = 0;
5324
5325 static void print_error (guestfs_h *g, void *data, const char *msg)
5326 {
5327   if (!suppress_error)
5328     fprintf (stderr, \"%%s\\n\", msg);
5329 }
5330
5331 /* FIXME: nearly identical code appears in fish.c */
5332 static void print_strings (char *const *argv)
5333 {
5334   int argc;
5335
5336   for (argc = 0; argv[argc] != NULL; ++argc)
5337     printf (\"\\t%%s\\n\", argv[argc]);
5338 }
5339
5340 /*
5341 static void print_table (char const *const *argv)
5342 {
5343   int i;
5344
5345   for (i = 0; argv[i] != NULL; i += 2)
5346     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5347 }
5348 */
5349
5350 ";
5351
5352   (* Generate a list of commands which are not tested anywhere. *)
5353   pr "static void no_test_warnings (void)\n";
5354   pr "{\n";
5355
5356   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5357   List.iter (
5358     fun (_, _, _, _, tests, _, _) ->
5359       let tests = filter_map (
5360         function
5361         | (_, (Always|If _|Unless _), test) -> Some test
5362         | (_, Disabled, _) -> None
5363       ) tests in
5364       let seq = List.concat (List.map seq_of_test tests) in
5365       let cmds_tested = List.map List.hd seq in
5366       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5367   ) all_functions;
5368
5369   List.iter (
5370     fun (name, _, _, _, _, _, _) ->
5371       if not (Hashtbl.mem hash name) then
5372         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5373   ) all_functions;
5374
5375   pr "}\n";
5376   pr "\n";
5377
5378   (* Generate the actual tests.  Note that we generate the tests
5379    * in reverse order, deliberately, so that (in general) the
5380    * newest tests run first.  This makes it quicker and easier to
5381    * debug them.
5382    *)
5383   let test_names =
5384     List.map (
5385       fun (name, _, _, _, tests, _, _) ->
5386         mapi (generate_one_test name) tests
5387     ) (List.rev all_functions) in
5388   let test_names = List.concat test_names in
5389   let nr_tests = List.length test_names in
5390
5391   pr "\
5392 int main (int argc, char *argv[])
5393 {
5394   char c = 0;
5395   unsigned long int n_failed = 0;
5396   const char *filename;
5397   int fd;
5398   int nr_tests, test_num = 0;
5399
5400   setbuf (stdout, NULL);
5401
5402   no_test_warnings ();
5403
5404   g = guestfs_create ();
5405   if (g == NULL) {
5406     printf (\"guestfs_create FAILED\\n\");
5407     exit (1);
5408   }
5409
5410   guestfs_set_error_handler (g, print_error, NULL);
5411
5412   guestfs_set_path (g, \"../appliance\");
5413
5414   filename = \"test1.img\";
5415   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5416   if (fd == -1) {
5417     perror (filename);
5418     exit (1);
5419   }
5420   if (lseek (fd, %d, SEEK_SET) == -1) {
5421     perror (\"lseek\");
5422     close (fd);
5423     unlink (filename);
5424     exit (1);
5425   }
5426   if (write (fd, &c, 1) == -1) {
5427     perror (\"write\");
5428     close (fd);
5429     unlink (filename);
5430     exit (1);
5431   }
5432   if (close (fd) == -1) {
5433     perror (filename);
5434     unlink (filename);
5435     exit (1);
5436   }
5437   if (guestfs_add_drive (g, filename) == -1) {
5438     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5439     exit (1);
5440   }
5441
5442   filename = \"test2.img\";
5443   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5444   if (fd == -1) {
5445     perror (filename);
5446     exit (1);
5447   }
5448   if (lseek (fd, %d, SEEK_SET) == -1) {
5449     perror (\"lseek\");
5450     close (fd);
5451     unlink (filename);
5452     exit (1);
5453   }
5454   if (write (fd, &c, 1) == -1) {
5455     perror (\"write\");
5456     close (fd);
5457     unlink (filename);
5458     exit (1);
5459   }
5460   if (close (fd) == -1) {
5461     perror (filename);
5462     unlink (filename);
5463     exit (1);
5464   }
5465   if (guestfs_add_drive (g, filename) == -1) {
5466     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5467     exit (1);
5468   }
5469
5470   filename = \"test3.img\";
5471   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5472   if (fd == -1) {
5473     perror (filename);
5474     exit (1);
5475   }
5476   if (lseek (fd, %d, SEEK_SET) == -1) {
5477     perror (\"lseek\");
5478     close (fd);
5479     unlink (filename);
5480     exit (1);
5481   }
5482   if (write (fd, &c, 1) == -1) {
5483     perror (\"write\");
5484     close (fd);
5485     unlink (filename);
5486     exit (1);
5487   }
5488   if (close (fd) == -1) {
5489     perror (filename);
5490     unlink (filename);
5491     exit (1);
5492   }
5493   if (guestfs_add_drive (g, filename) == -1) {
5494     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5495     exit (1);
5496   }
5497
5498   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
5499     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
5500     exit (1);
5501   }
5502
5503   if (guestfs_launch (g) == -1) {
5504     printf (\"guestfs_launch FAILED\\n\");
5505     exit (1);
5506   }
5507
5508   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5509   alarm (600);
5510
5511   if (guestfs_wait_ready (g) == -1) {
5512     printf (\"guestfs_wait_ready FAILED\\n\");
5513     exit (1);
5514   }
5515
5516   /* Cancel previous alarm. */
5517   alarm (0);
5518
5519   nr_tests = %d;
5520
5521 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5522
5523   iteri (
5524     fun i test_name ->
5525       pr "  test_num++;\n";
5526       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5527       pr "  if (%s () == -1) {\n" test_name;
5528       pr "    printf (\"%s FAILED\\n\");\n" test_name;
5529       pr "    n_failed++;\n";
5530       pr "  }\n";
5531   ) test_names;
5532   pr "\n";
5533
5534   pr "  guestfs_close (g);\n";
5535   pr "  unlink (\"test1.img\");\n";
5536   pr "  unlink (\"test2.img\");\n";
5537   pr "  unlink (\"test3.img\");\n";
5538   pr "\n";
5539
5540   pr "  if (n_failed > 0) {\n";
5541   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
5542   pr "    exit (1);\n";
5543   pr "  }\n";
5544   pr "\n";
5545
5546   pr "  exit (0);\n";
5547   pr "}\n"
5548
5549 and generate_one_test name i (init, prereq, test) =
5550   let test_name = sprintf "test_%s_%d" name i in
5551
5552   pr "\
5553 static int %s_skip (void)
5554 {
5555   const char *str;
5556
5557   str = getenv (\"TEST_ONLY\");
5558   if (str)
5559     return strstr (str, \"%s\") == NULL;
5560   str = getenv (\"SKIP_%s\");
5561   if (str && strcmp (str, \"1\") == 0) return 1;
5562   str = getenv (\"SKIP_TEST_%s\");
5563   if (str && strcmp (str, \"1\") == 0) return 1;
5564   return 0;
5565 }
5566
5567 " test_name name (String.uppercase test_name) (String.uppercase name);
5568
5569   (match prereq with
5570    | Disabled | Always -> ()
5571    | If code | Unless code ->
5572        pr "static int %s_prereq (void)\n" test_name;
5573        pr "{\n";
5574        pr "  %s\n" code;
5575        pr "}\n";
5576        pr "\n";
5577   );
5578
5579   pr "\
5580 static int %s (void)
5581 {
5582   if (%s_skip ()) {
5583     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
5584     return 0;
5585   }
5586
5587 " test_name test_name test_name;
5588
5589   (match prereq with
5590    | Disabled ->
5591        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5592    | If _ ->
5593        pr "  if (! %s_prereq ()) {\n" test_name;
5594        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5595        pr "    return 0;\n";
5596        pr "  }\n";
5597        pr "\n";
5598        generate_one_test_body name i test_name init test;
5599    | Unless _ ->
5600        pr "  if (%s_prereq ()) {\n" test_name;
5601        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5602        pr "    return 0;\n";
5603        pr "  }\n";
5604        pr "\n";
5605        generate_one_test_body name i test_name init test;
5606    | Always ->
5607        generate_one_test_body name i test_name init test
5608   );
5609
5610   pr "  return 0;\n";
5611   pr "}\n";
5612   pr "\n";
5613   test_name
5614
5615 and generate_one_test_body name i test_name init test =
5616   (match init with
5617    | InitNone (* XXX at some point, InitNone and InitEmpty became
5618                * folded together as the same thing.  Really we should
5619                * make InitNone do nothing at all, but the tests may
5620                * need to be checked to make sure this is OK.
5621                *)
5622    | InitEmpty ->
5623        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
5624        List.iter (generate_test_command_call test_name)
5625          [["blockdev_setrw"; "/dev/sda"];
5626           ["umount_all"];
5627           ["lvm_remove_all"]]
5628    | InitPartition ->
5629        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5630        List.iter (generate_test_command_call test_name)
5631          [["blockdev_setrw"; "/dev/sda"];
5632           ["umount_all"];
5633           ["lvm_remove_all"];
5634           ["sfdiskM"; "/dev/sda"; ","]]
5635    | InitBasicFS ->
5636        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5637        List.iter (generate_test_command_call test_name)
5638          [["blockdev_setrw"; "/dev/sda"];
5639           ["umount_all"];
5640           ["lvm_remove_all"];
5641           ["sfdiskM"; "/dev/sda"; ","];
5642           ["mkfs"; "ext2"; "/dev/sda1"];
5643           ["mount"; "/dev/sda1"; "/"]]
5644    | InitBasicFSonLVM ->
5645        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5646          test_name;
5647        List.iter (generate_test_command_call test_name)
5648          [["blockdev_setrw"; "/dev/sda"];
5649           ["umount_all"];
5650           ["lvm_remove_all"];
5651           ["sfdiskM"; "/dev/sda"; ","];
5652           ["pvcreate"; "/dev/sda1"];
5653           ["vgcreate"; "VG"; "/dev/sda1"];
5654           ["lvcreate"; "LV"; "VG"; "8"];
5655           ["mkfs"; "ext2"; "/dev/VG/LV"];
5656           ["mount"; "/dev/VG/LV"; "/"]]
5657    | InitISOFS ->
5658        pr "  /* InitISOFS for %s */\n" test_name;
5659        List.iter (generate_test_command_call test_name)
5660          [["blockdev_setrw"; "/dev/sda"];
5661           ["umount_all"];
5662           ["lvm_remove_all"];
5663           ["mount_ro"; "/dev/sdd"; "/"]]
5664   );
5665
5666   let get_seq_last = function
5667     | [] ->
5668         failwithf "%s: you cannot use [] (empty list) when expecting a command"
5669           test_name
5670     | seq ->
5671         let seq = List.rev seq in
5672         List.rev (List.tl seq), List.hd seq
5673   in
5674
5675   match test with
5676   | TestRun seq ->
5677       pr "  /* TestRun for %s (%d) */\n" name i;
5678       List.iter (generate_test_command_call test_name) seq
5679   | TestOutput (seq, expected) ->
5680       pr "  /* TestOutput for %s (%d) */\n" name i;
5681       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5682       let seq, last = get_seq_last seq in
5683       let test () =
5684         pr "    if (strcmp (r, expected) != 0) {\n";
5685         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5686         pr "      return -1;\n";
5687         pr "    }\n"
5688       in
5689       List.iter (generate_test_command_call test_name) seq;
5690       generate_test_command_call ~test test_name last
5691   | TestOutputList (seq, expected) ->
5692       pr "  /* TestOutputList for %s (%d) */\n" name i;
5693       let seq, last = get_seq_last seq in
5694       let test () =
5695         iteri (
5696           fun i str ->
5697             pr "    if (!r[%d]) {\n" i;
5698             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5699             pr "      print_strings (r);\n";
5700             pr "      return -1;\n";
5701             pr "    }\n";
5702             pr "    {\n";
5703             pr "      const char *expected = \"%s\";\n" (c_quote str);
5704             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5705             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5706             pr "        return -1;\n";
5707             pr "      }\n";
5708             pr "    }\n"
5709         ) expected;
5710         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5711         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5712           test_name;
5713         pr "      print_strings (r);\n";
5714         pr "      return -1;\n";
5715         pr "    }\n"
5716       in
5717       List.iter (generate_test_command_call test_name) seq;
5718       generate_test_command_call ~test test_name last
5719   | TestOutputListOfDevices (seq, expected) ->
5720       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
5721       let seq, last = get_seq_last seq in
5722       let test () =
5723         iteri (
5724           fun i str ->
5725             pr "    if (!r[%d]) {\n" i;
5726             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5727             pr "      print_strings (r);\n";
5728             pr "      return -1;\n";
5729             pr "    }\n";
5730             pr "    {\n";
5731             pr "      const char *expected = \"%s\";\n" (c_quote str);
5732             pr "      r[%d][5] = 's';\n" i;
5733             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5734             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5735             pr "        return -1;\n";
5736             pr "      }\n";
5737             pr "    }\n"
5738         ) expected;
5739         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5740         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5741           test_name;
5742         pr "      print_strings (r);\n";
5743         pr "      return -1;\n";
5744         pr "    }\n"
5745       in
5746       List.iter (generate_test_command_call test_name) seq;
5747       generate_test_command_call ~test test_name last
5748   | TestOutputInt (seq, expected) ->
5749       pr "  /* TestOutputInt for %s (%d) */\n" name i;
5750       let seq, last = get_seq_last seq in
5751       let test () =
5752         pr "    if (r != %d) {\n" expected;
5753         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5754           test_name expected;
5755         pr "               (int) r);\n";
5756         pr "      return -1;\n";
5757         pr "    }\n"
5758       in
5759       List.iter (generate_test_command_call test_name) seq;
5760       generate_test_command_call ~test test_name last
5761   | TestOutputIntOp (seq, op, expected) ->
5762       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
5763       let seq, last = get_seq_last seq in
5764       let test () =
5765         pr "    if (! (r %s %d)) {\n" op expected;
5766         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5767           test_name op expected;
5768         pr "               (int) 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   | TestOutputTrue seq ->
5775       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
5776       let seq, last = get_seq_last seq in
5777       let test () =
5778         pr "    if (!r) {\n";
5779         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5780           test_name;
5781         pr "      return -1;\n";
5782         pr "    }\n"
5783       in
5784       List.iter (generate_test_command_call test_name) seq;
5785       generate_test_command_call ~test test_name last
5786   | TestOutputFalse seq ->
5787       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
5788       let seq, last = get_seq_last seq in
5789       let test () =
5790         pr "    if (r) {\n";
5791         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
5792           test_name;
5793         pr "      return -1;\n";
5794         pr "    }\n"
5795       in
5796       List.iter (generate_test_command_call test_name) seq;
5797       generate_test_command_call ~test test_name last
5798   | TestOutputLength (seq, expected) ->
5799       pr "  /* TestOutputLength for %s (%d) */\n" name i;
5800       let seq, last = get_seq_last seq in
5801       let test () =
5802         pr "    int j;\n";
5803         pr "    for (j = 0; j < %d; ++j)\n" expected;
5804         pr "      if (r[j] == NULL) {\n";
5805         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
5806           test_name;
5807         pr "        print_strings (r);\n";
5808         pr "        return -1;\n";
5809         pr "      }\n";
5810         pr "    if (r[j] != NULL) {\n";
5811         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
5812           test_name;
5813         pr "      print_strings (r);\n";
5814         pr "      return -1;\n";
5815         pr "    }\n"
5816       in
5817       List.iter (generate_test_command_call test_name) seq;
5818       generate_test_command_call ~test test_name last
5819   | TestOutputBuffer (seq, expected) ->
5820       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
5821       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5822       let seq, last = get_seq_last seq in
5823       let len = String.length expected in
5824       let test () =
5825         pr "    if (size != %d) {\n" len;
5826         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
5827         pr "      return -1;\n";
5828         pr "    }\n";
5829         pr "    if (strncmp (r, expected, size) != 0) {\n";
5830         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5831         pr "      return -1;\n";
5832         pr "    }\n"
5833       in
5834       List.iter (generate_test_command_call test_name) seq;
5835       generate_test_command_call ~test test_name last
5836   | TestOutputStruct (seq, checks) ->
5837       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
5838       let seq, last = get_seq_last seq in
5839       let test () =
5840         List.iter (
5841           function
5842           | CompareWithInt (field, expected) ->
5843               pr "    if (r->%s != %d) {\n" field expected;
5844               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
5845                 test_name field expected;
5846               pr "               (int) r->%s);\n" field;
5847               pr "      return -1;\n";
5848               pr "    }\n"
5849           | CompareWithIntOp (field, op, expected) ->
5850               pr "    if (!(r->%s %s %d)) {\n" field op expected;
5851               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
5852                 test_name field op expected;
5853               pr "               (int) r->%s);\n" field;
5854               pr "      return -1;\n";
5855               pr "    }\n"
5856           | CompareWithString (field, expected) ->
5857               pr "    if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
5858               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
5859                 test_name field expected;
5860               pr "               r->%s);\n" field;
5861               pr "      return -1;\n";
5862               pr "    }\n"
5863           | CompareFieldsIntEq (field1, field2) ->
5864               pr "    if (r->%s != r->%s) {\n" field1 field2;
5865               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
5866                 test_name field1 field2;
5867               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
5868               pr "      return -1;\n";
5869               pr "    }\n"
5870           | CompareFieldsStrEq (field1, field2) ->
5871               pr "    if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
5872               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
5873                 test_name field1 field2;
5874               pr "               r->%s, r->%s);\n" field1 field2;
5875               pr "      return -1;\n";
5876               pr "    }\n"
5877         ) checks
5878       in
5879       List.iter (generate_test_command_call test_name) seq;
5880       generate_test_command_call ~test test_name last
5881   | TestLastFail seq ->
5882       pr "  /* TestLastFail for %s (%d) */\n" name i;
5883       let seq, last = get_seq_last seq in
5884       List.iter (generate_test_command_call test_name) seq;
5885       generate_test_command_call test_name ~expect_error:true last
5886
5887 (* Generate the code to run a command, leaving the result in 'r'.
5888  * If you expect to get an error then you should set expect_error:true.
5889  *)
5890 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
5891   match cmd with
5892   | [] -> assert false
5893   | name :: args ->
5894       (* Look up the command to find out what args/ret it has. *)
5895       let style =
5896         try
5897           let _, style, _, _, _, _, _ =
5898             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
5899           style
5900         with Not_found ->
5901           failwithf "%s: in test, command %s was not found" test_name name in
5902
5903       if List.length (snd style) <> List.length args then
5904         failwithf "%s: in test, wrong number of args given to %s"
5905           test_name name;
5906
5907       pr "  {\n";
5908
5909       List.iter (
5910         function
5911         | OptString n, "NULL" -> ()
5912         | Pathname n, arg
5913         | Device n, arg
5914         | Dev_or_Path n, arg
5915         | String n, arg
5916         | OptString n, arg ->
5917             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
5918         | Int _, _
5919         | Bool _, _
5920         | FileIn _, _ | FileOut _, _ -> ()
5921         | StringList n, arg | DeviceList n, arg ->
5922             let strs = string_split " " arg in
5923             iteri (
5924               fun i str ->
5925                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
5926             ) strs;
5927             pr "    const char *const %s[] = {\n" n;
5928             iteri (
5929               fun i _ -> pr "      %s_%d,\n" n i
5930             ) strs;
5931             pr "      NULL\n";
5932             pr "    };\n";
5933       ) (List.combine (snd style) args);
5934
5935       let error_code =
5936         match fst style with
5937         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
5938         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
5939         | RConstString _ | RConstOptString _ ->
5940             pr "    const char *r;\n"; "NULL"
5941         | RString _ -> pr "    char *r;\n"; "NULL"
5942         | RStringList _ | RHashtable _ ->
5943             pr "    char **r;\n";
5944             pr "    int i;\n";
5945             "NULL"
5946         | RStruct (_, typ) ->
5947             pr "    struct guestfs_%s *r;\n" typ; "NULL"
5948         | RStructList (_, typ) ->
5949             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
5950         | RBufferOut _ ->
5951             pr "    char *r;\n";
5952             pr "    size_t size;\n";
5953             "NULL" in
5954
5955       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
5956       pr "    r = guestfs_%s (g" name;
5957
5958       (* Generate the parameters. *)
5959       List.iter (
5960         function
5961         | OptString _, "NULL" -> pr ", NULL"
5962         | Pathname n, _
5963         | Device n, _ | Dev_or_Path n, _
5964         | String n, _
5965         | OptString n, _ ->
5966             pr ", %s" n
5967         | FileIn _, arg | FileOut _, arg ->
5968             pr ", \"%s\"" (c_quote arg)
5969         | StringList n, _ | DeviceList n, _ ->
5970             pr ", (char **) %s" n
5971         | Int _, arg ->
5972             let i =
5973               try int_of_string arg
5974               with Failure "int_of_string" ->
5975                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
5976             pr ", %d" i
5977         | Bool _, arg ->
5978             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
5979       ) (List.combine (snd style) args);
5980
5981       (match fst style with
5982        | RBufferOut _ -> pr ", &size"
5983        | _ -> ()
5984       );
5985
5986       pr ");\n";
5987
5988       if not expect_error then
5989         pr "    if (r == %s)\n" error_code
5990       else
5991         pr "    if (r != %s)\n" error_code;
5992       pr "      return -1;\n";
5993
5994       (* Insert the test code. *)
5995       (match test with
5996        | None -> ()
5997        | Some f -> f ()
5998       );
5999
6000       (match fst style with
6001        | RErr | RInt _ | RInt64 _ | RBool _
6002        | RConstString _ | RConstOptString _ -> ()
6003        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6004        | RStringList _ | RHashtable _ ->
6005            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6006            pr "      free (r[i]);\n";
6007            pr "    free (r);\n"
6008        | RStruct (_, typ) ->
6009            pr "    guestfs_free_%s (r);\n" typ
6010        | RStructList (_, typ) ->
6011            pr "    guestfs_free_%s_list (r);\n" typ
6012       );
6013
6014       pr "  }\n"
6015
6016 and c_quote str =
6017   let str = replace_str str "\r" "\\r" in
6018   let str = replace_str str "\n" "\\n" in
6019   let str = replace_str str "\t" "\\t" in
6020   let str = replace_str str "\000" "\\0" in
6021   str
6022
6023 (* Generate a lot of different functions for guestfish. *)
6024 and generate_fish_cmds () =
6025   generate_header CStyle GPLv2;
6026
6027   let all_functions =
6028     List.filter (
6029       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6030     ) all_functions in
6031   let all_functions_sorted =
6032     List.filter (
6033       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6034     ) all_functions_sorted in
6035
6036   pr "#include <stdio.h>\n";
6037   pr "#include <stdlib.h>\n";
6038   pr "#include <string.h>\n";
6039   pr "#include <inttypes.h>\n";
6040   pr "#include <ctype.h>\n";
6041   pr "\n";
6042   pr "#include <guestfs.h>\n";
6043   pr "#include \"fish.h\"\n";
6044   pr "\n";
6045
6046   (* list_commands function, which implements guestfish -h *)
6047   pr "void list_commands (void)\n";
6048   pr "{\n";
6049   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6050   pr "  list_builtin_commands ();\n";
6051   List.iter (
6052     fun (name, _, _, flags, _, shortdesc, _) ->
6053       let name = replace_char name '_' '-' in
6054       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6055         name shortdesc
6056   ) all_functions_sorted;
6057   pr "  printf (\"    %%s\\n\",";
6058   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6059   pr "}\n";
6060   pr "\n";
6061
6062   (* display_command function, which implements guestfish -h cmd *)
6063   pr "void display_command (const char *cmd)\n";
6064   pr "{\n";
6065   List.iter (
6066     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6067       let name2 = replace_char name '_' '-' in
6068       let alias =
6069         try find_map (function FishAlias n -> Some n | _ -> None) flags
6070         with Not_found -> name in
6071       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6072       let synopsis =
6073         match snd style with
6074         | [] -> name2
6075         | args ->
6076             sprintf "%s <%s>"
6077               name2 (String.concat "> <" (List.map name_of_argt args)) in
6078
6079       let warnings =
6080         if List.mem ProtocolLimitWarning flags then
6081           ("\n\n" ^ protocol_limit_warning)
6082         else "" in
6083
6084       (* For DangerWillRobinson commands, we should probably have
6085        * guestfish prompt before allowing you to use them (especially
6086        * in interactive mode). XXX
6087        *)
6088       let warnings =
6089         warnings ^
6090           if List.mem DangerWillRobinson flags then
6091             ("\n\n" ^ danger_will_robinson)
6092           else "" in
6093
6094       let warnings =
6095         warnings ^
6096           match deprecation_notice flags with
6097           | None -> ""
6098           | Some txt -> "\n\n" ^ txt in
6099
6100       let describe_alias =
6101         if name <> alias then
6102           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6103         else "" in
6104
6105       pr "  if (";
6106       pr "strcasecmp (cmd, \"%s\") == 0" name;
6107       if name <> name2 then
6108         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6109       if name <> alias then
6110         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6111       pr ")\n";
6112       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6113         name2 shortdesc
6114         (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
6115       pr "  else\n"
6116   ) all_functions;
6117   pr "    display_builtin_command (cmd);\n";
6118   pr "}\n";
6119   pr "\n";
6120
6121   let emit_print_list_function typ =
6122     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6123       typ typ typ;
6124     pr "{\n";
6125     pr "  unsigned int i;\n";
6126     pr "\n";
6127     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6128     pr "    printf (\"[%%d] = {\\n\", i);\n";
6129     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6130     pr "    printf (\"}\\n\");\n";
6131     pr "  }\n";
6132     pr "}\n";
6133     pr "\n";
6134   in
6135
6136   (* print_* functions *)
6137   List.iter (
6138     fun (typ, cols) ->
6139       let needs_i =
6140         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6141
6142       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6143       pr "{\n";
6144       if needs_i then (
6145         pr "  unsigned int i;\n";
6146         pr "\n"
6147       );
6148       List.iter (
6149         function
6150         | name, FString ->
6151             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6152         | name, FUUID ->
6153             pr "  printf (\"%s: \");\n" name;
6154             pr "  for (i = 0; i < 32; ++i)\n";
6155             pr "    printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6156             pr "  printf (\"\\n\");\n"
6157         | name, FBuffer ->
6158             pr "  printf (\"%%s%s: \", indent);\n" name;
6159             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6160             pr "    if (isprint (%s->%s[i]))\n" typ name;
6161             pr "      printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6162             pr "    else\n";
6163             pr "      printf (\"%%s\\\\x%%02x\", indent, %s->%s[i]);\n" typ name;
6164             pr "  printf (\"\\n\");\n"
6165         | name, (FUInt64|FBytes) ->
6166             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6167               name typ name
6168         | name, FInt64 ->
6169             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6170               name typ name
6171         | name, FUInt32 ->
6172             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6173               name typ name
6174         | name, FInt32 ->
6175             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6176               name typ name
6177         | name, FChar ->
6178             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6179               name typ name
6180         | name, FOptPercent ->
6181             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6182               typ name name typ name;
6183             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6184       ) cols;
6185       pr "}\n";
6186       pr "\n";
6187   ) structs;
6188
6189   (* Emit a print_TYPE_list function definition only if that function is used. *)
6190   List.iter (
6191     function
6192     | typ, (RStructListOnly | RStructAndList) ->
6193         (* generate the function for typ *)
6194         emit_print_list_function typ
6195     | typ, _ -> () (* empty *)
6196   ) rstructs_used;
6197
6198   (* Emit a print_TYPE function definition only if that function is used. *)
6199   List.iter (
6200     function
6201     | typ, RStructOnly ->
6202         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6203         pr "{\n";
6204         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6205         pr "}\n";
6206         pr "\n";
6207     | typ, _ -> () (* empty *)
6208   ) rstructs_used;
6209
6210   (* run_<action> actions *)
6211   List.iter (
6212     fun (name, style, _, flags, _, _, _) ->
6213       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6214       pr "{\n";
6215       (match fst style with
6216        | RErr
6217        | RInt _
6218        | RBool _ -> pr "  int r;\n"
6219        | RInt64 _ -> pr "  int64_t r;\n"
6220        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6221        | RString _ -> pr "  char *r;\n"
6222        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6223        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6224        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6225        | RBufferOut _ ->
6226            pr "  char *r;\n";
6227            pr "  size_t size;\n";
6228       );
6229       List.iter (
6230         function
6231         | Pathname n
6232         | Device n | Dev_or_Path n
6233         | String n
6234         | OptString n
6235         | FileIn n
6236         | FileOut n -> pr "  const char *%s;\n" n
6237         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6238         | Bool n -> pr "  int %s;\n" n
6239         | Int n -> pr "  int %s;\n" n
6240       ) (snd style);
6241
6242       (* Check and convert parameters. *)
6243       let argc_expected = List.length (snd style) in
6244       pr "  if (argc != %d) {\n" argc_expected;
6245       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6246         argc_expected;
6247       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6248       pr "    return -1;\n";
6249       pr "  }\n";
6250       iteri (
6251         fun i ->
6252           function
6253           | Pathname name
6254           | Device name | Dev_or_Path name | String name -> pr "  %s = argv[%d];\n" name i
6255           | OptString name ->
6256               pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6257                 name i i
6258           | FileIn name ->
6259               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6260                 name i i
6261           | FileOut name ->
6262               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6263                 name i i
6264           | StringList name | DeviceList name ->
6265               pr "  %s = parse_string_list (argv[%d]);\n" name i
6266           | Bool name ->
6267               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6268           | Int name ->
6269               pr "  %s = atoi (argv[%d]);\n" name i
6270       ) (snd style);
6271
6272       (* Call C API function. *)
6273       let fn =
6274         try find_map (function FishAction n -> Some n | _ -> None) flags
6275         with Not_found -> sprintf "guestfs_%s" name in
6276       pr "  r = %s " fn;
6277       generate_c_call_args ~handle:"g" style;
6278       pr ";\n";
6279
6280       List.iter (
6281         function
6282         | Pathname name | Device name | Dev_or_Path name | String name
6283         | OptString name | FileIn name | FileOut name | Bool name
6284         | Int name -> ()
6285         | StringList name | DeviceList name ->
6286             pr "  free_strings (%s);\n" name
6287       ) (snd style);
6288
6289       (* Check return value for errors and display command results. *)
6290       (match fst style with
6291        | RErr -> pr "  return r;\n"
6292        | RInt _ ->
6293            pr "  if (r == -1) return -1;\n";
6294            pr "  printf (\"%%d\\n\", r);\n";
6295            pr "  return 0;\n"
6296        | RInt64 _ ->
6297            pr "  if (r == -1) return -1;\n";
6298            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6299            pr "  return 0;\n"
6300        | RBool _ ->
6301            pr "  if (r == -1) return -1;\n";
6302            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6303            pr "  return 0;\n"
6304        | RConstString _ ->
6305            pr "  if (r == NULL) return -1;\n";
6306            pr "  printf (\"%%s\\n\", r);\n";
6307            pr "  return 0;\n"
6308        | RConstOptString _ ->
6309            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6310            pr "  return 0;\n"
6311        | RString _ ->
6312            pr "  if (r == NULL) return -1;\n";
6313            pr "  printf (\"%%s\\n\", r);\n";
6314            pr "  free (r);\n";
6315            pr "  return 0;\n"
6316        | RStringList _ ->
6317            pr "  if (r == NULL) return -1;\n";
6318            pr "  print_strings (r);\n";
6319            pr "  free_strings (r);\n";
6320            pr "  return 0;\n"
6321        | RStruct (_, typ) ->
6322            pr "  if (r == NULL) return -1;\n";
6323            pr "  print_%s (r);\n" typ;
6324            pr "  guestfs_free_%s (r);\n" typ;
6325            pr "  return 0;\n"
6326        | RStructList (_, typ) ->
6327            pr "  if (r == NULL) return -1;\n";
6328            pr "  print_%s_list (r);\n" typ;
6329            pr "  guestfs_free_%s_list (r);\n" typ;
6330            pr "  return 0;\n"
6331        | RHashtable _ ->
6332            pr "  if (r == NULL) return -1;\n";
6333            pr "  print_table (r);\n";
6334            pr "  free_strings (r);\n";
6335            pr "  return 0;\n"
6336        | RBufferOut _ ->
6337            pr "  if (r == NULL) return -1;\n";
6338            pr "  fwrite (r, size, 1, stdout);\n";
6339            pr "  free (r);\n";
6340            pr "  return 0;\n"
6341       );
6342       pr "}\n";
6343       pr "\n"
6344   ) all_functions;
6345
6346   (* run_action function *)
6347   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6348   pr "{\n";
6349   List.iter (
6350     fun (name, _, _, flags, _, _, _) ->
6351       let name2 = replace_char name '_' '-' in
6352       let alias =
6353         try find_map (function FishAlias n -> Some n | _ -> None) flags
6354         with Not_found -> name in
6355       pr "  if (";
6356       pr "strcasecmp (cmd, \"%s\") == 0" name;
6357       if name <> name2 then
6358         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6359       if name <> alias then
6360         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6361       pr ")\n";
6362       pr "    return run_%s (cmd, argc, argv);\n" name;
6363       pr "  else\n";
6364   ) all_functions;
6365   pr "    {\n";
6366   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6367   pr "      return -1;\n";
6368   pr "    }\n";
6369   pr "  return 0;\n";
6370   pr "}\n";
6371   pr "\n"
6372
6373 (* Readline completion for guestfish. *)
6374 and generate_fish_completion () =
6375   generate_header CStyle GPLv2;
6376
6377   let all_functions =
6378     List.filter (
6379       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6380     ) all_functions in
6381
6382   pr "\
6383 #include <config.h>
6384
6385 #include <stdio.h>
6386 #include <stdlib.h>
6387 #include <string.h>
6388
6389 #ifdef HAVE_LIBREADLINE
6390 #include <readline/readline.h>
6391 #endif
6392
6393 #include \"fish.h\"
6394
6395 #ifdef HAVE_LIBREADLINE
6396
6397 static const char *const commands[] = {
6398   BUILTIN_COMMANDS_FOR_COMPLETION,
6399 ";
6400
6401   (* Get the commands, including the aliases.  They don't need to be
6402    * sorted - the generator() function just does a dumb linear search.
6403    *)
6404   let commands =
6405     List.map (
6406       fun (name, _, _, flags, _, _, _) ->
6407         let name2 = replace_char name '_' '-' in
6408         let alias =
6409           try find_map (function FishAlias n -> Some n | _ -> None) flags
6410           with Not_found -> name in
6411
6412         if name <> alias then [name2; alias] else [name2]
6413     ) all_functions in
6414   let commands = List.flatten commands in
6415
6416   List.iter (pr "  \"%s\",\n") commands;
6417
6418   pr "  NULL
6419 };
6420
6421 static char *
6422 generator (const char *text, int state)
6423 {
6424   static int index, len;
6425   const char *name;
6426
6427   if (!state) {
6428     index = 0;
6429     len = strlen (text);
6430   }
6431
6432   rl_attempted_completion_over = 1;
6433
6434   while ((name = commands[index]) != NULL) {
6435     index++;
6436     if (strncasecmp (name, text, len) == 0)
6437       return strdup (name);
6438   }
6439
6440   return NULL;
6441 }
6442
6443 #endif /* HAVE_LIBREADLINE */
6444
6445 char **do_completion (const char *text, int start, int end)
6446 {
6447   char **matches = NULL;
6448
6449 #ifdef HAVE_LIBREADLINE
6450   rl_completion_append_character = ' ';
6451
6452   if (start == 0)
6453     matches = rl_completion_matches (text, generator);
6454   else if (complete_dest_paths)
6455     matches = rl_completion_matches (text, complete_dest_paths_generator);
6456 #endif
6457
6458   return matches;
6459 }
6460 ";
6461
6462 (* Generate the POD documentation for guestfish. *)
6463 and generate_fish_actions_pod () =
6464   let all_functions_sorted =
6465     List.filter (
6466       fun (_, _, _, flags, _, _, _) ->
6467         not (List.mem NotInFish flags || List.mem NotInDocs flags)
6468     ) all_functions_sorted in
6469
6470   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6471
6472   List.iter (
6473     fun (name, style, _, flags, _, _, longdesc) ->
6474       let longdesc =
6475         Str.global_substitute rex (
6476           fun s ->
6477             let sub =
6478               try Str.matched_group 1 s
6479               with Not_found ->
6480                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6481             "C<" ^ replace_char sub '_' '-' ^ ">"
6482         ) longdesc in
6483       let name = replace_char name '_' '-' in
6484       let alias =
6485         try find_map (function FishAlias n -> Some n | _ -> None) flags
6486         with Not_found -> name in
6487
6488       pr "=head2 %s" name;
6489       if name <> alias then
6490         pr " | %s" alias;
6491       pr "\n";
6492       pr "\n";
6493       pr " %s" name;
6494       List.iter (
6495         function
6496         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6497         | OptString n -> pr " %s" n
6498         | StringList n | DeviceList n -> pr " '%s ...'" n
6499         | Bool _ -> pr " true|false"
6500         | Int n -> pr " %s" n
6501         | FileIn n | FileOut n -> pr " (%s|-)" n
6502       ) (snd style);
6503       pr "\n";
6504       pr "\n";
6505       pr "%s\n\n" longdesc;
6506
6507       if List.exists (function FileIn _ | FileOut _ -> true
6508                       | _ -> false) (snd style) then
6509         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6510
6511       if List.mem ProtocolLimitWarning flags then
6512         pr "%s\n\n" protocol_limit_warning;
6513
6514       if List.mem DangerWillRobinson flags then
6515         pr "%s\n\n" danger_will_robinson;
6516
6517       match deprecation_notice flags with
6518       | None -> ()
6519       | Some txt -> pr "%s\n\n" txt
6520   ) all_functions_sorted
6521
6522 (* Generate a C function prototype. *)
6523 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6524     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6525     ?(prefix = "")
6526     ?handle name style =
6527   if extern then pr "extern ";
6528   if static then pr "static ";
6529   (match fst style with
6530    | RErr -> pr "int "
6531    | RInt _ -> pr "int "
6532    | RInt64 _ -> pr "int64_t "
6533    | RBool _ -> pr "int "
6534    | RConstString _ | RConstOptString _ -> pr "const char *"
6535    | RString _ | RBufferOut _ -> pr "char *"
6536    | RStringList _ | RHashtable _ -> pr "char **"
6537    | RStruct (_, typ) ->
6538        if not in_daemon then pr "struct guestfs_%s *" typ
6539        else pr "guestfs_int_%s *" typ
6540    | RStructList (_, typ) ->
6541        if not in_daemon then pr "struct guestfs_%s_list *" typ
6542        else pr "guestfs_int_%s_list *" typ
6543   );
6544   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6545   pr "%s%s (" prefix name;
6546   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6547     pr "void"
6548   else (
6549     let comma = ref false in
6550     (match handle with
6551      | None -> ()
6552      | Some handle -> pr "guestfs_h *%s" handle; comma := true
6553     );
6554     let next () =
6555       if !comma then (
6556         if single_line then pr ", " else pr ",\n\t\t"
6557       );
6558       comma := true
6559     in
6560     List.iter (
6561       function
6562       | Pathname n
6563       | Device n | Dev_or_Path n
6564       | String n
6565       | OptString n ->
6566           next ();
6567           pr "const char *%s" n
6568       | StringList n | DeviceList n ->
6569           next ();
6570           pr "char *const *%s" n
6571       | Bool n -> next (); pr "int %s" n
6572       | Int n -> next (); pr "int %s" n
6573       | FileIn n
6574       | FileOut n ->
6575           if not in_daemon then (next (); pr "const char *%s" n)
6576     ) (snd style);
6577     if is_RBufferOut then (next (); pr "size_t *size_r");
6578   );
6579   pr ")";
6580   if semicolon then pr ";";
6581   if newline then pr "\n"
6582
6583 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6584 and generate_c_call_args ?handle ?(decl = false) style =
6585   pr "(";
6586   let comma = ref false in
6587   let next () =
6588     if !comma then pr ", ";
6589     comma := true
6590   in
6591   (match handle with
6592    | None -> ()
6593    | Some handle -> pr "%s" handle; comma := true
6594   );
6595   List.iter (
6596     fun arg ->
6597       next ();
6598       pr "%s" (name_of_argt arg)
6599   ) (snd style);
6600   (* For RBufferOut calls, add implicit &size parameter. *)
6601   if not decl then (
6602     match fst style with
6603     | RBufferOut _ ->
6604         next ();
6605         pr "&size"
6606     | _ -> ()
6607   );
6608   pr ")"
6609
6610 (* Generate the OCaml bindings interface. *)
6611 and generate_ocaml_mli () =
6612   generate_header OCamlStyle LGPLv2;
6613
6614   pr "\
6615 (** For API documentation you should refer to the C API
6616     in the guestfs(3) manual page.  The OCaml API uses almost
6617     exactly the same calls. *)
6618
6619 type t
6620 (** A [guestfs_h] handle. *)
6621
6622 exception Error of string
6623 (** This exception is raised when there is an error. *)
6624
6625 val create : unit -> t
6626
6627 val close : t -> unit
6628 (** Handles are closed by the garbage collector when they become
6629     unreferenced, but callers can also call this in order to
6630     provide predictable cleanup. *)
6631
6632 ";
6633   generate_ocaml_structure_decls ();
6634
6635   (* The actions. *)
6636   List.iter (
6637     fun (name, style, _, _, _, shortdesc, _) ->
6638       generate_ocaml_prototype name style;
6639       pr "(** %s *)\n" shortdesc;
6640       pr "\n"
6641   ) all_functions
6642
6643 (* Generate the OCaml bindings implementation. *)
6644 and generate_ocaml_ml () =
6645   generate_header OCamlStyle LGPLv2;
6646
6647   pr "\
6648 type t
6649 exception Error of string
6650 external create : unit -> t = \"ocaml_guestfs_create\"
6651 external close : t -> unit = \"ocaml_guestfs_close\"
6652
6653 let () =
6654   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6655
6656 ";
6657
6658   generate_ocaml_structure_decls ();
6659
6660   (* The actions. *)
6661   List.iter (
6662     fun (name, style, _, _, _, shortdesc, _) ->
6663       generate_ocaml_prototype ~is_external:true name style;
6664   ) all_functions
6665
6666 (* Generate the OCaml bindings C implementation. *)
6667 and generate_ocaml_c () =
6668   generate_header CStyle LGPLv2;
6669
6670   pr "\
6671 #include <stdio.h>
6672 #include <stdlib.h>
6673 #include <string.h>
6674
6675 #include <caml/config.h>
6676 #include <caml/alloc.h>
6677 #include <caml/callback.h>
6678 #include <caml/fail.h>
6679 #include <caml/memory.h>
6680 #include <caml/mlvalues.h>
6681 #include <caml/signals.h>
6682
6683 #include <guestfs.h>
6684
6685 #include \"guestfs_c.h\"
6686
6687 /* Copy a hashtable of string pairs into an assoc-list.  We return
6688  * the list in reverse order, but hashtables aren't supposed to be
6689  * ordered anyway.
6690  */
6691 static CAMLprim value
6692 copy_table (char * const * argv)
6693 {
6694   CAMLparam0 ();
6695   CAMLlocal5 (rv, pairv, kv, vv, cons);
6696   int i;
6697
6698   rv = Val_int (0);
6699   for (i = 0; argv[i] != NULL; i += 2) {
6700     kv = caml_copy_string (argv[i]);
6701     vv = caml_copy_string (argv[i+1]);
6702     pairv = caml_alloc (2, 0);
6703     Store_field (pairv, 0, kv);
6704     Store_field (pairv, 1, vv);
6705     cons = caml_alloc (2, 0);
6706     Store_field (cons, 1, rv);
6707     rv = cons;
6708     Store_field (cons, 0, pairv);
6709   }
6710
6711   CAMLreturn (rv);
6712 }
6713
6714 ";
6715
6716   (* Struct copy functions. *)
6717
6718   let emit_ocaml_copy_list_function typ =
6719     pr "static CAMLprim value\n";
6720     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
6721     pr "{\n";
6722     pr "  CAMLparam0 ();\n";
6723     pr "  CAMLlocal2 (rv, v);\n";
6724     pr "  unsigned int i;\n";
6725     pr "\n";
6726     pr "  if (%ss->len == 0)\n" typ;
6727     pr "    CAMLreturn (Atom (0));\n";
6728     pr "  else {\n";
6729     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
6730     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
6731     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
6732     pr "      caml_modify (&Field (rv, i), v);\n";
6733     pr "    }\n";
6734     pr "    CAMLreturn (rv);\n";
6735     pr "  }\n";
6736     pr "}\n";
6737     pr "\n";
6738   in
6739
6740   List.iter (
6741     fun (typ, cols) ->
6742       let has_optpercent_col =
6743         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6744
6745       pr "static CAMLprim value\n";
6746       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6747       pr "{\n";
6748       pr "  CAMLparam0 ();\n";
6749       if has_optpercent_col then
6750         pr "  CAMLlocal3 (rv, v, v2);\n"
6751       else
6752         pr "  CAMLlocal2 (rv, v);\n";
6753       pr "\n";
6754       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
6755       iteri (
6756         fun i col ->
6757           (match col with
6758            | name, FString ->
6759                pr "  v = caml_copy_string (%s->%s);\n" typ name
6760            | name, FBuffer ->
6761                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
6762                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6763                  typ name typ name
6764            | name, FUUID ->
6765                pr "  v = caml_alloc_string (32);\n";
6766                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
6767            | name, (FBytes|FInt64|FUInt64) ->
6768                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
6769            | name, (FInt32|FUInt32) ->
6770                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
6771            | name, FOptPercent ->
6772                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
6773                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
6774                pr "    v = caml_alloc (1, 0);\n";
6775                pr "    Store_field (v, 0, v2);\n";
6776                pr "  } else /* None */\n";
6777                pr "    v = Val_int (0);\n";
6778            | name, FChar ->
6779                pr "  v = Val_int (%s->%s);\n" typ name
6780           );
6781           pr "  Store_field (rv, %d, v);\n" i
6782       ) cols;
6783       pr "  CAMLreturn (rv);\n";
6784       pr "}\n";
6785       pr "\n";
6786   ) structs;
6787
6788   (* Emit a copy_TYPE_list function definition only if that function is used. *)
6789   List.iter (
6790     function
6791     | typ, (RStructListOnly | RStructAndList) ->
6792         (* generate the function for typ *)
6793         emit_ocaml_copy_list_function typ
6794     | typ, _ -> () (* empty *)
6795   ) rstructs_used;
6796
6797   (* The wrappers. *)
6798   List.iter (
6799     fun (name, style, _, _, _, _, _) ->
6800       let params =
6801         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
6802
6803       let needs_extra_vs =
6804         match fst style with RConstOptString _ -> true | _ -> false in
6805
6806       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
6807       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
6808       List.iter (pr ", value %s") (List.tl params); pr ");\n";
6809
6810       pr "CAMLprim value\n";
6811       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
6812       List.iter (pr ", value %s") (List.tl params);
6813       pr ")\n";
6814       pr "{\n";
6815
6816       (match params with
6817        | [p1; p2; p3; p4; p5] ->
6818            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
6819        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
6820            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
6821            pr "  CAMLxparam%d (%s);\n"
6822              (List.length rest) (String.concat ", " rest)
6823        | ps ->
6824            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
6825       );
6826       if not needs_extra_vs then
6827         pr "  CAMLlocal1 (rv);\n"
6828       else
6829         pr "  CAMLlocal3 (rv, v, v2);\n";
6830       pr "\n";
6831
6832       pr "  guestfs_h *g = Guestfs_val (gv);\n";
6833       pr "  if (g == NULL)\n";
6834       pr "    caml_failwith (\"%s: used handle after closing it\");\n" name;
6835       pr "\n";
6836
6837       List.iter (
6838         function
6839         | Pathname n
6840         | Device n | Dev_or_Path n
6841         | String n
6842         | FileIn n
6843         | FileOut n ->
6844             pr "  const char *%s = String_val (%sv);\n" n n
6845         | OptString n ->
6846             pr "  const char *%s =\n" n;
6847             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
6848               n n
6849         | StringList n | DeviceList n ->
6850             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
6851         | Bool n ->
6852             pr "  int %s = Bool_val (%sv);\n" n n
6853         | Int n ->
6854             pr "  int %s = Int_val (%sv);\n" n n
6855       ) (snd style);
6856       let error_code =
6857         match fst style with
6858         | RErr -> pr "  int r;\n"; "-1"
6859         | RInt _ -> pr "  int r;\n"; "-1"
6860         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6861         | RBool _ -> pr "  int r;\n"; "-1"
6862         | RConstString _ | RConstOptString _ ->
6863             pr "  const char *r;\n"; "NULL"
6864         | RString _ -> pr "  char *r;\n"; "NULL"
6865         | RStringList _ ->
6866             pr "  int i;\n";
6867             pr "  char **r;\n";
6868             "NULL"
6869         | RStruct (_, typ) ->
6870             pr "  struct guestfs_%s *r;\n" typ; "NULL"
6871         | RStructList (_, typ) ->
6872             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
6873         | RHashtable _ ->
6874             pr "  int i;\n";
6875             pr "  char **r;\n";
6876             "NULL"
6877         | RBufferOut _ ->
6878             pr "  char *r;\n";
6879             pr "  size_t size;\n";
6880             "NULL" in
6881       pr "\n";
6882
6883       pr "  caml_enter_blocking_section ();\n";
6884       pr "  r = guestfs_%s " name;
6885       generate_c_call_args ~handle:"g" style;
6886       pr ";\n";
6887       pr "  caml_leave_blocking_section ();\n";
6888
6889       List.iter (
6890         function
6891         | StringList n | DeviceList n ->
6892             pr "  ocaml_guestfs_free_strings (%s);\n" n;
6893         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
6894         | FileIn _ | FileOut _ -> ()
6895       ) (snd style);
6896
6897       pr "  if (r == %s)\n" error_code;
6898       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
6899       pr "\n";
6900
6901       (match fst style with
6902        | RErr -> pr "  rv = Val_unit;\n"
6903        | RInt _ -> pr "  rv = Val_int (r);\n"
6904        | RInt64 _ ->
6905            pr "  rv = caml_copy_int64 (r);\n"
6906        | RBool _ -> pr "  rv = Val_bool (r);\n"
6907        | RConstString _ ->
6908            pr "  rv = caml_copy_string (r);\n"
6909        | RConstOptString _ ->
6910            pr "  if (r) { /* Some string */\n";
6911            pr "    v = caml_alloc (1, 0);\n";
6912            pr "    v2 = caml_copy_string (r);\n";
6913            pr "    Store_field (v, 0, v2);\n";
6914            pr "  } else /* None */\n";
6915            pr "    v = Val_int (0);\n";
6916        | RString _ ->
6917            pr "  rv = caml_copy_string (r);\n";
6918            pr "  free (r);\n"
6919        | RStringList _ ->
6920            pr "  rv = caml_copy_string_array ((const char **) r);\n";
6921            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6922            pr "  free (r);\n"
6923        | RStruct (_, typ) ->
6924            pr "  rv = copy_%s (r);\n" typ;
6925            pr "  guestfs_free_%s (r);\n" typ;
6926        | RStructList (_, typ) ->
6927            pr "  rv = copy_%s_list (r);\n" typ;
6928            pr "  guestfs_free_%s_list (r);\n" typ;
6929        | RHashtable _ ->
6930            pr "  rv = copy_table (r);\n";
6931            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6932            pr "  free (r);\n";
6933        | RBufferOut _ ->
6934            pr "  rv = caml_alloc_string (size);\n";
6935            pr "  memcpy (String_val (rv), r, size);\n";
6936       );
6937
6938       pr "  CAMLreturn (rv);\n";
6939       pr "}\n";
6940       pr "\n";
6941
6942       if List.length params > 5 then (
6943         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
6944         pr "CAMLprim value ";
6945         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
6946         pr "CAMLprim value\n";
6947         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
6948         pr "{\n";
6949         pr "  return ocaml_guestfs_%s (argv[0]" name;
6950         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
6951         pr ");\n";
6952         pr "}\n";
6953         pr "\n"
6954       )
6955   ) all_functions
6956
6957 and generate_ocaml_structure_decls () =
6958   List.iter (
6959     fun (typ, cols) ->
6960       pr "type %s = {\n" typ;
6961       List.iter (
6962         function
6963         | name, FString -> pr "  %s : string;\n" name
6964         | name, FBuffer -> pr "  %s : string;\n" name
6965         | name, FUUID -> pr "  %s : string;\n" name
6966         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
6967         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
6968         | name, FChar -> pr "  %s : char;\n" name
6969         | name, FOptPercent -> pr "  %s : float option;\n" name
6970       ) cols;
6971       pr "}\n";
6972       pr "\n"
6973   ) structs
6974
6975 and generate_ocaml_prototype ?(is_external = false) name style =
6976   if is_external then pr "external " else pr "val ";
6977   pr "%s : t -> " name;
6978   List.iter (
6979     function
6980     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
6981     | OptString _ -> pr "string option -> "
6982     | StringList _ | DeviceList _ -> pr "string array -> "
6983     | Bool _ -> pr "bool -> "
6984     | Int _ -> pr "int -> "
6985   ) (snd style);
6986   (match fst style with
6987    | RErr -> pr "unit" (* all errors are turned into exceptions *)
6988    | RInt _ -> pr "int"
6989    | RInt64 _ -> pr "int64"
6990    | RBool _ -> pr "bool"
6991    | RConstString _ -> pr "string"
6992    | RConstOptString _ -> pr "string option"
6993    | RString _ | RBufferOut _ -> pr "string"
6994    | RStringList _ -> pr "string array"
6995    | RStruct (_, typ) -> pr "%s" typ
6996    | RStructList (_, typ) -> pr "%s array" typ
6997    | RHashtable _ -> pr "(string * string) list"
6998   );
6999   if is_external then (
7000     pr " = ";
7001     if List.length (snd style) + 1 > 5 then
7002       pr "\"ocaml_guestfs_%s_byte\" " name;
7003     pr "\"ocaml_guestfs_%s\"" name
7004   );
7005   pr "\n"
7006
7007 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7008 and generate_perl_xs () =
7009   generate_header CStyle LGPLv2;
7010
7011   pr "\
7012 #include \"EXTERN.h\"
7013 #include \"perl.h\"
7014 #include \"XSUB.h\"
7015
7016 #include <guestfs.h>
7017
7018 #ifndef PRId64
7019 #define PRId64 \"lld\"
7020 #endif
7021
7022 static SV *
7023 my_newSVll(long long val) {
7024 #ifdef USE_64_BIT_ALL
7025   return newSViv(val);
7026 #else
7027   char buf[100];
7028   int len;
7029   len = snprintf(buf, 100, \"%%\" PRId64, val);
7030   return newSVpv(buf, len);
7031 #endif
7032 }
7033
7034 #ifndef PRIu64
7035 #define PRIu64 \"llu\"
7036 #endif
7037
7038 static SV *
7039 my_newSVull(unsigned long long val) {
7040 #ifdef USE_64_BIT_ALL
7041   return newSVuv(val);
7042 #else
7043   char buf[100];
7044   int len;
7045   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7046   return newSVpv(buf, len);
7047 #endif
7048 }
7049
7050 /* http://www.perlmonks.org/?node_id=680842 */
7051 static char **
7052 XS_unpack_charPtrPtr (SV *arg) {
7053   char **ret;
7054   AV *av;
7055   I32 i;
7056
7057   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7058     croak (\"array reference expected\");
7059
7060   av = (AV *)SvRV (arg);
7061   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7062   if (!ret)
7063     croak (\"malloc failed\");
7064
7065   for (i = 0; i <= av_len (av); i++) {
7066     SV **elem = av_fetch (av, i, 0);
7067
7068     if (!elem || !*elem)
7069       croak (\"missing element in list\");
7070
7071     ret[i] = SvPV_nolen (*elem);
7072   }
7073
7074   ret[i] = NULL;
7075
7076   return ret;
7077 }
7078
7079 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7080
7081 PROTOTYPES: ENABLE
7082
7083 guestfs_h *
7084 _create ()
7085    CODE:
7086       RETVAL = guestfs_create ();
7087       if (!RETVAL)
7088         croak (\"could not create guestfs handle\");
7089       guestfs_set_error_handler (RETVAL, NULL, NULL);
7090  OUTPUT:
7091       RETVAL
7092
7093 void
7094 DESTROY (g)
7095       guestfs_h *g;
7096  PPCODE:
7097       guestfs_close (g);
7098
7099 ";
7100
7101   List.iter (
7102     fun (name, style, _, _, _, _, _) ->
7103       (match fst style with
7104        | RErr -> pr "void\n"
7105        | RInt _ -> pr "SV *\n"
7106        | RInt64 _ -> pr "SV *\n"
7107        | RBool _ -> pr "SV *\n"
7108        | RConstString _ -> pr "SV *\n"
7109        | RConstOptString _ -> pr "SV *\n"
7110        | RString _ -> pr "SV *\n"
7111        | RBufferOut _ -> pr "SV *\n"
7112        | RStringList _
7113        | RStruct _ | RStructList _
7114        | RHashtable _ ->
7115            pr "void\n" (* all lists returned implictly on the stack *)
7116       );
7117       (* Call and arguments. *)
7118       pr "%s " name;
7119       generate_c_call_args ~handle:"g" ~decl:true style;
7120       pr "\n";
7121       pr "      guestfs_h *g;\n";
7122       iteri (
7123         fun i ->
7124           function
7125           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7126               pr "      char *%s;\n" n
7127           | OptString n ->
7128               (* http://www.perlmonks.org/?node_id=554277
7129                * Note that the implicit handle argument means we have
7130                * to add 1 to the ST(x) operator.
7131                *)
7132               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7133           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7134           | Bool n -> pr "      int %s;\n" n
7135           | Int n -> pr "      int %s;\n" n
7136       ) (snd style);
7137
7138       let do_cleanups () =
7139         List.iter (
7140           function
7141           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
7142           | FileIn _ | FileOut _ -> ()
7143           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7144         ) (snd style)
7145       in
7146
7147       (* Code. *)
7148       (match fst style with
7149        | RErr ->
7150            pr "PREINIT:\n";
7151            pr "      int r;\n";
7152            pr " PPCODE:\n";
7153            pr "      r = guestfs_%s " name;
7154            generate_c_call_args ~handle:"g" style;
7155            pr ";\n";
7156            do_cleanups ();
7157            pr "      if (r == -1)\n";
7158            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7159        | RInt n
7160        | RBool n ->
7161            pr "PREINIT:\n";
7162            pr "      int %s;\n" n;
7163            pr "   CODE:\n";
7164            pr "      %s = guestfs_%s " n name;
7165            generate_c_call_args ~handle:"g" style;
7166            pr ";\n";
7167            do_cleanups ();
7168            pr "      if (%s == -1)\n" n;
7169            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7170            pr "      RETVAL = newSViv (%s);\n" n;
7171            pr " OUTPUT:\n";
7172            pr "      RETVAL\n"
7173        | RInt64 n ->
7174            pr "PREINIT:\n";
7175            pr "      int64_t %s;\n" n;
7176            pr "   CODE:\n";
7177            pr "      %s = guestfs_%s " n name;
7178            generate_c_call_args ~handle:"g" style;
7179            pr ";\n";
7180            do_cleanups ();
7181            pr "      if (%s == -1)\n" n;
7182            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7183            pr "      RETVAL = my_newSVll (%s);\n" n;
7184            pr " OUTPUT:\n";
7185            pr "      RETVAL\n"
7186        | RConstString n ->
7187            pr "PREINIT:\n";
7188            pr "      const char *%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 == NULL)\n" n;
7195            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7196            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7197            pr " OUTPUT:\n";
7198            pr "      RETVAL\n"
7199        | RConstOptString n ->
7200            pr "PREINIT:\n";
7201            pr "      const char *%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 == NULL)\n" n;
7208            pr "        RETVAL = &PL_sv_undef;\n";
7209            pr "      else\n";
7210            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7211            pr " OUTPUT:\n";
7212            pr "      RETVAL\n"
7213        | RString n ->
7214            pr "PREINIT:\n";
7215            pr "      char *%s;\n" n;
7216            pr "   CODE:\n";
7217            pr "      %s = guestfs_%s " n name;
7218            generate_c_call_args ~handle:"g" style;
7219            pr ";\n";
7220            do_cleanups ();
7221            pr "      if (%s == NULL)\n" n;
7222            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7223            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7224            pr "      free (%s);\n" n;
7225            pr " OUTPUT:\n";
7226            pr "      RETVAL\n"
7227        | RStringList n | RHashtable n ->
7228            pr "PREINIT:\n";
7229            pr "      char **%s;\n" n;
7230            pr "      int i, n;\n";
7231            pr " PPCODE:\n";
7232            pr "      %s = guestfs_%s " n name;
7233            generate_c_call_args ~handle:"g" style;
7234            pr ";\n";
7235            do_cleanups ();
7236            pr "      if (%s == NULL)\n" n;
7237            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7238            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7239            pr "      EXTEND (SP, n);\n";
7240            pr "      for (i = 0; i < n; ++i) {\n";
7241            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7242            pr "        free (%s[i]);\n" n;
7243            pr "      }\n";
7244            pr "      free (%s);\n" n;
7245        | RStruct (n, typ) ->
7246            let cols = cols_of_struct typ in
7247            generate_perl_struct_code typ cols name style n do_cleanups
7248        | RStructList (n, typ) ->
7249            let cols = cols_of_struct typ in
7250            generate_perl_struct_list_code typ cols name style n do_cleanups
7251        | RBufferOut n ->
7252            pr "PREINIT:\n";
7253            pr "      char *%s;\n" n;
7254            pr "      size_t size;\n";
7255            pr "   CODE:\n";
7256            pr "      %s = guestfs_%s " n name;
7257            generate_c_call_args ~handle:"g" style;
7258            pr ";\n";
7259            do_cleanups ();
7260            pr "      if (%s == NULL)\n" n;
7261            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7262            pr "      RETVAL = newSVpv (%s, size);\n" n;
7263            pr "      free (%s);\n" n;
7264            pr " OUTPUT:\n";
7265            pr "      RETVAL\n"
7266       );
7267
7268       pr "\n"
7269   ) all_functions
7270
7271 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7272   pr "PREINIT:\n";
7273   pr "      struct guestfs_%s_list *%s;\n" typ n;
7274   pr "      int i;\n";
7275   pr "      HV *hv;\n";
7276   pr " PPCODE:\n";
7277   pr "      %s = guestfs_%s " n name;
7278   generate_c_call_args ~handle:"g" style;
7279   pr ";\n";
7280   do_cleanups ();
7281   pr "      if (%s == NULL)\n" n;
7282   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7283   pr "      EXTEND (SP, %s->len);\n" n;
7284   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7285   pr "        hv = newHV ();\n";
7286   List.iter (
7287     function
7288     | name, FString ->
7289         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7290           name (String.length name) n name
7291     | name, FUUID ->
7292         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7293           name (String.length name) n name
7294     | name, FBuffer ->
7295         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7296           name (String.length name) n name n name
7297     | name, (FBytes|FUInt64) ->
7298         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7299           name (String.length name) n name
7300     | name, FInt64 ->
7301         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7302           name (String.length name) n name
7303     | name, (FInt32|FUInt32) ->
7304         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7305           name (String.length name) n name
7306     | name, FChar ->
7307         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7308           name (String.length name) n name
7309     | name, FOptPercent ->
7310         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7311           name (String.length name) n name
7312   ) cols;
7313   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7314   pr "      }\n";
7315   pr "      guestfs_free_%s_list (%s);\n" typ n
7316
7317 and generate_perl_struct_code typ cols name style n do_cleanups =
7318   pr "PREINIT:\n";
7319   pr "      struct guestfs_%s *%s;\n" typ n;
7320   pr " PPCODE:\n";
7321   pr "      %s = guestfs_%s " n name;
7322   generate_c_call_args ~handle:"g" style;
7323   pr ";\n";
7324   do_cleanups ();
7325   pr "      if (%s == NULL)\n" n;
7326   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7327   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
7328   List.iter (
7329     fun ((name, _) as col) ->
7330       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7331
7332       match col with
7333       | name, FString ->
7334           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7335             n name
7336       | name, FBuffer ->
7337           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7338             n name n name
7339       | name, FUUID ->
7340           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7341             n name
7342       | name, (FBytes|FUInt64) ->
7343           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7344             n name
7345       | name, FInt64 ->
7346           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7347             n name
7348       | name, (FInt32|FUInt32) ->
7349           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7350             n name
7351       | name, FChar ->
7352           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7353             n name
7354       | name, FOptPercent ->
7355           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7356             n name
7357   ) cols;
7358   pr "      free (%s);\n" n
7359
7360 (* Generate Sys/Guestfs.pm. *)
7361 and generate_perl_pm () =
7362   generate_header HashStyle LGPLv2;
7363
7364   pr "\
7365 =pod
7366
7367 =head1 NAME
7368
7369 Sys::Guestfs - Perl bindings for libguestfs
7370
7371 =head1 SYNOPSIS
7372
7373  use Sys::Guestfs;
7374
7375  my $h = Sys::Guestfs->new ();
7376  $h->add_drive ('guest.img');
7377  $h->launch ();
7378  $h->wait_ready ();
7379  $h->mount ('/dev/sda1', '/');
7380  $h->touch ('/hello');
7381  $h->sync ();
7382
7383 =head1 DESCRIPTION
7384
7385 The C<Sys::Guestfs> module provides a Perl XS binding to the
7386 libguestfs API for examining and modifying virtual machine
7387 disk images.
7388
7389 Amongst the things this is good for: making batch configuration
7390 changes to guests, getting disk used/free statistics (see also:
7391 virt-df), migrating between virtualization systems (see also:
7392 virt-p2v), performing partial backups, performing partial guest
7393 clones, cloning guests and changing registry/UUID/hostname info, and
7394 much else besides.
7395
7396 Libguestfs uses Linux kernel and qemu code, and can access any type of
7397 guest filesystem that Linux and qemu can, including but not limited
7398 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7399 schemes, qcow, qcow2, vmdk.
7400
7401 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7402 LVs, what filesystem is in each LV, etc.).  It can also run commands
7403 in the context of the guest.  Also you can access filesystems over FTP.
7404
7405 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7406 functions for using libguestfs from Perl, including integration
7407 with libvirt.
7408
7409 =head1 ERRORS
7410
7411 All errors turn into calls to C<croak> (see L<Carp(3)>).
7412
7413 =head1 METHODS
7414
7415 =over 4
7416
7417 =cut
7418
7419 package Sys::Guestfs;
7420
7421 use strict;
7422 use warnings;
7423
7424 require XSLoader;
7425 XSLoader::load ('Sys::Guestfs');
7426
7427 =item $h = Sys::Guestfs->new ();
7428
7429 Create a new guestfs handle.
7430
7431 =cut
7432
7433 sub new {
7434   my $proto = shift;
7435   my $class = ref ($proto) || $proto;
7436
7437   my $self = Sys::Guestfs::_create ();
7438   bless $self, $class;
7439   return $self;
7440 }
7441
7442 ";
7443
7444   (* Actions.  We only need to print documentation for these as
7445    * they are pulled in from the XS code automatically.
7446    *)
7447   List.iter (
7448     fun (name, style, _, flags, _, _, longdesc) ->
7449       if not (List.mem NotInDocs flags) then (
7450         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7451         pr "=item ";
7452         generate_perl_prototype name style;
7453         pr "\n\n";
7454         pr "%s\n\n" longdesc;
7455         if List.mem ProtocolLimitWarning flags then
7456           pr "%s\n\n" protocol_limit_warning;
7457         if List.mem DangerWillRobinson flags then
7458           pr "%s\n\n" danger_will_robinson;
7459         match deprecation_notice flags with
7460         | None -> ()
7461         | Some txt -> pr "%s\n\n" txt
7462       )
7463   ) all_functions_sorted;
7464
7465   (* End of file. *)
7466   pr "\
7467 =cut
7468
7469 1;
7470
7471 =back
7472
7473 =head1 COPYRIGHT
7474
7475 Copyright (C) 2009 Red Hat Inc.
7476
7477 =head1 LICENSE
7478
7479 Please see the file COPYING.LIB for the full license.
7480
7481 =head1 SEE ALSO
7482
7483 L<guestfs(3)>,
7484 L<guestfish(1)>,
7485 L<http://libguestfs.org>,
7486 L<Sys::Guestfs::Lib(3)>.
7487
7488 =cut
7489 "
7490
7491 and generate_perl_prototype name style =
7492   (match fst style with
7493    | RErr -> ()
7494    | RBool n
7495    | RInt n
7496    | RInt64 n
7497    | RConstString n
7498    | RConstOptString n
7499    | RString n
7500    | RBufferOut n -> pr "$%s = " n
7501    | RStruct (n,_)
7502    | RHashtable n -> pr "%%%s = " n
7503    | RStringList n
7504    | RStructList (n,_) -> pr "@%s = " n
7505   );
7506   pr "$h->%s (" name;
7507   let comma = ref false in
7508   List.iter (
7509     fun arg ->
7510       if !comma then pr ", ";
7511       comma := true;
7512       match arg with
7513       | Pathname n | Device n | Dev_or_Path n | String n
7514       | OptString n | Bool n | Int n | FileIn n | FileOut n ->
7515           pr "$%s" n
7516       | StringList n | DeviceList n ->
7517           pr "\\@%s" n
7518   ) (snd style);
7519   pr ");"
7520
7521 (* Generate Python C module. *)
7522 and generate_python_c () =
7523   generate_header CStyle LGPLv2;
7524
7525   pr "\
7526 #include <Python.h>
7527
7528 #include <stdio.h>
7529 #include <stdlib.h>
7530 #include <assert.h>
7531
7532 #include \"guestfs.h\"
7533
7534 typedef struct {
7535   PyObject_HEAD
7536   guestfs_h *g;
7537 } Pyguestfs_Object;
7538
7539 static guestfs_h *
7540 get_handle (PyObject *obj)
7541 {
7542   assert (obj);
7543   assert (obj != Py_None);
7544   return ((Pyguestfs_Object *) obj)->g;
7545 }
7546
7547 static PyObject *
7548 put_handle (guestfs_h *g)
7549 {
7550   assert (g);
7551   return
7552     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7553 }
7554
7555 /* This list should be freed (but not the strings) after use. */
7556 static char **
7557 get_string_list (PyObject *obj)
7558 {
7559   int i, len;
7560   char **r;
7561
7562   assert (obj);
7563
7564   if (!PyList_Check (obj)) {
7565     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7566     return NULL;
7567   }
7568
7569   len = PyList_Size (obj);
7570   r = malloc (sizeof (char *) * (len+1));
7571   if (r == NULL) {
7572     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7573     return NULL;
7574   }
7575
7576   for (i = 0; i < len; ++i)
7577     r[i] = PyString_AsString (PyList_GetItem (obj, i));
7578   r[len] = NULL;
7579
7580   return r;
7581 }
7582
7583 static PyObject *
7584 put_string_list (char * const * const argv)
7585 {
7586   PyObject *list;
7587   int argc, i;
7588
7589   for (argc = 0; argv[argc] != NULL; ++argc)
7590     ;
7591
7592   list = PyList_New (argc);
7593   for (i = 0; i < argc; ++i)
7594     PyList_SetItem (list, i, PyString_FromString (argv[i]));
7595
7596   return list;
7597 }
7598
7599 static PyObject *
7600 put_table (char * const * const argv)
7601 {
7602   PyObject *list, *item;
7603   int argc, i;
7604
7605   for (argc = 0; argv[argc] != NULL; ++argc)
7606     ;
7607
7608   list = PyList_New (argc >> 1);
7609   for (i = 0; i < argc; i += 2) {
7610     item = PyTuple_New (2);
7611     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7612     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7613     PyList_SetItem (list, i >> 1, item);
7614   }
7615
7616   return list;
7617 }
7618
7619 static void
7620 free_strings (char **argv)
7621 {
7622   int argc;
7623
7624   for (argc = 0; argv[argc] != NULL; ++argc)
7625     free (argv[argc]);
7626   free (argv);
7627 }
7628
7629 static PyObject *
7630 py_guestfs_create (PyObject *self, PyObject *args)
7631 {
7632   guestfs_h *g;
7633
7634   g = guestfs_create ();
7635   if (g == NULL) {
7636     PyErr_SetString (PyExc_RuntimeError,
7637                      \"guestfs.create: failed to allocate handle\");
7638     return NULL;
7639   }
7640   guestfs_set_error_handler (g, NULL, NULL);
7641   return put_handle (g);
7642 }
7643
7644 static PyObject *
7645 py_guestfs_close (PyObject *self, PyObject *args)
7646 {
7647   PyObject *py_g;
7648   guestfs_h *g;
7649
7650   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7651     return NULL;
7652   g = get_handle (py_g);
7653
7654   guestfs_close (g);
7655
7656   Py_INCREF (Py_None);
7657   return Py_None;
7658 }
7659
7660 ";
7661
7662   let emit_put_list_function typ =
7663     pr "static PyObject *\n";
7664     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7665     pr "{\n";
7666     pr "  PyObject *list;\n";
7667     pr "  int i;\n";
7668     pr "\n";
7669     pr "  list = PyList_New (%ss->len);\n" typ;
7670     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
7671     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7672     pr "  return list;\n";
7673     pr "};\n";
7674     pr "\n"
7675   in
7676
7677   (* Structures, turned into Python dictionaries. *)
7678   List.iter (
7679     fun (typ, cols) ->
7680       pr "static PyObject *\n";
7681       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7682       pr "{\n";
7683       pr "  PyObject *dict;\n";
7684       pr "\n";
7685       pr "  dict = PyDict_New ();\n";
7686       List.iter (
7687         function
7688         | name, FString ->
7689             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7690             pr "                        PyString_FromString (%s->%s));\n"
7691               typ name
7692         | name, FBuffer ->
7693             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7694             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7695               typ name typ name
7696         | name, FUUID ->
7697             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7698             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
7699               typ name
7700         | name, (FBytes|FUInt64) ->
7701             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7702             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
7703               typ name
7704         | name, FInt64 ->
7705             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7706             pr "                        PyLong_FromLongLong (%s->%s));\n"
7707               typ name
7708         | name, FUInt32 ->
7709             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7710             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
7711               typ name
7712         | name, FInt32 ->
7713             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7714             pr "                        PyLong_FromLong (%s->%s));\n"
7715               typ name
7716         | name, FOptPercent ->
7717             pr "  if (%s->%s >= 0)\n" typ name;
7718             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
7719             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
7720               typ name;
7721             pr "  else {\n";
7722             pr "    Py_INCREF (Py_None);\n";
7723             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
7724             pr "  }\n"
7725         | name, FChar ->
7726             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7727             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7728       ) cols;
7729       pr "  return dict;\n";
7730       pr "};\n";
7731       pr "\n";
7732
7733   ) structs;
7734
7735   (* Emit a put_TYPE_list function definition only if that function is used. *)
7736   List.iter (
7737     function
7738     | typ, (RStructListOnly | RStructAndList) ->
7739         (* generate the function for typ *)
7740         emit_put_list_function typ
7741     | typ, _ -> () (* empty *)
7742   ) rstructs_used;
7743
7744   (* Python wrapper functions. *)
7745   List.iter (
7746     fun (name, style, _, _, _, _, _) ->
7747       pr "static PyObject *\n";
7748       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7749       pr "{\n";
7750
7751       pr "  PyObject *py_g;\n";
7752       pr "  guestfs_h *g;\n";
7753       pr "  PyObject *py_r;\n";
7754
7755       let error_code =
7756         match fst style with
7757         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
7758         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7759         | RConstString _ | RConstOptString _ ->
7760             pr "  const char *r;\n"; "NULL"
7761         | RString _ -> pr "  char *r;\n"; "NULL"
7762         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
7763         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
7764         | RStructList (_, typ) ->
7765             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7766         | RBufferOut _ ->
7767             pr "  char *r;\n";
7768             pr "  size_t size;\n";
7769             "NULL" in
7770
7771       List.iter (
7772         function
7773         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7774             pr "  const char *%s;\n" n
7775         | OptString n -> pr "  const char *%s;\n" n
7776         | StringList n | DeviceList n ->
7777             pr "  PyObject *py_%s;\n" n;
7778             pr "  char **%s;\n" n
7779         | Bool n -> pr "  int %s;\n" n
7780         | Int n -> pr "  int %s;\n" n
7781       ) (snd style);
7782
7783       pr "\n";
7784
7785       (* Convert the parameters. *)
7786       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
7787       List.iter (
7788         function
7789         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
7790         | OptString _ -> pr "z"
7791         | StringList _ | DeviceList _ -> pr "O"
7792         | Bool _ -> pr "i" (* XXX Python has booleans? *)
7793         | Int _ -> pr "i"
7794       ) (snd style);
7795       pr ":guestfs_%s\",\n" name;
7796       pr "                         &py_g";
7797       List.iter (
7798         function
7799         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
7800         | OptString n -> pr ", &%s" n
7801         | StringList n | DeviceList n -> pr ", &py_%s" n
7802         | Bool n -> pr ", &%s" n
7803         | Int n -> pr ", &%s" n
7804       ) (snd style);
7805
7806       pr "))\n";
7807       pr "    return NULL;\n";
7808
7809       pr "  g = get_handle (py_g);\n";
7810       List.iter (
7811         function
7812         | Pathname _ | Device _ | Dev_or_Path _ | String _
7813         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7814         | StringList n | DeviceList n ->
7815             pr "  %s = get_string_list (py_%s);\n" n n;
7816             pr "  if (!%s) return NULL;\n" n
7817       ) (snd style);
7818
7819       pr "\n";
7820
7821       pr "  r = guestfs_%s " name;
7822       generate_c_call_args ~handle:"g" style;
7823       pr ";\n";
7824
7825       List.iter (
7826         function
7827         | Pathname _ | Device _ | Dev_or_Path _ | String _
7828         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7829         | StringList n | DeviceList n ->
7830             pr "  free (%s);\n" n
7831       ) (snd style);
7832
7833       pr "  if (r == %s) {\n" error_code;
7834       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
7835       pr "    return NULL;\n";
7836       pr "  }\n";
7837       pr "\n";
7838
7839       (match fst style with
7840        | RErr ->
7841            pr "  Py_INCREF (Py_None);\n";
7842            pr "  py_r = Py_None;\n"
7843        | RInt _
7844        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
7845        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
7846        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
7847        | RConstOptString _ ->
7848            pr "  if (r)\n";
7849            pr "    py_r = PyString_FromString (r);\n";
7850            pr "  else {\n";
7851            pr "    Py_INCREF (Py_None);\n";
7852            pr "    py_r = Py_None;\n";
7853            pr "  }\n"
7854        | RString _ ->
7855            pr "  py_r = PyString_FromString (r);\n";
7856            pr "  free (r);\n"
7857        | RStringList _ ->
7858            pr "  py_r = put_string_list (r);\n";
7859            pr "  free_strings (r);\n"
7860        | RStruct (_, typ) ->
7861            pr "  py_r = put_%s (r);\n" typ;
7862            pr "  guestfs_free_%s (r);\n" typ
7863        | RStructList (_, typ) ->
7864            pr "  py_r = put_%s_list (r);\n" typ;
7865            pr "  guestfs_free_%s_list (r);\n" typ
7866        | RHashtable n ->
7867            pr "  py_r = put_table (r);\n";
7868            pr "  free_strings (r);\n"
7869        | RBufferOut _ ->
7870            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
7871            pr "  free (r);\n"
7872       );
7873
7874       pr "  return py_r;\n";
7875       pr "}\n";
7876       pr "\n"
7877   ) all_functions;
7878
7879   (* Table of functions. *)
7880   pr "static PyMethodDef methods[] = {\n";
7881   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
7882   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
7883   List.iter (
7884     fun (name, _, _, _, _, _, _) ->
7885       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
7886         name name
7887   ) all_functions;
7888   pr "  { NULL, NULL, 0, NULL }\n";
7889   pr "};\n";
7890   pr "\n";
7891
7892   (* Init function. *)
7893   pr "\
7894 void
7895 initlibguestfsmod (void)
7896 {
7897   static int initialized = 0;
7898
7899   if (initialized) return;
7900   Py_InitModule ((char *) \"libguestfsmod\", methods);
7901   initialized = 1;
7902 }
7903 "
7904
7905 (* Generate Python module. *)
7906 and generate_python_py () =
7907   generate_header HashStyle LGPLv2;
7908
7909   pr "\
7910 u\"\"\"Python bindings for libguestfs
7911
7912 import guestfs
7913 g = guestfs.GuestFS ()
7914 g.add_drive (\"guest.img\")
7915 g.launch ()
7916 g.wait_ready ()
7917 parts = g.list_partitions ()
7918
7919 The guestfs module provides a Python binding to the libguestfs API
7920 for examining and modifying virtual machine disk images.
7921
7922 Amongst the things this is good for: making batch configuration
7923 changes to guests, getting disk used/free statistics (see also:
7924 virt-df), migrating between virtualization systems (see also:
7925 virt-p2v), performing partial backups, performing partial guest
7926 clones, cloning guests and changing registry/UUID/hostname info, and
7927 much else besides.
7928
7929 Libguestfs uses Linux kernel and qemu code, and can access any type of
7930 guest filesystem that Linux and qemu can, including but not limited
7931 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7932 schemes, qcow, qcow2, vmdk.
7933
7934 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7935 LVs, what filesystem is in each LV, etc.).  It can also run commands
7936 in the context of the guest.  Also you can access filesystems over FTP.
7937
7938 Errors which happen while using the API are turned into Python
7939 RuntimeError exceptions.
7940
7941 To create a guestfs handle you usually have to perform the following
7942 sequence of calls:
7943
7944 # Create the handle, call add_drive at least once, and possibly
7945 # several times if the guest has multiple block devices:
7946 g = guestfs.GuestFS ()
7947 g.add_drive (\"guest.img\")
7948
7949 # Launch the qemu subprocess and wait for it to become ready:
7950 g.launch ()
7951 g.wait_ready ()
7952
7953 # Now you can issue commands, for example:
7954 logvols = g.lvs ()
7955
7956 \"\"\"
7957
7958 import libguestfsmod
7959
7960 class GuestFS:
7961     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
7962
7963     def __init__ (self):
7964         \"\"\"Create a new libguestfs handle.\"\"\"
7965         self._o = libguestfsmod.create ()
7966
7967     def __del__ (self):
7968         libguestfsmod.close (self._o)
7969
7970 ";
7971
7972   List.iter (
7973     fun (name, style, _, flags, _, _, longdesc) ->
7974       pr "    def %s " name;
7975       generate_py_call_args ~handle:"self" (snd style);
7976       pr ":\n";
7977
7978       if not (List.mem NotInDocs flags) then (
7979         let doc = replace_str longdesc "C<guestfs_" "C<g." in
7980         let doc =
7981           match fst style with
7982           | RErr | RInt _ | RInt64 _ | RBool _
7983           | RConstOptString _ | RConstString _
7984           | RString _ | RBufferOut _ -> doc
7985           | RStringList _ ->
7986               doc ^ "\n\nThis function returns a list of strings."
7987           | RStruct (_, typ) ->
7988               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
7989           | RStructList (_, typ) ->
7990               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
7991           | RHashtable _ ->
7992               doc ^ "\n\nThis function returns a dictionary." in
7993         let doc =
7994           if List.mem ProtocolLimitWarning flags then
7995             doc ^ "\n\n" ^ protocol_limit_warning
7996           else doc in
7997         let doc =
7998           if List.mem DangerWillRobinson flags then
7999             doc ^ "\n\n" ^ danger_will_robinson
8000           else doc in
8001         let doc =
8002           match deprecation_notice flags with
8003           | None -> doc
8004           | Some txt -> doc ^ "\n\n" ^ txt in
8005         let doc = pod2text ~width:60 name doc in
8006         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8007         let doc = String.concat "\n        " doc in
8008         pr "        u\"\"\"%s\"\"\"\n" doc;
8009       );
8010       pr "        return libguestfsmod.%s " name;
8011       generate_py_call_args ~handle:"self._o" (snd style);
8012       pr "\n";
8013       pr "\n";
8014   ) all_functions
8015
8016 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8017 and generate_py_call_args ~handle args =
8018   pr "(%s" handle;
8019   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8020   pr ")"
8021
8022 (* Useful if you need the longdesc POD text as plain text.  Returns a
8023  * list of lines.
8024  *
8025  * Because this is very slow (the slowest part of autogeneration),
8026  * we memoize the results.
8027  *)
8028 and pod2text ~width name longdesc =
8029   let key = width, name, longdesc in
8030   try Hashtbl.find pod2text_memo key
8031   with Not_found ->
8032     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8033     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8034     close_out chan;
8035     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8036     let chan = Unix.open_process_in cmd in
8037     let lines = ref [] in
8038     let rec loop i =
8039       let line = input_line chan in
8040       if i = 1 then             (* discard the first line of output *)
8041         loop (i+1)
8042       else (
8043         let line = triml line in
8044         lines := line :: !lines;
8045         loop (i+1)
8046       ) in
8047     let lines = try loop 1 with End_of_file -> List.rev !lines in
8048     Unix.unlink filename;
8049     (match Unix.close_process_in chan with
8050      | Unix.WEXITED 0 -> ()
8051      | Unix.WEXITED i ->
8052          failwithf "pod2text: process exited with non-zero status (%d)" i
8053      | Unix.WSIGNALED i | Unix.WSTOPPED i ->
8054          failwithf "pod2text: process signalled or stopped by signal %d" i
8055     );
8056     Hashtbl.add pod2text_memo key lines;
8057     pod2text_memo_updated ();
8058     lines
8059
8060 (* Generate ruby bindings. *)
8061 and generate_ruby_c () =
8062   generate_header CStyle LGPLv2;
8063
8064   pr "\
8065 #include <stdio.h>
8066 #include <stdlib.h>
8067
8068 #include <ruby.h>
8069
8070 #include \"guestfs.h\"
8071
8072 #include \"extconf.h\"
8073
8074 /* For Ruby < 1.9 */
8075 #ifndef RARRAY_LEN
8076 #define RARRAY_LEN(r) (RARRAY((r))->len)
8077 #endif
8078
8079 static VALUE m_guestfs;                 /* guestfs module */
8080 static VALUE c_guestfs;                 /* guestfs_h handle */
8081 static VALUE e_Error;                   /* used for all errors */
8082
8083 static void ruby_guestfs_free (void *p)
8084 {
8085   if (!p) return;
8086   guestfs_close ((guestfs_h *) p);
8087 }
8088
8089 static VALUE ruby_guestfs_create (VALUE m)
8090 {
8091   guestfs_h *g;
8092
8093   g = guestfs_create ();
8094   if (!g)
8095     rb_raise (e_Error, \"failed to create guestfs handle\");
8096
8097   /* Don't print error messages to stderr by default. */
8098   guestfs_set_error_handler (g, NULL, NULL);
8099
8100   /* Wrap it, and make sure the close function is called when the
8101    * handle goes away.
8102    */
8103   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8104 }
8105
8106 static VALUE ruby_guestfs_close (VALUE gv)
8107 {
8108   guestfs_h *g;
8109   Data_Get_Struct (gv, guestfs_h, g);
8110
8111   ruby_guestfs_free (g);
8112   DATA_PTR (gv) = NULL;
8113
8114   return Qnil;
8115 }
8116
8117 ";
8118
8119   List.iter (
8120     fun (name, style, _, _, _, _, _) ->
8121       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8122       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8123       pr ")\n";
8124       pr "{\n";
8125       pr "  guestfs_h *g;\n";
8126       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8127       pr "  if (!g)\n";
8128       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8129         name;
8130       pr "\n";
8131
8132       List.iter (
8133         function
8134         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8135             pr "  Check_Type (%sv, T_STRING);\n" n;
8136             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8137             pr "  if (!%s)\n" n;
8138             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8139             pr "              \"%s\", \"%s\");\n" n name
8140         | OptString n ->
8141             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8142         | StringList n | DeviceList n ->
8143             pr "  char **%s;\n" n;
8144             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8145             pr "  {\n";
8146             pr "    int i, len;\n";
8147             pr "    len = RARRAY_LEN (%sv);\n" n;
8148             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8149               n;
8150             pr "    for (i = 0; i < len; ++i) {\n";
8151             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8152             pr "      %s[i] = StringValueCStr (v);\n" n;
8153             pr "    }\n";
8154             pr "    %s[len] = NULL;\n" n;
8155             pr "  }\n";
8156         | Bool n ->
8157             pr "  int %s = RTEST (%sv);\n" n n
8158         | Int n ->
8159             pr "  int %s = NUM2INT (%sv);\n" n n
8160       ) (snd style);
8161       pr "\n";
8162
8163       let error_code =
8164         match fst style with
8165         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8166         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8167         | RConstString _ | RConstOptString _ ->
8168             pr "  const char *r;\n"; "NULL"
8169         | RString _ -> pr "  char *r;\n"; "NULL"
8170         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8171         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8172         | RStructList (_, typ) ->
8173             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8174         | RBufferOut _ ->
8175             pr "  char *r;\n";
8176             pr "  size_t size;\n";
8177             "NULL" in
8178       pr "\n";
8179
8180       pr "  r = guestfs_%s " name;
8181       generate_c_call_args ~handle:"g" style;
8182       pr ";\n";
8183
8184       List.iter (
8185         function
8186         | Pathname _ | Device _ | Dev_or_Path _ | String _
8187         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
8188         | StringList n | DeviceList n ->
8189             pr "  free (%s);\n" n
8190       ) (snd style);
8191
8192       pr "  if (r == %s)\n" error_code;
8193       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8194       pr "\n";
8195
8196       (match fst style with
8197        | RErr ->
8198            pr "  return Qnil;\n"
8199        | RInt _ | RBool _ ->
8200            pr "  return INT2NUM (r);\n"
8201        | RInt64 _ ->
8202            pr "  return ULL2NUM (r);\n"
8203        | RConstString _ ->
8204            pr "  return rb_str_new2 (r);\n";
8205        | RConstOptString _ ->
8206            pr "  if (r)\n";
8207            pr "    return rb_str_new2 (r);\n";
8208            pr "  else\n";
8209            pr "    return Qnil;\n";
8210        | RString _ ->
8211            pr "  VALUE rv = rb_str_new2 (r);\n";
8212            pr "  free (r);\n";
8213            pr "  return rv;\n";
8214        | RStringList _ ->
8215            pr "  int i, len = 0;\n";
8216            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8217            pr "  VALUE rv = rb_ary_new2 (len);\n";
8218            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8219            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8220            pr "    free (r[i]);\n";
8221            pr "  }\n";
8222            pr "  free (r);\n";
8223            pr "  return rv;\n"
8224        | RStruct (_, typ) ->
8225            let cols = cols_of_struct typ in
8226            generate_ruby_struct_code typ cols
8227        | RStructList (_, typ) ->
8228            let cols = cols_of_struct typ in
8229            generate_ruby_struct_list_code typ cols
8230        | RHashtable _ ->
8231            pr "  VALUE rv = rb_hash_new ();\n";
8232            pr "  int i;\n";
8233            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8234            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8235            pr "    free (r[i]);\n";
8236            pr "    free (r[i+1]);\n";
8237            pr "  }\n";
8238            pr "  free (r);\n";
8239            pr "  return rv;\n"
8240        | RBufferOut _ ->
8241            pr "  VALUE rv = rb_str_new (r, size);\n";
8242            pr "  free (r);\n";
8243            pr "  return rv;\n";
8244       );
8245
8246       pr "}\n";
8247       pr "\n"
8248   ) all_functions;
8249
8250   pr "\
8251 /* Initialize the module. */
8252 void Init__guestfs ()
8253 {
8254   m_guestfs = rb_define_module (\"Guestfs\");
8255   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8256   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8257
8258   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8259   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8260
8261 ";
8262   (* Define the rest of the methods. *)
8263   List.iter (
8264     fun (name, style, _, _, _, _, _) ->
8265       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8266       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8267   ) all_functions;
8268
8269   pr "}\n"
8270
8271 (* Ruby code to return a struct. *)
8272 and generate_ruby_struct_code typ cols =
8273   pr "  VALUE rv = rb_hash_new ();\n";
8274   List.iter (
8275     function
8276     | name, FString ->
8277         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8278     | name, FBuffer ->
8279         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8280     | name, FUUID ->
8281         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8282     | name, (FBytes|FUInt64) ->
8283         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8284     | name, FInt64 ->
8285         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8286     | name, FUInt32 ->
8287         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8288     | name, FInt32 ->
8289         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8290     | name, FOptPercent ->
8291         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8292     | name, FChar -> (* XXX wrong? *)
8293         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8294   ) cols;
8295   pr "  guestfs_free_%s (r);\n" typ;
8296   pr "  return rv;\n"
8297
8298 (* Ruby code to return a struct list. *)
8299 and generate_ruby_struct_list_code typ cols =
8300   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8301   pr "  int i;\n";
8302   pr "  for (i = 0; i < r->len; ++i) {\n";
8303   pr "    VALUE hv = rb_hash_new ();\n";
8304   List.iter (
8305     function
8306     | name, FString ->
8307         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8308     | name, FBuffer ->
8309         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
8310     | name, FUUID ->
8311         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8312     | name, (FBytes|FUInt64) ->
8313         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8314     | name, FInt64 ->
8315         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8316     | name, FUInt32 ->
8317         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8318     | name, FInt32 ->
8319         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8320     | name, FOptPercent ->
8321         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8322     | name, FChar -> (* XXX wrong? *)
8323         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8324   ) cols;
8325   pr "    rb_ary_push (rv, hv);\n";
8326   pr "  }\n";
8327   pr "  guestfs_free_%s_list (r);\n" typ;
8328   pr "  return rv;\n"
8329
8330 (* Generate Java bindings GuestFS.java file. *)
8331 and generate_java_java () =
8332   generate_header CStyle LGPLv2;
8333
8334   pr "\
8335 package com.redhat.et.libguestfs;
8336
8337 import java.util.HashMap;
8338 import com.redhat.et.libguestfs.LibGuestFSException;
8339 import com.redhat.et.libguestfs.PV;
8340 import com.redhat.et.libguestfs.VG;
8341 import com.redhat.et.libguestfs.LV;
8342 import com.redhat.et.libguestfs.Stat;
8343 import com.redhat.et.libguestfs.StatVFS;
8344 import com.redhat.et.libguestfs.IntBool;
8345 import com.redhat.et.libguestfs.Dirent;
8346
8347 /**
8348  * The GuestFS object is a libguestfs handle.
8349  *
8350  * @author rjones
8351  */
8352 public class GuestFS {
8353   // Load the native code.
8354   static {
8355     System.loadLibrary (\"guestfs_jni\");
8356   }
8357
8358   /**
8359    * The native guestfs_h pointer.
8360    */
8361   long g;
8362
8363   /**
8364    * Create a libguestfs handle.
8365    *
8366    * @throws LibGuestFSException
8367    */
8368   public GuestFS () throws LibGuestFSException
8369   {
8370     g = _create ();
8371   }
8372   private native long _create () throws LibGuestFSException;
8373
8374   /**
8375    * Close a libguestfs handle.
8376    *
8377    * You can also leave handles to be collected by the garbage
8378    * collector, but this method ensures that the resources used
8379    * by the handle are freed up immediately.  If you call any
8380    * other methods after closing the handle, you will get an
8381    * exception.
8382    *
8383    * @throws LibGuestFSException
8384    */
8385   public void close () throws LibGuestFSException
8386   {
8387     if (g != 0)
8388       _close (g);
8389     g = 0;
8390   }
8391   private native void _close (long g) throws LibGuestFSException;
8392
8393   public void finalize () throws LibGuestFSException
8394   {
8395     close ();
8396   }
8397
8398 ";
8399
8400   List.iter (
8401     fun (name, style, _, flags, _, shortdesc, longdesc) ->
8402       if not (List.mem NotInDocs flags); then (
8403         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8404         let doc =
8405           if List.mem ProtocolLimitWarning flags then
8406             doc ^ "\n\n" ^ protocol_limit_warning
8407           else doc in
8408         let doc =
8409           if List.mem DangerWillRobinson flags then
8410             doc ^ "\n\n" ^ danger_will_robinson
8411           else doc in
8412         let doc =
8413           match deprecation_notice flags with
8414           | None -> doc
8415           | Some txt -> doc ^ "\n\n" ^ txt in
8416         let doc = pod2text ~width:60 name doc in
8417         let doc = List.map (            (* RHBZ#501883 *)
8418           function
8419           | "" -> "<p>"
8420           | nonempty -> nonempty
8421         ) doc in
8422         let doc = String.concat "\n   * " doc in
8423
8424         pr "  /**\n";
8425         pr "   * %s\n" shortdesc;
8426         pr "   * <p>\n";
8427         pr "   * %s\n" doc;
8428         pr "   * @throws LibGuestFSException\n";
8429         pr "   */\n";
8430         pr "  ";
8431       );
8432       generate_java_prototype ~public:true ~semicolon:false name style;
8433       pr "\n";
8434       pr "  {\n";
8435       pr "    if (g == 0)\n";
8436       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
8437         name;
8438       pr "    ";
8439       if fst style <> RErr then pr "return ";
8440       pr "_%s " name;
8441       generate_java_call_args ~handle:"g" (snd style);
8442       pr ";\n";
8443       pr "  }\n";
8444       pr "  ";
8445       generate_java_prototype ~privat:true ~native:true name style;
8446       pr "\n";
8447       pr "\n";
8448   ) all_functions;
8449
8450   pr "}\n"
8451
8452 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8453 and generate_java_call_args ~handle args =
8454   pr "(%s" handle;
8455   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8456   pr ")"
8457
8458 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8459     ?(semicolon=true) name style =
8460   if privat then pr "private ";
8461   if public then pr "public ";
8462   if native then pr "native ";
8463
8464   (* return type *)
8465   (match fst style with
8466    | RErr -> pr "void ";
8467    | RInt _ -> pr "int ";
8468    | RInt64 _ -> pr "long ";
8469    | RBool _ -> pr "boolean ";
8470    | RConstString _ | RConstOptString _ | RString _
8471    | RBufferOut _ -> pr "String ";
8472    | RStringList _ -> pr "String[] ";
8473    | RStruct (_, typ) ->
8474        let name = java_name_of_struct typ in
8475        pr "%s " name;
8476    | RStructList (_, typ) ->
8477        let name = java_name_of_struct typ in
8478        pr "%s[] " name;
8479    | RHashtable _ -> pr "HashMap<String,String> ";
8480   );
8481
8482   if native then pr "_%s " name else pr "%s " name;
8483   pr "(";
8484   let needs_comma = ref false in
8485   if native then (
8486     pr "long g";
8487     needs_comma := true
8488   );
8489
8490   (* args *)
8491   List.iter (
8492     fun arg ->
8493       if !needs_comma then pr ", ";
8494       needs_comma := true;
8495
8496       match arg with
8497       | Pathname n
8498       | Device n | Dev_or_Path n
8499       | String n
8500       | OptString n
8501       | FileIn n
8502       | FileOut n ->
8503           pr "String %s" n
8504       | StringList n | DeviceList n ->
8505           pr "String[] %s" n
8506       | Bool n ->
8507           pr "boolean %s" n
8508       | Int n ->
8509           pr "int %s" n
8510   ) (snd style);
8511
8512   pr ")\n";
8513   pr "    throws LibGuestFSException";
8514   if semicolon then pr ";"
8515
8516 and generate_java_struct jtyp cols =
8517   generate_header CStyle LGPLv2;
8518
8519   pr "\
8520 package com.redhat.et.libguestfs;
8521
8522 /**
8523  * Libguestfs %s structure.
8524  *
8525  * @author rjones
8526  * @see GuestFS
8527  */
8528 public class %s {
8529 " jtyp jtyp;
8530
8531   List.iter (
8532     function
8533     | name, FString
8534     | name, FUUID
8535     | name, FBuffer -> pr "  public String %s;\n" name
8536     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
8537     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
8538     | name, FChar -> pr "  public char %s;\n" name
8539     | name, FOptPercent ->
8540         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
8541         pr "  public float %s;\n" name
8542   ) cols;
8543
8544   pr "}\n"
8545
8546 and generate_java_c () =
8547   generate_header CStyle LGPLv2;
8548
8549   pr "\
8550 #include <stdio.h>
8551 #include <stdlib.h>
8552 #include <string.h>
8553
8554 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8555 #include \"guestfs.h\"
8556
8557 /* Note that this function returns.  The exception is not thrown
8558  * until after the wrapper function returns.
8559  */
8560 static void
8561 throw_exception (JNIEnv *env, const char *msg)
8562 {
8563   jclass cl;
8564   cl = (*env)->FindClass (env,
8565                           \"com/redhat/et/libguestfs/LibGuestFSException\");
8566   (*env)->ThrowNew (env, cl, msg);
8567 }
8568
8569 JNIEXPORT jlong JNICALL
8570 Java_com_redhat_et_libguestfs_GuestFS__1create
8571   (JNIEnv *env, jobject obj)
8572 {
8573   guestfs_h *g;
8574
8575   g = guestfs_create ();
8576   if (g == NULL) {
8577     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8578     return 0;
8579   }
8580   guestfs_set_error_handler (g, NULL, NULL);
8581   return (jlong) (long) g;
8582 }
8583
8584 JNIEXPORT void JNICALL
8585 Java_com_redhat_et_libguestfs_GuestFS__1close
8586   (JNIEnv *env, jobject obj, jlong jg)
8587 {
8588   guestfs_h *g = (guestfs_h *) (long) jg;
8589   guestfs_close (g);
8590 }
8591
8592 ";
8593
8594   List.iter (
8595     fun (name, style, _, _, _, _, _) ->
8596       pr "JNIEXPORT ";
8597       (match fst style with
8598        | RErr -> pr "void ";
8599        | RInt _ -> pr "jint ";
8600        | RInt64 _ -> pr "jlong ";
8601        | RBool _ -> pr "jboolean ";
8602        | RConstString _ | RConstOptString _ | RString _
8603        | RBufferOut _ -> pr "jstring ";
8604        | RStruct _ | RHashtable _ ->
8605            pr "jobject ";
8606        | RStringList _ | RStructList _ ->
8607            pr "jobjectArray ";
8608       );
8609       pr "JNICALL\n";
8610       pr "Java_com_redhat_et_libguestfs_GuestFS_";
8611       pr "%s" (replace_str ("_" ^ name) "_" "_1");
8612       pr "\n";
8613       pr "  (JNIEnv *env, jobject obj, jlong jg";
8614       List.iter (
8615         function
8616         | Pathname n
8617         | Device n | Dev_or_Path n
8618         | String n
8619         | OptString n
8620         | FileIn n
8621         | FileOut n ->
8622             pr ", jstring j%s" n
8623         | StringList n | DeviceList n ->
8624             pr ", jobjectArray j%s" n
8625         | Bool n ->
8626             pr ", jboolean j%s" n
8627         | Int n ->
8628             pr ", jint j%s" n
8629       ) (snd style);
8630       pr ")\n";
8631       pr "{\n";
8632       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
8633       let error_code, no_ret =
8634         match fst style with
8635         | RErr -> pr "  int r;\n"; "-1", ""
8636         | RBool _
8637         | RInt _ -> pr "  int r;\n"; "-1", "0"
8638         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
8639         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8640         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8641         | RString _ ->
8642             pr "  jstring jr;\n";
8643             pr "  char *r;\n"; "NULL", "NULL"
8644         | RStringList _ ->
8645             pr "  jobjectArray jr;\n";
8646             pr "  int r_len;\n";
8647             pr "  jclass cl;\n";
8648             pr "  jstring jstr;\n";
8649             pr "  char **r;\n"; "NULL", "NULL"
8650         | RStruct (_, typ) ->
8651             pr "  jobject jr;\n";
8652             pr "  jclass cl;\n";
8653             pr "  jfieldID fl;\n";
8654             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8655         | RStructList (_, typ) ->
8656             pr "  jobjectArray jr;\n";
8657             pr "  jclass cl;\n";
8658             pr "  jfieldID fl;\n";
8659             pr "  jobject jfl;\n";
8660             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8661         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
8662         | RBufferOut _ ->
8663             pr "  jstring jr;\n";
8664             pr "  char *r;\n";
8665             pr "  size_t size;\n";
8666             "NULL", "NULL" in
8667       List.iter (
8668         function
8669         | Pathname n
8670         | Device n | Dev_or_Path n
8671         | String n
8672         | OptString n
8673         | FileIn n
8674         | FileOut n ->
8675             pr "  const char *%s;\n" n
8676         | StringList n | DeviceList n ->
8677             pr "  int %s_len;\n" n;
8678             pr "  const char **%s;\n" n
8679         | Bool n
8680         | Int n ->
8681             pr "  int %s;\n" n
8682       ) (snd style);
8683
8684       let needs_i =
8685         (match fst style with
8686          | RStringList _ | RStructList _ -> true
8687          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8688          | RConstOptString _
8689          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8690           List.exists (function
8691                        | StringList _ -> true
8692                        | DeviceList _ -> true
8693                        | _ -> false) (snd style) in
8694       if needs_i then
8695         pr "  int i;\n";
8696
8697       pr "\n";
8698
8699       (* Get the parameters. *)
8700       List.iter (
8701         function
8702         | Pathname n
8703         | Device n | Dev_or_Path n
8704         | String n
8705         | FileIn n
8706         | FileOut n ->
8707             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8708         | OptString n ->
8709             (* This is completely undocumented, but Java null becomes
8710              * a NULL parameter.
8711              *)
8712             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8713         | StringList n | DeviceList n ->
8714             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8715             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8716             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8717             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8718               n;
8719             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8720             pr "  }\n";
8721             pr "  %s[%s_len] = NULL;\n" n n;
8722         | Bool n
8723         | Int n ->
8724             pr "  %s = j%s;\n" n n
8725       ) (snd style);
8726
8727       (* Make the call. *)
8728       pr "  r = guestfs_%s " name;
8729       generate_c_call_args ~handle:"g" style;
8730       pr ";\n";
8731
8732       (* Release the parameters. *)
8733       List.iter (
8734         function
8735         | Pathname n
8736         | Device n | Dev_or_Path n
8737         | String n
8738         | FileIn n
8739         | FileOut n ->
8740             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8741         | OptString n ->
8742             pr "  if (j%s)\n" n;
8743             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8744         | StringList n | DeviceList n ->
8745             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8746             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8747               n;
8748             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8749             pr "  }\n";
8750             pr "  free (%s);\n" n
8751         | Bool n
8752         | Int n -> ()
8753       ) (snd style);
8754
8755       (* Check for errors. *)
8756       pr "  if (r == %s) {\n" error_code;
8757       pr "    throw_exception (env, guestfs_last_error (g));\n";
8758       pr "    return %s;\n" no_ret;
8759       pr "  }\n";
8760
8761       (* Return value. *)
8762       (match fst style with
8763        | RErr -> ()
8764        | RInt _ -> pr "  return (jint) r;\n"
8765        | RBool _ -> pr "  return (jboolean) r;\n"
8766        | RInt64 _ -> pr "  return (jlong) r;\n"
8767        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
8768        | RConstOptString _ ->
8769            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
8770        | RString _ ->
8771            pr "  jr = (*env)->NewStringUTF (env, r);\n";
8772            pr "  free (r);\n";
8773            pr "  return jr;\n"
8774        | RStringList _ ->
8775            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
8776            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
8777            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
8778            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
8779            pr "  for (i = 0; i < r_len; ++i) {\n";
8780            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
8781            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
8782            pr "    free (r[i]);\n";
8783            pr "  }\n";
8784            pr "  free (r);\n";
8785            pr "  return jr;\n"
8786        | RStruct (_, typ) ->
8787            let jtyp = java_name_of_struct typ in
8788            let cols = cols_of_struct typ in
8789            generate_java_struct_return typ jtyp cols
8790        | RStructList (_, typ) ->
8791            let jtyp = java_name_of_struct typ in
8792            let cols = cols_of_struct typ in
8793            generate_java_struct_list_return typ jtyp cols
8794        | RHashtable _ ->
8795            (* XXX *)
8796            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
8797            pr "  return NULL;\n"
8798        | RBufferOut _ ->
8799            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
8800            pr "  free (r);\n";
8801            pr "  return jr;\n"
8802       );
8803
8804       pr "}\n";
8805       pr "\n"
8806   ) all_functions
8807
8808 and generate_java_struct_return typ jtyp cols =
8809   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8810   pr "  jr = (*env)->AllocObject (env, cl);\n";
8811   List.iter (
8812     function
8813     | name, FString ->
8814         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8815         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
8816     | name, FUUID ->
8817         pr "  {\n";
8818         pr "    char s[33];\n";
8819         pr "    memcpy (s, r->%s, 32);\n" name;
8820         pr "    s[32] = 0;\n";
8821         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8822         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8823         pr "  }\n";
8824     | name, FBuffer ->
8825         pr "  {\n";
8826         pr "    int len = r->%s_len;\n" name;
8827         pr "    char s[len+1];\n";
8828         pr "    memcpy (s, r->%s, len);\n" name;
8829         pr "    s[len] = 0;\n";
8830         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8831         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8832         pr "  }\n";
8833     | name, (FBytes|FUInt64|FInt64) ->
8834         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8835         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8836     | name, (FUInt32|FInt32) ->
8837         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8838         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8839     | name, FOptPercent ->
8840         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8841         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
8842     | name, FChar ->
8843         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8844         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8845   ) cols;
8846   pr "  free (r);\n";
8847   pr "  return jr;\n"
8848
8849 and generate_java_struct_list_return typ jtyp cols =
8850   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8851   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
8852   pr "  for (i = 0; i < r->len; ++i) {\n";
8853   pr "    jfl = (*env)->AllocObject (env, cl);\n";
8854   List.iter (
8855     function
8856     | name, FString ->
8857         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8858         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
8859     | name, FUUID ->
8860         pr "    {\n";
8861         pr "      char s[33];\n";
8862         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
8863         pr "      s[32] = 0;\n";
8864         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8865         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8866         pr "    }\n";
8867     | name, FBuffer ->
8868         pr "    {\n";
8869         pr "      int len = r->val[i].%s_len;\n" name;
8870         pr "      char s[len+1];\n";
8871         pr "      memcpy (s, r->val[i].%s, len);\n" name;
8872         pr "      s[len] = 0;\n";
8873         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8874         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8875         pr "    }\n";
8876     | name, (FBytes|FUInt64|FInt64) ->
8877         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8878         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8879     | name, (FUInt32|FInt32) ->
8880         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8881         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8882     | name, FOptPercent ->
8883         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8884         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
8885     | name, FChar ->
8886         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8887         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8888   ) cols;
8889   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
8890   pr "  }\n";
8891   pr "  guestfs_free_%s_list (r);\n" typ;
8892   pr "  return jr;\n"
8893
8894 and generate_java_makefile_inc () =
8895   generate_header HashStyle GPLv2;
8896
8897   pr "java_built_sources = \\\n";
8898   List.iter (
8899     fun (typ, jtyp) ->
8900         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
8901   ) java_structs;
8902   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
8903
8904 and generate_haskell_hs () =
8905   generate_header HaskellStyle LGPLv2;
8906
8907   (* XXX We only know how to generate partial FFI for Haskell
8908    * at the moment.  Please help out!
8909    *)
8910   let can_generate style =
8911     match style with
8912     | RErr, _
8913     | RInt _, _
8914     | RInt64 _, _ -> true
8915     | RBool _, _
8916     | RConstString _, _
8917     | RConstOptString _, _
8918     | RString _, _
8919     | RStringList _, _
8920     | RStruct _, _
8921     | RStructList _, _
8922     | RHashtable _, _
8923     | RBufferOut _, _ -> false in
8924
8925   pr "\
8926 {-# INCLUDE <guestfs.h> #-}
8927 {-# LANGUAGE ForeignFunctionInterface #-}
8928
8929 module Guestfs (
8930   create";
8931
8932   (* List out the names of the actions we want to export. *)
8933   List.iter (
8934     fun (name, style, _, _, _, _, _) ->
8935       if can_generate style then pr ",\n  %s" name
8936   ) all_functions;
8937
8938   pr "
8939   ) where
8940 import Foreign
8941 import Foreign.C
8942 import Foreign.C.Types
8943 import IO
8944 import Control.Exception
8945 import Data.Typeable
8946
8947 data GuestfsS = GuestfsS            -- represents the opaque C struct
8948 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
8949 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
8950
8951 -- XXX define properly later XXX
8952 data PV = PV
8953 data VG = VG
8954 data LV = LV
8955 data IntBool = IntBool
8956 data Stat = Stat
8957 data StatVFS = StatVFS
8958 data Hashtable = Hashtable
8959
8960 foreign import ccall unsafe \"guestfs_create\" c_create
8961   :: IO GuestfsP
8962 foreign import ccall unsafe \"&guestfs_close\" c_close
8963   :: FunPtr (GuestfsP -> IO ())
8964 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
8965   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
8966
8967 create :: IO GuestfsH
8968 create = do
8969   p <- c_create
8970   c_set_error_handler p nullPtr nullPtr
8971   h <- newForeignPtr c_close p
8972   return h
8973
8974 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
8975   :: GuestfsP -> IO CString
8976
8977 -- last_error :: GuestfsH -> IO (Maybe String)
8978 -- last_error h = do
8979 --   str <- withForeignPtr h (\\p -> c_last_error p)
8980 --   maybePeek peekCString str
8981
8982 last_error :: GuestfsH -> IO (String)
8983 last_error h = do
8984   str <- withForeignPtr h (\\p -> c_last_error p)
8985   if (str == nullPtr)
8986     then return \"no error\"
8987     else peekCString str
8988
8989 ";
8990
8991   (* Generate wrappers for each foreign function. *)
8992   List.iter (
8993     fun (name, style, _, _, _, _, _) ->
8994       if can_generate style then (
8995         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
8996         pr "  :: ";
8997         generate_haskell_prototype ~handle:"GuestfsP" style;
8998         pr "\n";
8999         pr "\n";
9000         pr "%s :: " name;
9001         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9002         pr "\n";
9003         pr "%s %s = do\n" name
9004           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9005         pr "  r <- ";
9006         (* Convert pointer arguments using with* functions. *)
9007         List.iter (
9008           function
9009           | FileIn n
9010           | FileOut n
9011           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9012           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9013           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9014           | Bool _ | Int _ -> ()
9015         ) (snd style);
9016         (* Convert integer arguments. *)
9017         let args =
9018           List.map (
9019             function
9020             | Bool n -> sprintf "(fromBool %s)" n
9021             | Int n -> sprintf "(fromIntegral %s)" n
9022             | FileIn n | FileOut n
9023             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9024           ) (snd style) in
9025         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9026           (String.concat " " ("p" :: args));
9027         (match fst style with
9028          | RErr | RInt _ | RInt64 _ | RBool _ ->
9029              pr "  if (r == -1)\n";
9030              pr "    then do\n";
9031              pr "      err <- last_error h\n";
9032              pr "      fail err\n";
9033          | RConstString _ | RConstOptString _ | RString _
9034          | RStringList _ | RStruct _
9035          | RStructList _ | RHashtable _ | RBufferOut _ ->
9036              pr "  if (r == nullPtr)\n";
9037              pr "    then do\n";
9038              pr "      err <- last_error h\n";
9039              pr "      fail err\n";
9040         );
9041         (match fst style with
9042          | RErr ->
9043              pr "    else return ()\n"
9044          | RInt _ ->
9045              pr "    else return (fromIntegral r)\n"
9046          | RInt64 _ ->
9047              pr "    else return (fromIntegral r)\n"
9048          | RBool _ ->
9049              pr "    else return (toBool r)\n"
9050          | RConstString _
9051          | RConstOptString _
9052          | RString _
9053          | RStringList _
9054          | RStruct _
9055          | RStructList _
9056          | RHashtable _
9057          | RBufferOut _ ->
9058              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9059         );
9060         pr "\n";
9061       )
9062   ) all_functions
9063
9064 and generate_haskell_prototype ~handle ?(hs = false) style =
9065   pr "%s -> " handle;
9066   let string = if hs then "String" else "CString" in
9067   let int = if hs then "Int" else "CInt" in
9068   let bool = if hs then "Bool" else "CInt" in
9069   let int64 = if hs then "Integer" else "Int64" in
9070   List.iter (
9071     fun arg ->
9072       (match arg with
9073        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9074        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9075        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9076        | Bool _ -> pr "%s" bool
9077        | Int _ -> pr "%s" int
9078        | FileIn _ -> pr "%s" string
9079        | FileOut _ -> pr "%s" string
9080       );
9081       pr " -> ";
9082   ) (snd style);
9083   pr "IO (";
9084   (match fst style with
9085    | RErr -> if not hs then pr "CInt"
9086    | RInt _ -> pr "%s" int
9087    | RInt64 _ -> pr "%s" int64
9088    | RBool _ -> pr "%s" bool
9089    | RConstString _ -> pr "%s" string
9090    | RConstOptString _ -> pr "Maybe %s" string
9091    | RString _ -> pr "%s" string
9092    | RStringList _ -> pr "[%s]" string
9093    | RStruct (_, typ) ->
9094        let name = java_name_of_struct typ in
9095        pr "%s" name
9096    | RStructList (_, typ) ->
9097        let name = java_name_of_struct typ in
9098        pr "[%s]" name
9099    | RHashtable _ -> pr "Hashtable"
9100    | RBufferOut _ -> pr "%s" string
9101   );
9102   pr ")"
9103
9104 and generate_bindtests () =
9105   generate_header CStyle LGPLv2;
9106
9107   pr "\
9108 #include <stdio.h>
9109 #include <stdlib.h>
9110 #include <inttypes.h>
9111 #include <string.h>
9112
9113 #include \"guestfs.h\"
9114 #include \"guestfs_protocol.h\"
9115
9116 #define error guestfs_error
9117 #define safe_calloc guestfs_safe_calloc
9118 #define safe_malloc guestfs_safe_malloc
9119
9120 static void
9121 print_strings (char *const *argv)
9122 {
9123   int argc;
9124
9125   printf (\"[\");
9126   for (argc = 0; argv[argc] != NULL; ++argc) {
9127     if (argc > 0) printf (\", \");
9128     printf (\"\\\"%%s\\\"\", argv[argc]);
9129   }
9130   printf (\"]\\n\");
9131 }
9132
9133 /* The test0 function prints its parameters to stdout. */
9134 ";
9135
9136   let test0, tests =
9137     match test_functions with
9138     | [] -> assert false
9139     | test0 :: tests -> test0, tests in
9140
9141   let () =
9142     let (name, style, _, _, _, _, _) = test0 in
9143     generate_prototype ~extern:false ~semicolon:false ~newline:true
9144       ~handle:"g" ~prefix:"guestfs_" name style;
9145     pr "{\n";
9146     List.iter (
9147       function
9148       | Pathname n
9149       | Device n | Dev_or_Path n
9150       | String n
9151       | FileIn n
9152       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9153       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9154       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9155       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9156       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9157     ) (snd style);
9158     pr "  /* Java changes stdout line buffering so we need this: */\n";
9159     pr "  fflush (stdout);\n";
9160     pr "  return 0;\n";
9161     pr "}\n";
9162     pr "\n" in
9163
9164   List.iter (
9165     fun (name, style, _, _, _, _, _) ->
9166       if String.sub name (String.length name - 3) 3 <> "err" then (
9167         pr "/* Test normal return. */\n";
9168         generate_prototype ~extern:false ~semicolon:false ~newline:true
9169           ~handle:"g" ~prefix:"guestfs_" name style;
9170         pr "{\n";
9171         (match fst style with
9172          | RErr ->
9173              pr "  return 0;\n"
9174          | RInt _ ->
9175              pr "  int r;\n";
9176              pr "  sscanf (val, \"%%d\", &r);\n";
9177              pr "  return r;\n"
9178          | RInt64 _ ->
9179              pr "  int64_t r;\n";
9180              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9181              pr "  return r;\n"
9182          | RBool _ ->
9183              pr "  return strcmp (val, \"true\") == 0;\n"
9184          | RConstString _
9185          | RConstOptString _ ->
9186              (* Can't return the input string here.  Return a static
9187               * string so we ensure we get a segfault if the caller
9188               * tries to free it.
9189               *)
9190              pr "  return \"static string\";\n"
9191          | RString _ ->
9192              pr "  return strdup (val);\n"
9193          | RStringList _ ->
9194              pr "  char **strs;\n";
9195              pr "  int n, i;\n";
9196              pr "  sscanf (val, \"%%d\", &n);\n";
9197              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9198              pr "  for (i = 0; i < n; ++i) {\n";
9199              pr "    strs[i] = safe_malloc (g, 16);\n";
9200              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9201              pr "  }\n";
9202              pr "  strs[n] = NULL;\n";
9203              pr "  return strs;\n"
9204          | RStruct (_, typ) ->
9205              pr "  struct guestfs_%s *r;\n" typ;
9206              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9207              pr "  return r;\n"
9208          | RStructList (_, typ) ->
9209              pr "  struct guestfs_%s_list *r;\n" typ;
9210              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9211              pr "  sscanf (val, \"%%d\", &r->len);\n";
9212              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9213              pr "  return r;\n"
9214          | RHashtable _ ->
9215              pr "  char **strs;\n";
9216              pr "  int n, i;\n";
9217              pr "  sscanf (val, \"%%d\", &n);\n";
9218              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9219              pr "  for (i = 0; i < n; ++i) {\n";
9220              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9221              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9222              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9223              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9224              pr "  }\n";
9225              pr "  strs[n*2] = NULL;\n";
9226              pr "  return strs;\n"
9227          | RBufferOut _ ->
9228              pr "  return strdup (val);\n"
9229         );
9230         pr "}\n";
9231         pr "\n"
9232       ) else (
9233         pr "/* Test error return. */\n";
9234         generate_prototype ~extern:false ~semicolon:false ~newline:true
9235           ~handle:"g" ~prefix:"guestfs_" name style;
9236         pr "{\n";
9237         pr "  error (g, \"error\");\n";
9238         (match fst style with
9239          | RErr | RInt _ | RInt64 _ | RBool _ ->
9240              pr "  return -1;\n"
9241          | RConstString _ | RConstOptString _
9242          | RString _ | RStringList _ | RStruct _
9243          | RStructList _
9244          | RHashtable _
9245          | RBufferOut _ ->
9246              pr "  return NULL;\n"
9247         );
9248         pr "}\n";
9249         pr "\n"
9250       )
9251   ) tests
9252
9253 and generate_ocaml_bindtests () =
9254   generate_header OCamlStyle GPLv2;
9255
9256   pr "\
9257 let () =
9258   let g = Guestfs.create () in
9259 ";
9260
9261   let mkargs args =
9262     String.concat " " (
9263       List.map (
9264         function
9265         | CallString s -> "\"" ^ s ^ "\""
9266         | CallOptString None -> "None"
9267         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9268         | CallStringList xs ->
9269             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9270         | CallInt i when i >= 0 -> string_of_int i
9271         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9272         | CallBool b -> string_of_bool b
9273       ) args
9274     )
9275   in
9276
9277   generate_lang_bindtests (
9278     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9279   );
9280
9281   pr "print_endline \"EOF\"\n"
9282
9283 and generate_perl_bindtests () =
9284   pr "#!/usr/bin/perl -w\n";
9285   generate_header HashStyle GPLv2;
9286
9287   pr "\
9288 use strict;
9289
9290 use Sys::Guestfs;
9291
9292 my $g = Sys::Guestfs->new ();
9293 ";
9294
9295   let mkargs args =
9296     String.concat ", " (
9297       List.map (
9298         function
9299         | CallString s -> "\"" ^ s ^ "\""
9300         | CallOptString None -> "undef"
9301         | CallOptString (Some s) -> sprintf "\"%s\"" s
9302         | CallStringList xs ->
9303             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9304         | CallInt i -> string_of_int i
9305         | CallBool b -> if b then "1" else "0"
9306       ) args
9307     )
9308   in
9309
9310   generate_lang_bindtests (
9311     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9312   );
9313
9314   pr "print \"EOF\\n\"\n"
9315
9316 and generate_python_bindtests () =
9317   generate_header HashStyle GPLv2;
9318
9319   pr "\
9320 import guestfs
9321
9322 g = guestfs.GuestFS ()
9323 ";
9324
9325   let mkargs args =
9326     String.concat ", " (
9327       List.map (
9328         function
9329         | CallString s -> "\"" ^ s ^ "\""
9330         | CallOptString None -> "None"
9331         | CallOptString (Some s) -> sprintf "\"%s\"" s
9332         | CallStringList xs ->
9333             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9334         | CallInt i -> string_of_int i
9335         | CallBool b -> if b then "1" else "0"
9336       ) args
9337     )
9338   in
9339
9340   generate_lang_bindtests (
9341     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9342   );
9343
9344   pr "print \"EOF\"\n"
9345
9346 and generate_ruby_bindtests () =
9347   generate_header HashStyle GPLv2;
9348
9349   pr "\
9350 require 'guestfs'
9351
9352 g = Guestfs::create()
9353 ";
9354
9355   let mkargs args =
9356     String.concat ", " (
9357       List.map (
9358         function
9359         | CallString s -> "\"" ^ s ^ "\""
9360         | CallOptString None -> "nil"
9361         | CallOptString (Some s) -> sprintf "\"%s\"" s
9362         | CallStringList xs ->
9363             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9364         | CallInt i -> string_of_int i
9365         | CallBool b -> string_of_bool b
9366       ) args
9367     )
9368   in
9369
9370   generate_lang_bindtests (
9371     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9372   );
9373
9374   pr "print \"EOF\\n\"\n"
9375
9376 and generate_java_bindtests () =
9377   generate_header CStyle GPLv2;
9378
9379   pr "\
9380 import com.redhat.et.libguestfs.*;
9381
9382 public class Bindtests {
9383     public static void main (String[] argv)
9384     {
9385         try {
9386             GuestFS g = new GuestFS ();
9387 ";
9388
9389   let mkargs args =
9390     String.concat ", " (
9391       List.map (
9392         function
9393         | CallString s -> "\"" ^ s ^ "\""
9394         | CallOptString None -> "null"
9395         | CallOptString (Some s) -> sprintf "\"%s\"" s
9396         | CallStringList xs ->
9397             "new String[]{" ^
9398               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9399         | CallInt i -> string_of_int i
9400         | CallBool b -> string_of_bool b
9401       ) args
9402     )
9403   in
9404
9405   generate_lang_bindtests (
9406     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
9407   );
9408
9409   pr "
9410             System.out.println (\"EOF\");
9411         }
9412         catch (Exception exn) {
9413             System.err.println (exn);
9414             System.exit (1);
9415         }
9416     }
9417 }
9418 "
9419
9420 and generate_haskell_bindtests () =
9421   generate_header HaskellStyle GPLv2;
9422
9423   pr "\
9424 module Bindtests where
9425 import qualified Guestfs
9426
9427 main = do
9428   g <- Guestfs.create
9429 ";
9430
9431   let mkargs args =
9432     String.concat " " (
9433       List.map (
9434         function
9435         | CallString s -> "\"" ^ s ^ "\""
9436         | CallOptString None -> "Nothing"
9437         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9438         | CallStringList xs ->
9439             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9440         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9441         | CallInt i -> string_of_int i
9442         | CallBool true -> "True"
9443         | CallBool false -> "False"
9444       ) args
9445     )
9446   in
9447
9448   generate_lang_bindtests (
9449     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
9450   );
9451
9452   pr "  putStrLn \"EOF\"\n"
9453
9454 (* Language-independent bindings tests - we do it this way to
9455  * ensure there is parity in testing bindings across all languages.
9456  *)
9457 and generate_lang_bindtests call =
9458   call "test0" [CallString "abc"; CallOptString (Some "def");
9459                 CallStringList []; CallBool false;
9460                 CallInt 0; CallString "123"; CallString "456"];
9461   call "test0" [CallString "abc"; CallOptString None;
9462                 CallStringList []; CallBool false;
9463                 CallInt 0; CallString "123"; CallString "456"];
9464   call "test0" [CallString ""; CallOptString (Some "def");
9465                 CallStringList []; CallBool false;
9466                 CallInt 0; CallString "123"; CallString "456"];
9467   call "test0" [CallString ""; CallOptString (Some "");
9468                 CallStringList []; CallBool false;
9469                 CallInt 0; CallString "123"; CallString "456"];
9470   call "test0" [CallString "abc"; CallOptString (Some "def");
9471                 CallStringList ["1"]; CallBool false;
9472                 CallInt 0; CallString "123"; CallString "456"];
9473   call "test0" [CallString "abc"; CallOptString (Some "def");
9474                 CallStringList ["1"; "2"]; CallBool false;
9475                 CallInt 0; CallString "123"; CallString "456"];
9476   call "test0" [CallString "abc"; CallOptString (Some "def");
9477                 CallStringList ["1"]; CallBool true;
9478                 CallInt 0; CallString "123"; CallString "456"];
9479   call "test0" [CallString "abc"; CallOptString (Some "def");
9480                 CallStringList ["1"]; CallBool false;
9481                 CallInt (-1); CallString "123"; CallString "456"];
9482   call "test0" [CallString "abc"; CallOptString (Some "def");
9483                 CallStringList ["1"]; CallBool false;
9484                 CallInt (-2); CallString "123"; CallString "456"];
9485   call "test0" [CallString "abc"; CallOptString (Some "def");
9486                 CallStringList ["1"]; CallBool false;
9487                 CallInt 1; CallString "123"; CallString "456"];
9488   call "test0" [CallString "abc"; CallOptString (Some "def");
9489                 CallStringList ["1"]; CallBool false;
9490                 CallInt 2; CallString "123"; CallString "456"];
9491   call "test0" [CallString "abc"; CallOptString (Some "def");
9492                 CallStringList ["1"]; CallBool false;
9493                 CallInt 4095; CallString "123"; CallString "456"];
9494   call "test0" [CallString "abc"; CallOptString (Some "def");
9495                 CallStringList ["1"]; CallBool false;
9496                 CallInt 0; CallString ""; CallString ""]
9497
9498 (* XXX Add here tests of the return and error functions. *)
9499
9500 (* This is used to generate the src/MAX_PROC_NR file which
9501  * contains the maximum procedure number, a surrogate for the
9502  * ABI version number.  See src/Makefile.am for the details.
9503  *)
9504 and generate_max_proc_nr () =
9505   let proc_nrs = List.map (
9506     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9507   ) daemon_functions in
9508
9509   let max_proc_nr = List.fold_left max 0 proc_nrs in
9510
9511   pr "%d\n" max_proc_nr
9512
9513 let output_to filename =
9514   let filename_new = filename ^ ".new" in
9515   chan := open_out filename_new;
9516   let close () =
9517     close_out !chan;
9518     chan := stdout;
9519
9520     (* Is the new file different from the current file? *)
9521     if Sys.file_exists filename && files_equal filename filename_new then
9522       Unix.unlink filename_new          (* same, so skip it *)
9523     else (
9524       (* different, overwrite old one *)
9525       (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9526       Unix.rename filename_new filename;
9527       Unix.chmod filename 0o444;
9528       printf "written %s\n%!" filename;
9529     )
9530   in
9531   close
9532
9533 (* Main program. *)
9534 let () =
9535   check_functions ();
9536
9537   if not (Sys.file_exists "HACKING") then (
9538     eprintf "\
9539 You are probably running this from the wrong directory.
9540 Run it from the top source directory using the command
9541   src/generator.ml
9542 ";
9543     exit 1
9544   );
9545
9546   let close = output_to "src/guestfs_protocol.x" in
9547   generate_xdr ();
9548   close ();
9549
9550   let close = output_to "src/guestfs-structs.h" in
9551   generate_structs_h ();
9552   close ();
9553
9554   let close = output_to "src/guestfs-actions.h" in
9555   generate_actions_h ();
9556   close ();
9557
9558   let close = output_to "src/guestfs-actions.c" in
9559   generate_client_actions ();
9560   close ();
9561
9562   let close = output_to "daemon/actions.h" in
9563   generate_daemon_actions_h ();
9564   close ();
9565
9566   let close = output_to "daemon/stubs.c" in
9567   generate_daemon_actions ();
9568   close ();
9569
9570   let close = output_to "daemon/names.c" in
9571   generate_daemon_names ();
9572   close ();
9573
9574   let close = output_to "capitests/tests.c" in
9575   generate_tests ();
9576   close ();
9577
9578   let close = output_to "src/guestfs-bindtests.c" in
9579   generate_bindtests ();
9580   close ();
9581
9582   let close = output_to "fish/cmds.c" in
9583   generate_fish_cmds ();
9584   close ();
9585
9586   let close = output_to "fish/completion.c" in
9587   generate_fish_completion ();
9588   close ();
9589
9590   let close = output_to "guestfs-structs.pod" in
9591   generate_structs_pod ();
9592   close ();
9593
9594   let close = output_to "guestfs-actions.pod" in
9595   generate_actions_pod ();
9596   close ();
9597
9598   let close = output_to "guestfish-actions.pod" in
9599   generate_fish_actions_pod ();
9600   close ();
9601
9602   let close = output_to "ocaml/guestfs.mli" in
9603   generate_ocaml_mli ();
9604   close ();
9605
9606   let close = output_to "ocaml/guestfs.ml" in
9607   generate_ocaml_ml ();
9608   close ();
9609
9610   let close = output_to "ocaml/guestfs_c_actions.c" in
9611   generate_ocaml_c ();
9612   close ();
9613
9614   let close = output_to "ocaml/bindtests.ml" in
9615   generate_ocaml_bindtests ();
9616   close ();
9617
9618   let close = output_to "perl/Guestfs.xs" in
9619   generate_perl_xs ();
9620   close ();
9621
9622   let close = output_to "perl/lib/Sys/Guestfs.pm" in
9623   generate_perl_pm ();
9624   close ();
9625
9626   let close = output_to "perl/bindtests.pl" in
9627   generate_perl_bindtests ();
9628   close ();
9629
9630   let close = output_to "python/guestfs-py.c" in
9631   generate_python_c ();
9632   close ();
9633
9634   let close = output_to "python/guestfs.py" in
9635   generate_python_py ();
9636   close ();
9637
9638   let close = output_to "python/bindtests.py" in
9639   generate_python_bindtests ();
9640   close ();
9641
9642   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9643   generate_ruby_c ();
9644   close ();
9645
9646   let close = output_to "ruby/bindtests.rb" in
9647   generate_ruby_bindtests ();
9648   close ();
9649
9650   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9651   generate_java_java ();
9652   close ();
9653
9654   List.iter (
9655     fun (typ, jtyp) ->
9656       let cols = cols_of_struct typ in
9657       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9658       let close = output_to filename in
9659       generate_java_struct jtyp cols;
9660       close ();
9661   ) java_structs;
9662
9663   let close = output_to "java/Makefile.inc" in
9664   generate_java_makefile_inc ();
9665   close ();
9666
9667   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9668   generate_java_c ();
9669   close ();
9670
9671   let close = output_to "java/Bindtests.java" in
9672   generate_java_bindtests ();
9673   close ();
9674
9675   let close = output_to "haskell/Guestfs.hs" in
9676   generate_haskell_hs ();
9677   close ();
9678
9679   let close = output_to "haskell/Bindtests.hs" in
9680   generate_haskell_bindtests ();
9681   close ();
9682
9683   let close = output_to "src/MAX_PROC_NR" in
9684   generate_max_proc_nr ();
9685   close ();
9686
9687   (* Always generate this file last, and unconditionally.  It's used
9688    * by the Makefile to know when we must re-run the generator.
9689    *)
9690   let chan = open_out "src/stamp-generator" in
9691   fprintf chan "1\n";
9692   close_out chan