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