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