71aeeed84f7c8fb4e29b4a8412e5ce08dd4f00ef
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table below), and
25  * daemon/<somefile>.c to write the implementation.
26  *
27  * After editing this file, run it (./src/generator.ml) to regenerate all the
28  * output files.  Note that if you are using a separate build directory you
29  * must run generator.ml from the _source_ directory.
30  *
31  * IMPORTANT: This script should NOT print any warnings.  If it prints
32  * warnings, you should treat them as errors.
33  *)
34
35 #load "unix.cma";;
36 #load "str.cma";;
37
38 open Printf
39
40 type style = ret * args
41 and ret =
42     (* "RErr" as a return value means an int used as a simple error
43      * indication, ie. 0 or -1.
44      *)
45   | RErr
46
47     (* "RInt" as a return value means an int which is -1 for error
48      * or any value >= 0 on success.  Only use this for smallish
49      * positive ints (0 <= i < 2^30).
50      *)
51   | RInt of string
52
53     (* "RInt64" is the same as RInt, but is guaranteed to be able
54      * to return a full 64 bit value, _except_ that -1 means error
55      * (so -1 cannot be a valid, non-error return value).
56      *)
57   | RInt64 of string
58
59     (* "RBool" is a bool return value which can be true/false or
60      * -1 for error.
61      *)
62   | RBool of string
63
64     (* "RConstString" is a string that refers to a constant value.
65      * The return value must NOT be NULL (since NULL indicates
66      * an error).
67      *
68      * Try to avoid using this.  In particular you cannot use this
69      * for values returned from the daemon, because there is no
70      * thread-safe way to return them in the C API.
71      *)
72   | RConstString of string
73
74     (* "RConstOptString" is an even more broken version of
75      * "RConstString".  The returned string may be NULL and there
76      * is no way to return an error indication.  Avoid using this!
77      *)
78   | RConstOptString of string
79
80     (* "RString" is a returned string.  It must NOT be NULL, since
81      * a NULL return indicates an error.  The caller frees this.
82      *)
83   | RString of string
84
85     (* "RStringList" is a list of strings.  No string in the list
86      * can be NULL.  The caller frees the strings and the array.
87      *)
88   | RStringList of string
89
90     (* "RStruct" is a function which returns a single named structure
91      * or an error indication (in C, a struct, and in other languages
92      * with varying representations, but usually very efficient).  See
93      * after the function list below for the structures.
94      *)
95   | RStruct of string * string          (* name of retval, name of struct *)
96
97     (* "RStructList" is a function which returns either a list/array
98      * of structures (could be zero-length), or an error indication.
99      *)
100   | RStructList of string * string      (* name of retval, name of struct *)
101
102     (* Key-value pairs of untyped strings.  Turns into a hashtable or
103      * dictionary in languages which support it.  DON'T use this as a
104      * general "bucket" for results.  Prefer a stronger typed return
105      * value if one is available, or write a custom struct.  Don't use
106      * this if the list could potentially be very long, since it is
107      * inefficient.  Keys should be unique.  NULLs are not permitted.
108      *)
109   | RHashtable of string
110
111     (* "RBufferOut" is handled almost exactly like RString, but
112      * it allows the string to contain arbitrary 8 bit data including
113      * ASCII NUL.  In the C API this causes an implicit extra parameter
114      * to be added of type <size_t *size_r>.  The extra parameter
115      * returns the actual size of the return buffer in bytes.
116      *
117      * Other programming languages support strings with arbitrary 8 bit
118      * data.
119      *
120      * At the RPC layer we have to use the opaque<> type instead of
121      * string<>.  Returned data is still limited to the max message
122      * size (ie. ~ 2 MB).
123      *)
124   | RBufferOut of string
125
126 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
127
128     (* Note in future we should allow a "variable args" parameter as
129      * the final parameter, to allow commands like
130      *   chmod mode file [file(s)...]
131      * This is not implemented yet, but many commands (such as chmod)
132      * are currently defined with the argument order keeping this future
133      * possibility in mind.
134      *)
135 and argt =
136   | String of string    (* const char *name, cannot be NULL *)
137   | Device of string    (* /dev device name, cannot be NULL *)
138   | Pathname of string  (* file name, cannot be NULL *)
139   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
140   | OptString of string (* const char *name, may be NULL *)
141   | StringList of string(* list of strings (each string cannot be NULL) *)
142   | DeviceList of string(* list of Device names (each cannot be NULL) *)
143   | Bool of string      (* boolean *)
144   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
145     (* These are treated as filenames (simple string parameters) in
146      * the C API and bindings.  But in the RPC protocol, we transfer
147      * the actual file content up to or down from the daemon.
148      * FileIn: local machine -> daemon (in request)
149      * FileOut: daemon -> local machine (in reply)
150      * In guestfish (only), the special name "-" means read from
151      * stdin or write to stdout.
152      *)
153   | FileIn of string
154   | FileOut of string
155 (* Not implemented:
156     (* Opaque buffer which can contain arbitrary 8 bit data.
157      * In the C API, this is expressed as <char *, int> pair.
158      * Most other languages have a string type which can contain
159      * ASCII NUL.  We use whatever type is appropriate for each
160      * language.
161      * Buffers are limited by the total message size.  To transfer
162      * large blocks of data, use FileIn/FileOut parameters instead.
163      * To return an arbitrary buffer, use RBufferOut.
164      *)
165   | BufferIn of string
166 *)
167
168 type flags =
169   | ProtocolLimitWarning  (* display warning about protocol size limits *)
170   | DangerWillRobinson    (* flags particularly dangerous commands *)
171   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
172   | FishAction of string  (* call this function in guestfish *)
173   | NotInFish             (* do not export via guestfish *)
174   | NotInDocs             (* do not add this function to documentation *)
175   | DeprecatedBy of string (* function is deprecated, use .. instead *)
176
177 (* You can supply zero or as many tests as you want per API call.
178  *
179  * Note that the test environment has 3 block devices, of size 500MB,
180  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
181  * a fourth ISO block device with some known files on it (/dev/sdd).
182  *
183  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
184  * Number of cylinders was 63 for IDE emulated disks with precisely
185  * the same size.  How exactly this is calculated is a mystery.
186  *
187  * The ISO block device (/dev/sdd) comes from images/test.iso.
188  *
189  * To be able to run the tests in a reasonable amount of time,
190  * the virtual machine and block devices are reused between tests.
191  * So don't try testing kill_subprocess :-x
192  *
193  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
194  *
195  * Don't assume anything about the previous contents of the block
196  * devices.  Use 'Init*' to create some initial scenarios.
197  *
198  * You can add a prerequisite clause to any individual test.  This
199  * is a run-time check, which, if it fails, causes the test to be
200  * skipped.  Useful if testing a command which might not work on
201  * all variations of libguestfs builds.  A test that has prerequisite
202  * of 'Always' is run unconditionally.
203  *
204  * In addition, packagers can skip individual tests by setting the
205  * environment variables:     eg:
206  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
207  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
208  *)
209 type tests = (test_init * test_prereq * test) list
210 and test =
211     (* Run the command sequence and just expect nothing to fail. *)
212   | TestRun of seq
213
214     (* Run the command sequence and expect the output of the final
215      * command to be the string.
216      *)
217   | TestOutput of seq * string
218
219     (* Run the command sequence and expect the output of the final
220      * command to be the list of strings.
221      *)
222   | TestOutputList of seq * string list
223
224     (* Run the command sequence and expect the output of the final
225      * command to be the list of block devices (could be either
226      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
227      * character of each string).
228      *)
229   | TestOutputListOfDevices of seq * string list
230
231     (* Run the command sequence and expect the output of the final
232      * command to be the integer.
233      *)
234   | TestOutputInt of seq * int
235
236     (* Run the command sequence and expect the output of the final
237      * command to be <op> <int>, eg. ">=", "1".
238      *)
239   | TestOutputIntOp of seq * string * int
240
241     (* Run the command sequence and expect the output of the final
242      * command to be a true value (!= 0 or != NULL).
243      *)
244   | TestOutputTrue of seq
245
246     (* Run the command sequence and expect the output of the final
247      * command to be a false value (== 0 or == NULL, but not an error).
248      *)
249   | TestOutputFalse of seq
250
251     (* Run the command sequence and expect the output of the final
252      * command to be a list of the given length (but don't care about
253      * content).
254      *)
255   | TestOutputLength of seq * int
256
257     (* Run the command sequence and expect the output of the final
258      * command to be a buffer (RBufferOut), ie. string + size.
259      *)
260   | TestOutputBuffer of seq * string
261
262     (* Run the command sequence and expect the output of the final
263      * command to be a structure.
264      *)
265   | TestOutputStruct of seq * test_field_compare list
266
267     (* Run the command sequence and expect the final command (only)
268      * to fail.
269      *)
270   | TestLastFail of seq
271
272 and test_field_compare =
273   | CompareWithInt of string * int
274   | CompareWithIntOp of string * string * int
275   | CompareWithString of string * string
276   | CompareFieldsIntEq of string * string
277   | CompareFieldsStrEq of string * string
278
279 (* Test prerequisites. *)
280 and test_prereq =
281     (* Test always runs. *)
282   | Always
283
284     (* Test is currently disabled - eg. it fails, or it tests some
285      * unimplemented feature.
286      *)
287   | Disabled
288
289     (* 'string' is some C code (a function body) that should return
290      * true or false.  The test will run if the code returns true.
291      *)
292   | If of string
293
294     (* As for 'If' but the test runs _unless_ the code returns true. *)
295   | Unless of string
296
297 (* Some initial scenarios for testing. *)
298 and test_init =
299     (* Do nothing, block devices could contain random stuff including
300      * LVM PVs, and some filesystems might be mounted.  This is usually
301      * a bad idea.
302      *)
303   | InitNone
304
305     (* Block devices are empty and no filesystems are mounted. *)
306   | InitEmpty
307
308     (* /dev/sda contains a single partition /dev/sda1, with random
309      * content.  /dev/sdb and /dev/sdc may have random content.
310      * No LVM.
311      *)
312   | InitPartition
313
314     (* /dev/sda contains a single partition /dev/sda1, which is formatted
315      * as ext2, empty [except for lost+found] and mounted on /.
316      * /dev/sdb and /dev/sdc may have random content.
317      * No LVM.
318      *)
319   | InitBasicFS
320
321     (* /dev/sda:
322      *   /dev/sda1 (is a PV):
323      *     /dev/VG/LV (size 8MB):
324      *       formatted as ext2, empty [except for lost+found], mounted on /
325      * /dev/sdb and /dev/sdc may have random content.
326      *)
327   | InitBasicFSonLVM
328
329     (* /dev/sdd (the ISO, see images/ directory in source)
330      * is mounted on /
331      *)
332   | InitISOFS
333
334 (* Sequence of commands for testing. *)
335 and seq = cmd list
336 and cmd = string list
337
338 (* Note about long descriptions: When referring to another
339  * action, use the format C<guestfs_other> (ie. the full name of
340  * the C function).  This will be replaced as appropriate in other
341  * language bindings.
342  *
343  * Apart from that, long descriptions are just perldoc paragraphs.
344  *)
345
346 (* Generate a random UUID (used in tests). *)
347 let uuidgen () =
348   let chan = Unix.open_process_in "uuidgen" in
349   let uuid = input_line chan in
350   (match Unix.close_process_in chan with
351    | Unix.WEXITED 0 -> ()
352    | Unix.WEXITED _ ->
353        failwith "uuidgen: process exited with non-zero status"
354    | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
355        failwith "uuidgen: process signalled or stopped by signal"
356   );
357   uuid
358
359 (* These test functions are used in the language binding tests. *)
360
361 let test_all_args = [
362   String "str";
363   OptString "optstr";
364   StringList "strlist";
365   Bool "b";
366   Int "integer";
367   FileIn "filein";
368   FileOut "fileout";
369 ]
370
371 let test_all_rets = [
372   (* except for RErr, which is tested thoroughly elsewhere *)
373   "test0rint",         RInt "valout";
374   "test0rint64",       RInt64 "valout";
375   "test0rbool",        RBool "valout";
376   "test0rconststring", RConstString "valout";
377   "test0rconstoptstring", RConstOptString "valout";
378   "test0rstring",      RString "valout";
379   "test0rstringlist",  RStringList "valout";
380   "test0rstruct",      RStruct ("valout", "lvm_pv");
381   "test0rstructlist",  RStructList ("valout", "lvm_pv");
382   "test0rhashtable",   RHashtable "valout";
383 ]
384
385 let test_functions = [
386   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
387    [],
388    "internal test function - do not use",
389    "\
390 This is an internal test function which is used to test whether
391 the automatically generated bindings can handle every possible
392 parameter type correctly.
393
394 It echos the contents of each parameter to stdout.
395
396 You probably don't want to call this function.");
397 ] @ List.flatten (
398   List.map (
399     fun (name, ret) ->
400       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
401         [],
402         "internal test function - do not use",
403         "\
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 return type correctly.
407
408 It converts string C<val> to the return type.
409
410 You probably don't want to call this function.");
411        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
412         [],
413         "internal test function - do not use",
414         "\
415 This is an internal test function which is used to test whether
416 the automatically generated bindings can handle every possible
417 return type correctly.
418
419 This function always returns an error.
420
421 You probably don't want to call this function.")]
422   ) test_all_rets
423 )
424
425 (* non_daemon_functions are any functions which don't get processed
426  * in the daemon, eg. functions for setting and getting local
427  * configuration values.
428  *)
429
430 let non_daemon_functions = test_functions @ [
431   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
432    [],
433    "launch the qemu subprocess",
434    "\
435 Internally libguestfs is implemented by running a virtual machine
436 using L<qemu(1)>.
437
438 You should call this after configuring the handle
439 (eg. adding drives) but before performing any actions.");
440
441   ("wait_ready", (RErr, []), -1, [NotInFish],
442    [],
443    "wait until the qemu subprocess launches",
444    "\
445 Internally libguestfs is implemented by running a virtual machine
446 using L<qemu(1)>.
447
448 You should call this after C<guestfs_launch> to wait for the launch
449 to complete.");
450
451   ("kill_subprocess", (RErr, []), -1, [],
452    [],
453    "kill the qemu subprocess",
454    "\
455 This kills the qemu subprocess.  You should never need to call this.");
456
457   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
458    [],
459    "add an image to examine or modify",
460    "\
461 This function adds a virtual machine disk image C<filename> to the
462 guest.  The first time you call this function, the disk appears as IDE
463 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
464 so on.
465
466 You don't necessarily need to be root when using libguestfs.  However
467 you obviously do need sufficient permissions to access the filename
468 for whatever operations you want to perform (ie. read access if you
469 just want to read the image or write access if you want to modify the
470 image).
471
472 This is equivalent to the qemu parameter
473 C<-drive file=filename,cache=off,if=...>.
474 C<cache=off> is omitted in cases where it is not supported by
475 the underlying filesystem.
476
477 Note that this call checks for the existence of C<filename>.  This
478 stops you from specifying other types of drive which are supported
479 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
480 the general C<guestfs_config> call instead.");
481
482   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
483    [],
484    "add a CD-ROM disk image to examine",
485    "\
486 This function adds a virtual CD-ROM disk image to the guest.
487
488 This is equivalent to the qemu parameter C<-cdrom filename>.
489
490 Note that this call checks for the existence of C<filename>.  This
491 stops you from specifying other types of drive which are supported
492 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
493 the general C<guestfs_config> call instead.");
494
495   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
496    [],
497    "add a drive in snapshot mode (read-only)",
498    "\
499 This adds a drive in snapshot mode, making it effectively
500 read-only.
501
502 Note that writes to the device are allowed, and will be seen for
503 the duration of the guestfs handle, but they are written
504 to a temporary file which is discarded as soon as the guestfs
505 handle is closed.  We don't currently have any method to enable
506 changes to be committed, although qemu can support this.
507
508 This is equivalent to the qemu parameter
509 C<-drive file=filename,snapshot=on,if=...>.
510
511 Note that this call checks for the existence of C<filename>.  This
512 stops you from specifying other types of drive which are supported
513 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
514 the general C<guestfs_config> call instead.");
515
516   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
517    [],
518    "add qemu parameters",
519    "\
520 This can be used to add arbitrary qemu command line parameters
521 of the form C<-param value>.  Actually it's not quite arbitrary - we
522 prevent you from setting some parameters which would interfere with
523 parameters that we use.
524
525 The first character of C<param> string must be a C<-> (dash).
526
527 C<value> can be NULL.");
528
529   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
530    [],
531    "set the qemu binary",
532    "\
533 Set the qemu binary that we will use.
534
535 The default is chosen when the library was compiled by the
536 configure script.
537
538 You can also override this by setting the C<LIBGUESTFS_QEMU>
539 environment variable.
540
541 Setting C<qemu> to C<NULL> restores the default qemu binary.");
542
543   ("get_qemu", (RConstString "qemu", []), -1, [],
544    [InitNone, Always, TestRun (
545       [["get_qemu"]])],
546    "get the qemu binary",
547    "\
548 Return the current qemu binary.
549
550 This is always non-NULL.  If it wasn't set already, then this will
551 return the default qemu binary name.");
552
553   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
554    [],
555    "set the search path",
556    "\
557 Set the path that libguestfs searches for kernel and initrd.img.
558
559 The default is C<$libdir/guestfs> unless overridden by setting
560 C<LIBGUESTFS_PATH> environment variable.
561
562 Setting C<path> to C<NULL> restores the default path.");
563
564   ("get_path", (RConstString "path", []), -1, [],
565    [InitNone, Always, TestRun (
566       [["get_path"]])],
567    "get the search path",
568    "\
569 Return the current search path.
570
571 This is always non-NULL.  If it wasn't set already, then this will
572 return the default path.");
573
574   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
575    [],
576    "add options to kernel command line",
577    "\
578 This function is used to add additional options to the
579 guest kernel command line.
580
581 The default is C<NULL> unless overridden by setting
582 C<LIBGUESTFS_APPEND> environment variable.
583
584 Setting C<append> to C<NULL> means I<no> additional options
585 are passed (libguestfs always adds a few of its own).");
586
587   ("get_append", (RConstOptString "append", []), -1, [],
588    (* This cannot be tested with the current framework.  The
589     * function can return NULL in normal operations, which the
590     * test framework interprets as an error.
591     *)
592    [],
593    "get the additional kernel options",
594    "\
595 Return the additional kernel options which are added to the
596 guest kernel command line.
597
598 If C<NULL> then no options are added.");
599
600   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
601    [],
602    "set autosync mode",
603    "\
604 If C<autosync> is true, this enables autosync.  Libguestfs will make a
605 best effort attempt to run C<guestfs_umount_all> followed by
606 C<guestfs_sync> when the handle is closed
607 (also if the program exits without closing handles).
608
609 This is disabled by default (except in guestfish where it is
610 enabled by default).");
611
612   ("get_autosync", (RBool "autosync", []), -1, [],
613    [InitNone, Always, TestRun (
614       [["get_autosync"]])],
615    "get autosync mode",
616    "\
617 Get the autosync flag.");
618
619   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
620    [],
621    "set verbose mode",
622    "\
623 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
624
625 Verbose messages are disabled unless the environment variable
626 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
627
628   ("get_verbose", (RBool "verbose", []), -1, [],
629    [],
630    "get verbose mode",
631    "\
632 This returns the verbose messages flag.");
633
634   ("is_ready", (RBool "ready", []), -1, [],
635    [InitNone, Always, TestOutputTrue (
636       [["is_ready"]])],
637    "is ready to accept commands",
638    "\
639 This returns true iff this handle is ready to accept commands
640 (in the C<READY> state).
641
642 For more information on states, see L<guestfs(3)>.");
643
644   ("is_config", (RBool "config", []), -1, [],
645    [InitNone, Always, TestOutputFalse (
646       [["is_config"]])],
647    "is in configuration state",
648    "\
649 This returns true iff this handle is being configured
650 (in the C<CONFIG> state).
651
652 For more information on states, see L<guestfs(3)>.");
653
654   ("is_launching", (RBool "launching", []), -1, [],
655    [InitNone, Always, TestOutputFalse (
656       [["is_launching"]])],
657    "is launching subprocess",
658    "\
659 This returns true iff this handle is launching the subprocess
660 (in the C<LAUNCHING> state).
661
662 For more information on states, see L<guestfs(3)>.");
663
664   ("is_busy", (RBool "busy", []), -1, [],
665    [InitNone, Always, TestOutputFalse (
666       [["is_busy"]])],
667    "is busy processing a command",
668    "\
669 This returns true iff this handle is busy processing a command
670 (in the C<BUSY> state).
671
672 For more information on states, see L<guestfs(3)>.");
673
674   ("get_state", (RInt "state", []), -1, [],
675    [],
676    "get the current state",
677    "\
678 This returns the current state as an opaque integer.  This is
679 only useful for printing debug and internal error messages.
680
681 For more information on states, see L<guestfs(3)>.");
682
683   ("set_busy", (RErr, []), -1, [NotInFish],
684    [],
685    "set state to busy",
686    "\
687 This sets the state to C<BUSY>.  This is only used when implementing
688 actions using the low-level API.
689
690 For more information on states, see L<guestfs(3)>.");
691
692   ("set_ready", (RErr, []), -1, [NotInFish],
693    [],
694    "set state to ready",
695    "\
696 This sets the state to C<READY>.  This is only used when implementing
697 actions using the low-level API.
698
699 For more information on states, see L<guestfs(3)>.");
700
701   ("end_busy", (RErr, []), -1, [NotInFish],
702    [],
703    "leave the busy state",
704    "\
705 This sets the state to C<READY>, or if in C<CONFIG> then it leaves the
706 state as is.  This is only used when implementing
707 actions using the low-level API.
708
709 For more information on states, see L<guestfs(3)>.");
710
711   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
712    [InitNone, Always, TestOutputInt (
713       [["set_memsize"; "500"];
714        ["get_memsize"]], 500)],
715    "set memory allocated to the qemu subprocess",
716    "\
717 This sets the memory size in megabytes allocated to the
718 qemu subprocess.  This only has any effect if called before
719 C<guestfs_launch>.
720
721 You can also change this by setting the environment
722 variable C<LIBGUESTFS_MEMSIZE> before the handle is
723 created.
724
725 For more information on the architecture of libguestfs,
726 see L<guestfs(3)>.");
727
728   ("get_memsize", (RInt "memsize", []), -1, [],
729    [InitNone, Always, TestOutputIntOp (
730       [["get_memsize"]], ">=", 256)],
731    "get memory allocated to the qemu subprocess",
732    "\
733 This gets the memory size in megabytes allocated to the
734 qemu subprocess.
735
736 If C<guestfs_set_memsize> was not called
737 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
738 then this returns the compiled-in default value for memsize.
739
740 For more information on the architecture of libguestfs,
741 see L<guestfs(3)>.");
742
743   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
744    [InitNone, Always, TestOutputIntOp (
745       [["get_pid"]], ">=", 1)],
746    "get PID of qemu subprocess",
747    "\
748 Return the process ID of the qemu subprocess.  If there is no
749 qemu subprocess, then this will return an error.
750
751 This is an internal call used for debugging and testing.");
752
753   ("version", (RStruct ("version", "version"), []), -1, [],
754    [InitNone, Always, TestOutputStruct (
755       [["version"]], [CompareWithInt ("major", 1)])],
756    "get the library version number",
757    "\
758 Return the libguestfs version number that the program is linked
759 against.
760
761 Note that because of dynamic linking this is not necessarily
762 the version of libguestfs that you compiled against.  You can
763 compile the program, and then at runtime dynamically link
764 against a completely different C<libguestfs.so> library.
765
766 This call was added in version C<1.0.58>.  In previous
767 versions of libguestfs there was no way to get the version
768 number.  From C code you can use ELF weak linking tricks to find out if
769 this symbol exists (if it doesn't, then it's an earlier version).
770
771 The call returns a structure with four elements.  The first
772 three (C<major>, C<minor> and C<release>) are numbers and
773 correspond to the usual version triplet.  The fourth element
774 (C<extra>) is a string and is normally empty, but may be
775 used for distro-specific information.
776
777 To construct the original version string:
778 C<$major.$minor.$release$extra>
779
780 I<Note:> Don't use this call to test for availability
781 of features.  Distro backports makes this unreliable.");
782
783   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
784    [InitNone, Always, TestOutputTrue (
785       [["set_selinux"; "true"];
786        ["get_selinux"]])],
787    "set SELinux enabled or disabled at appliance boot",
788    "\
789 This sets the selinux flag that is passed to the appliance
790 at boot time.  The default is C<selinux=0> (disabled).
791
792 Note that if SELinux is enabled, it is always in
793 Permissive mode (C<enforcing=0>).
794
795 For more information on the architecture of libguestfs,
796 see L<guestfs(3)>.");
797
798   ("get_selinux", (RBool "selinux", []), -1, [],
799    [],
800    "get SELinux enabled flag",
801    "\
802 This returns the current setting of the selinux flag which
803 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
804
805 For more information on the architecture of libguestfs,
806 see L<guestfs(3)>.");
807
808   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
809    [InitNone, Always, TestOutputTrue (
810       [["set_trace"; "true"];
811        ["get_trace"]])],
812    "enable or disable command traces",
813    "\
814 If the command trace flag is set to 1, then commands are
815 printed on stdout before they are executed in a format
816 which is very similar to the one used by guestfish.  In
817 other words, you can run a program with this enabled, and
818 you will get out a script which you can feed to guestfish
819 to perform the same set of actions.
820
821 If you want to trace C API calls into libguestfs (and
822 other libraries) then possibly a better way is to use
823 the external ltrace(1) command.
824
825 Command traces are disabled unless the environment variable
826 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
827
828   ("get_trace", (RBool "trace", []), -1, [],
829    [],
830    "get command trace enabled flag",
831    "\
832 Return the command trace flag.");
833
834 ]
835
836 (* daemon_functions are any functions which cause some action
837  * to take place in the daemon.
838  *)
839
840 let daemon_functions = [
841   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
842    [InitEmpty, Always, TestOutput (
843       [["sfdiskM"; "/dev/sda"; ","];
844        ["mkfs"; "ext2"; "/dev/sda1"];
845        ["mount"; "/dev/sda1"; "/"];
846        ["write_file"; "/new"; "new file contents"; "0"];
847        ["cat"; "/new"]], "new file contents")],
848    "mount a guest disk at a position in the filesystem",
849    "\
850 Mount a guest disk at a position in the filesystem.  Block devices
851 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
852 the guest.  If those block devices contain partitions, they will have
853 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
854 names can be used.
855
856 The rules are the same as for L<mount(2)>:  A filesystem must
857 first be mounted on C</> before others can be mounted.  Other
858 filesystems can only be mounted on directories which already
859 exist.
860
861 The mounted filesystem is writable, if we have sufficient permissions
862 on the underlying device.
863
864 The filesystem options C<sync> and C<noatime> are set with this
865 call, in order to improve reliability.");
866
867   ("sync", (RErr, []), 2, [],
868    [ InitEmpty, Always, TestRun [["sync"]]],
869    "sync disks, writes are flushed through to the disk image",
870    "\
871 This syncs the disk, so that any writes are flushed through to the
872 underlying disk image.
873
874 You should always call this if you have modified a disk image, before
875 closing the handle.");
876
877   ("touch", (RErr, [Pathname "path"]), 3, [],
878    [InitBasicFS, Always, TestOutputTrue (
879       [["touch"; "/new"];
880        ["exists"; "/new"]])],
881    "update file timestamps or create a new file",
882    "\
883 Touch acts like the L<touch(1)> command.  It can be used to
884 update the timestamps on a file, or, if the file does not exist,
885 to create a new zero-length file.");
886
887   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
888    [InitISOFS, Always, TestOutput (
889       [["cat"; "/known-2"]], "abcdef\n")],
890    "list the contents of a file",
891    "\
892 Return the contents of the file named C<path>.
893
894 Note that this function cannot correctly handle binary files
895 (specifically, files containing C<\\0> character which is treated
896 as end of string).  For those you need to use the C<guestfs_read_file>
897 or C<guestfs_download> functions which have a more complex interface.");
898
899   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
900    [], (* XXX Tricky to test because it depends on the exact format
901         * of the 'ls -l' command, which changes between F10 and F11.
902         *)
903    "list the files in a directory (long format)",
904    "\
905 List the files in C<directory> (relative to the root directory,
906 there is no cwd) in the format of 'ls -la'.
907
908 This command is mostly useful for interactive sessions.  It
909 is I<not> intended that you try to parse the output string.");
910
911   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
912    [InitBasicFS, Always, TestOutputList (
913       [["touch"; "/new"];
914        ["touch"; "/newer"];
915        ["touch"; "/newest"];
916        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
917    "list the files in a directory",
918    "\
919 List the files in C<directory> (relative to the root directory,
920 there is no cwd).  The '.' and '..' entries are not returned, but
921 hidden files are shown.
922
923 This command is mostly useful for interactive sessions.  Programs
924 should probably use C<guestfs_readdir> instead.");
925
926   ("list_devices", (RStringList "devices", []), 7, [],
927    [InitEmpty, Always, TestOutputListOfDevices (
928       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
929    "list the block devices",
930    "\
931 List all the block devices.
932
933 The full block device names are returned, eg. C</dev/sda>");
934
935   ("list_partitions", (RStringList "partitions", []), 8, [],
936    [InitBasicFS, Always, TestOutputListOfDevices (
937       [["list_partitions"]], ["/dev/sda1"]);
938     InitEmpty, Always, TestOutputListOfDevices (
939       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
940        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
941    "list the partitions",
942    "\
943 List all the partitions detected on all block devices.
944
945 The full partition device names are returned, eg. C</dev/sda1>
946
947 This does not return logical volumes.  For that you will need to
948 call C<guestfs_lvs>.");
949
950   ("pvs", (RStringList "physvols", []), 9, [],
951    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
952       [["pvs"]], ["/dev/sda1"]);
953     InitEmpty, Always, TestOutputListOfDevices (
954       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
955        ["pvcreate"; "/dev/sda1"];
956        ["pvcreate"; "/dev/sda2"];
957        ["pvcreate"; "/dev/sda3"];
958        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
959    "list the LVM physical volumes (PVs)",
960    "\
961 List all the physical volumes detected.  This is the equivalent
962 of the L<pvs(8)> command.
963
964 This returns a list of just the device names that contain
965 PVs (eg. C</dev/sda2>).
966
967 See also C<guestfs_pvs_full>.");
968
969   ("vgs", (RStringList "volgroups", []), 10, [],
970    [InitBasicFSonLVM, Always, TestOutputList (
971       [["vgs"]], ["VG"]);
972     InitEmpty, Always, TestOutputList (
973       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
974        ["pvcreate"; "/dev/sda1"];
975        ["pvcreate"; "/dev/sda2"];
976        ["pvcreate"; "/dev/sda3"];
977        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
978        ["vgcreate"; "VG2"; "/dev/sda3"];
979        ["vgs"]], ["VG1"; "VG2"])],
980    "list the LVM volume groups (VGs)",
981    "\
982 List all the volumes groups detected.  This is the equivalent
983 of the L<vgs(8)> command.
984
985 This returns a list of just the volume group names that were
986 detected (eg. C<VolGroup00>).
987
988 See also C<guestfs_vgs_full>.");
989
990   ("lvs", (RStringList "logvols", []), 11, [],
991    [InitBasicFSonLVM, Always, TestOutputList (
992       [["lvs"]], ["/dev/VG/LV"]);
993     InitEmpty, Always, TestOutputList (
994       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
995        ["pvcreate"; "/dev/sda1"];
996        ["pvcreate"; "/dev/sda2"];
997        ["pvcreate"; "/dev/sda3"];
998        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
999        ["vgcreate"; "VG2"; "/dev/sda3"];
1000        ["lvcreate"; "LV1"; "VG1"; "50"];
1001        ["lvcreate"; "LV2"; "VG1"; "50"];
1002        ["lvcreate"; "LV3"; "VG2"; "50"];
1003        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1004    "list the LVM logical volumes (LVs)",
1005    "\
1006 List all the logical volumes detected.  This is the equivalent
1007 of the L<lvs(8)> command.
1008
1009 This returns a list of the logical volume device names
1010 (eg. C</dev/VolGroup00/LogVol00>).
1011
1012 See also C<guestfs_lvs_full>.");
1013
1014   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
1015    [], (* XXX how to test? *)
1016    "list the LVM physical volumes (PVs)",
1017    "\
1018 List all the physical volumes detected.  This is the equivalent
1019 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1020
1021   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
1022    [], (* XXX how to test? *)
1023    "list the LVM volume groups (VGs)",
1024    "\
1025 List all the volumes groups detected.  This is the equivalent
1026 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1027
1028   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1029    [], (* XXX how to test? *)
1030    "list the LVM logical volumes (LVs)",
1031    "\
1032 List all the logical volumes detected.  This is the equivalent
1033 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1034
1035   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1036    [InitISOFS, Always, TestOutputList (
1037       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1038     InitISOFS, Always, TestOutputList (
1039       [["read_lines"; "/empty"]], [])],
1040    "read file as lines",
1041    "\
1042 Return the contents of the file named C<path>.
1043
1044 The file contents are returned as a list of lines.  Trailing
1045 C<LF> and C<CRLF> character sequences are I<not> returned.
1046
1047 Note that this function cannot correctly handle binary files
1048 (specifically, files containing C<\\0> character which is treated
1049 as end of line).  For those you need to use the C<guestfs_read_file>
1050 function which has a more complex interface.");
1051
1052   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1053    [], (* XXX Augeas code needs tests. *)
1054    "create a new Augeas handle",
1055    "\
1056 Create a new Augeas handle for editing configuration files.
1057 If there was any previous Augeas handle associated with this
1058 guestfs session, then it is closed.
1059
1060 You must call this before using any other C<guestfs_aug_*>
1061 commands.
1062
1063 C<root> is the filesystem root.  C<root> must not be NULL,
1064 use C</> instead.
1065
1066 The flags are the same as the flags defined in
1067 E<lt>augeas.hE<gt>, the logical I<or> of the following
1068 integers:
1069
1070 =over 4
1071
1072 =item C<AUG_SAVE_BACKUP> = 1
1073
1074 Keep the original file with a C<.augsave> extension.
1075
1076 =item C<AUG_SAVE_NEWFILE> = 2
1077
1078 Save changes into a file with extension C<.augnew>, and
1079 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1080
1081 =item C<AUG_TYPE_CHECK> = 4
1082
1083 Typecheck lenses (can be expensive).
1084
1085 =item C<AUG_NO_STDINC> = 8
1086
1087 Do not use standard load path for modules.
1088
1089 =item C<AUG_SAVE_NOOP> = 16
1090
1091 Make save a no-op, just record what would have been changed.
1092
1093 =item C<AUG_NO_LOAD> = 32
1094
1095 Do not load the tree in C<guestfs_aug_init>.
1096
1097 =back
1098
1099 To close the handle, you can call C<guestfs_aug_close>.
1100
1101 To find out more about Augeas, see L<http://augeas.net/>.");
1102
1103   ("aug_close", (RErr, []), 26, [],
1104    [], (* XXX Augeas code needs tests. *)
1105    "close the current Augeas handle",
1106    "\
1107 Close the current Augeas handle and free up any resources
1108 used by it.  After calling this, you have to call
1109 C<guestfs_aug_init> again before you can use any other
1110 Augeas functions.");
1111
1112   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1113    [], (* XXX Augeas code needs tests. *)
1114    "define an Augeas variable",
1115    "\
1116 Defines an Augeas variable C<name> whose value is the result
1117 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1118 undefined.
1119
1120 On success this returns the number of nodes in C<expr>, or
1121 C<0> if C<expr> evaluates to something which is not a nodeset.");
1122
1123   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1124    [], (* XXX Augeas code needs tests. *)
1125    "define an Augeas node",
1126    "\
1127 Defines a variable C<name> whose value is the result of
1128 evaluating C<expr>.
1129
1130 If C<expr> evaluates to an empty nodeset, a node is created,
1131 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1132 C<name> will be the nodeset containing that single node.
1133
1134 On success this returns a pair containing the
1135 number of nodes in the nodeset, and a boolean flag
1136 if a node was created.");
1137
1138   ("aug_get", (RString "val", [String "augpath"]), 19, [],
1139    [], (* XXX Augeas code needs tests. *)
1140    "look up the value of an Augeas path",
1141    "\
1142 Look up the value associated with C<path>.  If C<path>
1143 matches exactly one node, the C<value> is returned.");
1144
1145   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1146    [], (* XXX Augeas code needs tests. *)
1147    "set Augeas path to value",
1148    "\
1149 Set the value associated with C<path> to C<value>.");
1150
1151   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1152    [], (* XXX Augeas code needs tests. *)
1153    "insert a sibling Augeas node",
1154    "\
1155 Create a new sibling C<label> for C<path>, inserting it into
1156 the tree before or after C<path> (depending on the boolean
1157 flag C<before>).
1158
1159 C<path> must match exactly one existing node in the tree, and
1160 C<label> must be a label, ie. not contain C</>, C<*> or end
1161 with a bracketed index C<[N]>.");
1162
1163   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1164    [], (* XXX Augeas code needs tests. *)
1165    "remove an Augeas path",
1166    "\
1167 Remove C<path> and all of its children.
1168
1169 On success this returns the number of entries which were removed.");
1170
1171   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1172    [], (* XXX Augeas code needs tests. *)
1173    "move Augeas node",
1174    "\
1175 Move the node C<src> to C<dest>.  C<src> must match exactly
1176 one node.  C<dest> is overwritten if it exists.");
1177
1178   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1179    [], (* XXX Augeas code needs tests. *)
1180    "return Augeas nodes which match augpath",
1181    "\
1182 Returns a list of paths which match the path expression C<path>.
1183 The returned paths are sufficiently qualified so that they match
1184 exactly one node in the current tree.");
1185
1186   ("aug_save", (RErr, []), 25, [],
1187    [], (* XXX Augeas code needs tests. *)
1188    "write all pending Augeas changes to disk",
1189    "\
1190 This writes all pending changes to disk.
1191
1192 The flags which were passed to C<guestfs_aug_init> affect exactly
1193 how files are saved.");
1194
1195   ("aug_load", (RErr, []), 27, [],
1196    [], (* XXX Augeas code needs tests. *)
1197    "load files into the tree",
1198    "\
1199 Load files into the tree.
1200
1201 See C<aug_load> in the Augeas documentation for the full gory
1202 details.");
1203
1204   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1205    [], (* XXX Augeas code needs tests. *)
1206    "list Augeas nodes under augpath",
1207    "\
1208 This is just a shortcut for listing C<guestfs_aug_match>
1209 C<path/*> and sorting the resulting nodes into alphabetical order.");
1210
1211   ("rm", (RErr, [Pathname "path"]), 29, [],
1212    [InitBasicFS, Always, TestRun
1213       [["touch"; "/new"];
1214        ["rm"; "/new"]];
1215     InitBasicFS, Always, TestLastFail
1216       [["rm"; "/new"]];
1217     InitBasicFS, Always, TestLastFail
1218       [["mkdir"; "/new"];
1219        ["rm"; "/new"]]],
1220    "remove a file",
1221    "\
1222 Remove the single file C<path>.");
1223
1224   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1225    [InitBasicFS, Always, TestRun
1226       [["mkdir"; "/new"];
1227        ["rmdir"; "/new"]];
1228     InitBasicFS, Always, TestLastFail
1229       [["rmdir"; "/new"]];
1230     InitBasicFS, Always, TestLastFail
1231       [["touch"; "/new"];
1232        ["rmdir"; "/new"]]],
1233    "remove a directory",
1234    "\
1235 Remove the single directory C<path>.");
1236
1237   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1238    [InitBasicFS, Always, TestOutputFalse
1239       [["mkdir"; "/new"];
1240        ["mkdir"; "/new/foo"];
1241        ["touch"; "/new/foo/bar"];
1242        ["rm_rf"; "/new"];
1243        ["exists"; "/new"]]],
1244    "remove a file or directory recursively",
1245    "\
1246 Remove the file or directory C<path>, recursively removing the
1247 contents if its a directory.  This is like the C<rm -rf> shell
1248 command.");
1249
1250   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1251    [InitBasicFS, Always, TestOutputTrue
1252       [["mkdir"; "/new"];
1253        ["is_dir"; "/new"]];
1254     InitBasicFS, Always, TestLastFail
1255       [["mkdir"; "/new/foo/bar"]]],
1256    "create a directory",
1257    "\
1258 Create a directory named C<path>.");
1259
1260   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1261    [InitBasicFS, Always, TestOutputTrue
1262       [["mkdir_p"; "/new/foo/bar"];
1263        ["is_dir"; "/new/foo/bar"]];
1264     InitBasicFS, Always, TestOutputTrue
1265       [["mkdir_p"; "/new/foo/bar"];
1266        ["is_dir"; "/new/foo"]];
1267     InitBasicFS, Always, TestOutputTrue
1268       [["mkdir_p"; "/new/foo/bar"];
1269        ["is_dir"; "/new"]];
1270     (* Regression tests for RHBZ#503133: *)
1271     InitBasicFS, Always, TestRun
1272       [["mkdir"; "/new"];
1273        ["mkdir_p"; "/new"]];
1274     InitBasicFS, Always, TestLastFail
1275       [["touch"; "/new"];
1276        ["mkdir_p"; "/new"]]],
1277    "create a directory and parents",
1278    "\
1279 Create a directory named C<path>, creating any parent directories
1280 as necessary.  This is like the C<mkdir -p> shell command.");
1281
1282   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1283    [], (* XXX Need stat command to test *)
1284    "change file mode",
1285    "\
1286 Change the mode (permissions) of C<path> to C<mode>.  Only
1287 numeric modes are supported.");
1288
1289   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1290    [], (* XXX Need stat command to test *)
1291    "change file owner and group",
1292    "\
1293 Change the file owner to C<owner> and group to C<group>.
1294
1295 Only numeric uid and gid are supported.  If you want to use
1296 names, you will need to locate and parse the password file
1297 yourself (Augeas support makes this relatively easy).");
1298
1299   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1300    [InitISOFS, Always, TestOutputTrue (
1301       [["exists"; "/empty"]]);
1302     InitISOFS, Always, TestOutputTrue (
1303       [["exists"; "/directory"]])],
1304    "test if file or directory exists",
1305    "\
1306 This returns C<true> if and only if there is a file, directory
1307 (or anything) with the given C<path> name.
1308
1309 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1310
1311   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1312    [InitISOFS, Always, TestOutputTrue (
1313       [["is_file"; "/known-1"]]);
1314     InitISOFS, Always, TestOutputFalse (
1315       [["is_file"; "/directory"]])],
1316    "test if file exists",
1317    "\
1318 This returns C<true> if and only if there is a file
1319 with the given C<path> name.  Note that it returns false for
1320 other objects like directories.
1321
1322 See also C<guestfs_stat>.");
1323
1324   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1325    [InitISOFS, Always, TestOutputFalse (
1326       [["is_dir"; "/known-3"]]);
1327     InitISOFS, Always, TestOutputTrue (
1328       [["is_dir"; "/directory"]])],
1329    "test if file exists",
1330    "\
1331 This returns C<true> if and only if there is a directory
1332 with the given C<path> name.  Note that it returns false for
1333 other objects like files.
1334
1335 See also C<guestfs_stat>.");
1336
1337   ("pvcreate", (RErr, [Device "device"]), 39, [],
1338    [InitEmpty, Always, TestOutputListOfDevices (
1339       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1340        ["pvcreate"; "/dev/sda1"];
1341        ["pvcreate"; "/dev/sda2"];
1342        ["pvcreate"; "/dev/sda3"];
1343        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1344    "create an LVM physical volume",
1345    "\
1346 This creates an LVM physical volume on the named C<device>,
1347 where C<device> should usually be a partition name such
1348 as C</dev/sda1>.");
1349
1350   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
1351    [InitEmpty, Always, TestOutputList (
1352       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1353        ["pvcreate"; "/dev/sda1"];
1354        ["pvcreate"; "/dev/sda2"];
1355        ["pvcreate"; "/dev/sda3"];
1356        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1357        ["vgcreate"; "VG2"; "/dev/sda3"];
1358        ["vgs"]], ["VG1"; "VG2"])],
1359    "create an LVM volume group",
1360    "\
1361 This creates an LVM volume group called C<volgroup>
1362 from the non-empty list of physical volumes C<physvols>.");
1363
1364   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1365    [InitEmpty, Always, TestOutputList (
1366       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1367        ["pvcreate"; "/dev/sda1"];
1368        ["pvcreate"; "/dev/sda2"];
1369        ["pvcreate"; "/dev/sda3"];
1370        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1371        ["vgcreate"; "VG2"; "/dev/sda3"];
1372        ["lvcreate"; "LV1"; "VG1"; "50"];
1373        ["lvcreate"; "LV2"; "VG1"; "50"];
1374        ["lvcreate"; "LV3"; "VG2"; "50"];
1375        ["lvcreate"; "LV4"; "VG2"; "50"];
1376        ["lvcreate"; "LV5"; "VG2"; "50"];
1377        ["lvs"]],
1378       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1379        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1380    "create an LVM volume group",
1381    "\
1382 This creates an LVM volume group called C<logvol>
1383 on the volume group C<volgroup>, with C<size> megabytes.");
1384
1385   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1386    [InitEmpty, Always, TestOutput (
1387       [["sfdiskM"; "/dev/sda"; ","];
1388        ["mkfs"; "ext2"; "/dev/sda1"];
1389        ["mount"; "/dev/sda1"; "/"];
1390        ["write_file"; "/new"; "new file contents"; "0"];
1391        ["cat"; "/new"]], "new file contents")],
1392    "make a filesystem",
1393    "\
1394 This creates a filesystem on C<device> (usually a partition
1395 or LVM logical volume).  The filesystem type is C<fstype>, for
1396 example C<ext3>.");
1397
1398   ("sfdisk", (RErr, [Device "device";
1399                      Int "cyls"; Int "heads"; Int "sectors";
1400                      StringList "lines"]), 43, [DangerWillRobinson],
1401    [],
1402    "create partitions on a block device",
1403    "\
1404 This is a direct interface to the L<sfdisk(8)> program for creating
1405 partitions on block devices.
1406
1407 C<device> should be a block device, for example C</dev/sda>.
1408
1409 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1410 and sectors on the device, which are passed directly to sfdisk as
1411 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1412 of these, then the corresponding parameter is omitted.  Usually for
1413 'large' disks, you can just pass C<0> for these, but for small
1414 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1415 out the right geometry and you will need to tell it.
1416
1417 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1418 information refer to the L<sfdisk(8)> manpage.
1419
1420 To create a single partition occupying the whole disk, you would
1421 pass C<lines> as a single element list, when the single element being
1422 the string C<,> (comma).
1423
1424 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1425
1426   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1427    [InitBasicFS, Always, TestOutput (
1428       [["write_file"; "/new"; "new file contents"; "0"];
1429        ["cat"; "/new"]], "new file contents");
1430     InitBasicFS, Always, TestOutput (
1431       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1432        ["cat"; "/new"]], "\nnew file contents\n");
1433     InitBasicFS, Always, TestOutput (
1434       [["write_file"; "/new"; "\n\n"; "0"];
1435        ["cat"; "/new"]], "\n\n");
1436     InitBasicFS, Always, TestOutput (
1437       [["write_file"; "/new"; ""; "0"];
1438        ["cat"; "/new"]], "");
1439     InitBasicFS, Always, TestOutput (
1440       [["write_file"; "/new"; "\n\n\n"; "0"];
1441        ["cat"; "/new"]], "\n\n\n");
1442     InitBasicFS, Always, TestOutput (
1443       [["write_file"; "/new"; "\n"; "0"];
1444        ["cat"; "/new"]], "\n")],
1445    "create a file",
1446    "\
1447 This call creates a file called C<path>.  The contents of the
1448 file is the string C<content> (which can contain any 8 bit data),
1449 with length C<size>.
1450
1451 As a special case, if C<size> is C<0>
1452 then the length is calculated using C<strlen> (so in this case
1453 the content cannot contain embedded ASCII NULs).
1454
1455 I<NB.> Owing to a bug, writing content containing ASCII NUL
1456 characters does I<not> work, even if the length is specified.
1457 We hope to resolve this bug in a future version.  In the meantime
1458 use C<guestfs_upload>.");
1459
1460   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1461    [InitEmpty, Always, TestOutputListOfDevices (
1462       [["sfdiskM"; "/dev/sda"; ","];
1463        ["mkfs"; "ext2"; "/dev/sda1"];
1464        ["mount"; "/dev/sda1"; "/"];
1465        ["mounts"]], ["/dev/sda1"]);
1466     InitEmpty, Always, TestOutputList (
1467       [["sfdiskM"; "/dev/sda"; ","];
1468        ["mkfs"; "ext2"; "/dev/sda1"];
1469        ["mount"; "/dev/sda1"; "/"];
1470        ["umount"; "/"];
1471        ["mounts"]], [])],
1472    "unmount a filesystem",
1473    "\
1474 This unmounts the given filesystem.  The filesystem may be
1475 specified either by its mountpoint (path) or the device which
1476 contains the filesystem.");
1477
1478   ("mounts", (RStringList "devices", []), 46, [],
1479    [InitBasicFS, Always, TestOutputListOfDevices (
1480       [["mounts"]], ["/dev/sda1"])],
1481    "show mounted filesystems",
1482    "\
1483 This returns the list of currently mounted filesystems.  It returns
1484 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1485
1486 Some internal mounts are not shown.
1487
1488 See also: C<guestfs_mountpoints>");
1489
1490   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1491    [InitBasicFS, Always, TestOutputList (
1492       [["umount_all"];
1493        ["mounts"]], []);
1494     (* check that umount_all can unmount nested mounts correctly: *)
1495     InitEmpty, Always, TestOutputList (
1496       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1497        ["mkfs"; "ext2"; "/dev/sda1"];
1498        ["mkfs"; "ext2"; "/dev/sda2"];
1499        ["mkfs"; "ext2"; "/dev/sda3"];
1500        ["mount"; "/dev/sda1"; "/"];
1501        ["mkdir"; "/mp1"];
1502        ["mount"; "/dev/sda2"; "/mp1"];
1503        ["mkdir"; "/mp1/mp2"];
1504        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1505        ["mkdir"; "/mp1/mp2/mp3"];
1506        ["umount_all"];
1507        ["mounts"]], [])],
1508    "unmount all filesystems",
1509    "\
1510 This unmounts all mounted filesystems.
1511
1512 Some internal mounts are not unmounted by this call.");
1513
1514   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1515    [],
1516    "remove all LVM LVs, VGs and PVs",
1517    "\
1518 This command removes all LVM logical volumes, volume groups
1519 and physical volumes.");
1520
1521   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1522    [InitISOFS, Always, TestOutput (
1523       [["file"; "/empty"]], "empty");
1524     InitISOFS, Always, TestOutput (
1525       [["file"; "/known-1"]], "ASCII text");
1526     InitISOFS, Always, TestLastFail (
1527       [["file"; "/notexists"]])],
1528    "determine file type",
1529    "\
1530 This call uses the standard L<file(1)> command to determine
1531 the type or contents of the file.  This also works on devices,
1532 for example to find out whether a partition contains a filesystem.
1533
1534 This call will also transparently look inside various types
1535 of compressed file.
1536
1537 The exact command which runs is C<file -zbsL path>.  Note in
1538 particular that the filename is not prepended to the output
1539 (the C<-b> option).");
1540
1541   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1542    [InitBasicFS, Always, TestOutput (
1543       [["upload"; "test-command"; "/test-command"];
1544        ["chmod"; "0o755"; "/test-command"];
1545        ["command"; "/test-command 1"]], "Result1");
1546     InitBasicFS, Always, TestOutput (
1547       [["upload"; "test-command"; "/test-command"];
1548        ["chmod"; "0o755"; "/test-command"];
1549        ["command"; "/test-command 2"]], "Result2\n");
1550     InitBasicFS, Always, TestOutput (
1551       [["upload"; "test-command"; "/test-command"];
1552        ["chmod"; "0o755"; "/test-command"];
1553        ["command"; "/test-command 3"]], "\nResult3");
1554     InitBasicFS, Always, TestOutput (
1555       [["upload"; "test-command"; "/test-command"];
1556        ["chmod"; "0o755"; "/test-command"];
1557        ["command"; "/test-command 4"]], "\nResult4\n");
1558     InitBasicFS, Always, TestOutput (
1559       [["upload"; "test-command"; "/test-command"];
1560        ["chmod"; "0o755"; "/test-command"];
1561        ["command"; "/test-command 5"]], "\nResult5\n\n");
1562     InitBasicFS, Always, TestOutput (
1563       [["upload"; "test-command"; "/test-command"];
1564        ["chmod"; "0o755"; "/test-command"];
1565        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1566     InitBasicFS, Always, TestOutput (
1567       [["upload"; "test-command"; "/test-command"];
1568        ["chmod"; "0o755"; "/test-command"];
1569        ["command"; "/test-command 7"]], "");
1570     InitBasicFS, Always, TestOutput (
1571       [["upload"; "test-command"; "/test-command"];
1572        ["chmod"; "0o755"; "/test-command"];
1573        ["command"; "/test-command 8"]], "\n");
1574     InitBasicFS, Always, TestOutput (
1575       [["upload"; "test-command"; "/test-command"];
1576        ["chmod"; "0o755"; "/test-command"];
1577        ["command"; "/test-command 9"]], "\n\n");
1578     InitBasicFS, Always, TestOutput (
1579       [["upload"; "test-command"; "/test-command"];
1580        ["chmod"; "0o755"; "/test-command"];
1581        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1582     InitBasicFS, Always, TestOutput (
1583       [["upload"; "test-command"; "/test-command"];
1584        ["chmod"; "0o755"; "/test-command"];
1585        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1586     InitBasicFS, Always, TestLastFail (
1587       [["upload"; "test-command"; "/test-command"];
1588        ["chmod"; "0o755"; "/test-command"];
1589        ["command"; "/test-command"]])],
1590    "run a command from the guest filesystem",
1591    "\
1592 This call runs a command from the guest filesystem.  The
1593 filesystem must be mounted, and must contain a compatible
1594 operating system (ie. something Linux, with the same
1595 or compatible processor architecture).
1596
1597 The single parameter is an argv-style list of arguments.
1598 The first element is the name of the program to run.
1599 Subsequent elements are parameters.  The list must be
1600 non-empty (ie. must contain a program name).  Note that
1601 the command runs directly, and is I<not> invoked via
1602 the shell (see C<guestfs_sh>).
1603
1604 The return value is anything printed to I<stdout> by
1605 the command.
1606
1607 If the command returns a non-zero exit status, then
1608 this function returns an error message.  The error message
1609 string is the content of I<stderr> from the command.
1610
1611 The C<$PATH> environment variable will contain at least
1612 C</usr/bin> and C</bin>.  If you require a program from
1613 another location, you should provide the full path in the
1614 first parameter.
1615
1616 Shared libraries and data files required by the program
1617 must be available on filesystems which are mounted in the
1618 correct places.  It is the caller's responsibility to ensure
1619 all filesystems that are needed are mounted at the right
1620 locations.");
1621
1622   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1623    [InitBasicFS, Always, TestOutputList (
1624       [["upload"; "test-command"; "/test-command"];
1625        ["chmod"; "0o755"; "/test-command"];
1626        ["command_lines"; "/test-command 1"]], ["Result1"]);
1627     InitBasicFS, Always, TestOutputList (
1628       [["upload"; "test-command"; "/test-command"];
1629        ["chmod"; "0o755"; "/test-command"];
1630        ["command_lines"; "/test-command 2"]], ["Result2"]);
1631     InitBasicFS, Always, TestOutputList (
1632       [["upload"; "test-command"; "/test-command"];
1633        ["chmod"; "0o755"; "/test-command"];
1634        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1635     InitBasicFS, Always, TestOutputList (
1636       [["upload"; "test-command"; "/test-command"];
1637        ["chmod"; "0o755"; "/test-command"];
1638        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1639     InitBasicFS, Always, TestOutputList (
1640       [["upload"; "test-command"; "/test-command"];
1641        ["chmod"; "0o755"; "/test-command"];
1642        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1643     InitBasicFS, Always, TestOutputList (
1644       [["upload"; "test-command"; "/test-command"];
1645        ["chmod"; "0o755"; "/test-command"];
1646        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1647     InitBasicFS, Always, TestOutputList (
1648       [["upload"; "test-command"; "/test-command"];
1649        ["chmod"; "0o755"; "/test-command"];
1650        ["command_lines"; "/test-command 7"]], []);
1651     InitBasicFS, Always, TestOutputList (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command_lines"; "/test-command 8"]], [""]);
1655     InitBasicFS, Always, TestOutputList (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command_lines"; "/test-command 9"]], ["";""]);
1659     InitBasicFS, Always, TestOutputList (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1663     InitBasicFS, Always, TestOutputList (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1667    "run a command, returning lines",
1668    "\
1669 This is the same as C<guestfs_command>, but splits the
1670 result into a list of lines.
1671
1672 See also: C<guestfs_sh_lines>");
1673
1674   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1675    [InitISOFS, Always, TestOutputStruct (
1676       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1677    "get file information",
1678    "\
1679 Returns file information for the given C<path>.
1680
1681 This is the same as the C<stat(2)> system call.");
1682
1683   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1684    [InitISOFS, Always, TestOutputStruct (
1685       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1686    "get file information for a symbolic link",
1687    "\
1688 Returns file information for the given C<path>.
1689
1690 This is the same as C<guestfs_stat> except that if C<path>
1691 is a symbolic link, then the link is stat-ed, not the file it
1692 refers to.
1693
1694 This is the same as the C<lstat(2)> system call.");
1695
1696   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1697    [InitISOFS, Always, TestOutputStruct (
1698       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1699    "get file system statistics",
1700    "\
1701 Returns file system statistics for any mounted file system.
1702 C<path> should be a file or directory in the mounted file system
1703 (typically it is the mount point itself, but it doesn't need to be).
1704
1705 This is the same as the C<statvfs(2)> system call.");
1706
1707   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1708    [], (* XXX test *)
1709    "get ext2/ext3/ext4 superblock details",
1710    "\
1711 This returns the contents of the ext2, ext3 or ext4 filesystem
1712 superblock on C<device>.
1713
1714 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1715 manpage for more details.  The list of fields returned isn't
1716 clearly defined, and depends on both the version of C<tune2fs>
1717 that libguestfs was built against, and the filesystem itself.");
1718
1719   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1720    [InitEmpty, Always, TestOutputTrue (
1721       [["blockdev_setro"; "/dev/sda"];
1722        ["blockdev_getro"; "/dev/sda"]])],
1723    "set block device to read-only",
1724    "\
1725 Sets the block device named C<device> to read-only.
1726
1727 This uses the L<blockdev(8)> command.");
1728
1729   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1730    [InitEmpty, Always, TestOutputFalse (
1731       [["blockdev_setrw"; "/dev/sda"];
1732        ["blockdev_getro"; "/dev/sda"]])],
1733    "set block device to read-write",
1734    "\
1735 Sets the block device named C<device> to read-write.
1736
1737 This uses the L<blockdev(8)> command.");
1738
1739   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1740    [InitEmpty, Always, TestOutputTrue (
1741       [["blockdev_setro"; "/dev/sda"];
1742        ["blockdev_getro"; "/dev/sda"]])],
1743    "is block device set to read-only",
1744    "\
1745 Returns a boolean indicating if the block device is read-only
1746 (true if read-only, false if not).
1747
1748 This uses the L<blockdev(8)> command.");
1749
1750   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1751    [InitEmpty, Always, TestOutputInt (
1752       [["blockdev_getss"; "/dev/sda"]], 512)],
1753    "get sectorsize of block device",
1754    "\
1755 This returns the size of sectors on a block device.
1756 Usually 512, but can be larger for modern devices.
1757
1758 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1759 for that).
1760
1761 This uses the L<blockdev(8)> command.");
1762
1763   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1764    [InitEmpty, Always, TestOutputInt (
1765       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1766    "get blocksize of block device",
1767    "\
1768 This returns the block size of a device.
1769
1770 (Note this is different from both I<size in blocks> and
1771 I<filesystem block size>).
1772
1773 This uses the L<blockdev(8)> command.");
1774
1775   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1776    [], (* XXX test *)
1777    "set blocksize of block device",
1778    "\
1779 This sets the block size of a device.
1780
1781 (Note this is different from both I<size in blocks> and
1782 I<filesystem block size>).
1783
1784 This uses the L<blockdev(8)> command.");
1785
1786   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1787    [InitEmpty, Always, TestOutputInt (
1788       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1789    "get total size of device in 512-byte sectors",
1790    "\
1791 This returns the size of the device in units of 512-byte sectors
1792 (even if the sectorsize isn't 512 bytes ... weird).
1793
1794 See also C<guestfs_blockdev_getss> for the real sector size of
1795 the device, and C<guestfs_blockdev_getsize64> for the more
1796 useful I<size in bytes>.
1797
1798 This uses the L<blockdev(8)> command.");
1799
1800   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1801    [InitEmpty, Always, TestOutputInt (
1802       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1803    "get total size of device in bytes",
1804    "\
1805 This returns the size of the device in bytes.
1806
1807 See also C<guestfs_blockdev_getsz>.
1808
1809 This uses the L<blockdev(8)> command.");
1810
1811   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1812    [InitEmpty, Always, TestRun
1813       [["blockdev_flushbufs"; "/dev/sda"]]],
1814    "flush device buffers",
1815    "\
1816 This tells the kernel to flush internal buffers associated
1817 with C<device>.
1818
1819 This uses the L<blockdev(8)> command.");
1820
1821   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1822    [InitEmpty, Always, TestRun
1823       [["blockdev_rereadpt"; "/dev/sda"]]],
1824    "reread partition table",
1825    "\
1826 Reread the partition table on C<device>.
1827
1828 This uses the L<blockdev(8)> command.");
1829
1830   ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1831    [InitBasicFS, Always, TestOutput (
1832       (* Pick a file from cwd which isn't likely to change. *)
1833       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1834        ["checksum"; "md5"; "/COPYING.LIB"]],
1835         Digest.to_hex (Digest.file "COPYING.LIB"))],
1836    "upload a file from the local machine",
1837    "\
1838 Upload local file C<filename> to C<remotefilename> on the
1839 filesystem.
1840
1841 C<filename> can also be a named pipe.
1842
1843 See also C<guestfs_download>.");
1844
1845   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1846    [InitBasicFS, Always, TestOutput (
1847       (* Pick a file from cwd which isn't likely to change. *)
1848       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1849        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1850        ["upload"; "testdownload.tmp"; "/upload"];
1851        ["checksum"; "md5"; "/upload"]],
1852         Digest.to_hex (Digest.file "COPYING.LIB"))],
1853    "download a file to the local machine",
1854    "\
1855 Download file C<remotefilename> and save it as C<filename>
1856 on the local machine.
1857
1858 C<filename> can also be a named pipe.
1859
1860 See also C<guestfs_upload>, C<guestfs_cat>.");
1861
1862   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1863    [InitISOFS, Always, TestOutput (
1864       [["checksum"; "crc"; "/known-3"]], "2891671662");
1865     InitISOFS, Always, TestLastFail (
1866       [["checksum"; "crc"; "/notexists"]]);
1867     InitISOFS, Always, TestOutput (
1868       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1869     InitISOFS, Always, TestOutput (
1870       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1871     InitISOFS, Always, TestOutput (
1872       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1873     InitISOFS, Always, TestOutput (
1874       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1875     InitISOFS, Always, TestOutput (
1876       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1877     InitISOFS, Always, TestOutput (
1878       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1879    "compute MD5, SHAx or CRC checksum of file",
1880    "\
1881 This call computes the MD5, SHAx or CRC checksum of the
1882 file named C<path>.
1883
1884 The type of checksum to compute is given by the C<csumtype>
1885 parameter which must have one of the following values:
1886
1887 =over 4
1888
1889 =item C<crc>
1890
1891 Compute the cyclic redundancy check (CRC) specified by POSIX
1892 for the C<cksum> command.
1893
1894 =item C<md5>
1895
1896 Compute the MD5 hash (using the C<md5sum> program).
1897
1898 =item C<sha1>
1899
1900 Compute the SHA1 hash (using the C<sha1sum> program).
1901
1902 =item C<sha224>
1903
1904 Compute the SHA224 hash (using the C<sha224sum> program).
1905
1906 =item C<sha256>
1907
1908 Compute the SHA256 hash (using the C<sha256sum> program).
1909
1910 =item C<sha384>
1911
1912 Compute the SHA384 hash (using the C<sha384sum> program).
1913
1914 =item C<sha512>
1915
1916 Compute the SHA512 hash (using the C<sha512sum> program).
1917
1918 =back
1919
1920 The checksum is returned as a printable string.");
1921
1922   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1923    [InitBasicFS, Always, TestOutput (
1924       [["tar_in"; "../images/helloworld.tar"; "/"];
1925        ["cat"; "/hello"]], "hello\n")],
1926    "unpack tarfile to directory",
1927    "\
1928 This command uploads and unpacks local file C<tarfile> (an
1929 I<uncompressed> tar file) into C<directory>.
1930
1931 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1932
1933   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1934    [],
1935    "pack directory into tarfile",
1936    "\
1937 This command packs the contents of C<directory> and downloads
1938 it to local file C<tarfile>.
1939
1940 To download a compressed tarball, use C<guestfs_tgz_out>.");
1941
1942   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1943    [InitBasicFS, Always, TestOutput (
1944       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1945        ["cat"; "/hello"]], "hello\n")],
1946    "unpack compressed tarball to directory",
1947    "\
1948 This command uploads and unpacks local file C<tarball> (a
1949 I<gzip compressed> tar file) into C<directory>.
1950
1951 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1952
1953   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1954    [],
1955    "pack directory into compressed tarball",
1956    "\
1957 This command packs the contents of C<directory> and downloads
1958 it to local file C<tarball>.
1959
1960 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1961
1962   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1963    [InitBasicFS, Always, TestLastFail (
1964       [["umount"; "/"];
1965        ["mount_ro"; "/dev/sda1"; "/"];
1966        ["touch"; "/new"]]);
1967     InitBasicFS, Always, TestOutput (
1968       [["write_file"; "/new"; "data"; "0"];
1969        ["umount"; "/"];
1970        ["mount_ro"; "/dev/sda1"; "/"];
1971        ["cat"; "/new"]], "data")],
1972    "mount a guest disk, read-only",
1973    "\
1974 This is the same as the C<guestfs_mount> command, but it
1975 mounts the filesystem with the read-only (I<-o ro>) flag.");
1976
1977   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
1978    [],
1979    "mount a guest disk with mount options",
1980    "\
1981 This is the same as the C<guestfs_mount> command, but it
1982 allows you to set the mount options as for the
1983 L<mount(8)> I<-o> flag.");
1984
1985   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
1986    [],
1987    "mount a guest disk with mount options and vfstype",
1988    "\
1989 This is the same as the C<guestfs_mount> command, but it
1990 allows you to set both the mount options and the vfstype
1991 as for the L<mount(8)> I<-o> and I<-t> flags.");
1992
1993   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1994    [],
1995    "debugging and internals",
1996    "\
1997 The C<guestfs_debug> command exposes some internals of
1998 C<guestfsd> (the guestfs daemon) that runs inside the
1999 qemu subprocess.
2000
2001 There is no comprehensive help for this command.  You have
2002 to look at the file C<daemon/debug.c> in the libguestfs source
2003 to find out what you can do.");
2004
2005   ("lvremove", (RErr, [Device "device"]), 77, [],
2006    [InitEmpty, Always, TestOutputList (
2007       [["sfdiskM"; "/dev/sda"; ","];
2008        ["pvcreate"; "/dev/sda1"];
2009        ["vgcreate"; "VG"; "/dev/sda1"];
2010        ["lvcreate"; "LV1"; "VG"; "50"];
2011        ["lvcreate"; "LV2"; "VG"; "50"];
2012        ["lvremove"; "/dev/VG/LV1"];
2013        ["lvs"]], ["/dev/VG/LV2"]);
2014     InitEmpty, Always, TestOutputList (
2015       [["sfdiskM"; "/dev/sda"; ","];
2016        ["pvcreate"; "/dev/sda1"];
2017        ["vgcreate"; "VG"; "/dev/sda1"];
2018        ["lvcreate"; "LV1"; "VG"; "50"];
2019        ["lvcreate"; "LV2"; "VG"; "50"];
2020        ["lvremove"; "/dev/VG"];
2021        ["lvs"]], []);
2022     InitEmpty, Always, TestOutputList (
2023       [["sfdiskM"; "/dev/sda"; ","];
2024        ["pvcreate"; "/dev/sda1"];
2025        ["vgcreate"; "VG"; "/dev/sda1"];
2026        ["lvcreate"; "LV1"; "VG"; "50"];
2027        ["lvcreate"; "LV2"; "VG"; "50"];
2028        ["lvremove"; "/dev/VG"];
2029        ["vgs"]], ["VG"])],
2030    "remove an LVM logical volume",
2031    "\
2032 Remove an LVM logical volume C<device>, where C<device> is
2033 the path to the LV, such as C</dev/VG/LV>.
2034
2035 You can also remove all LVs in a volume group by specifying
2036 the VG name, C</dev/VG>.");
2037
2038   ("vgremove", (RErr, [String "vgname"]), 78, [],
2039    [InitEmpty, Always, TestOutputList (
2040       [["sfdiskM"; "/dev/sda"; ","];
2041        ["pvcreate"; "/dev/sda1"];
2042        ["vgcreate"; "VG"; "/dev/sda1"];
2043        ["lvcreate"; "LV1"; "VG"; "50"];
2044        ["lvcreate"; "LV2"; "VG"; "50"];
2045        ["vgremove"; "VG"];
2046        ["lvs"]], []);
2047     InitEmpty, Always, TestOutputList (
2048       [["sfdiskM"; "/dev/sda"; ","];
2049        ["pvcreate"; "/dev/sda1"];
2050        ["vgcreate"; "VG"; "/dev/sda1"];
2051        ["lvcreate"; "LV1"; "VG"; "50"];
2052        ["lvcreate"; "LV2"; "VG"; "50"];
2053        ["vgremove"; "VG"];
2054        ["vgs"]], [])],
2055    "remove an LVM volume group",
2056    "\
2057 Remove an LVM volume group C<vgname>, (for example C<VG>).
2058
2059 This also forcibly removes all logical volumes in the volume
2060 group (if any).");
2061
2062   ("pvremove", (RErr, [Device "device"]), 79, [],
2063    [InitEmpty, Always, TestOutputListOfDevices (
2064       [["sfdiskM"; "/dev/sda"; ","];
2065        ["pvcreate"; "/dev/sda1"];
2066        ["vgcreate"; "VG"; "/dev/sda1"];
2067        ["lvcreate"; "LV1"; "VG"; "50"];
2068        ["lvcreate"; "LV2"; "VG"; "50"];
2069        ["vgremove"; "VG"];
2070        ["pvremove"; "/dev/sda1"];
2071        ["lvs"]], []);
2072     InitEmpty, Always, TestOutputListOfDevices (
2073       [["sfdiskM"; "/dev/sda"; ","];
2074        ["pvcreate"; "/dev/sda1"];
2075        ["vgcreate"; "VG"; "/dev/sda1"];
2076        ["lvcreate"; "LV1"; "VG"; "50"];
2077        ["lvcreate"; "LV2"; "VG"; "50"];
2078        ["vgremove"; "VG"];
2079        ["pvremove"; "/dev/sda1"];
2080        ["vgs"]], []);
2081     InitEmpty, Always, TestOutputListOfDevices (
2082       [["sfdiskM"; "/dev/sda"; ","];
2083        ["pvcreate"; "/dev/sda1"];
2084        ["vgcreate"; "VG"; "/dev/sda1"];
2085        ["lvcreate"; "LV1"; "VG"; "50"];
2086        ["lvcreate"; "LV2"; "VG"; "50"];
2087        ["vgremove"; "VG"];
2088        ["pvremove"; "/dev/sda1"];
2089        ["pvs"]], [])],
2090    "remove an LVM physical volume",
2091    "\
2092 This wipes a physical volume C<device> so that LVM will no longer
2093 recognise it.
2094
2095 The implementation uses the C<pvremove> command which refuses to
2096 wipe physical volumes that contain any volume groups, so you have
2097 to remove those first.");
2098
2099   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2100    [InitBasicFS, Always, TestOutput (
2101       [["set_e2label"; "/dev/sda1"; "testlabel"];
2102        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2103    "set the ext2/3/4 filesystem label",
2104    "\
2105 This sets the ext2/3/4 filesystem label of the filesystem on
2106 C<device> to C<label>.  Filesystem labels are limited to
2107 16 characters.
2108
2109 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2110 to return the existing label on a filesystem.");
2111
2112   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2113    [],
2114    "get the ext2/3/4 filesystem label",
2115    "\
2116 This returns the ext2/3/4 filesystem label of the filesystem on
2117 C<device>.");
2118
2119   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2120    (let uuid = uuidgen () in
2121     [InitBasicFS, Always, TestOutput (
2122        [["set_e2uuid"; "/dev/sda1"; uuid];
2123         ["get_e2uuid"; "/dev/sda1"]], uuid);
2124      InitBasicFS, Always, TestOutput (
2125        [["set_e2uuid"; "/dev/sda1"; "clear"];
2126         ["get_e2uuid"; "/dev/sda1"]], "");
2127      (* We can't predict what UUIDs will be, so just check the commands run. *)
2128      InitBasicFS, Always, TestRun (
2129        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2130      InitBasicFS, Always, TestRun (
2131        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2132    "set the ext2/3/4 filesystem UUID",
2133    "\
2134 This sets the ext2/3/4 filesystem UUID of the filesystem on
2135 C<device> to C<uuid>.  The format of the UUID and alternatives
2136 such as C<clear>, C<random> and C<time> are described in the
2137 L<tune2fs(8)> manpage.
2138
2139 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2140 to return the existing UUID of a filesystem.");
2141
2142   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2143    [],
2144    "get the ext2/3/4 filesystem UUID",
2145    "\
2146 This returns the ext2/3/4 filesystem UUID of the filesystem on
2147 C<device>.");
2148
2149   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2150    [InitBasicFS, Always, TestOutputInt (
2151       [["umount"; "/dev/sda1"];
2152        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2153     InitBasicFS, Always, TestOutputInt (
2154       [["umount"; "/dev/sda1"];
2155        ["zero"; "/dev/sda1"];
2156        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2157    "run the filesystem checker",
2158    "\
2159 This runs the filesystem checker (fsck) on C<device> which
2160 should have filesystem type C<fstype>.
2161
2162 The returned integer is the status.  See L<fsck(8)> for the
2163 list of status codes from C<fsck>.
2164
2165 Notes:
2166
2167 =over 4
2168
2169 =item *
2170
2171 Multiple status codes can be summed together.
2172
2173 =item *
2174
2175 A non-zero return code can mean \"success\", for example if
2176 errors have been corrected on the filesystem.
2177
2178 =item *
2179
2180 Checking or repairing NTFS volumes is not supported
2181 (by linux-ntfs).
2182
2183 =back
2184
2185 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2186
2187   ("zero", (RErr, [Device "device"]), 85, [],
2188    [InitBasicFS, Always, TestOutput (
2189       [["umount"; "/dev/sda1"];
2190        ["zero"; "/dev/sda1"];
2191        ["file"; "/dev/sda1"]], "data")],
2192    "write zeroes to the device",
2193    "\
2194 This command writes zeroes over the first few blocks of C<device>.
2195
2196 How many blocks are zeroed isn't specified (but it's I<not> enough
2197 to securely wipe the device).  It should be sufficient to remove
2198 any partition tables, filesystem superblocks and so on.
2199
2200 See also: C<guestfs_scrub_device>.");
2201
2202   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2203    (* Test disabled because grub-install incompatible with virtio-blk driver.
2204     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2205     *)
2206    [InitBasicFS, Disabled, TestOutputTrue (
2207       [["grub_install"; "/"; "/dev/sda1"];
2208        ["is_dir"; "/boot"]])],
2209    "install GRUB",
2210    "\
2211 This command installs GRUB (the Grand Unified Bootloader) on
2212 C<device>, with the root directory being C<root>.");
2213
2214   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2215    [InitBasicFS, Always, TestOutput (
2216       [["write_file"; "/old"; "file content"; "0"];
2217        ["cp"; "/old"; "/new"];
2218        ["cat"; "/new"]], "file content");
2219     InitBasicFS, Always, TestOutputTrue (
2220       [["write_file"; "/old"; "file content"; "0"];
2221        ["cp"; "/old"; "/new"];
2222        ["is_file"; "/old"]]);
2223     InitBasicFS, Always, TestOutput (
2224       [["write_file"; "/old"; "file content"; "0"];
2225        ["mkdir"; "/dir"];
2226        ["cp"; "/old"; "/dir/new"];
2227        ["cat"; "/dir/new"]], "file content")],
2228    "copy a file",
2229    "\
2230 This copies a file from C<src> to C<dest> where C<dest> is
2231 either a destination filename or destination directory.");
2232
2233   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2234    [InitBasicFS, Always, TestOutput (
2235       [["mkdir"; "/olddir"];
2236        ["mkdir"; "/newdir"];
2237        ["write_file"; "/olddir/file"; "file content"; "0"];
2238        ["cp_a"; "/olddir"; "/newdir"];
2239        ["cat"; "/newdir/olddir/file"]], "file content")],
2240    "copy a file or directory recursively",
2241    "\
2242 This copies a file or directory from C<src> to C<dest>
2243 recursively using the C<cp -a> command.");
2244
2245   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2246    [InitBasicFS, Always, TestOutput (
2247       [["write_file"; "/old"; "file content"; "0"];
2248        ["mv"; "/old"; "/new"];
2249        ["cat"; "/new"]], "file content");
2250     InitBasicFS, Always, TestOutputFalse (
2251       [["write_file"; "/old"; "file content"; "0"];
2252        ["mv"; "/old"; "/new"];
2253        ["is_file"; "/old"]])],
2254    "move a file",
2255    "\
2256 This moves a file from C<src> to C<dest> where C<dest> is
2257 either a destination filename or destination directory.");
2258
2259   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2260    [InitEmpty, Always, TestRun (
2261       [["drop_caches"; "3"]])],
2262    "drop kernel page cache, dentries and inodes",
2263    "\
2264 This instructs the guest kernel to drop its page cache,
2265 and/or dentries and inode caches.  The parameter C<whattodrop>
2266 tells the kernel what precisely to drop, see
2267 L<http://linux-mm.org/Drop_Caches>
2268
2269 Setting C<whattodrop> to 3 should drop everything.
2270
2271 This automatically calls L<sync(2)> before the operation,
2272 so that the maximum guest memory is freed.");
2273
2274   ("dmesg", (RString "kmsgs", []), 91, [],
2275    [InitEmpty, Always, TestRun (
2276       [["dmesg"]])],
2277    "return kernel messages",
2278    "\
2279 This returns the kernel messages (C<dmesg> output) from
2280 the guest kernel.  This is sometimes useful for extended
2281 debugging of problems.
2282
2283 Another way to get the same information is to enable
2284 verbose messages with C<guestfs_set_verbose> or by setting
2285 the environment variable C<LIBGUESTFS_DEBUG=1> before
2286 running the program.");
2287
2288   ("ping_daemon", (RErr, []), 92, [],
2289    [InitEmpty, Always, TestRun (
2290       [["ping_daemon"]])],
2291    "ping the guest daemon",
2292    "\
2293 This is a test probe into the guestfs daemon running inside
2294 the qemu subprocess.  Calling this function checks that the
2295 daemon responds to the ping message, without affecting the daemon
2296 or attached block device(s) in any other way.");
2297
2298   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2299    [InitBasicFS, Always, TestOutputTrue (
2300       [["write_file"; "/file1"; "contents of a file"; "0"];
2301        ["cp"; "/file1"; "/file2"];
2302        ["equal"; "/file1"; "/file2"]]);
2303     InitBasicFS, Always, TestOutputFalse (
2304       [["write_file"; "/file1"; "contents of a file"; "0"];
2305        ["write_file"; "/file2"; "contents of another file"; "0"];
2306        ["equal"; "/file1"; "/file2"]]);
2307     InitBasicFS, Always, TestLastFail (
2308       [["equal"; "/file1"; "/file2"]])],
2309    "test if two files have equal contents",
2310    "\
2311 This compares the two files C<file1> and C<file2> and returns
2312 true if their content is exactly equal, or false otherwise.
2313
2314 The external L<cmp(1)> program is used for the comparison.");
2315
2316   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2317    [InitISOFS, Always, TestOutputList (
2318       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2319     InitISOFS, Always, TestOutputList (
2320       [["strings"; "/empty"]], [])],
2321    "print the printable strings in a file",
2322    "\
2323 This runs the L<strings(1)> command on a file and returns
2324 the list of printable strings found.");
2325
2326   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2327    [InitISOFS, Always, TestOutputList (
2328       [["strings_e"; "b"; "/known-5"]], []);
2329     InitBasicFS, Disabled, TestOutputList (
2330       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2331        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2332    "print the printable strings in a file",
2333    "\
2334 This is like the C<guestfs_strings> command, but allows you to
2335 specify the encoding.
2336
2337 See the L<strings(1)> manpage for the full list of encodings.
2338
2339 Commonly useful encodings are C<l> (lower case L) which will
2340 show strings inside Windows/x86 files.
2341
2342 The returned strings are transcoded to UTF-8.");
2343
2344   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2345    [InitISOFS, Always, TestOutput (
2346       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2347     (* Test for RHBZ#501888c2 regression which caused large hexdump
2348      * commands to segfault.
2349      *)
2350     InitISOFS, Always, TestRun (
2351       [["hexdump"; "/100krandom"]])],
2352    "dump a file in hexadecimal",
2353    "\
2354 This runs C<hexdump -C> on the given C<path>.  The result is
2355 the human-readable, canonical hex dump of the file.");
2356
2357   ("zerofree", (RErr, [Device "device"]), 97, [],
2358    [InitNone, Always, TestOutput (
2359       [["sfdiskM"; "/dev/sda"; ","];
2360        ["mkfs"; "ext3"; "/dev/sda1"];
2361        ["mount"; "/dev/sda1"; "/"];
2362        ["write_file"; "/new"; "test file"; "0"];
2363        ["umount"; "/dev/sda1"];
2364        ["zerofree"; "/dev/sda1"];
2365        ["mount"; "/dev/sda1"; "/"];
2366        ["cat"; "/new"]], "test file")],
2367    "zero unused inodes and disk blocks on ext2/3 filesystem",
2368    "\
2369 This runs the I<zerofree> program on C<device>.  This program
2370 claims to zero unused inodes and disk blocks on an ext2/3
2371 filesystem, thus making it possible to compress the filesystem
2372 more effectively.
2373
2374 You should B<not> run this program if the filesystem is
2375 mounted.
2376
2377 It is possible that using this program can damage the filesystem
2378 or data on the filesystem.");
2379
2380   ("pvresize", (RErr, [Device "device"]), 98, [],
2381    [],
2382    "resize an LVM physical volume",
2383    "\
2384 This resizes (expands or shrinks) an existing LVM physical
2385 volume to match the new size of the underlying device.");
2386
2387   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2388                        Int "cyls"; Int "heads"; Int "sectors";
2389                        String "line"]), 99, [DangerWillRobinson],
2390    [],
2391    "modify a single partition on a block device",
2392    "\
2393 This runs L<sfdisk(8)> option to modify just the single
2394 partition C<n> (note: C<n> counts from 1).
2395
2396 For other parameters, see C<guestfs_sfdisk>.  You should usually
2397 pass C<0> for the cyls/heads/sectors parameters.");
2398
2399   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2400    [],
2401    "display the partition table",
2402    "\
2403 This displays the partition table on C<device>, in the
2404 human-readable output of the L<sfdisk(8)> command.  It is
2405 not intended to be parsed.");
2406
2407   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2408    [],
2409    "display the kernel geometry",
2410    "\
2411 This displays the kernel's idea of the geometry of C<device>.
2412
2413 The result is in human-readable format, and not designed to
2414 be parsed.");
2415
2416   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2417    [],
2418    "display the disk geometry from the partition table",
2419    "\
2420 This displays the disk geometry of C<device> read from the
2421 partition table.  Especially in the case where the underlying
2422 block device has been resized, this can be different from the
2423 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2424
2425 The result is in human-readable format, and not designed to
2426 be parsed.");
2427
2428   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2429    [],
2430    "activate or deactivate all volume groups",
2431    "\
2432 This command activates or (if C<activate> is false) deactivates
2433 all logical volumes in all volume groups.
2434 If activated, then they are made known to the
2435 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2436 then those devices disappear.
2437
2438 This command is the same as running C<vgchange -a y|n>");
2439
2440   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2441    [],
2442    "activate or deactivate some volume groups",
2443    "\
2444 This command activates or (if C<activate> is false) deactivates
2445 all logical volumes in the listed volume groups C<volgroups>.
2446 If activated, then they are made known to the
2447 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2448 then those devices disappear.
2449
2450 This command is the same as running C<vgchange -a y|n volgroups...>
2451
2452 Note that if C<volgroups> is an empty list then B<all> volume groups
2453 are activated or deactivated.");
2454
2455   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2456    [InitNone, Always, TestOutput (
2457       [["sfdiskM"; "/dev/sda"; ","];
2458        ["pvcreate"; "/dev/sda1"];
2459        ["vgcreate"; "VG"; "/dev/sda1"];
2460        ["lvcreate"; "LV"; "VG"; "10"];
2461        ["mkfs"; "ext2"; "/dev/VG/LV"];
2462        ["mount"; "/dev/VG/LV"; "/"];
2463        ["write_file"; "/new"; "test content"; "0"];
2464        ["umount"; "/"];
2465        ["lvresize"; "/dev/VG/LV"; "20"];
2466        ["e2fsck_f"; "/dev/VG/LV"];
2467        ["resize2fs"; "/dev/VG/LV"];
2468        ["mount"; "/dev/VG/LV"; "/"];
2469        ["cat"; "/new"]], "test content")],
2470    "resize an LVM logical volume",
2471    "\
2472 This resizes (expands or shrinks) an existing LVM logical
2473 volume to C<mbytes>.  When reducing, data in the reduced part
2474 is lost.");
2475
2476   ("resize2fs", (RErr, [Device "device"]), 106, [],
2477    [], (* lvresize tests this *)
2478    "resize an ext2/ext3 filesystem",
2479    "\
2480 This resizes an ext2 or ext3 filesystem to match the size of
2481 the underlying device.
2482
2483 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2484 on the C<device> before calling this command.  For unknown reasons
2485 C<resize2fs> sometimes gives an error about this and sometimes not.
2486 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2487 calling this function.");
2488
2489   ("find", (RStringList "names", [Pathname "directory"]), 107, [],
2490    [InitBasicFS, Always, TestOutputList (
2491       [["find"; "/"]], ["lost+found"]);
2492     InitBasicFS, Always, TestOutputList (
2493       [["touch"; "/a"];
2494        ["mkdir"; "/b"];
2495        ["touch"; "/b/c"];
2496        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2497     InitBasicFS, Always, TestOutputList (
2498       [["mkdir_p"; "/a/b/c"];
2499        ["touch"; "/a/b/c/d"];
2500        ["find"; "/a/b/"]], ["c"; "c/d"])],
2501    "find all files and directories",
2502    "\
2503 This command lists out all files and directories, recursively,
2504 starting at C<directory>.  It is essentially equivalent to
2505 running the shell command C<find directory -print> but some
2506 post-processing happens on the output, described below.
2507
2508 This returns a list of strings I<without any prefix>.  Thus
2509 if the directory structure was:
2510
2511  /tmp/a
2512  /tmp/b
2513  /tmp/c/d
2514
2515 then the returned list from C<guestfs_find> C</tmp> would be
2516 4 elements:
2517
2518  a
2519  b
2520  c
2521  c/d
2522
2523 If C<directory> is not a directory, then this command returns
2524 an error.
2525
2526 The returned list is sorted.");
2527
2528   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2529    [], (* lvresize tests this *)
2530    "check an ext2/ext3 filesystem",
2531    "\
2532 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2533 filesystem checker on C<device>, noninteractively (C<-p>),
2534 even if the filesystem appears to be clean (C<-f>).
2535
2536 This command is only needed because of C<guestfs_resize2fs>
2537 (q.v.).  Normally you should use C<guestfs_fsck>.");
2538
2539   ("sleep", (RErr, [Int "secs"]), 109, [],
2540    [InitNone, Always, TestRun (
2541       [["sleep"; "1"]])],
2542    "sleep for some seconds",
2543    "\
2544 Sleep for C<secs> seconds.");
2545
2546   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2547    [InitNone, Always, TestOutputInt (
2548       [["sfdiskM"; "/dev/sda"; ","];
2549        ["mkfs"; "ntfs"; "/dev/sda1"];
2550        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2551     InitNone, Always, TestOutputInt (
2552       [["sfdiskM"; "/dev/sda"; ","];
2553        ["mkfs"; "ext2"; "/dev/sda1"];
2554        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2555    "probe NTFS volume",
2556    "\
2557 This command runs the L<ntfs-3g.probe(8)> command which probes
2558 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2559 be mounted read-write, and some cannot be mounted at all).
2560
2561 C<rw> is a boolean flag.  Set it to true if you want to test
2562 if the volume can be mounted read-write.  Set it to false if
2563 you want to test if the volume can be mounted read-only.
2564
2565 The return value is an integer which C<0> if the operation
2566 would succeed, or some non-zero value documented in the
2567 L<ntfs-3g.probe(8)> manual page.");
2568
2569   ("sh", (RString "output", [String "command"]), 111, [],
2570    [], (* XXX needs tests *)
2571    "run a command via the shell",
2572    "\
2573 This call runs a command from the guest filesystem via the
2574 guest's C</bin/sh>.
2575
2576 This is like C<guestfs_command>, but passes the command to:
2577
2578  /bin/sh -c \"command\"
2579
2580 Depending on the guest's shell, this usually results in
2581 wildcards being expanded, shell expressions being interpolated
2582 and so on.
2583
2584 All the provisos about C<guestfs_command> apply to this call.");
2585
2586   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2587    [], (* XXX needs tests *)
2588    "run a command via the shell returning lines",
2589    "\
2590 This is the same as C<guestfs_sh>, but splits the result
2591 into a list of lines.
2592
2593 See also: C<guestfs_command_lines>");
2594
2595   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2596    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2597     * code in stubs.c, since all valid glob patterns must start with "/".
2598     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2599     *)
2600    [InitBasicFS, Always, TestOutputList (
2601       [["mkdir_p"; "/a/b/c"];
2602        ["touch"; "/a/b/c/d"];
2603        ["touch"; "/a/b/c/e"];
2604        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2605     InitBasicFS, Always, TestOutputList (
2606       [["mkdir_p"; "/a/b/c"];
2607        ["touch"; "/a/b/c/d"];
2608        ["touch"; "/a/b/c/e"];
2609        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2610     InitBasicFS, Always, TestOutputList (
2611       [["mkdir_p"; "/a/b/c"];
2612        ["touch"; "/a/b/c/d"];
2613        ["touch"; "/a/b/c/e"];
2614        ["glob_expand"; "/a/*/x/*"]], [])],
2615    "expand a wildcard path",
2616    "\
2617 This command searches for all the pathnames matching
2618 C<pattern> according to the wildcard expansion rules
2619 used by the shell.
2620
2621 If no paths match, then this returns an empty list
2622 (note: not an error).
2623
2624 It is just a wrapper around the C L<glob(3)> function
2625 with flags C<GLOB_MARK|GLOB_BRACE>.
2626 See that manual page for more details.");
2627
2628   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2629    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2630       [["scrub_device"; "/dev/sdc"]])],
2631    "scrub (securely wipe) a device",
2632    "\
2633 This command writes patterns over C<device> to make data retrieval
2634 more difficult.
2635
2636 It is an interface to the L<scrub(1)> program.  See that
2637 manual page for more details.");
2638
2639   ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2640    [InitBasicFS, Always, TestRun (
2641       [["write_file"; "/file"; "content"; "0"];
2642        ["scrub_file"; "/file"]])],
2643    "scrub (securely wipe) a file",
2644    "\
2645 This command writes patterns over a file to make data retrieval
2646 more difficult.
2647
2648 The file is I<removed> after scrubbing.
2649
2650 It is an interface to the L<scrub(1)> program.  See that
2651 manual page for more details.");
2652
2653   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2654    [], (* XXX needs testing *)
2655    "scrub (securely wipe) free space",
2656    "\
2657 This command creates the directory C<dir> and then fills it
2658 with files until the filesystem is full, and scrubs the files
2659 as for C<guestfs_scrub_file>, and deletes them.
2660 The intention is to scrub any free space on the partition
2661 containing C<dir>.
2662
2663 It is an interface to the L<scrub(1)> program.  See that
2664 manual page for more details.");
2665
2666   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2667    [InitBasicFS, Always, TestRun (
2668       [["mkdir"; "/tmp"];
2669        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2670    "create a temporary directory",
2671    "\
2672 This command creates a temporary directory.  The
2673 C<template> parameter should be a full pathname for the
2674 temporary directory name with the final six characters being
2675 \"XXXXXX\".
2676
2677 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2678 the second one being suitable for Windows filesystems.
2679
2680 The name of the temporary directory that was created
2681 is returned.
2682
2683 The temporary directory is created with mode 0700
2684 and is owned by root.
2685
2686 The caller is responsible for deleting the temporary
2687 directory and its contents after use.
2688
2689 See also: L<mkdtemp(3)>");
2690
2691   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2692    [InitISOFS, Always, TestOutputInt (
2693       [["wc_l"; "/10klines"]], 10000)],
2694    "count lines in a file",
2695    "\
2696 This command counts the lines in a file, using the
2697 C<wc -l> external command.");
2698
2699   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2700    [InitISOFS, Always, TestOutputInt (
2701       [["wc_w"; "/10klines"]], 10000)],
2702    "count words in a file",
2703    "\
2704 This command counts the words in a file, using the
2705 C<wc -w> external command.");
2706
2707   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2708    [InitISOFS, Always, TestOutputInt (
2709       [["wc_c"; "/100kallspaces"]], 102400)],
2710    "count characters in a file",
2711    "\
2712 This command counts the characters in a file, using the
2713 C<wc -c> external command.");
2714
2715   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2716    [InitISOFS, Always, TestOutputList (
2717       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2718    "return first 10 lines of a file",
2719    "\
2720 This command returns up to the first 10 lines of a file as
2721 a list of strings.");
2722
2723   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2724    [InitISOFS, Always, TestOutputList (
2725       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2726     InitISOFS, Always, TestOutputList (
2727       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2728     InitISOFS, Always, TestOutputList (
2729       [["head_n"; "0"; "/10klines"]], [])],
2730    "return first N lines of a file",
2731    "\
2732 If the parameter C<nrlines> is a positive number, this returns the first
2733 C<nrlines> lines of the file C<path>.
2734
2735 If the parameter C<nrlines> is a negative number, this returns lines
2736 from the file C<path>, excluding the last C<nrlines> lines.
2737
2738 If the parameter C<nrlines> is zero, this returns an empty list.");
2739
2740   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2741    [InitISOFS, Always, TestOutputList (
2742       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2743    "return last 10 lines of a file",
2744    "\
2745 This command returns up to the last 10 lines of a file as
2746 a list of strings.");
2747
2748   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2749    [InitISOFS, Always, TestOutputList (
2750       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2751     InitISOFS, Always, TestOutputList (
2752       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2753     InitISOFS, Always, TestOutputList (
2754       [["tail_n"; "0"; "/10klines"]], [])],
2755    "return last N lines of a file",
2756    "\
2757 If the parameter C<nrlines> is a positive number, this returns the last
2758 C<nrlines> lines of the file C<path>.
2759
2760 If the parameter C<nrlines> is a negative number, this returns lines
2761 from the file C<path>, starting with the C<-nrlines>th line.
2762
2763 If the parameter C<nrlines> is zero, this returns an empty list.");
2764
2765   ("df", (RString "output", []), 125, [],
2766    [], (* XXX Tricky to test because it depends on the exact format
2767         * of the 'df' command and other imponderables.
2768         *)
2769    "report file system disk space usage",
2770    "\
2771 This command runs the C<df> command to report disk space used.
2772
2773 This command is mostly useful for interactive sessions.  It
2774 is I<not> intended that you try to parse the output string.
2775 Use C<statvfs> from programs.");
2776
2777   ("df_h", (RString "output", []), 126, [],
2778    [], (* XXX Tricky to test because it depends on the exact format
2779         * of the 'df' command and other imponderables.
2780         *)
2781    "report file system disk space usage (human readable)",
2782    "\
2783 This command runs the C<df -h> command to report disk space used
2784 in human-readable format.
2785
2786 This command is mostly useful for interactive sessions.  It
2787 is I<not> intended that you try to parse the output string.
2788 Use C<statvfs> from programs.");
2789
2790   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2791    [InitISOFS, Always, TestOutputInt (
2792       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2793    "estimate file space usage",
2794    "\
2795 This command runs the C<du -s> command to estimate file space
2796 usage for C<path>.
2797
2798 C<path> can be a file or a directory.  If C<path> is a directory
2799 then the estimate includes the contents of the directory and all
2800 subdirectories (recursively).
2801
2802 The result is the estimated size in I<kilobytes>
2803 (ie. units of 1024 bytes).");
2804
2805   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2806    [InitISOFS, Always, TestOutputList (
2807       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2808    "list files in an initrd",
2809    "\
2810 This command lists out files contained in an initrd.
2811
2812 The files are listed without any initial C</> character.  The
2813 files are listed in the order they appear (not necessarily
2814 alphabetical).  Directory names are listed as separate items.
2815
2816 Old Linux kernels (2.4 and earlier) used a compressed ext2
2817 filesystem as initrd.  We I<only> support the newer initramfs
2818 format (compressed cpio files).");
2819
2820   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2821    [],
2822    "mount a file using the loop device",
2823    "\
2824 This command lets you mount C<file> (a filesystem image
2825 in a file) on a mount point.  It is entirely equivalent to
2826 the command C<mount -o loop file mountpoint>.");
2827
2828   ("mkswap", (RErr, [Device "device"]), 130, [],
2829    [InitEmpty, Always, TestRun (
2830       [["sfdiskM"; "/dev/sda"; ","];
2831        ["mkswap"; "/dev/sda1"]])],
2832    "create a swap partition",
2833    "\
2834 Create a swap partition on C<device>.");
2835
2836   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2837    [InitEmpty, Always, TestRun (
2838       [["sfdiskM"; "/dev/sda"; ","];
2839        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2840    "create a swap partition with a label",
2841    "\
2842 Create a swap partition on C<device> with label C<label>.
2843
2844 Note that you cannot attach a swap label to a block device
2845 (eg. C</dev/sda>), just to a partition.  This appears to be
2846 a limitation of the kernel or swap tools.");
2847
2848   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2849    (let uuid = uuidgen () in
2850     [InitEmpty, Always, TestRun (
2851        [["sfdiskM"; "/dev/sda"; ","];
2852         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2853    "create a swap partition with an explicit UUID",
2854    "\
2855 Create a swap partition on C<device> with UUID C<uuid>.");
2856
2857   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2858    [InitBasicFS, Always, TestOutputStruct (
2859       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2860        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2861        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2862     InitBasicFS, Always, TestOutputStruct (
2863       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2864        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2865    "make block, character or FIFO devices",
2866    "\
2867 This call creates block or character special devices, or
2868 named pipes (FIFOs).
2869
2870 The C<mode> parameter should be the mode, using the standard
2871 constants.  C<devmajor> and C<devminor> are the
2872 device major and minor numbers, only used when creating block
2873 and character special devices.");
2874
2875   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2876    [InitBasicFS, Always, TestOutputStruct (
2877       [["mkfifo"; "0o777"; "/node"];
2878        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2879    "make FIFO (named pipe)",
2880    "\
2881 This call creates a FIFO (named pipe) called C<path> with
2882 mode C<mode>.  It is just a convenient wrapper around
2883 C<guestfs_mknod>.");
2884
2885   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2886    [InitBasicFS, Always, TestOutputStruct (
2887       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2888        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2889    "make block device node",
2890    "\
2891 This call creates a block device node called C<path> with
2892 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2893 It is just a convenient wrapper around C<guestfs_mknod>.");
2894
2895   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2896    [InitBasicFS, Always, TestOutputStruct (
2897       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2898        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2899    "make char device node",
2900    "\
2901 This call creates a char device node called C<path> with
2902 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2903 It is just a convenient wrapper around C<guestfs_mknod>.");
2904
2905   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2906    [], (* XXX umask is one of those stateful things that we should
2907         * reset between each test.
2908         *)
2909    "set file mode creation mask (umask)",
2910    "\
2911 This function sets the mask used for creating new files and
2912 device nodes to C<mask & 0777>.
2913
2914 Typical umask values would be C<022> which creates new files
2915 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2916 C<002> which creates new files with permissions like
2917 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2918
2919 The default umask is C<022>.  This is important because it
2920 means that directories and device nodes will be created with
2921 C<0644> or C<0755> mode even if you specify C<0777>.
2922
2923 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2924
2925 This call returns the previous umask.");
2926
2927   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2928    [],
2929    "read directories entries",
2930    "\
2931 This returns the list of directory entries in directory C<dir>.
2932
2933 All entries in the directory are returned, including C<.> and
2934 C<..>.  The entries are I<not> sorted, but returned in the same
2935 order as the underlying filesystem.
2936
2937 Also this call returns basic file type information about each
2938 file.  The C<ftyp> field will contain one of the following characters:
2939
2940 =over 4
2941
2942 =item 'b'
2943
2944 Block special
2945
2946 =item 'c'
2947
2948 Char special
2949
2950 =item 'd'
2951
2952 Directory
2953
2954 =item 'f'
2955
2956 FIFO (named pipe)
2957
2958 =item 'l'
2959
2960 Symbolic link
2961
2962 =item 'r'
2963
2964 Regular file
2965
2966 =item 's'
2967
2968 Socket
2969
2970 =item 'u'
2971
2972 Unknown file type
2973
2974 =item '?'
2975
2976 The L<readdir(3)> returned a C<d_type> field with an
2977 unexpected value
2978
2979 =back
2980
2981 This function is primarily intended for use by programs.  To
2982 get a simple list of names, use C<guestfs_ls>.  To get a printable
2983 directory for human consumption, use C<guestfs_ll>.");
2984
2985   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
2986    [],
2987    "create partitions on a block device",
2988    "\
2989 This is a simplified interface to the C<guestfs_sfdisk>
2990 command, where partition sizes are specified in megabytes
2991 only (rounded to the nearest cylinder) and you don't need
2992 to specify the cyls, heads and sectors parameters which
2993 were rarely if ever used anyway.
2994
2995 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
2996
2997   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
2998    [],
2999    "determine file type inside a compressed file",
3000    "\
3001 This command runs C<file> after first decompressing C<path>
3002 using C<method>.
3003
3004 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3005
3006 Since 1.0.63, use C<guestfs_file> instead which can now
3007 process compressed files.");
3008
3009   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
3010    [],
3011    "list extended attributes of a file or directory",
3012    "\
3013 This call lists the extended attributes of the file or directory
3014 C<path>.
3015
3016 At the system call level, this is a combination of the
3017 L<listxattr(2)> and L<getxattr(2)> calls.
3018
3019 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3020
3021   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
3022    [],
3023    "list extended attributes of a file or directory",
3024    "\
3025 This is the same as C<guestfs_getxattrs>, but if C<path>
3026 is a symbolic link, then it returns the extended attributes
3027 of the link itself.");
3028
3029   ("setxattr", (RErr, [String "xattr";
3030                        String "val"; Int "vallen"; (* will be BufferIn *)
3031                        Pathname "path"]), 143, [],
3032    [],
3033    "set extended attribute of a file or directory",
3034    "\
3035 This call sets the extended attribute named C<xattr>
3036 of the file C<path> to the value C<val> (of length C<vallen>).
3037 The value is arbitrary 8 bit data.
3038
3039 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3040
3041   ("lsetxattr", (RErr, [String "xattr";
3042                         String "val"; Int "vallen"; (* will be BufferIn *)
3043                         Pathname "path"]), 144, [],
3044    [],
3045    "set extended attribute of a file or directory",
3046    "\
3047 This is the same as C<guestfs_setxattr>, but if C<path>
3048 is a symbolic link, then it sets an extended attribute
3049 of the link itself.");
3050
3051   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3052    [],
3053    "remove extended attribute of a file or directory",
3054    "\
3055 This call removes the extended attribute named C<xattr>
3056 of the file C<path>.
3057
3058 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3059
3060   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3061    [],
3062    "remove extended attribute of a file or directory",
3063    "\
3064 This is the same as C<guestfs_removexattr>, but if C<path>
3065 is a symbolic link, then it removes an extended attribute
3066 of the link itself.");
3067
3068   ("mountpoints", (RHashtable "mps", []), 147, [],
3069    [],
3070    "show mountpoints",
3071    "\
3072 This call is similar to C<guestfs_mounts>.  That call returns
3073 a list of devices.  This one returns a hash table (map) of
3074 device name to directory where the device is mounted.");
3075
3076   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3077   (* This is a special case: while you would expect a parameter
3078    * of type "Pathname", that doesn't work, because it implies
3079    * NEED_ROOT in the generated calling code in stubs.c, and
3080    * this function cannot use NEED_ROOT.
3081    *)
3082    [],
3083    "create a mountpoint",
3084    "\
3085 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3086 specialized calls that can be used to create extra mountpoints
3087 before mounting the first filesystem.
3088
3089 These calls are I<only> necessary in some very limited circumstances,
3090 mainly the case where you want to mount a mix of unrelated and/or
3091 read-only filesystems together.
3092
3093 For example, live CDs often contain a \"Russian doll\" nest of
3094 filesystems, an ISO outer layer, with a squashfs image inside, with
3095 an ext2/3 image inside that.  You can unpack this as follows
3096 in guestfish:
3097
3098  add-ro Fedora-11-i686-Live.iso
3099  run
3100  mkmountpoint /cd
3101  mkmountpoint /squash
3102  mkmountpoint /ext3
3103  mount /dev/sda /cd
3104  mount-loop /cd/LiveOS/squashfs.img /squash
3105  mount-loop /squash/LiveOS/ext3fs.img /ext3
3106
3107 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3108
3109   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3110    [],
3111    "remove a mountpoint",
3112    "\
3113 This calls removes a mountpoint that was previously created
3114 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3115 for full details.");
3116
3117   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3118    [InitISOFS, Always, TestOutputBuffer (
3119       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3120    "read a file",
3121    "\
3122 This calls returns the contents of the file C<path> as a
3123 buffer.
3124
3125 Unlike C<guestfs_cat>, this function can correctly
3126 handle files that contain embedded ASCII NUL characters.
3127 However unlike C<guestfs_download>, this function is limited
3128 in the total size of file that can be handled.");
3129
3130   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3131    [InitISOFS, Always, TestOutputList (
3132       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3133     InitISOFS, Always, TestOutputList (
3134       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3135    "return lines matching a pattern",
3136    "\
3137 This calls the external C<grep> program and returns the
3138 matching lines.");
3139
3140   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3141    [InitISOFS, Always, TestOutputList (
3142       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3143    "return lines matching a pattern",
3144    "\
3145 This calls the external C<egrep> program and returns the
3146 matching lines.");
3147
3148   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3149    [InitISOFS, Always, TestOutputList (
3150       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3151    "return lines matching a pattern",
3152    "\
3153 This calls the external C<fgrep> program and returns the
3154 matching lines.");
3155
3156   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3157    [InitISOFS, Always, TestOutputList (
3158       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3159    "return lines matching a pattern",
3160    "\
3161 This calls the external C<grep -i> program and returns the
3162 matching lines.");
3163
3164   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3165    [InitISOFS, Always, TestOutputList (
3166       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3167    "return lines matching a pattern",
3168    "\
3169 This calls the external C<egrep -i> program and returns the
3170 matching lines.");
3171
3172   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3173    [InitISOFS, Always, TestOutputList (
3174       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3175    "return lines matching a pattern",
3176    "\
3177 This calls the external C<fgrep -i> program and returns the
3178 matching lines.");
3179
3180   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3181    [InitISOFS, Always, TestOutputList (
3182       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3183    "return lines matching a pattern",
3184    "\
3185 This calls the external C<zgrep> program and returns the
3186 matching lines.");
3187
3188   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3189    [InitISOFS, Always, TestOutputList (
3190       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3191    "return lines matching a pattern",
3192    "\
3193 This calls the external C<zegrep> program and returns the
3194 matching lines.");
3195
3196   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3197    [InitISOFS, Always, TestOutputList (
3198       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3199    "return lines matching a pattern",
3200    "\
3201 This calls the external C<zfgrep> program and returns the
3202 matching lines.");
3203
3204   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3205    [InitISOFS, Always, TestOutputList (
3206       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3207    "return lines matching a pattern",
3208    "\
3209 This calls the external C<zgrep -i> program and returns the
3210 matching lines.");
3211
3212   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3213    [InitISOFS, Always, TestOutputList (
3214       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3215    "return lines matching a pattern",
3216    "\
3217 This calls the external C<zegrep -i> program and returns the
3218 matching lines.");
3219
3220   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3221    [InitISOFS, Always, TestOutputList (
3222       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3223    "return lines matching a pattern",
3224    "\
3225 This calls the external C<zfgrep -i> program and returns the
3226 matching lines.");
3227
3228   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3229    [InitISOFS, Always, TestOutput (
3230       [["realpath"; "/../directory"]], "/directory")],
3231    "canonicalized absolute pathname",
3232    "\
3233 Return the canonicalized absolute pathname of C<path>.  The
3234 returned path has no C<.>, C<..> or symbolic link path elements.");
3235
3236   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3237    [InitBasicFS, Always, TestOutputStruct (
3238       [["touch"; "/a"];
3239        ["ln"; "/a"; "/b"];
3240        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3241    "create a hard link",
3242    "\
3243 This command creates a hard link using the C<ln> command.");
3244
3245   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3246    [InitBasicFS, Always, TestOutputStruct (
3247       [["touch"; "/a"];
3248        ["touch"; "/b"];
3249        ["ln_f"; "/a"; "/b"];
3250        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3251    "create a hard link",
3252    "\
3253 This command creates a hard link using the C<ln -f> command.
3254 The C<-f> option removes the link (C<linkname>) if it exists already.");
3255
3256   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3257    [InitBasicFS, Always, TestOutputStruct (
3258       [["touch"; "/a"];
3259        ["ln_s"; "a"; "/b"];
3260        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3261    "create a symbolic link",
3262    "\
3263 This command creates a symbolic link using the C<ln -s> command.");
3264
3265   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3266    [InitBasicFS, Always, TestOutput (
3267       [["mkdir_p"; "/a/b"];
3268        ["touch"; "/a/b/c"];
3269        ["ln_sf"; "../d"; "/a/b/c"];
3270        ["readlink"; "/a/b/c"]], "../d")],
3271    "create a symbolic link",
3272    "\
3273 This command creates a symbolic link using the C<ln -sf> command,
3274 The C<-f> option removes the link (C<linkname>) if it exists already.");
3275
3276   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3277    [] (* XXX tested above *),
3278    "read the target of a symbolic link",
3279    "\
3280 This command reads the target of a symbolic link.");
3281
3282   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3283    [InitBasicFS, Always, TestOutputStruct (
3284       [["fallocate"; "/a"; "1000000"];
3285        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3286    "preallocate a file in the guest filesystem",
3287    "\
3288 This command preallocates a file (containing zero bytes) named
3289 C<path> of size C<len> bytes.  If the file exists already, it
3290 is overwritten.
3291
3292 Do not confuse this with the guestfish-specific
3293 C<alloc> command which allocates a file in the host and
3294 attaches it as a device.");
3295
3296   ("swapon_device", (RErr, [Device "device"]), 170, [],
3297    [InitPartition, Always, TestRun (
3298       [["mkswap"; "/dev/sda1"];
3299        ["swapon_device"; "/dev/sda1"];
3300        ["swapoff_device"; "/dev/sda1"]])],
3301    "enable swap on device",
3302    "\
3303 This command enables the libguestfs appliance to use the
3304 swap device or partition named C<device>.  The increased
3305 memory is made available for all commands, for example
3306 those run using C<guestfs_command> or C<guestfs_sh>.
3307
3308 Note that you should not swap to existing guest swap
3309 partitions unless you know what you are doing.  They may
3310 contain hibernation information, or other information that
3311 the guest doesn't want you to trash.  You also risk leaking
3312 information about the host to the guest this way.  Instead,
3313 attach a new host device to the guest and swap on that.");
3314
3315   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3316    [], (* XXX tested by swapon_device *)
3317    "disable swap on device",
3318    "\
3319 This command disables the libguestfs appliance swap
3320 device or partition named C<device>.
3321 See C<guestfs_swapon_device>.");
3322
3323   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3324    [InitBasicFS, Always, TestRun (
3325       [["fallocate"; "/swap"; "8388608"];
3326        ["mkswap_file"; "/swap"];
3327        ["swapon_file"; "/swap"];
3328        ["swapoff_file"; "/swap"]])],
3329    "enable swap on file",
3330    "\
3331 This command enables swap to a file.
3332 See C<guestfs_swapon_device> for other notes.");
3333
3334   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3335    [], (* XXX tested by swapon_file *)
3336    "disable swap on file",
3337    "\
3338 This command disables the libguestfs appliance swap on file.");
3339
3340   ("swapon_label", (RErr, [String "label"]), 174, [],
3341    [InitEmpty, Always, TestRun (
3342       [["sfdiskM"; "/dev/sdb"; ","];
3343        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3344        ["swapon_label"; "swapit"];
3345        ["swapoff_label"; "swapit"];
3346        ["zero"; "/dev/sdb"];
3347        ["blockdev_rereadpt"; "/dev/sdb"]])],
3348    "enable swap on labeled swap partition",
3349    "\
3350 This command enables swap to a labeled swap partition.
3351 See C<guestfs_swapon_device> for other notes.");
3352
3353   ("swapoff_label", (RErr, [String "label"]), 175, [],
3354    [], (* XXX tested by swapon_label *)
3355    "disable swap on labeled swap partition",
3356    "\
3357 This command disables the libguestfs appliance swap on
3358 labeled swap partition.");
3359
3360   ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3361    (let uuid = uuidgen () in
3362     [InitEmpty, Always, TestRun (
3363        [["mkswap_U"; uuid; "/dev/sdb"];
3364         ["swapon_uuid"; uuid];
3365         ["swapoff_uuid"; uuid]])]),
3366    "enable swap on swap partition by UUID",
3367    "\
3368 This command enables swap to a swap partition with the given UUID.
3369 See C<guestfs_swapon_device> for other notes.");
3370
3371   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3372    [], (* XXX tested by swapon_uuid *)
3373    "disable swap on swap partition by UUID",
3374    "\
3375 This command disables the libguestfs appliance swap partition
3376 with the given UUID.");
3377
3378   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3379    [InitBasicFS, Always, TestRun (
3380       [["fallocate"; "/swap"; "8388608"];
3381        ["mkswap_file"; "/swap"]])],
3382    "create a swap file",
3383    "\
3384 Create a swap file.
3385
3386 This command just writes a swap file signature to an existing
3387 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3388
3389   ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3390    [InitISOFS, Always, TestRun (
3391       [["inotify_init"; "0"]])],
3392    "create an inotify handle",
3393    "\
3394 This command creates a new inotify handle.
3395 The inotify subsystem can be used to notify events which happen to
3396 objects in the guest filesystem.
3397
3398 C<maxevents> is the maximum number of events which will be
3399 queued up between calls to C<guestfs_inotify_read> or
3400 C<guestfs_inotify_files>.
3401 If this is passed as C<0>, then the kernel (or previously set)
3402 default is used.  For Linux 2.6.29 the default was 16384 events.
3403 Beyond this limit, the kernel throws away events, but records
3404 the fact that it threw them away by setting a flag
3405 C<IN_Q_OVERFLOW> in the returned structure list (see
3406 C<guestfs_inotify_read>).
3407
3408 Before any events are generated, you have to add some
3409 watches to the internal watch list.  See:
3410 C<guestfs_inotify_add_watch>,
3411 C<guestfs_inotify_rm_watch> and
3412 C<guestfs_inotify_watch_all>.
3413
3414 Queued up events should be read periodically by calling
3415 C<guestfs_inotify_read>
3416 (or C<guestfs_inotify_files> which is just a helpful
3417 wrapper around C<guestfs_inotify_read>).  If you don't
3418 read the events out often enough then you risk the internal
3419 queue overflowing.
3420
3421 The handle should be closed after use by calling
3422 C<guestfs_inotify_close>.  This also removes any
3423 watches automatically.
3424
3425 See also L<inotify(7)> for an overview of the inotify interface
3426 as exposed by the Linux kernel, which is roughly what we expose
3427 via libguestfs.  Note that there is one global inotify handle
3428 per libguestfs instance.");
3429
3430   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3431    [InitBasicFS, Always, TestOutputList (
3432       [["inotify_init"; "0"];
3433        ["inotify_add_watch"; "/"; "1073741823"];
3434        ["touch"; "/a"];
3435        ["touch"; "/b"];
3436        ["inotify_files"]], ["a"; "b"])],
3437    "add an inotify watch",
3438    "\
3439 Watch C<path> for the events listed in C<mask>.
3440
3441 Note that if C<path> is a directory then events within that
3442 directory are watched, but this does I<not> happen recursively
3443 (in subdirectories).
3444
3445 Note for non-C or non-Linux callers: the inotify events are
3446 defined by the Linux kernel ABI and are listed in
3447 C</usr/include/sys/inotify.h>.");
3448
3449   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3450    [],
3451    "remove an inotify watch",
3452    "\
3453 Remove a previously defined inotify watch.
3454 See C<guestfs_inotify_add_watch>.");
3455
3456   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3457    [],
3458    "return list of inotify events",
3459    "\
3460 Return the complete queue of events that have happened
3461 since the previous read call.
3462
3463 If no events have happened, this returns an empty list.
3464
3465 I<Note>: In order to make sure that all events have been
3466 read, you must call this function repeatedly until it
3467 returns an empty list.  The reason is that the call will
3468 read events up to the maximum appliance-to-host message
3469 size and leave remaining events in the queue.");
3470
3471   ("inotify_files", (RStringList "paths", []), 183, [],
3472    [],
3473    "return list of watched files that had events",
3474    "\
3475 This function is a helpful wrapper around C<guestfs_inotify_read>
3476 which just returns a list of pathnames of objects that were
3477 touched.  The returned pathnames are sorted and deduplicated.");
3478
3479   ("inotify_close", (RErr, []), 184, [],
3480    [],
3481    "close the inotify handle",
3482    "\
3483 This closes the inotify handle which was previously
3484 opened by inotify_init.  It removes all watches, throws
3485 away any pending events, and deallocates all resources.");
3486
3487   ("setcon", (RErr, [String "context"]), 185, [],
3488    [],
3489    "set SELinux security context",
3490    "\
3491 This sets the SELinux security context of the daemon
3492 to the string C<context>.
3493
3494 See the documentation about SELINUX in L<guestfs(3)>.");
3495
3496   ("getcon", (RString "context", []), 186, [],
3497    [],
3498    "get SELinux security context",
3499    "\
3500 This gets the SELinux security context of the daemon.
3501
3502 See the documentation about SELINUX in L<guestfs(3)>,
3503 and C<guestfs_setcon>");
3504
3505   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3506    [InitEmpty, Always, TestOutput (
3507       [["sfdiskM"; "/dev/sda"; ","];
3508        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3509        ["mount"; "/dev/sda1"; "/"];
3510        ["write_file"; "/new"; "new file contents"; "0"];
3511        ["cat"; "/new"]], "new file contents")],
3512    "make a filesystem with block size",
3513    "\
3514 This call is similar to C<guestfs_mkfs>, but it allows you to
3515 control the block size of the resulting filesystem.  Supported
3516 block sizes depend on the filesystem type, but typically they
3517 are C<1024>, C<2048> or C<4096> only.");
3518
3519   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3520    [InitEmpty, Always, TestOutput (
3521       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3522        ["mke2journal"; "4096"; "/dev/sda1"];
3523        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3524        ["mount"; "/dev/sda2"; "/"];
3525        ["write_file"; "/new"; "new file contents"; "0"];
3526        ["cat"; "/new"]], "new file contents")],
3527    "make ext2/3/4 external journal",
3528    "\
3529 This creates an ext2 external journal on C<device>.  It is equivalent
3530 to the command:
3531
3532  mke2fs -O journal_dev -b blocksize device");
3533
3534   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3535    [InitEmpty, Always, TestOutput (
3536       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3537        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3538        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3539        ["mount"; "/dev/sda2"; "/"];
3540        ["write_file"; "/new"; "new file contents"; "0"];
3541        ["cat"; "/new"]], "new file contents")],
3542    "make ext2/3/4 external journal with label",
3543    "\
3544 This creates an ext2 external journal on C<device> with label C<label>.");
3545
3546   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3547    (let uuid = uuidgen () in
3548     [InitEmpty, Always, TestOutput (
3549        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3550         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3551         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3552         ["mount"; "/dev/sda2"; "/"];
3553         ["write_file"; "/new"; "new file contents"; "0"];
3554         ["cat"; "/new"]], "new file contents")]),
3555    "make ext2/3/4 external journal with UUID",
3556    "\
3557 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3558
3559   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3560    [],
3561    "make ext2/3/4 filesystem with external journal",
3562    "\
3563 This creates an ext2/3/4 filesystem on C<device> with
3564 an external journal on C<journal>.  It is equivalent
3565 to the command:
3566
3567  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3568
3569 See also C<guestfs_mke2journal>.");
3570
3571   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3572    [],
3573    "make ext2/3/4 filesystem with external journal",
3574    "\
3575 This creates an ext2/3/4 filesystem on C<device> with
3576 an external journal on the journal labeled C<label>.
3577
3578 See also C<guestfs_mke2journal_L>.");
3579
3580   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3581    [],
3582    "make ext2/3/4 filesystem with external journal",
3583    "\
3584 This creates an ext2/3/4 filesystem on C<device> with
3585 an external journal on the journal with UUID C<uuid>.
3586
3587 See also C<guestfs_mke2journal_U>.");
3588
3589   ("modprobe", (RErr, [String "modulename"]), 194, [],
3590    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3591    "load a kernel module",
3592    "\
3593 This loads a kernel module in the appliance.
3594
3595 The kernel module must have been whitelisted when libguestfs
3596 was built (see C<appliance/kmod.whitelist.in> in the source).");
3597
3598   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3599    [InitNone, Always, TestOutput (
3600      [["echo_daemon"; "This is a test"]], "This is a test"
3601    )],
3602    "echo arguments back to the client",
3603    "\
3604 This command concatenate the list of C<words> passed with single spaces between
3605 them and returns the resulting string.
3606
3607 You can use this command to test the connection through to the daemon.
3608
3609 See also C<guestfs_ping_daemon>.");
3610
3611 ]
3612
3613 let all_functions = non_daemon_functions @ daemon_functions
3614
3615 (* In some places we want the functions to be displayed sorted
3616  * alphabetically, so this is useful:
3617  *)
3618 let all_functions_sorted =
3619   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3620                compare n1 n2) all_functions
3621
3622 (* Field types for structures. *)
3623 type field =
3624   | FChar                       (* C 'char' (really, a 7 bit byte). *)
3625   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
3626   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
3627   | FUInt32
3628   | FInt32
3629   | FUInt64
3630   | FInt64
3631   | FBytes                      (* Any int measure that counts bytes. *)
3632   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
3633   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
3634
3635 (* Because we generate extra parsing code for LVM command line tools,
3636  * we have to pull out the LVM columns separately here.
3637  *)
3638 let lvm_pv_cols = [
3639   "pv_name", FString;
3640   "pv_uuid", FUUID;
3641   "pv_fmt", FString;
3642   "pv_size", FBytes;
3643   "dev_size", FBytes;
3644   "pv_free", FBytes;
3645   "pv_used", FBytes;
3646   "pv_attr", FString (* XXX *);
3647   "pv_pe_count", FInt64;
3648   "pv_pe_alloc_count", FInt64;
3649   "pv_tags", FString;
3650   "pe_start", FBytes;
3651   "pv_mda_count", FInt64;
3652   "pv_mda_free", FBytes;
3653   (* Not in Fedora 10:
3654      "pv_mda_size", FBytes;
3655   *)
3656 ]
3657 let lvm_vg_cols = [
3658   "vg_name", FString;
3659   "vg_uuid", FUUID;
3660   "vg_fmt", FString;
3661   "vg_attr", FString (* XXX *);
3662   "vg_size", FBytes;
3663   "vg_free", FBytes;
3664   "vg_sysid", FString;
3665   "vg_extent_size", FBytes;
3666   "vg_extent_count", FInt64;
3667   "vg_free_count", FInt64;
3668   "max_lv", FInt64;
3669   "max_pv", FInt64;
3670   "pv_count", FInt64;
3671   "lv_count", FInt64;
3672   "snap_count", FInt64;
3673   "vg_seqno", FInt64;
3674   "vg_tags", FString;
3675   "vg_mda_count", FInt64;
3676   "vg_mda_free", FBytes;
3677   (* Not in Fedora 10:
3678      "vg_mda_size", FBytes;
3679   *)
3680 ]
3681 let lvm_lv_cols = [
3682   "lv_name", FString;
3683   "lv_uuid", FUUID;
3684   "lv_attr", FString (* XXX *);
3685   "lv_major", FInt64;
3686   "lv_minor", FInt64;
3687   "lv_kernel_major", FInt64;
3688   "lv_kernel_minor", FInt64;
3689   "lv_size", FBytes;
3690   "seg_count", FInt64;
3691   "origin", FString;
3692   "snap_percent", FOptPercent;
3693   "copy_percent", FOptPercent;
3694   "move_pv", FString;
3695   "lv_tags", FString;
3696   "mirror_log", FString;
3697   "modules", FString;
3698 ]
3699
3700 (* Names and fields in all structures (in RStruct and RStructList)
3701  * that we support.
3702  *)
3703 let structs = [
3704   (* The old RIntBool return type, only ever used for aug_defnode.  Do
3705    * not use this struct in any new code.
3706    *)
3707   "int_bool", [
3708     "i", FInt32;                (* for historical compatibility *)
3709     "b", FInt32;                (* for historical compatibility *)
3710   ];
3711
3712   (* LVM PVs, VGs, LVs. *)
3713   "lvm_pv", lvm_pv_cols;
3714   "lvm_vg", lvm_vg_cols;
3715   "lvm_lv", lvm_lv_cols;
3716
3717   (* Column names and types from stat structures.
3718    * NB. Can't use things like 'st_atime' because glibc header files
3719    * define some of these as macros.  Ugh.
3720    *)
3721   "stat", [
3722     "dev", FInt64;
3723     "ino", FInt64;
3724     "mode", FInt64;
3725     "nlink", FInt64;
3726     "uid", FInt64;
3727     "gid", FInt64;
3728     "rdev", FInt64;
3729     "size", FInt64;
3730     "blksize", FInt64;
3731     "blocks", FInt64;
3732     "atime", FInt64;
3733     "mtime", FInt64;
3734     "ctime", FInt64;
3735   ];
3736   "statvfs", [
3737     "bsize", FInt64;
3738     "frsize", FInt64;
3739     "blocks", FInt64;
3740     "bfree", FInt64;
3741     "bavail", FInt64;
3742     "files", FInt64;
3743     "ffree", FInt64;
3744     "favail", FInt64;
3745     "fsid", FInt64;
3746     "flag", FInt64;
3747     "namemax", FInt64;
3748   ];
3749
3750   (* Column names in dirent structure. *)
3751   "dirent", [
3752     "ino", FInt64;
3753     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
3754     "ftyp", FChar;
3755     "name", FString;
3756   ];
3757
3758   (* Version numbers. *)
3759   "version", [
3760     "major", FInt64;
3761     "minor", FInt64;
3762     "release", FInt64;
3763     "extra", FString;
3764   ];
3765
3766   (* Extended attribute. *)
3767   "xattr", [
3768     "attrname", FString;
3769     "attrval", FBuffer;
3770   ];
3771
3772   (* Inotify events. *)
3773   "inotify_event", [
3774     "in_wd", FInt64;
3775     "in_mask", FUInt32;
3776     "in_cookie", FUInt32;
3777     "in_name", FString;
3778   ];
3779 ] (* end of structs *)
3780
3781 (* Ugh, Java has to be different ..
3782  * These names are also used by the Haskell bindings.
3783  *)
3784 let java_structs = [
3785   "int_bool", "IntBool";
3786   "lvm_pv", "PV";
3787   "lvm_vg", "VG";
3788   "lvm_lv", "LV";
3789   "stat", "Stat";
3790   "statvfs", "StatVFS";
3791   "dirent", "Dirent";
3792   "version", "Version";
3793   "xattr", "XAttr";
3794   "inotify_event", "INotifyEvent";
3795 ]
3796
3797 (* What structs are actually returned. *)
3798 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
3799
3800 (* Returns a list of RStruct/RStructList structs that are returned
3801  * by any function.  Each element of returned list is a pair:
3802  *
3803  * (structname, RStructOnly)
3804  *    == there exists function which returns RStruct (_, structname)
3805  * (structname, RStructListOnly)
3806  *    == there exists function which returns RStructList (_, structname)
3807  * (structname, RStructAndList)
3808  *    == there are functions returning both RStruct (_, structname)
3809  *                                      and RStructList (_, structname)
3810  *)
3811 let rstructs_used =
3812   (* ||| is a "logical OR" for rstructs_used_t *)
3813   let (|||) a b =
3814     match a, b with
3815     | RStructAndList, _
3816     | _, RStructAndList -> RStructAndList
3817     | RStructOnly, RStructListOnly
3818     | RStructListOnly, RStructOnly -> RStructAndList
3819     | RStructOnly, RStructOnly -> RStructOnly
3820     | RStructListOnly, RStructListOnly -> RStructListOnly
3821   in
3822
3823   let h = Hashtbl.create 13 in
3824
3825   (* if elem->oldv exists, update entry using ||| operator,
3826    * else just add elem->newv to the hash
3827    *)
3828   let update elem newv =
3829     try  let oldv = Hashtbl.find h elem in
3830          Hashtbl.replace h elem (newv ||| oldv)
3831     with Not_found -> Hashtbl.add h elem newv
3832   in
3833
3834   List.iter (
3835     fun (_, style, _, _, _, _, _) ->
3836       match fst style with
3837       | RStruct (_, structname) -> update structname RStructOnly
3838       | RStructList (_, structname) -> update structname RStructListOnly
3839       | _ -> ()
3840   ) all_functions;
3841
3842   (* return key->values as a list of (key,value) *)
3843   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
3844
3845 (* debug:
3846 let () =
3847   List.iter (
3848     function
3849     | sn, RStructOnly -> printf "%s RStructOnly\n" sn
3850     | sn, RStructListOnly -> printf "%s RStructListOnly\n" sn
3851     | sn, RStructAndList -> printf "%s RStructAndList\n" sn
3852   ) rstructs_used
3853 *)
3854
3855 (* Used for testing language bindings. *)
3856 type callt =
3857   | CallString of string
3858   | CallOptString of string option
3859   | CallStringList of string list
3860   | CallInt of int
3861   | CallBool of bool
3862
3863 (* Used to memoize the result of pod2text. *)
3864 let pod2text_memo_filename = "src/.pod2text.data"
3865 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
3866   try
3867     let chan = open_in pod2text_memo_filename in
3868     let v = input_value chan in
3869     close_in chan;
3870     v
3871   with
3872     _ -> Hashtbl.create 13
3873 let pod2text_memo_updated () =
3874   let chan = open_out pod2text_memo_filename in
3875   output_value chan pod2text_memo;
3876   close_out chan
3877
3878 (* Useful functions.
3879  * Note we don't want to use any external OCaml libraries which
3880  * makes this a bit harder than it should be.
3881  *)
3882 let failwithf fs = ksprintf failwith fs
3883
3884 let replace_char s c1 c2 =
3885   let s2 = String.copy s in
3886   let r = ref false in
3887   for i = 0 to String.length s2 - 1 do
3888     if String.unsafe_get s2 i = c1 then (
3889       String.unsafe_set s2 i c2;
3890       r := true
3891     )
3892   done;
3893   if not !r then s else s2
3894
3895 let isspace c =
3896   c = ' '
3897   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
3898
3899 let triml ?(test = isspace) str =
3900   let i = ref 0 in
3901   let n = ref (String.length str) in
3902   while !n > 0 && test str.[!i]; do
3903     decr n;
3904     incr i
3905   done;
3906   if !i = 0 then str
3907   else String.sub str !i !n
3908
3909 let trimr ?(test = isspace) str =
3910   let n = ref (String.length str) in
3911   while !n > 0 && test str.[!n-1]; do
3912     decr n
3913   done;
3914   if !n = String.length str then str
3915   else String.sub str 0 !n
3916
3917 let trim ?(test = isspace) str =
3918   trimr ~test (triml ~test str)
3919
3920 let rec find s sub =
3921   let len = String.length s in
3922   let sublen = String.length sub in
3923   let rec loop i =
3924     if i <= len-sublen then (
3925       let rec loop2 j =
3926         if j < sublen then (
3927           if s.[i+j] = sub.[j] then loop2 (j+1)
3928           else -1
3929         ) else
3930           i (* found *)
3931       in
3932       let r = loop2 0 in
3933       if r = -1 then loop (i+1) else r
3934     ) else
3935       -1 (* not found *)
3936   in
3937   loop 0
3938
3939 let rec replace_str s s1 s2 =
3940   let len = String.length s in
3941   let sublen = String.length s1 in
3942   let i = find s s1 in
3943   if i = -1 then s
3944   else (
3945     let s' = String.sub s 0 i in
3946     let s'' = String.sub s (i+sublen) (len-i-sublen) in
3947     s' ^ s2 ^ replace_str s'' s1 s2
3948   )
3949
3950 let rec string_split sep str =
3951   let len = String.length str in
3952   let seplen = String.length sep in
3953   let i = find str sep in
3954   if i = -1 then [str]
3955   else (
3956     let s' = String.sub str 0 i in
3957     let s'' = String.sub str (i+seplen) (len-i-seplen) in
3958     s' :: string_split sep s''
3959   )
3960
3961 let files_equal n1 n2 =
3962   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
3963   match Sys.command cmd with
3964   | 0 -> true
3965   | 1 -> false
3966   | i -> failwithf "%s: failed with error code %d" cmd i
3967
3968 let rec filter_map f = function
3969   | [] -> []
3970   | x :: xs ->
3971       match f x with
3972       | Some y -> y :: filter_map f xs
3973       | None -> filter_map f xs
3974
3975 let rec find_map f = function
3976   | [] -> raise Not_found
3977   | x :: xs ->
3978       match f x with
3979       | Some y -> y
3980       | None -> find_map f xs
3981
3982 let iteri f xs =
3983   let rec loop i = function
3984     | [] -> ()
3985     | x :: xs -> f i x; loop (i+1) xs
3986   in
3987   loop 0 xs
3988
3989 let mapi f xs =
3990   let rec loop i = function
3991     | [] -> []
3992     | x :: xs -> let r = f i x in r :: loop (i+1) xs
3993   in
3994   loop 0 xs
3995
3996 let name_of_argt = function
3997   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
3998   | StringList n | DeviceList n | Bool n | Int n
3999   | FileIn n | FileOut n -> n
4000
4001 let java_name_of_struct typ =
4002   try List.assoc typ java_structs
4003   with Not_found ->
4004     failwithf
4005       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4006
4007 let cols_of_struct typ =
4008   try List.assoc typ structs
4009   with Not_found ->
4010     failwithf "cols_of_struct: unknown struct %s" typ
4011
4012 let seq_of_test = function
4013   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4014   | TestOutputListOfDevices (s, _)
4015   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4016   | TestOutputTrue s | TestOutputFalse s
4017   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4018   | TestOutputStruct (s, _)
4019   | TestLastFail s -> s
4020
4021 (* Handling for function flags. *)
4022 let protocol_limit_warning =
4023   "Because of the message protocol, there is a transfer limit
4024 of somewhere between 2MB and 4MB.  To transfer large files you should use
4025 FTP."
4026
4027 let danger_will_robinson =
4028   "B<This command is dangerous.  Without careful use you
4029 can easily destroy all your data>."
4030
4031 let deprecation_notice flags =
4032   try
4033     let alt =
4034       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4035     let txt =
4036       sprintf "This function is deprecated.
4037 In new code, use the C<%s> call instead.
4038
4039 Deprecated functions will not be removed from the API, but the
4040 fact that they are deprecated indicates that there are problems
4041 with correct use of these functions." alt in
4042     Some txt
4043   with
4044     Not_found -> None
4045
4046 (* Check function names etc. for consistency. *)
4047 let check_functions () =
4048   let contains_uppercase str =
4049     let len = String.length str in
4050     let rec loop i =
4051       if i >= len then false
4052       else (
4053         let c = str.[i] in
4054         if c >= 'A' && c <= 'Z' then true
4055         else loop (i+1)
4056       )
4057     in
4058     loop 0
4059   in
4060
4061   (* Check function names. *)
4062   List.iter (
4063     fun (name, _, _, _, _, _, _) ->
4064       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4065         failwithf "function name %s does not need 'guestfs' prefix" name;
4066       if name = "" then
4067         failwithf "function name is empty";
4068       if name.[0] < 'a' || name.[0] > 'z' then
4069         failwithf "function name %s must start with lowercase a-z" name;
4070       if String.contains name '-' then
4071         failwithf "function name %s should not contain '-', use '_' instead."
4072           name
4073   ) all_functions;
4074
4075   (* Check function parameter/return names. *)
4076   List.iter (
4077     fun (name, style, _, _, _, _, _) ->
4078       let check_arg_ret_name n =
4079         if contains_uppercase n then
4080           failwithf "%s param/ret %s should not contain uppercase chars"
4081             name n;
4082         if String.contains n '-' || String.contains n '_' then
4083           failwithf "%s param/ret %s should not contain '-' or '_'"
4084             name n;
4085         if n = "value" then
4086           failwithf "%s has a param/ret called 'value', which causes conflicts in the OCaml bindings, use something like 'val' or a more descriptive name" name;
4087         if n = "int" || n = "char" || n = "short" || n = "long" then
4088           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4089         if n = "i" || n = "n" then
4090           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4091         if n = "argv" || n = "args" then
4092           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4093
4094         (* List Haskell, OCaml and C keywords here.
4095          * http://www.haskell.org/haskellwiki/Keywords
4096          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4097          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4098          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4099          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4100          * Omitting _-containing words, since they're handled above.
4101          * Omitting the OCaml reserved word, "val", is ok,
4102          * and saves us from renaming several parameters.
4103          *)
4104         let reserved = [
4105           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4106           "char"; "class"; "const"; "constraint"; "continue"; "data";
4107           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4108           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4109           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4110           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4111           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4112           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4113           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4114           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4115           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4116           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4117           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4118           "volatile"; "when"; "where"; "while";
4119           ] in
4120         if List.mem n reserved then
4121           failwithf "%s has param/ret using reserved word %s" name n;
4122       in
4123
4124       (match fst style with
4125        | RErr -> ()
4126        | RInt n | RInt64 n | RBool n
4127        | RConstString n | RConstOptString n | RString n
4128        | RStringList n | RStruct (n, _) | RStructList (n, _)
4129        | RHashtable n | RBufferOut n ->
4130            check_arg_ret_name n
4131       );
4132       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4133   ) all_functions;
4134
4135   (* Check short descriptions. *)
4136   List.iter (
4137     fun (name, _, _, _, _, shortdesc, _) ->
4138       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4139         failwithf "short description of %s should begin with lowercase." name;
4140       let c = shortdesc.[String.length shortdesc-1] in
4141       if c = '\n' || c = '.' then
4142         failwithf "short description of %s should not end with . or \\n." name
4143   ) all_functions;
4144
4145   (* Check long dscriptions. *)
4146   List.iter (
4147     fun (name, _, _, _, _, _, longdesc) ->
4148       if longdesc.[String.length longdesc-1] = '\n' then
4149         failwithf "long description of %s should not end with \\n." name
4150   ) all_functions;
4151
4152   (* Check proc_nrs. *)
4153   List.iter (
4154     fun (name, _, proc_nr, _, _, _, _) ->
4155       if proc_nr <= 0 then
4156         failwithf "daemon function %s should have proc_nr > 0" name
4157   ) daemon_functions;
4158
4159   List.iter (
4160     fun (name, _, proc_nr, _, _, _, _) ->
4161       if proc_nr <> -1 then
4162         failwithf "non-daemon function %s should have proc_nr -1" name
4163   ) non_daemon_functions;
4164
4165   let proc_nrs =
4166     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4167       daemon_functions in
4168   let proc_nrs =
4169     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4170   let rec loop = function
4171     | [] -> ()
4172     | [_] -> ()
4173     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4174         loop rest
4175     | (name1,nr1) :: (name2,nr2) :: _ ->
4176         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4177           name1 name2 nr1 nr2
4178   in
4179   loop proc_nrs;
4180
4181   (* Check tests. *)
4182   List.iter (
4183     function
4184       (* Ignore functions that have no tests.  We generate a
4185        * warning when the user does 'make check' instead.
4186        *)
4187     | name, _, _, _, [], _, _ -> ()
4188     | name, _, _, _, tests, _, _ ->
4189         let funcs =
4190           List.map (
4191             fun (_, _, test) ->
4192               match seq_of_test test with
4193               | [] ->
4194                   failwithf "%s has a test containing an empty sequence" name
4195               | cmds -> List.map List.hd cmds
4196           ) tests in
4197         let funcs = List.flatten funcs in
4198
4199         let tested = List.mem name funcs in
4200
4201         if not tested then
4202           failwithf "function %s has tests but does not test itself" name
4203   ) all_functions
4204
4205 (* 'pr' prints to the current output file. *)
4206 let chan = ref stdout
4207 let pr fs = ksprintf (output_string !chan) fs
4208
4209 (* Generate a header block in a number of standard styles. *)
4210 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4211 type license = GPLv2 | LGPLv2
4212
4213 let generate_header comment license =
4214   let c = match comment with
4215     | CStyle ->     pr "/* "; " *"
4216     | HashStyle ->  pr "# ";  "#"
4217     | OCamlStyle -> pr "(* "; " *"
4218     | HaskellStyle -> pr "{- "; "  " in
4219   pr "libguestfs generated file\n";
4220   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4221   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4222   pr "%s\n" c;
4223   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4224   pr "%s\n" c;
4225   (match license with
4226    | GPLv2 ->
4227        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4228        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4229        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4230        pr "%s (at your option) any later version.\n" c;
4231        pr "%s\n" c;
4232        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4233        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4234        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4235        pr "%s GNU General Public License for more details.\n" c;
4236        pr "%s\n" c;
4237        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4238        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4239        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4240
4241    | LGPLv2 ->
4242        pr "%s This library is free software; you can redistribute it and/or\n" c;
4243        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4244        pr "%s License as published by the Free Software Foundation; either\n" c;
4245        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4246        pr "%s\n" c;
4247        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4248        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4249        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4250        pr "%s Lesser General Public License for more details.\n" c;
4251        pr "%s\n" c;
4252        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4253        pr "%s License along with this library; if not, write to the Free Software\n" c;
4254        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4255   );
4256   (match comment with
4257    | CStyle -> pr " */\n"
4258    | HashStyle -> ()
4259    | OCamlStyle -> pr " *)\n"
4260    | HaskellStyle -> pr "-}\n"
4261   );
4262   pr "\n"
4263
4264 (* Start of main code generation functions below this line. *)
4265
4266 (* Generate the pod documentation for the C API. *)
4267 let rec generate_actions_pod () =
4268   List.iter (
4269     fun (shortname, style, _, flags, _, _, longdesc) ->
4270       if not (List.mem NotInDocs flags) then (
4271         let name = "guestfs_" ^ shortname in
4272         pr "=head2 %s\n\n" name;
4273         pr " ";
4274         generate_prototype ~extern:false ~handle:"handle" name style;
4275         pr "\n\n";
4276         pr "%s\n\n" longdesc;
4277         (match fst style with
4278          | RErr ->
4279              pr "This function returns 0 on success or -1 on error.\n\n"
4280          | RInt _ ->
4281              pr "On error this function returns -1.\n\n"
4282          | RInt64 _ ->
4283              pr "On error this function returns -1.\n\n"
4284          | RBool _ ->
4285              pr "This function returns a C truth value on success or -1 on error.\n\n"
4286          | RConstString _ ->
4287              pr "This function returns a string, or NULL on error.
4288 The string is owned by the guest handle and must I<not> be freed.\n\n"
4289          | RConstOptString _ ->
4290              pr "This function returns a string which may be NULL.
4291 There is way to return an error from this function.
4292 The string is owned by the guest handle and must I<not> be freed.\n\n"
4293          | RString _ ->
4294              pr "This function returns a string, or NULL on error.
4295 I<The caller must free the returned string after use>.\n\n"
4296          | RStringList _ ->
4297              pr "This function returns a NULL-terminated array of strings
4298 (like L<environ(3)>), or NULL if there was an error.
4299 I<The caller must free the strings and the array after use>.\n\n"
4300          | RStruct (_, typ) ->
4301              pr "This function returns a C<struct guestfs_%s *>,
4302 or NULL if there was an error.
4303 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4304          | RStructList (_, typ) ->
4305              pr "This function returns a C<struct guestfs_%s_list *>
4306 (see E<lt>guestfs-structs.hE<gt>),
4307 or NULL if there was an error.
4308 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4309          | RHashtable _ ->
4310              pr "This function returns a NULL-terminated array of
4311 strings, or NULL if there was an error.
4312 The array of strings will always have length C<2n+1>, where
4313 C<n> keys and values alternate, followed by the trailing NULL entry.
4314 I<The caller must free the strings and the array after use>.\n\n"
4315          | RBufferOut _ ->
4316              pr "This function returns a buffer, or NULL on error.
4317 The size of the returned buffer is written to C<*size_r>.
4318 I<The caller must free the returned buffer after use>.\n\n"
4319         );
4320         if List.mem ProtocolLimitWarning flags then
4321           pr "%s\n\n" protocol_limit_warning;
4322         if List.mem DangerWillRobinson flags then
4323           pr "%s\n\n" danger_will_robinson;
4324         match deprecation_notice flags with
4325         | None -> ()
4326         | Some txt -> pr "%s\n\n" txt
4327       )
4328   ) all_functions_sorted
4329
4330 and generate_structs_pod () =
4331   (* Structs documentation. *)
4332   List.iter (
4333     fun (typ, cols) ->
4334       pr "=head2 guestfs_%s\n" typ;
4335       pr "\n";
4336       pr " struct guestfs_%s {\n" typ;
4337       List.iter (
4338         function
4339         | name, FChar -> pr "   char %s;\n" name
4340         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4341         | name, FInt32 -> pr "   int32_t %s;\n" name
4342         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4343         | name, FInt64 -> pr "   int64_t %s;\n" name
4344         | name, FString -> pr "   char *%s;\n" name
4345         | name, FBuffer ->
4346             pr "   /* The next two fields describe a byte array. */\n";
4347             pr "   uint32_t %s_len;\n" name;
4348             pr "   char *%s;\n" name
4349         | name, FUUID ->
4350             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4351             pr "   char %s[32];\n" name
4352         | name, FOptPercent ->
4353             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4354             pr "   float %s;\n" name
4355       ) cols;
4356       pr " };\n";
4357       pr " \n";
4358       pr " struct guestfs_%s_list {\n" typ;
4359       pr "   uint32_t len; /* Number of elements in list. */\n";
4360       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4361       pr " };\n";
4362       pr " \n";
4363       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4364       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4365         typ typ;
4366       pr "\n"
4367   ) structs
4368
4369 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4370  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4371  *
4372  * We have to use an underscore instead of a dash because otherwise
4373  * rpcgen generates incorrect code.
4374  *
4375  * This header is NOT exported to clients, but see also generate_structs_h.
4376  *)
4377 and generate_xdr () =
4378   generate_header CStyle LGPLv2;
4379
4380   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4381   pr "typedef string str<>;\n";
4382   pr "\n";
4383
4384   (* Internal structures. *)
4385   List.iter (
4386     function
4387     | typ, cols ->
4388         pr "struct guestfs_int_%s {\n" typ;
4389         List.iter (function
4390                    | name, FChar -> pr "  char %s;\n" name
4391                    | name, FString -> pr "  string %s<>;\n" name
4392                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4393                    | name, FUUID -> pr "  opaque %s[32];\n" name
4394                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4395                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4396                    | name, FOptPercent -> pr "  float %s;\n" name
4397                   ) cols;
4398         pr "};\n";
4399         pr "\n";
4400         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4401         pr "\n";
4402   ) structs;
4403
4404   List.iter (
4405     fun (shortname, style, _, _, _, _, _) ->
4406       let name = "guestfs_" ^ shortname in
4407
4408       (match snd style with
4409        | [] -> ()
4410        | args ->
4411            pr "struct %s_args {\n" name;
4412            List.iter (
4413              function
4414              | Pathname n | Device n | Dev_or_Path n | String n -> pr "  string %s<>;\n" n
4415              | OptString n -> pr "  str *%s;\n" n
4416              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
4417              | Bool n -> pr "  bool %s;\n" n
4418              | Int n -> pr "  int %s;\n" n
4419              | FileIn _ | FileOut _ -> ()
4420            ) args;
4421            pr "};\n\n"
4422       );
4423       (match fst style with
4424        | RErr -> ()
4425        | RInt n ->
4426            pr "struct %s_ret {\n" name;
4427            pr "  int %s;\n" n;
4428            pr "};\n\n"
4429        | RInt64 n ->
4430            pr "struct %s_ret {\n" name;
4431            pr "  hyper %s;\n" n;
4432            pr "};\n\n"
4433        | RBool n ->
4434            pr "struct %s_ret {\n" name;
4435            pr "  bool %s;\n" n;
4436            pr "};\n\n"
4437        | RConstString _ | RConstOptString _ ->
4438            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4439        | RString n ->
4440            pr "struct %s_ret {\n" name;
4441            pr "  string %s<>;\n" n;
4442            pr "};\n\n"
4443        | RStringList n ->
4444            pr "struct %s_ret {\n" name;
4445            pr "  str %s<>;\n" n;
4446            pr "};\n\n"
4447        | RStruct (n, typ) ->
4448            pr "struct %s_ret {\n" name;
4449            pr "  guestfs_int_%s %s;\n" typ n;
4450            pr "};\n\n"
4451        | RStructList (n, typ) ->
4452            pr "struct %s_ret {\n" name;
4453            pr "  guestfs_int_%s_list %s;\n" typ n;
4454            pr "};\n\n"
4455        | RHashtable n ->
4456            pr "struct %s_ret {\n" name;
4457            pr "  str %s<>;\n" n;
4458            pr "};\n\n"
4459        | RBufferOut n ->
4460            pr "struct %s_ret {\n" name;
4461            pr "  opaque %s<>;\n" n;
4462            pr "};\n\n"
4463       );
4464   ) daemon_functions;
4465
4466   (* Table of procedure numbers. *)
4467   pr "enum guestfs_procedure {\n";
4468   List.iter (
4469     fun (shortname, _, proc_nr, _, _, _, _) ->
4470       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4471   ) daemon_functions;
4472   pr "  GUESTFS_PROC_NR_PROCS\n";
4473   pr "};\n";
4474   pr "\n";
4475
4476   (* Having to choose a maximum message size is annoying for several
4477    * reasons (it limits what we can do in the API), but it (a) makes
4478    * the protocol a lot simpler, and (b) provides a bound on the size
4479    * of the daemon which operates in limited memory space.  For large
4480    * file transfers you should use FTP.
4481    *)
4482   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4483   pr "\n";
4484
4485   (* Message header, etc. *)
4486   pr "\
4487 /* The communication protocol is now documented in the guestfs(3)
4488  * manpage.
4489  */
4490
4491 const GUESTFS_PROGRAM = 0x2000F5F5;
4492 const GUESTFS_PROTOCOL_VERSION = 1;
4493
4494 /* These constants must be larger than any possible message length. */
4495 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4496 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4497
4498 enum guestfs_message_direction {
4499   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
4500   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
4501 };
4502
4503 enum guestfs_message_status {
4504   GUESTFS_STATUS_OK = 0,
4505   GUESTFS_STATUS_ERROR = 1
4506 };
4507
4508 const GUESTFS_ERROR_LEN = 256;
4509
4510 struct guestfs_message_error {
4511   string error_message<GUESTFS_ERROR_LEN>;
4512 };
4513
4514 struct guestfs_message_header {
4515   unsigned prog;                     /* GUESTFS_PROGRAM */
4516   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
4517   guestfs_procedure proc;            /* GUESTFS_PROC_x */
4518   guestfs_message_direction direction;
4519   unsigned serial;                   /* message serial number */
4520   guestfs_message_status status;
4521 };
4522
4523 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4524
4525 struct guestfs_chunk {
4526   int cancel;                        /* if non-zero, transfer is cancelled */
4527   /* data size is 0 bytes if the transfer has finished successfully */
4528   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4529 };
4530 "
4531
4532 (* Generate the guestfs-structs.h file. *)
4533 and generate_structs_h () =
4534   generate_header CStyle LGPLv2;
4535
4536   (* This is a public exported header file containing various
4537    * structures.  The structures are carefully written to have
4538    * exactly the same in-memory format as the XDR structures that
4539    * we use on the wire to the daemon.  The reason for creating
4540    * copies of these structures here is just so we don't have to
4541    * export the whole of guestfs_protocol.h (which includes much
4542    * unrelated and XDR-dependent stuff that we don't want to be
4543    * public, or required by clients).
4544    *
4545    * To reiterate, we will pass these structures to and from the
4546    * client with a simple assignment or memcpy, so the format
4547    * must be identical to what rpcgen / the RFC defines.
4548    *)
4549
4550   (* Public structures. *)
4551   List.iter (
4552     fun (typ, cols) ->
4553       pr "struct guestfs_%s {\n" typ;
4554       List.iter (
4555         function
4556         | name, FChar -> pr "  char %s;\n" name
4557         | name, FString -> pr "  char *%s;\n" name
4558         | name, FBuffer ->
4559             pr "  uint32_t %s_len;\n" name;
4560             pr "  char *%s;\n" name
4561         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4562         | name, FUInt32 -> pr "  uint32_t %s;\n" name
4563         | name, FInt32 -> pr "  int32_t %s;\n" name
4564         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
4565         | name, FInt64 -> pr "  int64_t %s;\n" name
4566         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
4567       ) cols;
4568       pr "};\n";
4569       pr "\n";
4570       pr "struct guestfs_%s_list {\n" typ;
4571       pr "  uint32_t len;\n";
4572       pr "  struct guestfs_%s *val;\n" typ;
4573       pr "};\n";
4574       pr "\n";
4575       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4576       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4577       pr "\n"
4578   ) structs
4579
4580 (* Generate the guestfs-actions.h file. *)
4581 and generate_actions_h () =
4582   generate_header CStyle LGPLv2;
4583   List.iter (
4584     fun (shortname, style, _, _, _, _, _) ->
4585       let name = "guestfs_" ^ shortname in
4586       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4587         name style
4588   ) all_functions
4589
4590 (* Generate the guestfs-internal-actions.h file. *)
4591 and generate_internal_actions_h () =
4592   generate_header CStyle LGPLv2;
4593   List.iter (
4594     fun (shortname, style, _, _, _, _, _) ->
4595       let name = "guestfs__" ^ shortname in
4596       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4597         name style
4598   ) non_daemon_functions
4599
4600 (* Generate the client-side dispatch stubs. *)
4601 and generate_client_actions () =
4602   generate_header CStyle LGPLv2;
4603
4604   pr "\
4605 #include <stdio.h>
4606 #include <stdlib.h>
4607
4608 #include \"guestfs.h\"
4609 #include \"guestfs-internal-actions.h\"
4610 #include \"guestfs_protocol.h\"
4611
4612 #define error guestfs_error
4613 //#define perrorf guestfs_perrorf
4614 //#define safe_malloc guestfs_safe_malloc
4615 #define safe_realloc guestfs_safe_realloc
4616 //#define safe_strdup guestfs_safe_strdup
4617 #define safe_memdup guestfs_safe_memdup
4618
4619 /* Check the return message from a call for validity. */
4620 static int
4621 check_reply_header (guestfs_h *g,
4622                     const struct guestfs_message_header *hdr,
4623                     unsigned int proc_nr, unsigned int serial)
4624 {
4625   if (hdr->prog != GUESTFS_PROGRAM) {
4626     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4627     return -1;
4628   }
4629   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4630     error (g, \"wrong protocol version (%%d/%%d)\",
4631            hdr->vers, GUESTFS_PROTOCOL_VERSION);
4632     return -1;
4633   }
4634   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4635     error (g, \"unexpected message direction (%%d/%%d)\",
4636            hdr->direction, GUESTFS_DIRECTION_REPLY);
4637     return -1;
4638   }
4639   if (hdr->proc != proc_nr) {
4640     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4641     return -1;
4642   }
4643   if (hdr->serial != serial) {
4644     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4645     return -1;
4646   }
4647
4648   return 0;
4649 }
4650
4651 /* Check we are in the right state to run a high-level action. */
4652 static int
4653 check_state (guestfs_h *g, const char *caller)
4654 {
4655   if (!guestfs_is_ready (g)) {
4656     if (guestfs_is_config (g))
4657       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4658         caller);
4659     else if (guestfs_is_launching (g))
4660       error (g, \"%%s: call wait_ready() before using this function\",
4661         caller);
4662     else
4663       error (g, \"%%s called from the wrong state, %%d != READY\",
4664         caller, guestfs_get_state (g));
4665     return -1;
4666   }
4667   return 0;
4668 }
4669
4670 ";
4671
4672   (* Generate code to generate guestfish call traces. *)
4673   let trace_call shortname style =
4674     pr "  if (guestfs__get_trace (g)) {\n";
4675
4676     let needs_i =
4677       List.exists (function
4678                    | StringList _ | DeviceList _ -> true
4679                    | _ -> false) (snd style) in
4680     if needs_i then (
4681       pr "    int i;\n";
4682       pr "\n"
4683     );
4684
4685     pr "    printf (\"%s\");\n" shortname;
4686     List.iter (
4687       function
4688       | String n                        (* strings *)
4689       | Device n
4690       | Pathname n
4691       | Dev_or_Path n
4692       | FileIn n
4693       | FileOut n ->
4694           (* guestfish doesn't support string escaping, so neither do we *)
4695           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
4696       | OptString n ->                  (* string option *)
4697           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
4698           pr "    else printf (\" null\");\n"
4699       | StringList n
4700       | DeviceList n ->                 (* string list *)
4701           pr "    putchar (' ');\n";
4702           pr "    putchar ('\"');\n";
4703           pr "    for (i = 0; %s[i]; ++i) {\n" n;
4704           pr "      if (i > 0) putchar (' ');\n";
4705           pr "      fputs (%s[i], stdout);\n" n;
4706           pr "    }\n";
4707           pr "    putchar ('\"');\n";
4708       | Bool n ->                       (* boolean *)
4709           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
4710       | Int n ->                        (* int *)
4711           pr "    printf (\" %%d\", %s);\n" n
4712     ) (snd style);
4713     pr "    putchar ('\\n');\n";
4714     pr "  }\n";
4715     pr "\n";
4716   in
4717
4718   (* For non-daemon functions, generate a wrapper around each function. *)
4719   List.iter (
4720     fun (shortname, style, _, _, _, _, _) ->
4721       let name = "guestfs_" ^ shortname in
4722
4723       generate_prototype ~extern:false ~semicolon:false ~newline:true
4724         ~handle:"g" name style;
4725       pr "{\n";
4726       trace_call shortname style;
4727       pr "  return guestfs__%s " shortname;
4728       generate_c_call_args ~handle:"g" style;
4729       pr ";\n";
4730       pr "}\n";
4731       pr "\n"
4732   ) non_daemon_functions;
4733
4734   (* Client-side stubs for each function. *)
4735   List.iter (
4736     fun (shortname, style, _, _, _, _, _) ->
4737       let name = "guestfs_" ^ shortname in
4738
4739       (* Generate the context struct which stores the high-level
4740        * state between callback functions.
4741        *)
4742       pr "struct %s_ctx {\n" shortname;
4743       pr "  /* This flag is set by the callbacks, so we know we've done\n";
4744       pr "   * the callbacks as expected, and in the right sequence.\n";
4745       pr "   * 0 = not called, 1 = reply_cb called.\n";
4746       pr "   */\n";
4747       pr "  int cb_sequence;\n";
4748       pr "  struct guestfs_message_header hdr;\n";
4749       pr "  struct guestfs_message_error err;\n";
4750       (match fst style with
4751        | RErr -> ()
4752        | RConstString _ | RConstOptString _ ->
4753            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4754        | RInt _ | RInt64 _
4755        | RBool _ | RString _ | RStringList _
4756        | RStruct _ | RStructList _
4757        | RHashtable _ | RBufferOut _ ->
4758            pr "  struct %s_ret ret;\n" name
4759       );
4760       pr "};\n";
4761       pr "\n";
4762
4763       (* Generate the reply callback function. *)
4764       pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
4765       pr "{\n";
4766       pr "  guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4767       pr "  struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname;
4768       pr "\n";
4769       pr "  /* This should definitely not happen. */\n";
4770       pr "  if (ctx->cb_sequence != 0) {\n";
4771       pr "    ctx->cb_sequence = 9999;\n";
4772       pr "    error (g, \"%%s: internal error: reply callback called twice\", \"%s\");\n" name;
4773       pr "    return;\n";
4774       pr "  }\n";
4775       pr "\n";
4776       pr "  ml->main_loop_quit (ml, g);\n";
4777       pr "\n";
4778       pr "  if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n";
4779       pr "    error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name;
4780       pr "    return;\n";
4781       pr "  }\n";
4782       pr "  if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {\n";
4783       pr "    if (!xdr_guestfs_message_error (xdr, &ctx->err)) {\n";
4784       pr "      error (g, \"%%s: failed to parse reply error\", \"%s\");\n"
4785         name;
4786       pr "      return;\n";
4787       pr "    }\n";
4788       pr "    goto done;\n";
4789       pr "  }\n";
4790
4791       (match fst style with
4792        | RErr -> ()
4793        | RConstString _ | RConstOptString _ ->
4794            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4795        | RInt _ | RInt64 _
4796        | RBool _ | RString _ | RStringList _
4797        | RStruct _ | RStructList _
4798        | RHashtable _ | RBufferOut _ ->
4799            pr "  if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name;
4800            pr "    error (g, \"%%s: failed to parse reply\", \"%s\");\n" name;
4801            pr "    return;\n";
4802            pr "  }\n";
4803       );
4804
4805       pr " done:\n";
4806       pr "  ctx->cb_sequence = 1;\n";
4807       pr "}\n\n";
4808
4809       (* Generate the action stub. *)
4810       generate_prototype ~extern:false ~semicolon:false ~newline:true
4811         ~handle:"g" name style;
4812
4813       let error_code =
4814         match fst style with
4815         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4816         | RConstString _ | RConstOptString _ ->
4817             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4818         | RString _ | RStringList _
4819         | RStruct _ | RStructList _
4820         | RHashtable _ | RBufferOut _ ->
4821             "NULL" in
4822
4823       pr "{\n";
4824
4825       (match snd style with
4826        | [] -> ()
4827        | _ -> pr "  struct %s_args args;\n" name
4828       );
4829
4830       pr "  struct %s_ctx ctx;\n" shortname;
4831       pr "  guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4832       pr "  int serial;\n";
4833       pr "\n";
4834       trace_call shortname style;
4835       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4836       pr "  guestfs_set_busy (g);\n";
4837       pr "\n";
4838       pr "  memset (&ctx, 0, sizeof ctx);\n";
4839       pr "\n";
4840
4841       (* Send the main header and arguments. *)
4842       (match snd style with
4843        | [] ->
4844            pr "  serial = guestfs__send_sync (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4845              (String.uppercase shortname)
4846        | args ->
4847            List.iter (
4848              function
4849              | Pathname n | Device n | Dev_or_Path n | String n ->
4850                  pr "  args.%s = (char *) %s;\n" n n
4851              | OptString n ->
4852                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
4853              | StringList n | DeviceList n ->
4854                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
4855                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4856              | Bool n ->
4857                  pr "  args.%s = %s;\n" n n
4858              | Int n ->
4859                  pr "  args.%s = %s;\n" n n
4860              | FileIn _ | FileOut _ -> ()
4861            ) args;
4862            pr "  serial = guestfs__send_sync (g, GUESTFS_PROC_%s,\n"
4863              (String.uppercase shortname);
4864            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4865              name;
4866       );
4867       pr "  if (serial == -1) {\n";
4868       pr "    guestfs_end_busy (g);\n";
4869       pr "    return %s;\n" error_code;
4870       pr "  }\n";
4871       pr "\n";
4872
4873       (* Send any additional files (FileIn) requested. *)
4874       let need_read_reply_label = ref false in
4875       List.iter (
4876         function
4877         | FileIn n ->
4878             pr "  {\n";
4879             pr "    int r;\n";
4880             pr "\n";
4881             pr "    r = guestfs__send_file_sync (g, %s);\n" n;
4882             pr "    if (r == -1) {\n";
4883             pr "      guestfs_end_busy (g);\n";
4884             pr "      return %s;\n" error_code;
4885             pr "    }\n";
4886             pr "    if (r == -2) /* daemon cancelled */\n";
4887             pr "      goto read_reply;\n";
4888             need_read_reply_label := true;
4889             pr "  }\n";
4890             pr "\n";
4891         | _ -> ()
4892       ) (snd style);
4893
4894       (* Wait for the reply from the remote end. *)
4895       if !need_read_reply_label then pr " read_reply:\n";
4896       pr "  guestfs__switch_to_receiving (g);\n";
4897       pr "  ctx.cb_sequence = 0;\n";
4898       pr "  guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname;
4899       pr "  (void) ml->main_loop_run (ml, g);\n";
4900       pr "  guestfs_set_reply_callback (g, NULL, NULL);\n";
4901       pr "  if (ctx.cb_sequence != 1) {\n";
4902       pr "    error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name;
4903       pr "    guestfs_end_busy (g);\n";
4904       pr "    return %s;\n" error_code;
4905       pr "  }\n";
4906       pr "\n";
4907
4908       pr "  if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
4909         (String.uppercase shortname);
4910       pr "    guestfs_end_busy (g);\n";
4911       pr "    return %s;\n" error_code;
4912       pr "  }\n";
4913       pr "\n";
4914
4915       pr "  if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {\n";
4916       pr "    error (g, \"%%s\", ctx.err.error_message);\n";
4917       pr "    free (ctx.err.error_message);\n";
4918       pr "    guestfs_end_busy (g);\n";
4919       pr "    return %s;\n" error_code;
4920       pr "  }\n";
4921       pr "\n";
4922
4923       (* Expecting to receive further files (FileOut)? *)
4924       List.iter (
4925         function
4926         | FileOut n ->
4927             pr "  if (guestfs__receive_file_sync (g, %s) == -1) {\n" n;
4928             pr "    guestfs_end_busy (g);\n";
4929             pr "    return %s;\n" error_code;
4930             pr "  }\n";
4931             pr "\n";
4932         | _ -> ()
4933       ) (snd style);
4934
4935       pr "  guestfs_end_busy (g);\n";
4936
4937       (match fst style with
4938        | RErr -> pr "  return 0;\n"
4939        | RInt n | RInt64 n | RBool n ->
4940            pr "  return ctx.ret.%s;\n" n
4941        | RConstString _ | RConstOptString _ ->
4942            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4943        | RString n ->
4944            pr "  return ctx.ret.%s; /* caller will free */\n" n
4945        | RStringList n | RHashtable n ->
4946            pr "  /* caller will free this, but we need to add a NULL entry */\n";
4947            pr "  ctx.ret.%s.%s_val =\n" n n;
4948            pr "    safe_realloc (g, ctx.ret.%s.%s_val,\n" n n;
4949            pr "                  sizeof (char *) * (ctx.ret.%s.%s_len + 1));\n"
4950              n n;
4951            pr "  ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n;
4952            pr "  return ctx.ret.%s.%s_val;\n" n n
4953        | RStruct (n, _) ->
4954            pr "  /* caller will free this */\n";
4955            pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4956        | RStructList (n, _) ->
4957            pr "  /* caller will free this */\n";
4958            pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4959        | RBufferOut n ->
4960            pr "  *size_r = ctx.ret.%s.%s_len;\n" n n;
4961            pr "  return ctx.ret.%s.%s_val; /* caller will free */\n" n n
4962       );
4963
4964       pr "}\n\n"
4965   ) daemon_functions;
4966
4967   (* Functions to free structures. *)
4968   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
4969   pr " * structure format is identical to the XDR format.  See note in\n";
4970   pr " * generator.ml.\n";
4971   pr " */\n";
4972   pr "\n";
4973
4974   List.iter (
4975     fun (typ, _) ->
4976       pr "void\n";
4977       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
4978       pr "{\n";
4979       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
4980       pr "  free (x);\n";
4981       pr "}\n";
4982       pr "\n";
4983
4984       pr "void\n";
4985       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
4986       pr "{\n";
4987       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
4988       pr "  free (x);\n";
4989       pr "}\n";
4990       pr "\n";
4991
4992   ) structs;
4993
4994 (* Generate daemon/actions.h. *)
4995 and generate_daemon_actions_h () =
4996   generate_header CStyle GPLv2;
4997
4998   pr "#include \"../src/guestfs_protocol.h\"\n";
4999   pr "\n";
5000
5001   List.iter (
5002     fun (name, style, _, _, _, _, _) ->
5003       generate_prototype
5004         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5005         name style;
5006   ) daemon_functions
5007
5008 (* Generate the server-side stubs. *)
5009 and generate_daemon_actions () =
5010   generate_header CStyle GPLv2;
5011
5012   pr "#include <config.h>\n";
5013   pr "\n";
5014   pr "#include <stdio.h>\n";
5015   pr "#include <stdlib.h>\n";
5016   pr "#include <string.h>\n";
5017   pr "#include <inttypes.h>\n";
5018   pr "#include <ctype.h>\n";
5019   pr "#include <rpc/types.h>\n";
5020   pr "#include <rpc/xdr.h>\n";
5021   pr "\n";
5022   pr "#include \"daemon.h\"\n";
5023   pr "#include \"../src/guestfs_protocol.h\"\n";
5024   pr "#include \"actions.h\"\n";
5025   pr "\n";
5026
5027   List.iter (
5028     fun (name, style, _, _, _, _, _) ->
5029       (* Generate server-side stubs. *)
5030       pr "static void %s_stub (XDR *xdr_in)\n" name;
5031       pr "{\n";
5032       let error_code =
5033         match fst style with
5034         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5035         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5036         | RBool _ -> pr "  int r;\n"; "-1"
5037         | RConstString _ | RConstOptString _ ->
5038             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5039         | RString _ -> pr "  char *r;\n"; "NULL"
5040         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5041         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5042         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5043         | RBufferOut _ ->
5044             pr "  size_t size;\n";
5045             pr "  char *r;\n";
5046             "NULL" in
5047
5048       (match snd style with
5049        | [] -> ()
5050        | args ->
5051            pr "  struct guestfs_%s_args args;\n" name;
5052            List.iter (
5053              function
5054              | Device n | Dev_or_Path n
5055              | Pathname n
5056              | String n -> ()
5057              | OptString n -> pr "  char *%s;\n" n
5058              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5059              | Bool n -> pr "  int %s;\n" n
5060              | Int n -> pr "  int %s;\n" n
5061              | FileIn _ | FileOut _ -> ()
5062            ) args
5063       );
5064       pr "\n";
5065
5066       (match snd style with
5067        | [] -> ()
5068        | args ->
5069            pr "  memset (&args, 0, sizeof args);\n";
5070            pr "\n";
5071            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5072            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5073            pr "    return;\n";
5074            pr "  }\n";
5075            let pr_args n =
5076              pr "  char *%s = args.%s;\n" n n
5077            in
5078            let pr_list_handling_code n =
5079              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5080              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5081              pr "  if (%s == NULL) {\n" n;
5082              pr "    reply_with_perror (\"realloc\");\n";
5083              pr "    goto done;\n";
5084              pr "  }\n";
5085              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5086              pr "  args.%s.%s_val = %s;\n" n n n;
5087            in
5088            List.iter (
5089              function
5090              | Pathname n ->
5091                  pr_args n;
5092                  pr "  ABS_PATH (%s, goto done);\n" n;
5093              | Device n ->
5094                  pr_args n;
5095                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5096              | Dev_or_Path n ->
5097                  pr_args n;
5098                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5099              | String n -> pr_args n
5100              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5101              | StringList n ->
5102                  pr_list_handling_code n;
5103              | DeviceList n ->
5104                  pr_list_handling_code n;
5105                  pr "  /* Ensure that each is a device,\n";
5106                  pr "   * and perform device name translation. */\n";
5107                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5108                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5109                  pr "  }\n";
5110              | Bool n -> pr "  %s = args.%s;\n" n n
5111              | Int n -> pr "  %s = args.%s;\n" n n
5112              | FileIn _ | FileOut _ -> ()
5113            ) args;
5114            pr "\n"
5115       );
5116
5117
5118       (* this is used at least for do_equal *)
5119       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5120         (* Emit NEED_ROOT just once, even when there are two or
5121            more Pathname args *)
5122         pr "  NEED_ROOT (goto done);\n";
5123       );
5124
5125       (* Don't want to call the impl with any FileIn or FileOut
5126        * parameters, since these go "outside" the RPC protocol.
5127        *)
5128       let args' =
5129         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5130           (snd style) in
5131       pr "  r = do_%s " name;
5132       generate_c_call_args (fst style, args');
5133       pr ";\n";
5134
5135       pr "  if (r == %s)\n" error_code;
5136       pr "    /* do_%s has already called reply_with_error */\n" name;
5137       pr "    goto done;\n";
5138       pr "\n";
5139
5140       (* If there are any FileOut parameters, then the impl must
5141        * send its own reply.
5142        *)
5143       let no_reply =
5144         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5145       if no_reply then
5146         pr "  /* do_%s has already sent a reply */\n" name
5147       else (
5148         match fst style with
5149         | RErr -> pr "  reply (NULL, NULL);\n"
5150         | RInt n | RInt64 n | RBool n ->
5151             pr "  struct guestfs_%s_ret ret;\n" name;
5152             pr "  ret.%s = r;\n" n;
5153             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5154               name
5155         | RConstString _ | RConstOptString _ ->
5156             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5157         | RString n ->
5158             pr "  struct guestfs_%s_ret ret;\n" name;
5159             pr "  ret.%s = r;\n" n;
5160             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5161               name;
5162             pr "  free (r);\n"
5163         | RStringList n | RHashtable n ->
5164             pr "  struct guestfs_%s_ret ret;\n" name;
5165             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5166             pr "  ret.%s.%s_val = r;\n" n n;
5167             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5168               name;
5169             pr "  free_strings (r);\n"
5170         | RStruct (n, _) ->
5171             pr "  struct guestfs_%s_ret ret;\n" name;
5172             pr "  ret.%s = *r;\n" n;
5173             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5174               name;
5175             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5176               name
5177         | RStructList (n, _) ->
5178             pr "  struct guestfs_%s_ret ret;\n" name;
5179             pr "  ret.%s = *r;\n" n;
5180             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5181               name;
5182             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5183               name
5184         | RBufferOut n ->
5185             pr "  struct guestfs_%s_ret ret;\n" name;
5186             pr "  ret.%s.%s_val = r;\n" n n;
5187             pr "  ret.%s.%s_len = size;\n" n n;
5188             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5189               name;
5190             pr "  free (r);\n"
5191       );
5192
5193       (* Free the args. *)
5194       (match snd style with
5195        | [] ->
5196            pr "done: ;\n";
5197        | _ ->
5198            pr "done:\n";
5199            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5200              name
5201       );
5202
5203       pr "}\n\n";
5204   ) daemon_functions;
5205
5206   (* Dispatch function. *)
5207   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5208   pr "{\n";
5209   pr "  switch (proc_nr) {\n";
5210
5211   List.iter (
5212     fun (name, style, _, _, _, _, _) ->
5213       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5214       pr "      %s_stub (xdr_in);\n" name;
5215       pr "      break;\n"
5216   ) daemon_functions;
5217
5218   pr "    default:\n";
5219   pr "      reply_with_error (\"dispatch_incoming_message: unknown procedure number %%d, set LIBGUESTFS_PATH to point to the matching libguestfs appliance directory\", proc_nr);\n";
5220   pr "  }\n";
5221   pr "}\n";
5222   pr "\n";
5223
5224   (* LVM columns and tokenization functions. *)
5225   (* XXX This generates crap code.  We should rethink how we
5226    * do this parsing.
5227    *)
5228   List.iter (
5229     function
5230     | typ, cols ->
5231         pr "static const char *lvm_%s_cols = \"%s\";\n"
5232           typ (String.concat "," (List.map fst cols));
5233         pr "\n";
5234
5235         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5236         pr "{\n";
5237         pr "  char *tok, *p, *next;\n";
5238         pr "  int i, j;\n";
5239         pr "\n";
5240         (*
5241           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5242           pr "\n";
5243         *)
5244         pr "  if (!str) {\n";
5245         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5246         pr "    return -1;\n";
5247         pr "  }\n";
5248         pr "  if (!*str || isspace (*str)) {\n";
5249         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5250         pr "    return -1;\n";
5251         pr "  }\n";
5252         pr "  tok = str;\n";
5253         List.iter (
5254           fun (name, coltype) ->
5255             pr "  if (!tok) {\n";
5256             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5257             pr "    return -1;\n";
5258             pr "  }\n";
5259             pr "  p = strchrnul (tok, ',');\n";
5260             pr "  if (*p) next = p+1; else next = NULL;\n";
5261             pr "  *p = '\\0';\n";
5262             (match coltype with
5263              | FString ->
5264                  pr "  r->%s = strdup (tok);\n" name;
5265                  pr "  if (r->%s == NULL) {\n" name;
5266                  pr "    perror (\"strdup\");\n";
5267                  pr "    return -1;\n";
5268                  pr "  }\n"
5269              | FUUID ->
5270                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5271                  pr "    if (tok[j] == '\\0') {\n";
5272                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5273                  pr "      return -1;\n";
5274                  pr "    } else if (tok[j] != '-')\n";
5275                  pr "      r->%s[i++] = tok[j];\n" name;
5276                  pr "  }\n";
5277              | FBytes ->
5278                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5279                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5280                  pr "    return -1;\n";
5281                  pr "  }\n";
5282              | FInt64 ->
5283                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5284                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5285                  pr "    return -1;\n";
5286                  pr "  }\n";
5287              | FOptPercent ->
5288                  pr "  if (tok[0] == '\\0')\n";
5289                  pr "    r->%s = -1;\n" name;
5290                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5291                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5292                  pr "    return -1;\n";
5293                  pr "  }\n";
5294              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5295                  assert false (* can never be an LVM column *)
5296             );
5297             pr "  tok = next;\n";
5298         ) cols;
5299
5300         pr "  if (tok != NULL) {\n";
5301         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5302         pr "    return -1;\n";
5303         pr "  }\n";
5304         pr "  return 0;\n";
5305         pr "}\n";
5306         pr "\n";
5307
5308         pr "guestfs_int_lvm_%s_list *\n" typ;
5309         pr "parse_command_line_%ss (void)\n" typ;
5310         pr "{\n";
5311         pr "  char *out, *err;\n";
5312         pr "  char *p, *pend;\n";
5313         pr "  int r, i;\n";
5314         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5315         pr "  void *newp;\n";
5316         pr "\n";
5317         pr "  ret = malloc (sizeof *ret);\n";
5318         pr "  if (!ret) {\n";
5319         pr "    reply_with_perror (\"malloc\");\n";
5320         pr "    return NULL;\n";
5321         pr "  }\n";
5322         pr "\n";
5323         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5324         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5325         pr "\n";
5326         pr "  r = command (&out, &err,\n";
5327         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5328         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5329         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5330         pr "  if (r == -1) {\n";
5331         pr "    reply_with_error (\"%%s\", err);\n";
5332         pr "    free (out);\n";
5333         pr "    free (err);\n";
5334         pr "    free (ret);\n";
5335         pr "    return NULL;\n";
5336         pr "  }\n";
5337         pr "\n";
5338         pr "  free (err);\n";
5339         pr "\n";
5340         pr "  /* Tokenize each line of the output. */\n";
5341         pr "  p = out;\n";
5342         pr "  i = 0;\n";
5343         pr "  while (p) {\n";
5344         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5345         pr "    if (pend) {\n";
5346         pr "      *pend = '\\0';\n";
5347         pr "      pend++;\n";
5348         pr "    }\n";
5349         pr "\n";
5350         pr "    while (*p && isspace (*p))      /* Skip any leading whitespace. */\n";
5351         pr "      p++;\n";
5352         pr "\n";
5353         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5354         pr "      p = pend;\n";
5355         pr "      continue;\n";
5356         pr "    }\n";
5357         pr "\n";
5358         pr "    /* Allocate some space to store this next entry. */\n";
5359         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5360         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5361         pr "    if (newp == NULL) {\n";
5362         pr "      reply_with_perror (\"realloc\");\n";
5363         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5364         pr "      free (ret);\n";
5365         pr "      free (out);\n";
5366         pr "      return NULL;\n";
5367         pr "    }\n";
5368         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5369         pr "\n";
5370         pr "    /* Tokenize the next entry. */\n";
5371         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5372         pr "    if (r == -1) {\n";
5373         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5374         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5375         pr "      free (ret);\n";
5376         pr "      free (out);\n";
5377         pr "      return NULL;\n";
5378         pr "    }\n";
5379         pr "\n";
5380         pr "    ++i;\n";
5381         pr "    p = pend;\n";
5382         pr "  }\n";
5383         pr "\n";
5384         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5385         pr "\n";
5386         pr "  free (out);\n";
5387         pr "  return ret;\n";
5388         pr "}\n"
5389
5390   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5391
5392 (* Generate a list of function names, for debugging in the daemon.. *)
5393 and generate_daemon_names () =
5394   generate_header CStyle GPLv2;
5395
5396   pr "#include <config.h>\n";
5397   pr "\n";
5398   pr "#include \"daemon.h\"\n";
5399   pr "\n";
5400
5401   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5402   pr "const char *function_names[] = {\n";
5403   List.iter (
5404     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5405   ) daemon_functions;
5406   pr "};\n";
5407
5408 (* Generate the tests. *)
5409 and generate_tests () =
5410   generate_header CStyle GPLv2;
5411
5412   pr "\
5413 #include <stdio.h>
5414 #include <stdlib.h>
5415 #include <string.h>
5416 #include <unistd.h>
5417 #include <sys/types.h>
5418 #include <fcntl.h>
5419
5420 #include \"guestfs.h\"
5421
5422 static guestfs_h *g;
5423 static int suppress_error = 0;
5424
5425 static void print_error (guestfs_h *g, void *data, const char *msg)
5426 {
5427   if (!suppress_error)
5428     fprintf (stderr, \"%%s\\n\", msg);
5429 }
5430
5431 /* FIXME: nearly identical code appears in fish.c */
5432 static void print_strings (char *const *argv)
5433 {
5434   int argc;
5435
5436   for (argc = 0; argv[argc] != NULL; ++argc)
5437     printf (\"\\t%%s\\n\", argv[argc]);
5438 }
5439
5440 /*
5441 static void print_table (char const *const *argv)
5442 {
5443   int i;
5444
5445   for (i = 0; argv[i] != NULL; i += 2)
5446     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5447 }
5448 */
5449
5450 ";
5451
5452   (* Generate a list of commands which are not tested anywhere. *)
5453   pr "static void no_test_warnings (void)\n";
5454   pr "{\n";
5455
5456   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5457   List.iter (
5458     fun (_, _, _, _, tests, _, _) ->
5459       let tests = filter_map (
5460         function
5461         | (_, (Always|If _|Unless _), test) -> Some test
5462         | (_, Disabled, _) -> None
5463       ) tests in
5464       let seq = List.concat (List.map seq_of_test tests) in
5465       let cmds_tested = List.map List.hd seq in
5466       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5467   ) all_functions;
5468
5469   List.iter (
5470     fun (name, _, _, _, _, _, _) ->
5471       if not (Hashtbl.mem hash name) then
5472         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5473   ) all_functions;
5474
5475   pr "}\n";
5476   pr "\n";
5477
5478   (* Generate the actual tests.  Note that we generate the tests
5479    * in reverse order, deliberately, so that (in general) the
5480    * newest tests run first.  This makes it quicker and easier to
5481    * debug them.
5482    *)
5483   let test_names =
5484     List.map (
5485       fun (name, _, _, _, tests, _, _) ->
5486         mapi (generate_one_test name) tests
5487     ) (List.rev all_functions) in
5488   let test_names = List.concat test_names in
5489   let nr_tests = List.length test_names in
5490
5491   pr "\
5492 int main (int argc, char *argv[])
5493 {
5494   char c = 0;
5495   unsigned long int n_failed = 0;
5496   const char *filename;
5497   int fd;
5498   int nr_tests, test_num = 0;
5499
5500   setbuf (stdout, NULL);
5501
5502   no_test_warnings ();
5503
5504   g = guestfs_create ();
5505   if (g == NULL) {
5506     printf (\"guestfs_create FAILED\\n\");
5507     exit (1);
5508   }
5509
5510   guestfs_set_error_handler (g, print_error, NULL);
5511
5512   guestfs_set_path (g, \"../appliance\");
5513
5514   filename = \"test1.img\";
5515   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5516   if (fd == -1) {
5517     perror (filename);
5518     exit (1);
5519   }
5520   if (lseek (fd, %d, SEEK_SET) == -1) {
5521     perror (\"lseek\");
5522     close (fd);
5523     unlink (filename);
5524     exit (1);
5525   }
5526   if (write (fd, &c, 1) == -1) {
5527     perror (\"write\");
5528     close (fd);
5529     unlink (filename);
5530     exit (1);
5531   }
5532   if (close (fd) == -1) {
5533     perror (filename);
5534     unlink (filename);
5535     exit (1);
5536   }
5537   if (guestfs_add_drive (g, filename) == -1) {
5538     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5539     exit (1);
5540   }
5541
5542   filename = \"test2.img\";
5543   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5544   if (fd == -1) {
5545     perror (filename);
5546     exit (1);
5547   }
5548   if (lseek (fd, %d, SEEK_SET) == -1) {
5549     perror (\"lseek\");
5550     close (fd);
5551     unlink (filename);
5552     exit (1);
5553   }
5554   if (write (fd, &c, 1) == -1) {
5555     perror (\"write\");
5556     close (fd);
5557     unlink (filename);
5558     exit (1);
5559   }
5560   if (close (fd) == -1) {
5561     perror (filename);
5562     unlink (filename);
5563     exit (1);
5564   }
5565   if (guestfs_add_drive (g, filename) == -1) {
5566     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5567     exit (1);
5568   }
5569
5570   filename = \"test3.img\";
5571   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5572   if (fd == -1) {
5573     perror (filename);
5574     exit (1);
5575   }
5576   if (lseek (fd, %d, SEEK_SET) == -1) {
5577     perror (\"lseek\");
5578     close (fd);
5579     unlink (filename);
5580     exit (1);
5581   }
5582   if (write (fd, &c, 1) == -1) {
5583     perror (\"write\");
5584     close (fd);
5585     unlink (filename);
5586     exit (1);
5587   }
5588   if (close (fd) == -1) {
5589     perror (filename);
5590     unlink (filename);
5591     exit (1);
5592   }
5593   if (guestfs_add_drive (g, filename) == -1) {
5594     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5595     exit (1);
5596   }
5597
5598   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
5599     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
5600     exit (1);
5601   }
5602
5603   if (guestfs_launch (g) == -1) {
5604     printf (\"guestfs_launch FAILED\\n\");
5605     exit (1);
5606   }
5607
5608   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5609   alarm (600);
5610
5611   if (guestfs_wait_ready (g) == -1) {
5612     printf (\"guestfs_wait_ready FAILED\\n\");
5613     exit (1);
5614   }
5615
5616   /* Cancel previous alarm. */
5617   alarm (0);
5618
5619   nr_tests = %d;
5620
5621 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5622
5623   iteri (
5624     fun i test_name ->
5625       pr "  test_num++;\n";
5626       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5627       pr "  if (%s () == -1) {\n" test_name;
5628       pr "    printf (\"%s FAILED\\n\");\n" test_name;
5629       pr "    n_failed++;\n";
5630       pr "  }\n";
5631   ) test_names;
5632   pr "\n";
5633
5634   pr "  guestfs_close (g);\n";
5635   pr "  unlink (\"test1.img\");\n";
5636   pr "  unlink (\"test2.img\");\n";
5637   pr "  unlink (\"test3.img\");\n";
5638   pr "\n";
5639
5640   pr "  if (n_failed > 0) {\n";
5641   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
5642   pr "    exit (1);\n";
5643   pr "  }\n";
5644   pr "\n";
5645
5646   pr "  exit (0);\n";
5647   pr "}\n"
5648
5649 and generate_one_test name i (init, prereq, test) =
5650   let test_name = sprintf "test_%s_%d" name i in
5651
5652   pr "\
5653 static int %s_skip (void)
5654 {
5655   const char *str;
5656
5657   str = getenv (\"TEST_ONLY\");
5658   if (str)
5659     return strstr (str, \"%s\") == NULL;
5660   str = getenv (\"SKIP_%s\");
5661   if (str && strcmp (str, \"1\") == 0) return 1;
5662   str = getenv (\"SKIP_TEST_%s\");
5663   if (str && strcmp (str, \"1\") == 0) return 1;
5664   return 0;
5665 }
5666
5667 " test_name name (String.uppercase test_name) (String.uppercase name);
5668
5669   (match prereq with
5670    | Disabled | Always -> ()
5671    | If code | Unless code ->
5672        pr "static int %s_prereq (void)\n" test_name;
5673        pr "{\n";
5674        pr "  %s\n" code;
5675        pr "}\n";
5676        pr "\n";
5677   );
5678
5679   pr "\
5680 static int %s (void)
5681 {
5682   if (%s_skip ()) {
5683     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
5684     return 0;
5685   }
5686
5687 " test_name test_name test_name;
5688
5689   (match prereq with
5690    | Disabled ->
5691        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5692    | If _ ->
5693        pr "  if (! %s_prereq ()) {\n" test_name;
5694        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5695        pr "    return 0;\n";
5696        pr "  }\n";
5697        pr "\n";
5698        generate_one_test_body name i test_name init test;
5699    | Unless _ ->
5700        pr "  if (%s_prereq ()) {\n" test_name;
5701        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5702        pr "    return 0;\n";
5703        pr "  }\n";
5704        pr "\n";
5705        generate_one_test_body name i test_name init test;
5706    | Always ->
5707        generate_one_test_body name i test_name init test
5708   );
5709
5710   pr "  return 0;\n";
5711   pr "}\n";
5712   pr "\n";
5713   test_name
5714
5715 and generate_one_test_body name i test_name init test =
5716   (match init with
5717    | InitNone (* XXX at some point, InitNone and InitEmpty became
5718                * folded together as the same thing.  Really we should
5719                * make InitNone do nothing at all, but the tests may
5720                * need to be checked to make sure this is OK.
5721                *)
5722    | InitEmpty ->
5723        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
5724        List.iter (generate_test_command_call test_name)
5725          [["blockdev_setrw"; "/dev/sda"];
5726           ["umount_all"];
5727           ["lvm_remove_all"]]
5728    | InitPartition ->
5729        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5730        List.iter (generate_test_command_call test_name)
5731          [["blockdev_setrw"; "/dev/sda"];
5732           ["umount_all"];
5733           ["lvm_remove_all"];
5734           ["sfdiskM"; "/dev/sda"; ","]]
5735    | InitBasicFS ->
5736        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5737        List.iter (generate_test_command_call test_name)
5738          [["blockdev_setrw"; "/dev/sda"];
5739           ["umount_all"];
5740           ["lvm_remove_all"];
5741           ["sfdiskM"; "/dev/sda"; ","];
5742           ["mkfs"; "ext2"; "/dev/sda1"];
5743           ["mount"; "/dev/sda1"; "/"]]
5744    | InitBasicFSonLVM ->
5745        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5746          test_name;
5747        List.iter (generate_test_command_call test_name)
5748          [["blockdev_setrw"; "/dev/sda"];
5749           ["umount_all"];
5750           ["lvm_remove_all"];
5751           ["sfdiskM"; "/dev/sda"; ","];
5752           ["pvcreate"; "/dev/sda1"];
5753           ["vgcreate"; "VG"; "/dev/sda1"];
5754           ["lvcreate"; "LV"; "VG"; "8"];
5755           ["mkfs"; "ext2"; "/dev/VG/LV"];
5756           ["mount"; "/dev/VG/LV"; "/"]]
5757    | InitISOFS ->
5758        pr "  /* InitISOFS for %s */\n" test_name;
5759        List.iter (generate_test_command_call test_name)
5760          [["blockdev_setrw"; "/dev/sda"];
5761           ["umount_all"];
5762           ["lvm_remove_all"];
5763           ["mount_ro"; "/dev/sdd"; "/"]]
5764   );
5765
5766   let get_seq_last = function
5767     | [] ->
5768         failwithf "%s: you cannot use [] (empty list) when expecting a command"
5769           test_name
5770     | seq ->
5771         let seq = List.rev seq in
5772         List.rev (List.tl seq), List.hd seq
5773   in
5774
5775   match test with
5776   | TestRun seq ->
5777       pr "  /* TestRun for %s (%d) */\n" name i;
5778       List.iter (generate_test_command_call test_name) seq
5779   | TestOutput (seq, expected) ->
5780       pr "  /* TestOutput for %s (%d) */\n" name i;
5781       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5782       let seq, last = get_seq_last seq in
5783       let test () =
5784         pr "    if (strcmp (r, expected) != 0) {\n";
5785         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5786         pr "      return -1;\n";
5787         pr "    }\n"
5788       in
5789       List.iter (generate_test_command_call test_name) seq;
5790       generate_test_command_call ~test test_name last
5791   | TestOutputList (seq, expected) ->
5792       pr "  /* TestOutputList for %s (%d) */\n" name i;
5793       let seq, last = get_seq_last seq in
5794       let test () =
5795         iteri (
5796           fun i str ->
5797             pr "    if (!r[%d]) {\n" i;
5798             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5799             pr "      print_strings (r);\n";
5800             pr "      return -1;\n";
5801             pr "    }\n";
5802             pr "    {\n";
5803             pr "      const char *expected = \"%s\";\n" (c_quote str);
5804             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5805             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5806             pr "        return -1;\n";
5807             pr "      }\n";
5808             pr "    }\n"
5809         ) expected;
5810         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5811         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5812           test_name;
5813         pr "      print_strings (r);\n";
5814         pr "      return -1;\n";
5815         pr "    }\n"
5816       in
5817       List.iter (generate_test_command_call test_name) seq;
5818       generate_test_command_call ~test test_name last
5819   | TestOutputListOfDevices (seq, expected) ->
5820       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
5821       let seq, last = get_seq_last seq in
5822       let test () =
5823         iteri (
5824           fun i str ->
5825             pr "    if (!r[%d]) {\n" i;
5826             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5827             pr "      print_strings (r);\n";
5828             pr "      return -1;\n";
5829             pr "    }\n";
5830             pr "    {\n";
5831             pr "      const char *expected = \"%s\";\n" (c_quote str);
5832             pr "      r[%d][5] = 's';\n" i;
5833             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5834             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5835             pr "        return -1;\n";
5836             pr "      }\n";
5837             pr "    }\n"
5838         ) expected;
5839         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5840         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5841           test_name;
5842         pr "      print_strings (r);\n";
5843         pr "      return -1;\n";
5844         pr "    }\n"
5845       in
5846       List.iter (generate_test_command_call test_name) seq;
5847       generate_test_command_call ~test test_name last
5848   | TestOutputInt (seq, expected) ->
5849       pr "  /* TestOutputInt for %s (%d) */\n" name i;
5850       let seq, last = get_seq_last seq in
5851       let test () =
5852         pr "    if (r != %d) {\n" expected;
5853         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5854           test_name expected;
5855         pr "               (int) r);\n";
5856         pr "      return -1;\n";
5857         pr "    }\n"
5858       in
5859       List.iter (generate_test_command_call test_name) seq;
5860       generate_test_command_call ~test test_name last
5861   | TestOutputIntOp (seq, op, expected) ->
5862       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
5863       let seq, last = get_seq_last seq in
5864       let test () =
5865         pr "    if (! (r %s %d)) {\n" op expected;
5866         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5867           test_name op expected;
5868         pr "               (int) r);\n";
5869         pr "      return -1;\n";
5870         pr "    }\n"
5871       in
5872       List.iter (generate_test_command_call test_name) seq;
5873       generate_test_command_call ~test test_name last
5874   | TestOutputTrue seq ->
5875       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
5876       let seq, last = get_seq_last seq in
5877       let test () =
5878         pr "    if (!r) {\n";
5879         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5880           test_name;
5881         pr "      return -1;\n";
5882         pr "    }\n"
5883       in
5884       List.iter (generate_test_command_call test_name) seq;
5885       generate_test_command_call ~test test_name last
5886   | TestOutputFalse seq ->
5887       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
5888       let seq, last = get_seq_last seq in
5889       let test () =
5890         pr "    if (r) {\n";
5891         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
5892           test_name;
5893         pr "      return -1;\n";
5894         pr "    }\n"
5895       in
5896       List.iter (generate_test_command_call test_name) seq;
5897       generate_test_command_call ~test test_name last
5898   | TestOutputLength (seq, expected) ->
5899       pr "  /* TestOutputLength for %s (%d) */\n" name i;
5900       let seq, last = get_seq_last seq in
5901       let test () =
5902         pr "    int j;\n";
5903         pr "    for (j = 0; j < %d; ++j)\n" expected;
5904         pr "      if (r[j] == NULL) {\n";
5905         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
5906           test_name;
5907         pr "        print_strings (r);\n";
5908         pr "        return -1;\n";
5909         pr "      }\n";
5910         pr "    if (r[j] != NULL) {\n";
5911         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
5912           test_name;
5913         pr "      print_strings (r);\n";
5914         pr "      return -1;\n";
5915         pr "    }\n"
5916       in
5917       List.iter (generate_test_command_call test_name) seq;
5918       generate_test_command_call ~test test_name last
5919   | TestOutputBuffer (seq, expected) ->
5920       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
5921       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5922       let seq, last = get_seq_last seq in
5923       let len = String.length expected in
5924       let test () =
5925         pr "    if (size != %d) {\n" len;
5926         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
5927         pr "      return -1;\n";
5928         pr "    }\n";
5929         pr "    if (strncmp (r, expected, size) != 0) {\n";
5930         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5931         pr "      return -1;\n";
5932         pr "    }\n"
5933       in
5934       List.iter (generate_test_command_call test_name) seq;
5935       generate_test_command_call ~test test_name last
5936   | TestOutputStruct (seq, checks) ->
5937       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
5938       let seq, last = get_seq_last seq in
5939       let test () =
5940         List.iter (
5941           function
5942           | CompareWithInt (field, expected) ->
5943               pr "    if (r->%s != %d) {\n" field expected;
5944               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
5945                 test_name field expected;
5946               pr "               (int) r->%s);\n" field;
5947               pr "      return -1;\n";
5948               pr "    }\n"
5949           | CompareWithIntOp (field, op, expected) ->
5950               pr "    if (!(r->%s %s %d)) {\n" field op expected;
5951               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
5952                 test_name field op expected;
5953               pr "               (int) r->%s);\n" field;
5954               pr "      return -1;\n";
5955               pr "    }\n"
5956           | CompareWithString (field, expected) ->
5957               pr "    if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
5958               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
5959                 test_name field expected;
5960               pr "               r->%s);\n" field;
5961               pr "      return -1;\n";
5962               pr "    }\n"
5963           | CompareFieldsIntEq (field1, field2) ->
5964               pr "    if (r->%s != r->%s) {\n" field1 field2;
5965               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
5966                 test_name field1 field2;
5967               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
5968               pr "      return -1;\n";
5969               pr "    }\n"
5970           | CompareFieldsStrEq (field1, field2) ->
5971               pr "    if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
5972               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
5973                 test_name field1 field2;
5974               pr "               r->%s, r->%s);\n" field1 field2;
5975               pr "      return -1;\n";
5976               pr "    }\n"
5977         ) checks
5978       in
5979       List.iter (generate_test_command_call test_name) seq;
5980       generate_test_command_call ~test test_name last
5981   | TestLastFail seq ->
5982       pr "  /* TestLastFail for %s (%d) */\n" name i;
5983       let seq, last = get_seq_last seq in
5984       List.iter (generate_test_command_call test_name) seq;
5985       generate_test_command_call test_name ~expect_error:true last
5986
5987 (* Generate the code to run a command, leaving the result in 'r'.
5988  * If you expect to get an error then you should set expect_error:true.
5989  *)
5990 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
5991   match cmd with
5992   | [] -> assert false
5993   | name :: args ->
5994       (* Look up the command to find out what args/ret it has. *)
5995       let style =
5996         try
5997           let _, style, _, _, _, _, _ =
5998             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
5999           style
6000         with Not_found ->
6001           failwithf "%s: in test, command %s was not found" test_name name in
6002
6003       if List.length (snd style) <> List.length args then
6004         failwithf "%s: in test, wrong number of args given to %s"
6005           test_name name;
6006
6007       pr "  {\n";
6008
6009       List.iter (
6010         function
6011         | OptString n, "NULL" -> ()
6012         | Pathname n, arg
6013         | Device n, arg
6014         | Dev_or_Path n, arg
6015         | String n, arg
6016         | OptString n, arg ->
6017             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6018         | Int _, _
6019         | Bool _, _
6020         | FileIn _, _ | FileOut _, _ -> ()
6021         | StringList n, arg | DeviceList n, arg ->
6022             let strs = string_split " " arg in
6023             iteri (
6024               fun i str ->
6025                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6026             ) strs;
6027             pr "    const char *const %s[] = {\n" n;
6028             iteri (
6029               fun i _ -> pr "      %s_%d,\n" n i
6030             ) strs;
6031             pr "      NULL\n";
6032             pr "    };\n";
6033       ) (List.combine (snd style) args);
6034
6035       let error_code =
6036         match fst style with
6037         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6038         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6039         | RConstString _ | RConstOptString _ ->
6040             pr "    const char *r;\n"; "NULL"
6041         | RString _ -> pr "    char *r;\n"; "NULL"
6042         | RStringList _ | RHashtable _ ->
6043             pr "    char **r;\n";
6044             pr "    int i;\n";
6045             "NULL"
6046         | RStruct (_, typ) ->
6047             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6048         | RStructList (_, typ) ->
6049             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6050         | RBufferOut _ ->
6051             pr "    char *r;\n";
6052             pr "    size_t size;\n";
6053             "NULL" in
6054
6055       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6056       pr "    r = guestfs_%s (g" name;
6057
6058       (* Generate the parameters. *)
6059       List.iter (
6060         function
6061         | OptString _, "NULL" -> pr ", NULL"
6062         | Pathname n, _
6063         | Device n, _ | Dev_or_Path n, _
6064         | String n, _
6065         | OptString n, _ ->
6066             pr ", %s" n
6067         | FileIn _, arg | FileOut _, arg ->
6068             pr ", \"%s\"" (c_quote arg)
6069         | StringList n, _ | DeviceList n, _ ->
6070             pr ", (char **) %s" n
6071         | Int _, arg ->
6072             let i =
6073               try int_of_string arg
6074               with Failure "int_of_string" ->
6075                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6076             pr ", %d" i
6077         | Bool _, arg ->
6078             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6079       ) (List.combine (snd style) args);
6080
6081       (match fst style with
6082        | RBufferOut _ -> pr ", &size"
6083        | _ -> ()
6084       );
6085
6086       pr ");\n";
6087
6088       if not expect_error then
6089         pr "    if (r == %s)\n" error_code
6090       else
6091         pr "    if (r != %s)\n" error_code;
6092       pr "      return -1;\n";
6093
6094       (* Insert the test code. *)
6095       (match test with
6096        | None -> ()
6097        | Some f -> f ()
6098       );
6099
6100       (match fst style with
6101        | RErr | RInt _ | RInt64 _ | RBool _
6102        | RConstString _ | RConstOptString _ -> ()
6103        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6104        | RStringList _ | RHashtable _ ->
6105            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6106            pr "      free (r[i]);\n";
6107            pr "    free (r);\n"
6108        | RStruct (_, typ) ->
6109            pr "    guestfs_free_%s (r);\n" typ
6110        | RStructList (_, typ) ->
6111            pr "    guestfs_free_%s_list (r);\n" typ
6112       );
6113
6114       pr "  }\n"
6115
6116 and c_quote str =
6117   let str = replace_str str "\r" "\\r" in
6118   let str = replace_str str "\n" "\\n" in
6119   let str = replace_str str "\t" "\\t" in
6120   let str = replace_str str "\000" "\\0" in
6121   str
6122
6123 (* Generate a lot of different functions for guestfish. *)
6124 and generate_fish_cmds () =
6125   generate_header CStyle GPLv2;
6126
6127   let all_functions =
6128     List.filter (
6129       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6130     ) all_functions in
6131   let all_functions_sorted =
6132     List.filter (
6133       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6134     ) all_functions_sorted in
6135
6136   pr "#include <stdio.h>\n";
6137   pr "#include <stdlib.h>\n";
6138   pr "#include <string.h>\n";
6139   pr "#include <inttypes.h>\n";
6140   pr "#include <ctype.h>\n";
6141   pr "\n";
6142   pr "#include <guestfs.h>\n";
6143   pr "#include \"fish.h\"\n";
6144   pr "\n";
6145
6146   (* list_commands function, which implements guestfish -h *)
6147   pr "void list_commands (void)\n";
6148   pr "{\n";
6149   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6150   pr "  list_builtin_commands ();\n";
6151   List.iter (
6152     fun (name, _, _, flags, _, shortdesc, _) ->
6153       let name = replace_char name '_' '-' in
6154       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6155         name shortdesc
6156   ) all_functions_sorted;
6157   pr "  printf (\"    %%s\\n\",";
6158   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6159   pr "}\n";
6160   pr "\n";
6161
6162   (* display_command function, which implements guestfish -h cmd *)
6163   pr "void display_command (const char *cmd)\n";
6164   pr "{\n";
6165   List.iter (
6166     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6167       let name2 = replace_char name '_' '-' in
6168       let alias =
6169         try find_map (function FishAlias n -> Some n | _ -> None) flags
6170         with Not_found -> name in
6171       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6172       let synopsis =
6173         match snd style with
6174         | [] -> name2
6175         | args ->
6176             sprintf "%s <%s>"
6177               name2 (String.concat "> <" (List.map name_of_argt args)) in
6178
6179       let warnings =
6180         if List.mem ProtocolLimitWarning flags then
6181           ("\n\n" ^ protocol_limit_warning)
6182         else "" in
6183
6184       (* For DangerWillRobinson commands, we should probably have
6185        * guestfish prompt before allowing you to use them (especially
6186        * in interactive mode). XXX
6187        *)
6188       let warnings =
6189         warnings ^
6190           if List.mem DangerWillRobinson flags then
6191             ("\n\n" ^ danger_will_robinson)
6192           else "" in
6193
6194       let warnings =
6195         warnings ^
6196           match deprecation_notice flags with
6197           | None -> ""
6198           | Some txt -> "\n\n" ^ txt in
6199
6200       let describe_alias =
6201         if name <> alias then
6202           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6203         else "" in
6204
6205       pr "  if (";
6206       pr "strcasecmp (cmd, \"%s\") == 0" name;
6207       if name <> name2 then
6208         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6209       if name <> alias then
6210         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6211       pr ")\n";
6212       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6213         name2 shortdesc
6214         (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
6215       pr "  else\n"
6216   ) all_functions;
6217   pr "    display_builtin_command (cmd);\n";
6218   pr "}\n";
6219   pr "\n";
6220
6221   let emit_print_list_function typ =
6222     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6223       typ typ typ;
6224     pr "{\n";
6225     pr "  unsigned int i;\n";
6226     pr "\n";
6227     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6228     pr "    printf (\"[%%d] = {\\n\", i);\n";
6229     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6230     pr "    printf (\"}\\n\");\n";
6231     pr "  }\n";
6232     pr "}\n";
6233     pr "\n";
6234   in
6235
6236   (* print_* functions *)
6237   List.iter (
6238     fun (typ, cols) ->
6239       let needs_i =
6240         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6241
6242       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6243       pr "{\n";
6244       if needs_i then (
6245         pr "  unsigned int i;\n";
6246         pr "\n"
6247       );
6248       List.iter (
6249         function
6250         | name, FString ->
6251             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6252         | name, FUUID ->
6253             pr "  printf (\"%s: \");\n" name;
6254             pr "  for (i = 0; i < 32; ++i)\n";
6255             pr "    printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6256             pr "  printf (\"\\n\");\n"
6257         | name, FBuffer ->
6258             pr "  printf (\"%%s%s: \", indent);\n" name;
6259             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6260             pr "    if (isprint (%s->%s[i]))\n" typ name;
6261             pr "      printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6262             pr "    else\n";
6263             pr "      printf (\"%%s\\\\x%%02x\", indent, %s->%s[i]);\n" typ name;
6264             pr "  printf (\"\\n\");\n"
6265         | name, (FUInt64|FBytes) ->
6266             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6267               name typ name
6268         | name, FInt64 ->
6269             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6270               name typ name
6271         | name, FUInt32 ->
6272             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6273               name typ name
6274         | name, FInt32 ->
6275             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6276               name typ name
6277         | name, FChar ->
6278             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6279               name typ name
6280         | name, FOptPercent ->
6281             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6282               typ name name typ name;
6283             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6284       ) cols;
6285       pr "}\n";
6286       pr "\n";
6287   ) structs;
6288
6289   (* Emit a print_TYPE_list function definition only if that function is used. *)
6290   List.iter (
6291     function
6292     | typ, (RStructListOnly | RStructAndList) ->
6293         (* generate the function for typ *)
6294         emit_print_list_function typ
6295     | typ, _ -> () (* empty *)
6296   ) rstructs_used;
6297
6298   (* Emit a print_TYPE function definition only if that function is used. *)
6299   List.iter (
6300     function
6301     | typ, RStructOnly ->
6302         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6303         pr "{\n";
6304         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6305         pr "}\n";
6306         pr "\n";
6307     | typ, _ -> () (* empty *)
6308   ) rstructs_used;
6309
6310   (* run_<action> actions *)
6311   List.iter (
6312     fun (name, style, _, flags, _, _, _) ->
6313       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6314       pr "{\n";
6315       (match fst style with
6316        | RErr
6317        | RInt _
6318        | RBool _ -> pr "  int r;\n"
6319        | RInt64 _ -> pr "  int64_t r;\n"
6320        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6321        | RString _ -> pr "  char *r;\n"
6322        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6323        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6324        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6325        | RBufferOut _ ->
6326            pr "  char *r;\n";
6327            pr "  size_t size;\n";
6328       );
6329       List.iter (
6330         function
6331         | Pathname n
6332         | Device n | Dev_or_Path n
6333         | String n
6334         | OptString n
6335         | FileIn n
6336         | FileOut n -> pr "  const char *%s;\n" n
6337         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6338         | Bool n -> pr "  int %s;\n" n
6339         | Int n -> pr "  int %s;\n" n
6340       ) (snd style);
6341
6342       (* Check and convert parameters. *)
6343       let argc_expected = List.length (snd style) in
6344       pr "  if (argc != %d) {\n" argc_expected;
6345       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6346         argc_expected;
6347       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6348       pr "    return -1;\n";
6349       pr "  }\n";
6350       iteri (
6351         fun i ->
6352           function
6353           | Pathname name
6354           | Device name | Dev_or_Path name | String name -> pr "  %s = argv[%d];\n" name i
6355           | OptString name ->
6356               pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6357                 name i i
6358           | FileIn name ->
6359               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6360                 name i i
6361           | FileOut name ->
6362               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6363                 name i i
6364           | StringList name | DeviceList name ->
6365               pr "  %s = parse_string_list (argv[%d]);\n" name i
6366           | Bool name ->
6367               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6368           | Int name ->
6369               pr "  %s = atoi (argv[%d]);\n" name i
6370       ) (snd style);
6371
6372       (* Call C API function. *)
6373       let fn =
6374         try find_map (function FishAction n -> Some n | _ -> None) flags
6375         with Not_found -> sprintf "guestfs_%s" name in
6376       pr "  r = %s " fn;
6377       generate_c_call_args ~handle:"g" style;
6378       pr ";\n";
6379
6380       List.iter (
6381         function
6382         | Pathname name | Device name | Dev_or_Path name | String name
6383         | OptString name | FileIn name | FileOut name | Bool name
6384         | Int name -> ()
6385         | StringList name | DeviceList name ->
6386             pr "  free_strings (%s);\n" name
6387       ) (snd style);
6388
6389       (* Check return value for errors and display command results. *)
6390       (match fst style with
6391        | RErr -> pr "  return r;\n"
6392        | RInt _ ->
6393            pr "  if (r == -1) return -1;\n";
6394            pr "  printf (\"%%d\\n\", r);\n";
6395            pr "  return 0;\n"
6396        | RInt64 _ ->
6397            pr "  if (r == -1) return -1;\n";
6398            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6399            pr "  return 0;\n"
6400        | RBool _ ->
6401            pr "  if (r == -1) return -1;\n";
6402            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6403            pr "  return 0;\n"
6404        | RConstString _ ->
6405            pr "  if (r == NULL) return -1;\n";
6406            pr "  printf (\"%%s\\n\", r);\n";
6407            pr "  return 0;\n"
6408        | RConstOptString _ ->
6409            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6410            pr "  return 0;\n"
6411        | RString _ ->
6412            pr "  if (r == NULL) return -1;\n";
6413            pr "  printf (\"%%s\\n\", r);\n";
6414            pr "  free (r);\n";
6415            pr "  return 0;\n"
6416        | RStringList _ ->
6417            pr "  if (r == NULL) return -1;\n";
6418            pr "  print_strings (r);\n";
6419            pr "  free_strings (r);\n";
6420            pr "  return 0;\n"
6421        | RStruct (_, typ) ->
6422            pr "  if (r == NULL) return -1;\n";
6423            pr "  print_%s (r);\n" typ;
6424            pr "  guestfs_free_%s (r);\n" typ;
6425            pr "  return 0;\n"
6426        | RStructList (_, typ) ->
6427            pr "  if (r == NULL) return -1;\n";
6428            pr "  print_%s_list (r);\n" typ;
6429            pr "  guestfs_free_%s_list (r);\n" typ;
6430            pr "  return 0;\n"
6431        | RHashtable _ ->
6432            pr "  if (r == NULL) return -1;\n";
6433            pr "  print_table (r);\n";
6434            pr "  free_strings (r);\n";
6435            pr "  return 0;\n"
6436        | RBufferOut _ ->
6437            pr "  if (r == NULL) return -1;\n";
6438            pr "  fwrite (r, size, 1, stdout);\n";
6439            pr "  free (r);\n";
6440            pr "  return 0;\n"
6441       );
6442       pr "}\n";
6443       pr "\n"
6444   ) all_functions;
6445
6446   (* run_action function *)
6447   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6448   pr "{\n";
6449   List.iter (
6450     fun (name, _, _, flags, _, _, _) ->
6451       let name2 = replace_char name '_' '-' in
6452       let alias =
6453         try find_map (function FishAlias n -> Some n | _ -> None) flags
6454         with Not_found -> name in
6455       pr "  if (";
6456       pr "strcasecmp (cmd, \"%s\") == 0" name;
6457       if name <> name2 then
6458         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6459       if name <> alias then
6460         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6461       pr ")\n";
6462       pr "    return run_%s (cmd, argc, argv);\n" name;
6463       pr "  else\n";
6464   ) all_functions;
6465   pr "    {\n";
6466   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6467   pr "      return -1;\n";
6468   pr "    }\n";
6469   pr "  return 0;\n";
6470   pr "}\n";
6471   pr "\n"
6472
6473 (* Readline completion for guestfish. *)
6474 and generate_fish_completion () =
6475   generate_header CStyle GPLv2;
6476
6477   let all_functions =
6478     List.filter (
6479       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6480     ) all_functions in
6481
6482   pr "\
6483 #include <config.h>
6484
6485 #include <stdio.h>
6486 #include <stdlib.h>
6487 #include <string.h>
6488
6489 #ifdef HAVE_LIBREADLINE
6490 #include <readline/readline.h>
6491 #endif
6492
6493 #include \"fish.h\"
6494
6495 #ifdef HAVE_LIBREADLINE
6496
6497 static const char *const commands[] = {
6498   BUILTIN_COMMANDS_FOR_COMPLETION,
6499 ";
6500
6501   (* Get the commands, including the aliases.  They don't need to be
6502    * sorted - the generator() function just does a dumb linear search.
6503    *)
6504   let commands =
6505     List.map (
6506       fun (name, _, _, flags, _, _, _) ->
6507         let name2 = replace_char name '_' '-' in
6508         let alias =
6509           try find_map (function FishAlias n -> Some n | _ -> None) flags
6510           with Not_found -> name in
6511
6512         if name <> alias then [name2; alias] else [name2]
6513     ) all_functions in
6514   let commands = List.flatten commands in
6515
6516   List.iter (pr "  \"%s\",\n") commands;
6517
6518   pr "  NULL
6519 };
6520
6521 static char *
6522 generator (const char *text, int state)
6523 {
6524   static int index, len;
6525   const char *name;
6526
6527   if (!state) {
6528     index = 0;
6529     len = strlen (text);
6530   }
6531
6532   rl_attempted_completion_over = 1;
6533
6534   while ((name = commands[index]) != NULL) {
6535     index++;
6536     if (strncasecmp (name, text, len) == 0)
6537       return strdup (name);
6538   }
6539
6540   return NULL;
6541 }
6542
6543 #endif /* HAVE_LIBREADLINE */
6544
6545 char **do_completion (const char *text, int start, int end)
6546 {
6547   char **matches = NULL;
6548
6549 #ifdef HAVE_LIBREADLINE
6550   rl_completion_append_character = ' ';
6551
6552   if (start == 0)
6553     matches = rl_completion_matches (text, generator);
6554   else if (complete_dest_paths)
6555     matches = rl_completion_matches (text, complete_dest_paths_generator);
6556 #endif
6557
6558   return matches;
6559 }
6560 ";
6561
6562 (* Generate the POD documentation for guestfish. *)
6563 and generate_fish_actions_pod () =
6564   let all_functions_sorted =
6565     List.filter (
6566       fun (_, _, _, flags, _, _, _) ->
6567         not (List.mem NotInFish flags || List.mem NotInDocs flags)
6568     ) all_functions_sorted in
6569
6570   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6571
6572   List.iter (
6573     fun (name, style, _, flags, _, _, longdesc) ->
6574       let longdesc =
6575         Str.global_substitute rex (
6576           fun s ->
6577             let sub =
6578               try Str.matched_group 1 s
6579               with Not_found ->
6580                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6581             "C<" ^ replace_char sub '_' '-' ^ ">"
6582         ) longdesc in
6583       let name = replace_char name '_' '-' in
6584       let alias =
6585         try find_map (function FishAlias n -> Some n | _ -> None) flags
6586         with Not_found -> name in
6587
6588       pr "=head2 %s" name;
6589       if name <> alias then
6590         pr " | %s" alias;
6591       pr "\n";
6592       pr "\n";
6593       pr " %s" name;
6594       List.iter (
6595         function
6596         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6597         | OptString n -> pr " %s" n
6598         | StringList n | DeviceList n -> pr " '%s ...'" n
6599         | Bool _ -> pr " true|false"
6600         | Int n -> pr " %s" n
6601         | FileIn n | FileOut n -> pr " (%s|-)" n
6602       ) (snd style);
6603       pr "\n";
6604       pr "\n";
6605       pr "%s\n\n" longdesc;
6606
6607       if List.exists (function FileIn _ | FileOut _ -> true
6608                       | _ -> false) (snd style) then
6609         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6610
6611       if List.mem ProtocolLimitWarning flags then
6612         pr "%s\n\n" protocol_limit_warning;
6613
6614       if List.mem DangerWillRobinson flags then
6615         pr "%s\n\n" danger_will_robinson;
6616
6617       match deprecation_notice flags with
6618       | None -> ()
6619       | Some txt -> pr "%s\n\n" txt
6620   ) all_functions_sorted
6621
6622 (* Generate a C function prototype. *)
6623 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6624     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6625     ?(prefix = "")
6626     ?handle name style =
6627   if extern then pr "extern ";
6628   if static then pr "static ";
6629   (match fst style with
6630    | RErr -> pr "int "
6631    | RInt _ -> pr "int "
6632    | RInt64 _ -> pr "int64_t "
6633    | RBool _ -> pr "int "
6634    | RConstString _ | RConstOptString _ -> pr "const char *"
6635    | RString _ | RBufferOut _ -> pr "char *"
6636    | RStringList _ | RHashtable _ -> pr "char **"
6637    | RStruct (_, typ) ->
6638        if not in_daemon then pr "struct guestfs_%s *" typ
6639        else pr "guestfs_int_%s *" typ
6640    | RStructList (_, typ) ->
6641        if not in_daemon then pr "struct guestfs_%s_list *" typ
6642        else pr "guestfs_int_%s_list *" typ
6643   );
6644   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6645   pr "%s%s (" prefix name;
6646   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6647     pr "void"
6648   else (
6649     let comma = ref false in
6650     (match handle with
6651      | None -> ()
6652      | Some handle -> pr "guestfs_h *%s" handle; comma := true
6653     );
6654     let next () =
6655       if !comma then (
6656         if single_line then pr ", " else pr ",\n\t\t"
6657       );
6658       comma := true
6659     in
6660     List.iter (
6661       function
6662       | Pathname n
6663       | Device n | Dev_or_Path n
6664       | String n
6665       | OptString n ->
6666           next ();
6667           pr "const char *%s" n
6668       | StringList n | DeviceList n ->
6669           next ();
6670           pr "char *const *%s" n
6671       | Bool n -> next (); pr "int %s" n
6672       | Int n -> next (); pr "int %s" n
6673       | FileIn n
6674       | FileOut n ->
6675           if not in_daemon then (next (); pr "const char *%s" n)
6676     ) (snd style);
6677     if is_RBufferOut then (next (); pr "size_t *size_r");
6678   );
6679   pr ")";
6680   if semicolon then pr ";";
6681   if newline then pr "\n"
6682
6683 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6684 and generate_c_call_args ?handle ?(decl = false) style =
6685   pr "(";
6686   let comma = ref false in
6687   let next () =
6688     if !comma then pr ", ";
6689     comma := true
6690   in
6691   (match handle with
6692    | None -> ()
6693    | Some handle -> pr "%s" handle; comma := true
6694   );
6695   List.iter (
6696     fun arg ->
6697       next ();
6698       pr "%s" (name_of_argt arg)
6699   ) (snd style);
6700   (* For RBufferOut calls, add implicit &size parameter. *)
6701   if not decl then (
6702     match fst style with
6703     | RBufferOut _ ->
6704         next ();
6705         pr "&size"
6706     | _ -> ()
6707   );
6708   pr ")"
6709
6710 (* Generate the OCaml bindings interface. *)
6711 and generate_ocaml_mli () =
6712   generate_header OCamlStyle LGPLv2;
6713
6714   pr "\
6715 (** For API documentation you should refer to the C API
6716     in the guestfs(3) manual page.  The OCaml API uses almost
6717     exactly the same calls. *)
6718
6719 type t
6720 (** A [guestfs_h] handle. *)
6721
6722 exception Error of string
6723 (** This exception is raised when there is an error. *)
6724
6725 val create : unit -> t
6726
6727 val close : t -> unit
6728 (** Handles are closed by the garbage collector when they become
6729     unreferenced, but callers can also call this in order to
6730     provide predictable cleanup. *)
6731
6732 ";
6733   generate_ocaml_structure_decls ();
6734
6735   (* The actions. *)
6736   List.iter (
6737     fun (name, style, _, _, _, shortdesc, _) ->
6738       generate_ocaml_prototype name style;
6739       pr "(** %s *)\n" shortdesc;
6740       pr "\n"
6741   ) all_functions
6742
6743 (* Generate the OCaml bindings implementation. *)
6744 and generate_ocaml_ml () =
6745   generate_header OCamlStyle LGPLv2;
6746
6747   pr "\
6748 type t
6749 exception Error of string
6750 external create : unit -> t = \"ocaml_guestfs_create\"
6751 external close : t -> unit = \"ocaml_guestfs_close\"
6752
6753 let () =
6754   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6755
6756 ";
6757
6758   generate_ocaml_structure_decls ();
6759
6760   (* The actions. *)
6761   List.iter (
6762     fun (name, style, _, _, _, shortdesc, _) ->
6763       generate_ocaml_prototype ~is_external:true name style;
6764   ) all_functions
6765
6766 (* Generate the OCaml bindings C implementation. *)
6767 and generate_ocaml_c () =
6768   generate_header CStyle LGPLv2;
6769
6770   pr "\
6771 #include <stdio.h>
6772 #include <stdlib.h>
6773 #include <string.h>
6774
6775 #include <caml/config.h>
6776 #include <caml/alloc.h>
6777 #include <caml/callback.h>
6778 #include <caml/fail.h>
6779 #include <caml/memory.h>
6780 #include <caml/mlvalues.h>
6781 #include <caml/signals.h>
6782
6783 #include <guestfs.h>
6784
6785 #include \"guestfs_c.h\"
6786
6787 /* Copy a hashtable of string pairs into an assoc-list.  We return
6788  * the list in reverse order, but hashtables aren't supposed to be
6789  * ordered anyway.
6790  */
6791 static CAMLprim value
6792 copy_table (char * const * argv)
6793 {
6794   CAMLparam0 ();
6795   CAMLlocal5 (rv, pairv, kv, vv, cons);
6796   int i;
6797
6798   rv = Val_int (0);
6799   for (i = 0; argv[i] != NULL; i += 2) {
6800     kv = caml_copy_string (argv[i]);
6801     vv = caml_copy_string (argv[i+1]);
6802     pairv = caml_alloc (2, 0);
6803     Store_field (pairv, 0, kv);
6804     Store_field (pairv, 1, vv);
6805     cons = caml_alloc (2, 0);
6806     Store_field (cons, 1, rv);
6807     rv = cons;
6808     Store_field (cons, 0, pairv);
6809   }
6810
6811   CAMLreturn (rv);
6812 }
6813
6814 ";
6815
6816   (* Struct copy functions. *)
6817
6818   let emit_ocaml_copy_list_function typ =
6819     pr "static CAMLprim value\n";
6820     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
6821     pr "{\n";
6822     pr "  CAMLparam0 ();\n";
6823     pr "  CAMLlocal2 (rv, v);\n";
6824     pr "  unsigned int i;\n";
6825     pr "\n";
6826     pr "  if (%ss->len == 0)\n" typ;
6827     pr "    CAMLreturn (Atom (0));\n";
6828     pr "  else {\n";
6829     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
6830     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
6831     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
6832     pr "      caml_modify (&Field (rv, i), v);\n";
6833     pr "    }\n";
6834     pr "    CAMLreturn (rv);\n";
6835     pr "  }\n";
6836     pr "}\n";
6837     pr "\n";
6838   in
6839
6840   List.iter (
6841     fun (typ, cols) ->
6842       let has_optpercent_col =
6843         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6844
6845       pr "static CAMLprim value\n";
6846       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6847       pr "{\n";
6848       pr "  CAMLparam0 ();\n";
6849       if has_optpercent_col then
6850         pr "  CAMLlocal3 (rv, v, v2);\n"
6851       else
6852         pr "  CAMLlocal2 (rv, v);\n";
6853       pr "\n";
6854       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
6855       iteri (
6856         fun i col ->
6857           (match col with
6858            | name, FString ->
6859                pr "  v = caml_copy_string (%s->%s);\n" typ name
6860            | name, FBuffer ->
6861                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
6862                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6863                  typ name typ name
6864            | name, FUUID ->
6865                pr "  v = caml_alloc_string (32);\n";
6866                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
6867            | name, (FBytes|FInt64|FUInt64) ->
6868                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
6869            | name, (FInt32|FUInt32) ->
6870                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
6871            | name, FOptPercent ->
6872                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
6873                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
6874                pr "    v = caml_alloc (1, 0);\n";
6875                pr "    Store_field (v, 0, v2);\n";
6876                pr "  } else /* None */\n";
6877                pr "    v = Val_int (0);\n";
6878            | name, FChar ->
6879                pr "  v = Val_int (%s->%s);\n" typ name
6880           );
6881           pr "  Store_field (rv, %d, v);\n" i
6882       ) cols;
6883       pr "  CAMLreturn (rv);\n";
6884       pr "}\n";
6885       pr "\n";
6886   ) structs;
6887
6888   (* Emit a copy_TYPE_list function definition only if that function is used. *)
6889   List.iter (
6890     function
6891     | typ, (RStructListOnly | RStructAndList) ->
6892         (* generate the function for typ *)
6893         emit_ocaml_copy_list_function typ
6894     | typ, _ -> () (* empty *)
6895   ) rstructs_used;
6896
6897   (* The wrappers. *)
6898   List.iter (
6899     fun (name, style, _, _, _, _, _) ->
6900       let params =
6901         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
6902
6903       let needs_extra_vs =
6904         match fst style with RConstOptString _ -> true | _ -> false in
6905
6906       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
6907       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
6908       List.iter (pr ", value %s") (List.tl params); pr ");\n";
6909
6910       pr "CAMLprim value\n";
6911       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
6912       List.iter (pr ", value %s") (List.tl params);
6913       pr ")\n";
6914       pr "{\n";
6915
6916       (match params with
6917        | [p1; p2; p3; p4; p5] ->
6918            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
6919        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
6920            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
6921            pr "  CAMLxparam%d (%s);\n"
6922              (List.length rest) (String.concat ", " rest)
6923        | ps ->
6924            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
6925       );
6926       if not needs_extra_vs then
6927         pr "  CAMLlocal1 (rv);\n"
6928       else
6929         pr "  CAMLlocal3 (rv, v, v2);\n";
6930       pr "\n";
6931
6932       pr "  guestfs_h *g = Guestfs_val (gv);\n";
6933       pr "  if (g == NULL)\n";
6934       pr "    caml_failwith (\"%s: used handle after closing it\");\n" name;
6935       pr "\n";
6936
6937       List.iter (
6938         function
6939         | Pathname n
6940         | Device n | Dev_or_Path n
6941         | String n
6942         | FileIn n
6943         | FileOut n ->
6944             pr "  const char *%s = String_val (%sv);\n" n n
6945         | OptString n ->
6946             pr "  const char *%s =\n" n;
6947             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
6948               n n
6949         | StringList n | DeviceList n ->
6950             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
6951         | Bool n ->
6952             pr "  int %s = Bool_val (%sv);\n" n n
6953         | Int n ->
6954             pr "  int %s = Int_val (%sv);\n" n n
6955       ) (snd style);
6956       let error_code =
6957         match fst style with
6958         | RErr -> pr "  int r;\n"; "-1"
6959         | RInt _ -> pr "  int r;\n"; "-1"
6960         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6961         | RBool _ -> pr "  int r;\n"; "-1"
6962         | RConstString _ | RConstOptString _ ->
6963             pr "  const char *r;\n"; "NULL"
6964         | RString _ -> pr "  char *r;\n"; "NULL"
6965         | RStringList _ ->
6966             pr "  int i;\n";
6967             pr "  char **r;\n";
6968             "NULL"
6969         | RStruct (_, typ) ->
6970             pr "  struct guestfs_%s *r;\n" typ; "NULL"
6971         | RStructList (_, typ) ->
6972             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
6973         | RHashtable _ ->
6974             pr "  int i;\n";
6975             pr "  char **r;\n";
6976             "NULL"
6977         | RBufferOut _ ->
6978             pr "  char *r;\n";
6979             pr "  size_t size;\n";
6980             "NULL" in
6981       pr "\n";
6982
6983       pr "  caml_enter_blocking_section ();\n";
6984       pr "  r = guestfs_%s " name;
6985       generate_c_call_args ~handle:"g" style;
6986       pr ";\n";
6987       pr "  caml_leave_blocking_section ();\n";
6988
6989       List.iter (
6990         function
6991         | StringList n | DeviceList n ->
6992             pr "  ocaml_guestfs_free_strings (%s);\n" n;
6993         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
6994         | FileIn _ | FileOut _ -> ()
6995       ) (snd style);
6996
6997       pr "  if (r == %s)\n" error_code;
6998       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
6999       pr "\n";
7000
7001       (match fst style with
7002        | RErr -> pr "  rv = Val_unit;\n"
7003        | RInt _ -> pr "  rv = Val_int (r);\n"
7004        | RInt64 _ ->
7005            pr "  rv = caml_copy_int64 (r);\n"
7006        | RBool _ -> pr "  rv = Val_bool (r);\n"
7007        | RConstString _ ->
7008            pr "  rv = caml_copy_string (r);\n"
7009        | RConstOptString _ ->
7010            pr "  if (r) { /* Some string */\n";
7011            pr "    v = caml_alloc (1, 0);\n";
7012            pr "    v2 = caml_copy_string (r);\n";
7013            pr "    Store_field (v, 0, v2);\n";
7014            pr "  } else /* None */\n";
7015            pr "    v = Val_int (0);\n";
7016        | RString _ ->
7017            pr "  rv = caml_copy_string (r);\n";
7018            pr "  free (r);\n"
7019        | RStringList _ ->
7020            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7021            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7022            pr "  free (r);\n"
7023        | RStruct (_, typ) ->
7024            pr "  rv = copy_%s (r);\n" typ;
7025            pr "  guestfs_free_%s (r);\n" typ;
7026        | RStructList (_, typ) ->
7027            pr "  rv = copy_%s_list (r);\n" typ;
7028            pr "  guestfs_free_%s_list (r);\n" typ;
7029        | RHashtable _ ->
7030            pr "  rv = copy_table (r);\n";
7031            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7032            pr "  free (r);\n";
7033        | RBufferOut _ ->
7034            pr "  rv = caml_alloc_string (size);\n";
7035            pr "  memcpy (String_val (rv), r, size);\n";
7036       );
7037
7038       pr "  CAMLreturn (rv);\n";
7039       pr "}\n";
7040       pr "\n";
7041
7042       if List.length params > 5 then (
7043         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7044         pr "CAMLprim value ";
7045         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7046         pr "CAMLprim value\n";
7047         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7048         pr "{\n";
7049         pr "  return ocaml_guestfs_%s (argv[0]" name;
7050         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7051         pr ");\n";
7052         pr "}\n";
7053         pr "\n"
7054       )
7055   ) all_functions
7056
7057 and generate_ocaml_structure_decls () =
7058   List.iter (
7059     fun (typ, cols) ->
7060       pr "type %s = {\n" typ;
7061       List.iter (
7062         function
7063         | name, FString -> pr "  %s : string;\n" name
7064         | name, FBuffer -> pr "  %s : string;\n" name
7065         | name, FUUID -> pr "  %s : string;\n" name
7066         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7067         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7068         | name, FChar -> pr "  %s : char;\n" name
7069         | name, FOptPercent -> pr "  %s : float option;\n" name
7070       ) cols;
7071       pr "}\n";
7072       pr "\n"
7073   ) structs
7074
7075 and generate_ocaml_prototype ?(is_external = false) name style =
7076   if is_external then pr "external " else pr "val ";
7077   pr "%s : t -> " name;
7078   List.iter (
7079     function
7080     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7081     | OptString _ -> pr "string option -> "
7082     | StringList _ | DeviceList _ -> pr "string array -> "
7083     | Bool _ -> pr "bool -> "
7084     | Int _ -> pr "int -> "
7085   ) (snd style);
7086   (match fst style with
7087    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7088    | RInt _ -> pr "int"
7089    | RInt64 _ -> pr "int64"
7090    | RBool _ -> pr "bool"
7091    | RConstString _ -> pr "string"
7092    | RConstOptString _ -> pr "string option"
7093    | RString _ | RBufferOut _ -> pr "string"
7094    | RStringList _ -> pr "string array"
7095    | RStruct (_, typ) -> pr "%s" typ
7096    | RStructList (_, typ) -> pr "%s array" typ
7097    | RHashtable _ -> pr "(string * string) list"
7098   );
7099   if is_external then (
7100     pr " = ";
7101     if List.length (snd style) + 1 > 5 then
7102       pr "\"ocaml_guestfs_%s_byte\" " name;
7103     pr "\"ocaml_guestfs_%s\"" name
7104   );
7105   pr "\n"
7106
7107 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7108 and generate_perl_xs () =
7109   generate_header CStyle LGPLv2;
7110
7111   pr "\
7112 #include \"EXTERN.h\"
7113 #include \"perl.h\"
7114 #include \"XSUB.h\"
7115
7116 #include <guestfs.h>
7117
7118 #ifndef PRId64
7119 #define PRId64 \"lld\"
7120 #endif
7121
7122 static SV *
7123 my_newSVll(long long val) {
7124 #ifdef USE_64_BIT_ALL
7125   return newSViv(val);
7126 #else
7127   char buf[100];
7128   int len;
7129   len = snprintf(buf, 100, \"%%\" PRId64, val);
7130   return newSVpv(buf, len);
7131 #endif
7132 }
7133
7134 #ifndef PRIu64
7135 #define PRIu64 \"llu\"
7136 #endif
7137
7138 static SV *
7139 my_newSVull(unsigned long long val) {
7140 #ifdef USE_64_BIT_ALL
7141   return newSVuv(val);
7142 #else
7143   char buf[100];
7144   int len;
7145   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7146   return newSVpv(buf, len);
7147 #endif
7148 }
7149
7150 /* http://www.perlmonks.org/?node_id=680842 */
7151 static char **
7152 XS_unpack_charPtrPtr (SV *arg) {
7153   char **ret;
7154   AV *av;
7155   I32 i;
7156
7157   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7158     croak (\"array reference expected\");
7159
7160   av = (AV *)SvRV (arg);
7161   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7162   if (!ret)
7163     croak (\"malloc failed\");
7164
7165   for (i = 0; i <= av_len (av); i++) {
7166     SV **elem = av_fetch (av, i, 0);
7167
7168     if (!elem || !*elem)
7169       croak (\"missing element in list\");
7170
7171     ret[i] = SvPV_nolen (*elem);
7172   }
7173
7174   ret[i] = NULL;
7175
7176   return ret;
7177 }
7178
7179 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7180
7181 PROTOTYPES: ENABLE
7182
7183 guestfs_h *
7184 _create ()
7185    CODE:
7186       RETVAL = guestfs_create ();
7187       if (!RETVAL)
7188         croak (\"could not create guestfs handle\");
7189       guestfs_set_error_handler (RETVAL, NULL, NULL);
7190  OUTPUT:
7191       RETVAL
7192
7193 void
7194 DESTROY (g)
7195       guestfs_h *g;
7196  PPCODE:
7197       guestfs_close (g);
7198
7199 ";
7200
7201   List.iter (
7202     fun (name, style, _, _, _, _, _) ->
7203       (match fst style with
7204        | RErr -> pr "void\n"
7205        | RInt _ -> pr "SV *\n"
7206        | RInt64 _ -> pr "SV *\n"
7207        | RBool _ -> pr "SV *\n"
7208        | RConstString _ -> pr "SV *\n"
7209        | RConstOptString _ -> pr "SV *\n"
7210        | RString _ -> pr "SV *\n"
7211        | RBufferOut _ -> pr "SV *\n"
7212        | RStringList _
7213        | RStruct _ | RStructList _
7214        | RHashtable _ ->
7215            pr "void\n" (* all lists returned implictly on the stack *)
7216       );
7217       (* Call and arguments. *)
7218       pr "%s " name;
7219       generate_c_call_args ~handle:"g" ~decl:true style;
7220       pr "\n";
7221       pr "      guestfs_h *g;\n";
7222       iteri (
7223         fun i ->
7224           function
7225           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7226               pr "      char *%s;\n" n
7227           | OptString n ->
7228               (* http://www.perlmonks.org/?node_id=554277
7229                * Note that the implicit handle argument means we have
7230                * to add 1 to the ST(x) operator.
7231                *)
7232               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7233           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7234           | Bool n -> pr "      int %s;\n" n
7235           | Int n -> pr "      int %s;\n" n
7236       ) (snd style);
7237
7238       let do_cleanups () =
7239         List.iter (
7240           function
7241           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
7242           | FileIn _ | FileOut _ -> ()
7243           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7244         ) (snd style)
7245       in
7246
7247       (* Code. *)
7248       (match fst style with
7249        | RErr ->
7250            pr "PREINIT:\n";
7251            pr "      int r;\n";
7252            pr " PPCODE:\n";
7253            pr "      r = guestfs_%s " name;
7254            generate_c_call_args ~handle:"g" style;
7255            pr ";\n";
7256            do_cleanups ();
7257            pr "      if (r == -1)\n";
7258            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7259        | RInt n
7260        | RBool n ->
7261            pr "PREINIT:\n";
7262            pr "      int %s;\n" n;
7263            pr "   CODE:\n";
7264            pr "      %s = guestfs_%s " n name;
7265            generate_c_call_args ~handle:"g" style;
7266            pr ";\n";
7267            do_cleanups ();
7268            pr "      if (%s == -1)\n" n;
7269            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7270            pr "      RETVAL = newSViv (%s);\n" n;
7271            pr " OUTPUT:\n";
7272            pr "      RETVAL\n"
7273        | RInt64 n ->
7274            pr "PREINIT:\n";
7275            pr "      int64_t %s;\n" n;
7276            pr "   CODE:\n";
7277            pr "      %s = guestfs_%s " n name;
7278            generate_c_call_args ~handle:"g" style;
7279            pr ";\n";
7280            do_cleanups ();
7281            pr "      if (%s == -1)\n" n;
7282            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7283            pr "      RETVAL = my_newSVll (%s);\n" n;
7284            pr " OUTPUT:\n";
7285            pr "      RETVAL\n"
7286        | RConstString n ->
7287            pr "PREINIT:\n";
7288            pr "      const char *%s;\n" n;
7289            pr "   CODE:\n";
7290            pr "      %s = guestfs_%s " n name;
7291            generate_c_call_args ~handle:"g" style;
7292            pr ";\n";
7293            do_cleanups ();
7294            pr "      if (%s == NULL)\n" n;
7295            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7296            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7297            pr " OUTPUT:\n";
7298            pr "      RETVAL\n"
7299        | RConstOptString n ->
7300            pr "PREINIT:\n";
7301            pr "      const char *%s;\n" n;
7302            pr "   CODE:\n";
7303            pr "      %s = guestfs_%s " n name;
7304            generate_c_call_args ~handle:"g" style;
7305            pr ";\n";
7306            do_cleanups ();
7307            pr "      if (%s == NULL)\n" n;
7308            pr "        RETVAL = &PL_sv_undef;\n";
7309            pr "      else\n";
7310            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7311            pr " OUTPUT:\n";
7312            pr "      RETVAL\n"
7313        | RString n ->
7314            pr "PREINIT:\n";
7315            pr "      char *%s;\n" n;
7316            pr "   CODE:\n";
7317            pr "      %s = guestfs_%s " n name;
7318            generate_c_call_args ~handle:"g" style;
7319            pr ";\n";
7320            do_cleanups ();
7321            pr "      if (%s == NULL)\n" n;
7322            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7323            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7324            pr "      free (%s);\n" n;
7325            pr " OUTPUT:\n";
7326            pr "      RETVAL\n"
7327        | RStringList n | RHashtable n ->
7328            pr "PREINIT:\n";
7329            pr "      char **%s;\n" n;
7330            pr "      int i, n;\n";
7331            pr " PPCODE:\n";
7332            pr "      %s = guestfs_%s " n name;
7333            generate_c_call_args ~handle:"g" style;
7334            pr ";\n";
7335            do_cleanups ();
7336            pr "      if (%s == NULL)\n" n;
7337            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7338            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7339            pr "      EXTEND (SP, n);\n";
7340            pr "      for (i = 0; i < n; ++i) {\n";
7341            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7342            pr "        free (%s[i]);\n" n;
7343            pr "      }\n";
7344            pr "      free (%s);\n" n;
7345        | RStruct (n, typ) ->
7346            let cols = cols_of_struct typ in
7347            generate_perl_struct_code typ cols name style n do_cleanups
7348        | RStructList (n, typ) ->
7349            let cols = cols_of_struct typ in
7350            generate_perl_struct_list_code typ cols name style n do_cleanups
7351        | RBufferOut n ->
7352            pr "PREINIT:\n";
7353            pr "      char *%s;\n" n;
7354            pr "      size_t size;\n";
7355            pr "   CODE:\n";
7356            pr "      %s = guestfs_%s " n name;
7357            generate_c_call_args ~handle:"g" style;
7358            pr ";\n";
7359            do_cleanups ();
7360            pr "      if (%s == NULL)\n" n;
7361            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7362            pr "      RETVAL = newSVpv (%s, size);\n" n;
7363            pr "      free (%s);\n" n;
7364            pr " OUTPUT:\n";
7365            pr "      RETVAL\n"
7366       );
7367
7368       pr "\n"
7369   ) all_functions
7370
7371 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7372   pr "PREINIT:\n";
7373   pr "      struct guestfs_%s_list *%s;\n" typ n;
7374   pr "      int i;\n";
7375   pr "      HV *hv;\n";
7376   pr " PPCODE:\n";
7377   pr "      %s = guestfs_%s " n name;
7378   generate_c_call_args ~handle:"g" style;
7379   pr ";\n";
7380   do_cleanups ();
7381   pr "      if (%s == NULL)\n" n;
7382   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7383   pr "      EXTEND (SP, %s->len);\n" n;
7384   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7385   pr "        hv = newHV ();\n";
7386   List.iter (
7387     function
7388     | name, FString ->
7389         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7390           name (String.length name) n name
7391     | name, FUUID ->
7392         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7393           name (String.length name) n name
7394     | name, FBuffer ->
7395         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7396           name (String.length name) n name n name
7397     | name, (FBytes|FUInt64) ->
7398         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7399           name (String.length name) n name
7400     | name, FInt64 ->
7401         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7402           name (String.length name) n name
7403     | name, (FInt32|FUInt32) ->
7404         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7405           name (String.length name) n name
7406     | name, FChar ->
7407         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7408           name (String.length name) n name
7409     | name, FOptPercent ->
7410         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7411           name (String.length name) n name
7412   ) cols;
7413   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7414   pr "      }\n";
7415   pr "      guestfs_free_%s_list (%s);\n" typ n
7416
7417 and generate_perl_struct_code typ cols name style n do_cleanups =
7418   pr "PREINIT:\n";
7419   pr "      struct guestfs_%s *%s;\n" typ n;
7420   pr " PPCODE:\n";
7421   pr "      %s = guestfs_%s " n name;
7422   generate_c_call_args ~handle:"g" style;
7423   pr ";\n";
7424   do_cleanups ();
7425   pr "      if (%s == NULL)\n" n;
7426   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7427   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
7428   List.iter (
7429     fun ((name, _) as col) ->
7430       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7431
7432       match col with
7433       | name, FString ->
7434           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7435             n name
7436       | name, FBuffer ->
7437           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7438             n name n name
7439       | name, FUUID ->
7440           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7441             n name
7442       | name, (FBytes|FUInt64) ->
7443           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7444             n name
7445       | name, FInt64 ->
7446           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7447             n name
7448       | name, (FInt32|FUInt32) ->
7449           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7450             n name
7451       | name, FChar ->
7452           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7453             n name
7454       | name, FOptPercent ->
7455           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7456             n name
7457   ) cols;
7458   pr "      free (%s);\n" n
7459
7460 (* Generate Sys/Guestfs.pm. *)
7461 and generate_perl_pm () =
7462   generate_header HashStyle LGPLv2;
7463
7464   pr "\
7465 =pod
7466
7467 =head1 NAME
7468
7469 Sys::Guestfs - Perl bindings for libguestfs
7470
7471 =head1 SYNOPSIS
7472
7473  use Sys::Guestfs;
7474
7475  my $h = Sys::Guestfs->new ();
7476  $h->add_drive ('guest.img');
7477  $h->launch ();
7478  $h->wait_ready ();
7479  $h->mount ('/dev/sda1', '/');
7480  $h->touch ('/hello');
7481  $h->sync ();
7482
7483 =head1 DESCRIPTION
7484
7485 The C<Sys::Guestfs> module provides a Perl XS binding to the
7486 libguestfs API for examining and modifying virtual machine
7487 disk images.
7488
7489 Amongst the things this is good for: making batch configuration
7490 changes to guests, getting disk used/free statistics (see also:
7491 virt-df), migrating between virtualization systems (see also:
7492 virt-p2v), performing partial backups, performing partial guest
7493 clones, cloning guests and changing registry/UUID/hostname info, and
7494 much else besides.
7495
7496 Libguestfs uses Linux kernel and qemu code, and can access any type of
7497 guest filesystem that Linux and qemu can, including but not limited
7498 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7499 schemes, qcow, qcow2, vmdk.
7500
7501 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7502 LVs, what filesystem is in each LV, etc.).  It can also run commands
7503 in the context of the guest.  Also you can access filesystems over FTP.
7504
7505 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7506 functions for using libguestfs from Perl, including integration
7507 with libvirt.
7508
7509 =head1 ERRORS
7510
7511 All errors turn into calls to C<croak> (see L<Carp(3)>).
7512
7513 =head1 METHODS
7514
7515 =over 4
7516
7517 =cut
7518
7519 package Sys::Guestfs;
7520
7521 use strict;
7522 use warnings;
7523
7524 require XSLoader;
7525 XSLoader::load ('Sys::Guestfs');
7526
7527 =item $h = Sys::Guestfs->new ();
7528
7529 Create a new guestfs handle.
7530
7531 =cut
7532
7533 sub new {
7534   my $proto = shift;
7535   my $class = ref ($proto) || $proto;
7536
7537   my $self = Sys::Guestfs::_create ();
7538   bless $self, $class;
7539   return $self;
7540 }
7541
7542 ";
7543
7544   (* Actions.  We only need to print documentation for these as
7545    * they are pulled in from the XS code automatically.
7546    *)
7547   List.iter (
7548     fun (name, style, _, flags, _, _, longdesc) ->
7549       if not (List.mem NotInDocs flags) then (
7550         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7551         pr "=item ";
7552         generate_perl_prototype name style;
7553         pr "\n\n";
7554         pr "%s\n\n" longdesc;
7555         if List.mem ProtocolLimitWarning flags then
7556           pr "%s\n\n" protocol_limit_warning;
7557         if List.mem DangerWillRobinson flags then
7558           pr "%s\n\n" danger_will_robinson;
7559         match deprecation_notice flags with
7560         | None -> ()
7561         | Some txt -> pr "%s\n\n" txt
7562       )
7563   ) all_functions_sorted;
7564
7565   (* End of file. *)
7566   pr "\
7567 =cut
7568
7569 1;
7570
7571 =back
7572
7573 =head1 COPYRIGHT
7574
7575 Copyright (C) 2009 Red Hat Inc.
7576
7577 =head1 LICENSE
7578
7579 Please see the file COPYING.LIB for the full license.
7580
7581 =head1 SEE ALSO
7582
7583 L<guestfs(3)>,
7584 L<guestfish(1)>,
7585 L<http://libguestfs.org>,
7586 L<Sys::Guestfs::Lib(3)>.
7587
7588 =cut
7589 "
7590
7591 and generate_perl_prototype name style =
7592   (match fst style with
7593    | RErr -> ()
7594    | RBool n
7595    | RInt n
7596    | RInt64 n
7597    | RConstString n
7598    | RConstOptString n
7599    | RString n
7600    | RBufferOut n -> pr "$%s = " n
7601    | RStruct (n,_)
7602    | RHashtable n -> pr "%%%s = " n
7603    | RStringList n
7604    | RStructList (n,_) -> pr "@%s = " n
7605   );
7606   pr "$h->%s (" name;
7607   let comma = ref false in
7608   List.iter (
7609     fun arg ->
7610       if !comma then pr ", ";
7611       comma := true;
7612       match arg with
7613       | Pathname n | Device n | Dev_or_Path n | String n
7614       | OptString n | Bool n | Int n | FileIn n | FileOut n ->
7615           pr "$%s" n
7616       | StringList n | DeviceList n ->
7617           pr "\\@%s" n
7618   ) (snd style);
7619   pr ");"
7620
7621 (* Generate Python C module. *)
7622 and generate_python_c () =
7623   generate_header CStyle LGPLv2;
7624
7625   pr "\
7626 #include <Python.h>
7627
7628 #include <stdio.h>
7629 #include <stdlib.h>
7630 #include <assert.h>
7631
7632 #include \"guestfs.h\"
7633
7634 typedef struct {
7635   PyObject_HEAD
7636   guestfs_h *g;
7637 } Pyguestfs_Object;
7638
7639 static guestfs_h *
7640 get_handle (PyObject *obj)
7641 {
7642   assert (obj);
7643   assert (obj != Py_None);
7644   return ((Pyguestfs_Object *) obj)->g;
7645 }
7646
7647 static PyObject *
7648 put_handle (guestfs_h *g)
7649 {
7650   assert (g);
7651   return
7652     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7653 }
7654
7655 /* This list should be freed (but not the strings) after use. */
7656 static char **
7657 get_string_list (PyObject *obj)
7658 {
7659   int i, len;
7660   char **r;
7661
7662   assert (obj);
7663
7664   if (!PyList_Check (obj)) {
7665     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7666     return NULL;
7667   }
7668
7669   len = PyList_Size (obj);
7670   r = malloc (sizeof (char *) * (len+1));
7671   if (r == NULL) {
7672     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7673     return NULL;
7674   }
7675
7676   for (i = 0; i < len; ++i)
7677     r[i] = PyString_AsString (PyList_GetItem (obj, i));
7678   r[len] = NULL;
7679
7680   return r;
7681 }
7682
7683 static PyObject *
7684 put_string_list (char * const * const argv)
7685 {
7686   PyObject *list;
7687   int argc, i;
7688
7689   for (argc = 0; argv[argc] != NULL; ++argc)
7690     ;
7691
7692   list = PyList_New (argc);
7693   for (i = 0; i < argc; ++i)
7694     PyList_SetItem (list, i, PyString_FromString (argv[i]));
7695
7696   return list;
7697 }
7698
7699 static PyObject *
7700 put_table (char * const * const argv)
7701 {
7702   PyObject *list, *item;
7703   int argc, i;
7704
7705   for (argc = 0; argv[argc] != NULL; ++argc)
7706     ;
7707
7708   list = PyList_New (argc >> 1);
7709   for (i = 0; i < argc; i += 2) {
7710     item = PyTuple_New (2);
7711     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7712     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7713     PyList_SetItem (list, i >> 1, item);
7714   }
7715
7716   return list;
7717 }
7718
7719 static void
7720 free_strings (char **argv)
7721 {
7722   int argc;
7723
7724   for (argc = 0; argv[argc] != NULL; ++argc)
7725     free (argv[argc]);
7726   free (argv);
7727 }
7728
7729 static PyObject *
7730 py_guestfs_create (PyObject *self, PyObject *args)
7731 {
7732   guestfs_h *g;
7733
7734   g = guestfs_create ();
7735   if (g == NULL) {
7736     PyErr_SetString (PyExc_RuntimeError,
7737                      \"guestfs.create: failed to allocate handle\");
7738     return NULL;
7739   }
7740   guestfs_set_error_handler (g, NULL, NULL);
7741   return put_handle (g);
7742 }
7743
7744 static PyObject *
7745 py_guestfs_close (PyObject *self, PyObject *args)
7746 {
7747   PyObject *py_g;
7748   guestfs_h *g;
7749
7750   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7751     return NULL;
7752   g = get_handle (py_g);
7753
7754   guestfs_close (g);
7755
7756   Py_INCREF (Py_None);
7757   return Py_None;
7758 }
7759
7760 ";
7761
7762   let emit_put_list_function typ =
7763     pr "static PyObject *\n";
7764     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7765     pr "{\n";
7766     pr "  PyObject *list;\n";
7767     pr "  int i;\n";
7768     pr "\n";
7769     pr "  list = PyList_New (%ss->len);\n" typ;
7770     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
7771     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7772     pr "  return list;\n";
7773     pr "};\n";
7774     pr "\n"
7775   in
7776
7777   (* Structures, turned into Python dictionaries. *)
7778   List.iter (
7779     fun (typ, cols) ->
7780       pr "static PyObject *\n";
7781       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7782       pr "{\n";
7783       pr "  PyObject *dict;\n";
7784       pr "\n";
7785       pr "  dict = PyDict_New ();\n";
7786       List.iter (
7787         function
7788         | name, FString ->
7789             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7790             pr "                        PyString_FromString (%s->%s));\n"
7791               typ name
7792         | name, FBuffer ->
7793             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7794             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7795               typ name typ name
7796         | name, FUUID ->
7797             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7798             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
7799               typ name
7800         | name, (FBytes|FUInt64) ->
7801             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7802             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
7803               typ name
7804         | name, FInt64 ->
7805             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7806             pr "                        PyLong_FromLongLong (%s->%s));\n"
7807               typ name
7808         | name, FUInt32 ->
7809             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7810             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
7811               typ name
7812         | name, FInt32 ->
7813             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7814             pr "                        PyLong_FromLong (%s->%s));\n"
7815               typ name
7816         | name, FOptPercent ->
7817             pr "  if (%s->%s >= 0)\n" typ name;
7818             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
7819             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
7820               typ name;
7821             pr "  else {\n";
7822             pr "    Py_INCREF (Py_None);\n";
7823             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
7824             pr "  }\n"
7825         | name, FChar ->
7826             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7827             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7828       ) cols;
7829       pr "  return dict;\n";
7830       pr "};\n";
7831       pr "\n";
7832
7833   ) structs;
7834
7835   (* Emit a put_TYPE_list function definition only if that function is used. *)
7836   List.iter (
7837     function
7838     | typ, (RStructListOnly | RStructAndList) ->
7839         (* generate the function for typ *)
7840         emit_put_list_function typ
7841     | typ, _ -> () (* empty *)
7842   ) rstructs_used;
7843
7844   (* Python wrapper functions. *)
7845   List.iter (
7846     fun (name, style, _, _, _, _, _) ->
7847       pr "static PyObject *\n";
7848       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7849       pr "{\n";
7850
7851       pr "  PyObject *py_g;\n";
7852       pr "  guestfs_h *g;\n";
7853       pr "  PyObject *py_r;\n";
7854
7855       let error_code =
7856         match fst style with
7857         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
7858         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7859         | RConstString _ | RConstOptString _ ->
7860             pr "  const char *r;\n"; "NULL"
7861         | RString _ -> pr "  char *r;\n"; "NULL"
7862         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
7863         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
7864         | RStructList (_, typ) ->
7865             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7866         | RBufferOut _ ->
7867             pr "  char *r;\n";
7868             pr "  size_t size;\n";
7869             "NULL" in
7870
7871       List.iter (
7872         function
7873         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7874             pr "  const char *%s;\n" n
7875         | OptString n -> pr "  const char *%s;\n" n
7876         | StringList n | DeviceList n ->
7877             pr "  PyObject *py_%s;\n" n;
7878             pr "  char **%s;\n" n
7879         | Bool n -> pr "  int %s;\n" n
7880         | Int n -> pr "  int %s;\n" n
7881       ) (snd style);
7882
7883       pr "\n";
7884
7885       (* Convert the parameters. *)
7886       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
7887       List.iter (
7888         function
7889         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
7890         | OptString _ -> pr "z"
7891         | StringList _ | DeviceList _ -> pr "O"
7892         | Bool _ -> pr "i" (* XXX Python has booleans? *)
7893         | Int _ -> pr "i"
7894       ) (snd style);
7895       pr ":guestfs_%s\",\n" name;
7896       pr "                         &py_g";
7897       List.iter (
7898         function
7899         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
7900         | OptString n -> pr ", &%s" n
7901         | StringList n | DeviceList n -> pr ", &py_%s" n
7902         | Bool n -> pr ", &%s" n
7903         | Int n -> pr ", &%s" n
7904       ) (snd style);
7905
7906       pr "))\n";
7907       pr "    return NULL;\n";
7908
7909       pr "  g = get_handle (py_g);\n";
7910       List.iter (
7911         function
7912         | Pathname _ | Device _ | Dev_or_Path _ | String _
7913         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7914         | StringList n | DeviceList n ->
7915             pr "  %s = get_string_list (py_%s);\n" n n;
7916             pr "  if (!%s) return NULL;\n" n
7917       ) (snd style);
7918
7919       pr "\n";
7920
7921       pr "  r = guestfs_%s " name;
7922       generate_c_call_args ~handle:"g" style;
7923       pr ";\n";
7924
7925       List.iter (
7926         function
7927         | Pathname _ | Device _ | Dev_or_Path _ | String _
7928         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7929         | StringList n | DeviceList n ->
7930             pr "  free (%s);\n" n
7931       ) (snd style);
7932
7933       pr "  if (r == %s) {\n" error_code;
7934       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
7935       pr "    return NULL;\n";
7936       pr "  }\n";
7937       pr "\n";
7938
7939       (match fst style with
7940        | RErr ->
7941            pr "  Py_INCREF (Py_None);\n";
7942            pr "  py_r = Py_None;\n"
7943        | RInt _
7944        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
7945        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
7946        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
7947        | RConstOptString _ ->
7948            pr "  if (r)\n";
7949            pr "    py_r = PyString_FromString (r);\n";
7950            pr "  else {\n";
7951            pr "    Py_INCREF (Py_None);\n";
7952            pr "    py_r = Py_None;\n";
7953            pr "  }\n"
7954        | RString _ ->
7955            pr "  py_r = PyString_FromString (r);\n";
7956            pr "  free (r);\n"
7957        | RStringList _ ->
7958            pr "  py_r = put_string_list (r);\n";
7959            pr "  free_strings (r);\n"
7960        | RStruct (_, typ) ->
7961            pr "  py_r = put_%s (r);\n" typ;
7962            pr "  guestfs_free_%s (r);\n" typ
7963        | RStructList (_, typ) ->
7964            pr "  py_r = put_%s_list (r);\n" typ;
7965            pr "  guestfs_free_%s_list (r);\n" typ
7966        | RHashtable n ->
7967            pr "  py_r = put_table (r);\n";
7968            pr "  free_strings (r);\n"
7969        | RBufferOut _ ->
7970            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
7971            pr "  free (r);\n"
7972       );
7973
7974       pr "  return py_r;\n";
7975       pr "}\n";
7976       pr "\n"
7977   ) all_functions;
7978
7979   (* Table of functions. *)
7980   pr "static PyMethodDef methods[] = {\n";
7981   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
7982   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
7983   List.iter (
7984     fun (name, _, _, _, _, _, _) ->
7985       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
7986         name name
7987   ) all_functions;
7988   pr "  { NULL, NULL, 0, NULL }\n";
7989   pr "};\n";
7990   pr "\n";
7991
7992   (* Init function. *)
7993   pr "\
7994 void
7995 initlibguestfsmod (void)
7996 {
7997   static int initialized = 0;
7998
7999   if (initialized) return;
8000   Py_InitModule ((char *) \"libguestfsmod\", methods);
8001   initialized = 1;
8002 }
8003 "
8004
8005 (* Generate Python module. *)
8006 and generate_python_py () =
8007   generate_header HashStyle LGPLv2;
8008
8009   pr "\
8010 u\"\"\"Python bindings for libguestfs
8011
8012 import guestfs
8013 g = guestfs.GuestFS ()
8014 g.add_drive (\"guest.img\")
8015 g.launch ()
8016 g.wait_ready ()
8017 parts = g.list_partitions ()
8018
8019 The guestfs module provides a Python binding to the libguestfs API
8020 for examining and modifying virtual machine disk images.
8021
8022 Amongst the things this is good for: making batch configuration
8023 changes to guests, getting disk used/free statistics (see also:
8024 virt-df), migrating between virtualization systems (see also:
8025 virt-p2v), performing partial backups, performing partial guest
8026 clones, cloning guests and changing registry/UUID/hostname info, and
8027 much else besides.
8028
8029 Libguestfs uses Linux kernel and qemu code, and can access any type of
8030 guest filesystem that Linux and qemu can, including but not limited
8031 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8032 schemes, qcow, qcow2, vmdk.
8033
8034 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8035 LVs, what filesystem is in each LV, etc.).  It can also run commands
8036 in the context of the guest.  Also you can access filesystems over FTP.
8037
8038 Errors which happen while using the API are turned into Python
8039 RuntimeError exceptions.
8040
8041 To create a guestfs handle you usually have to perform the following
8042 sequence of calls:
8043
8044 # Create the handle, call add_drive at least once, and possibly
8045 # several times if the guest has multiple block devices:
8046 g = guestfs.GuestFS ()
8047 g.add_drive (\"guest.img\")
8048
8049 # Launch the qemu subprocess and wait for it to become ready:
8050 g.launch ()
8051 g.wait_ready ()
8052
8053 # Now you can issue commands, for example:
8054 logvols = g.lvs ()
8055
8056 \"\"\"
8057
8058 import libguestfsmod
8059
8060 class GuestFS:
8061     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8062
8063     def __init__ (self):
8064         \"\"\"Create a new libguestfs handle.\"\"\"
8065         self._o = libguestfsmod.create ()
8066
8067     def __del__ (self):
8068         libguestfsmod.close (self._o)
8069
8070 ";
8071
8072   List.iter (
8073     fun (name, style, _, flags, _, _, longdesc) ->
8074       pr "    def %s " name;
8075       generate_py_call_args ~handle:"self" (snd style);
8076       pr ":\n";
8077
8078       if not (List.mem NotInDocs flags) then (
8079         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8080         let doc =
8081           match fst style with
8082           | RErr | RInt _ | RInt64 _ | RBool _
8083           | RConstOptString _ | RConstString _
8084           | RString _ | RBufferOut _ -> doc
8085           | RStringList _ ->
8086               doc ^ "\n\nThis function returns a list of strings."
8087           | RStruct (_, typ) ->
8088               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8089           | RStructList (_, typ) ->
8090               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8091           | RHashtable _ ->
8092               doc ^ "\n\nThis function returns a dictionary." in
8093         let doc =
8094           if List.mem ProtocolLimitWarning flags then
8095             doc ^ "\n\n" ^ protocol_limit_warning
8096           else doc in
8097         let doc =
8098           if List.mem DangerWillRobinson flags then
8099             doc ^ "\n\n" ^ danger_will_robinson
8100           else doc in
8101         let doc =
8102           match deprecation_notice flags with
8103           | None -> doc
8104           | Some txt -> doc ^ "\n\n" ^ txt in
8105         let doc = pod2text ~width:60 name doc in
8106         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8107         let doc = String.concat "\n        " doc in
8108         pr "        u\"\"\"%s\"\"\"\n" doc;
8109       );
8110       pr "        return libguestfsmod.%s " name;
8111       generate_py_call_args ~handle:"self._o" (snd style);
8112       pr "\n";
8113       pr "\n";
8114   ) all_functions
8115
8116 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8117 and generate_py_call_args ~handle args =
8118   pr "(%s" handle;
8119   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8120   pr ")"
8121
8122 (* Useful if you need the longdesc POD text as plain text.  Returns a
8123  * list of lines.
8124  *
8125  * Because this is very slow (the slowest part of autogeneration),
8126  * we memoize the results.
8127  *)
8128 and pod2text ~width name longdesc =
8129   let key = width, name, longdesc in
8130   try Hashtbl.find pod2text_memo key
8131   with Not_found ->
8132     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8133     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8134     close_out chan;
8135     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8136     let chan = Unix.open_process_in cmd in
8137     let lines = ref [] in
8138     let rec loop i =
8139       let line = input_line chan in
8140       if i = 1 then             (* discard the first line of output *)
8141         loop (i+1)
8142       else (
8143         let line = triml line in
8144         lines := line :: !lines;
8145         loop (i+1)
8146       ) in
8147     let lines = try loop 1 with End_of_file -> List.rev !lines in
8148     Unix.unlink filename;
8149     (match Unix.close_process_in chan with
8150      | Unix.WEXITED 0 -> ()
8151      | Unix.WEXITED i ->
8152          failwithf "pod2text: process exited with non-zero status (%d)" i
8153      | Unix.WSIGNALED i | Unix.WSTOPPED i ->
8154          failwithf "pod2text: process signalled or stopped by signal %d" i
8155     );
8156     Hashtbl.add pod2text_memo key lines;
8157     pod2text_memo_updated ();
8158     lines
8159
8160 (* Generate ruby bindings. *)
8161 and generate_ruby_c () =
8162   generate_header CStyle LGPLv2;
8163
8164   pr "\
8165 #include <stdio.h>
8166 #include <stdlib.h>
8167
8168 #include <ruby.h>
8169
8170 #include \"guestfs.h\"
8171
8172 #include \"extconf.h\"
8173
8174 /* For Ruby < 1.9 */
8175 #ifndef RARRAY_LEN
8176 #define RARRAY_LEN(r) (RARRAY((r))->len)
8177 #endif
8178
8179 static VALUE m_guestfs;                 /* guestfs module */
8180 static VALUE c_guestfs;                 /* guestfs_h handle */
8181 static VALUE e_Error;                   /* used for all errors */
8182
8183 static void ruby_guestfs_free (void *p)
8184 {
8185   if (!p) return;
8186   guestfs_close ((guestfs_h *) p);
8187 }
8188
8189 static VALUE ruby_guestfs_create (VALUE m)
8190 {
8191   guestfs_h *g;
8192
8193   g = guestfs_create ();
8194   if (!g)
8195     rb_raise (e_Error, \"failed to create guestfs handle\");
8196
8197   /* Don't print error messages to stderr by default. */
8198   guestfs_set_error_handler (g, NULL, NULL);
8199
8200   /* Wrap it, and make sure the close function is called when the
8201    * handle goes away.
8202    */
8203   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8204 }
8205
8206 static VALUE ruby_guestfs_close (VALUE gv)
8207 {
8208   guestfs_h *g;
8209   Data_Get_Struct (gv, guestfs_h, g);
8210
8211   ruby_guestfs_free (g);
8212   DATA_PTR (gv) = NULL;
8213
8214   return Qnil;
8215 }
8216
8217 ";
8218
8219   List.iter (
8220     fun (name, style, _, _, _, _, _) ->
8221       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8222       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8223       pr ")\n";
8224       pr "{\n";
8225       pr "  guestfs_h *g;\n";
8226       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8227       pr "  if (!g)\n";
8228       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8229         name;
8230       pr "\n";
8231
8232       List.iter (
8233         function
8234         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8235             pr "  Check_Type (%sv, T_STRING);\n" n;
8236             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8237             pr "  if (!%s)\n" n;
8238             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8239             pr "              \"%s\", \"%s\");\n" n name
8240         | OptString n ->
8241             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8242         | StringList n | DeviceList n ->
8243             pr "  char **%s;\n" n;
8244             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8245             pr "  {\n";
8246             pr "    int i, len;\n";
8247             pr "    len = RARRAY_LEN (%sv);\n" n;
8248             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8249               n;
8250             pr "    for (i = 0; i < len; ++i) {\n";
8251             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8252             pr "      %s[i] = StringValueCStr (v);\n" n;
8253             pr "    }\n";
8254             pr "    %s[len] = NULL;\n" n;
8255             pr "  }\n";
8256         | Bool n ->
8257             pr "  int %s = RTEST (%sv);\n" n n
8258         | Int n ->
8259             pr "  int %s = NUM2INT (%sv);\n" n n
8260       ) (snd style);
8261       pr "\n";
8262
8263       let error_code =
8264         match fst style with
8265         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8266         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8267         | RConstString _ | RConstOptString _ ->
8268             pr "  const char *r;\n"; "NULL"
8269         | RString _ -> pr "  char *r;\n"; "NULL"
8270         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8271         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8272         | RStructList (_, typ) ->
8273             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8274         | RBufferOut _ ->
8275             pr "  char *r;\n";
8276             pr "  size_t size;\n";
8277             "NULL" in
8278       pr "\n";
8279
8280       pr "  r = guestfs_%s " name;
8281       generate_c_call_args ~handle:"g" style;
8282       pr ";\n";
8283
8284       List.iter (
8285         function
8286         | Pathname _ | Device _ | Dev_or_Path _ | String _
8287         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
8288         | StringList n | DeviceList n ->
8289             pr "  free (%s);\n" n
8290       ) (snd style);
8291
8292       pr "  if (r == %s)\n" error_code;
8293       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8294       pr "\n";
8295
8296       (match fst style with
8297        | RErr ->
8298            pr "  return Qnil;\n"
8299        | RInt _ | RBool _ ->
8300            pr "  return INT2NUM (r);\n"
8301        | RInt64 _ ->
8302            pr "  return ULL2NUM (r);\n"
8303        | RConstString _ ->
8304            pr "  return rb_str_new2 (r);\n";
8305        | RConstOptString _ ->
8306            pr "  if (r)\n";
8307            pr "    return rb_str_new2 (r);\n";
8308            pr "  else\n";
8309            pr "    return Qnil;\n";
8310        | RString _ ->
8311            pr "  VALUE rv = rb_str_new2 (r);\n";
8312            pr "  free (r);\n";
8313            pr "  return rv;\n";
8314        | RStringList _ ->
8315            pr "  int i, len = 0;\n";
8316            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8317            pr "  VALUE rv = rb_ary_new2 (len);\n";
8318            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8319            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8320            pr "    free (r[i]);\n";
8321            pr "  }\n";
8322            pr "  free (r);\n";
8323            pr "  return rv;\n"
8324        | RStruct (_, typ) ->
8325            let cols = cols_of_struct typ in
8326            generate_ruby_struct_code typ cols
8327        | RStructList (_, typ) ->
8328            let cols = cols_of_struct typ in
8329            generate_ruby_struct_list_code typ cols
8330        | RHashtable _ ->
8331            pr "  VALUE rv = rb_hash_new ();\n";
8332            pr "  int i;\n";
8333            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8334            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8335            pr "    free (r[i]);\n";
8336            pr "    free (r[i+1]);\n";
8337            pr "  }\n";
8338            pr "  free (r);\n";
8339            pr "  return rv;\n"
8340        | RBufferOut _ ->
8341            pr "  VALUE rv = rb_str_new (r, size);\n";
8342            pr "  free (r);\n";
8343            pr "  return rv;\n";
8344       );
8345
8346       pr "}\n";
8347       pr "\n"
8348   ) all_functions;
8349
8350   pr "\
8351 /* Initialize the module. */
8352 void Init__guestfs ()
8353 {
8354   m_guestfs = rb_define_module (\"Guestfs\");
8355   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8356   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8357
8358   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8359   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8360
8361 ";
8362   (* Define the rest of the methods. *)
8363   List.iter (
8364     fun (name, style, _, _, _, _, _) ->
8365       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8366       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8367   ) all_functions;
8368
8369   pr "}\n"
8370
8371 (* Ruby code to return a struct. *)
8372 and generate_ruby_struct_code typ cols =
8373   pr "  VALUE rv = rb_hash_new ();\n";
8374   List.iter (
8375     function
8376     | name, FString ->
8377         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8378     | name, FBuffer ->
8379         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8380     | name, FUUID ->
8381         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8382     | name, (FBytes|FUInt64) ->
8383         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8384     | name, FInt64 ->
8385         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8386     | name, FUInt32 ->
8387         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8388     | name, FInt32 ->
8389         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8390     | name, FOptPercent ->
8391         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8392     | name, FChar -> (* XXX wrong? *)
8393         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8394   ) cols;
8395   pr "  guestfs_free_%s (r);\n" typ;
8396   pr "  return rv;\n"
8397
8398 (* Ruby code to return a struct list. *)
8399 and generate_ruby_struct_list_code typ cols =
8400   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8401   pr "  int i;\n";
8402   pr "  for (i = 0; i < r->len; ++i) {\n";
8403   pr "    VALUE hv = rb_hash_new ();\n";
8404   List.iter (
8405     function
8406     | name, FString ->
8407         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8408     | name, FBuffer ->
8409         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
8410     | name, FUUID ->
8411         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8412     | name, (FBytes|FUInt64) ->
8413         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8414     | name, FInt64 ->
8415         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8416     | name, FUInt32 ->
8417         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8418     | name, FInt32 ->
8419         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8420     | name, FOptPercent ->
8421         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8422     | name, FChar -> (* XXX wrong? *)
8423         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8424   ) cols;
8425   pr "    rb_ary_push (rv, hv);\n";
8426   pr "  }\n";
8427   pr "  guestfs_free_%s_list (r);\n" typ;
8428   pr "  return rv;\n"
8429
8430 (* Generate Java bindings GuestFS.java file. *)
8431 and generate_java_java () =
8432   generate_header CStyle LGPLv2;
8433
8434   pr "\
8435 package com.redhat.et.libguestfs;
8436
8437 import java.util.HashMap;
8438 import com.redhat.et.libguestfs.LibGuestFSException;
8439 import com.redhat.et.libguestfs.PV;
8440 import com.redhat.et.libguestfs.VG;
8441 import com.redhat.et.libguestfs.LV;
8442 import com.redhat.et.libguestfs.Stat;
8443 import com.redhat.et.libguestfs.StatVFS;
8444 import com.redhat.et.libguestfs.IntBool;
8445 import com.redhat.et.libguestfs.Dirent;
8446
8447 /**
8448  * The GuestFS object is a libguestfs handle.
8449  *
8450  * @author rjones
8451  */
8452 public class GuestFS {
8453   // Load the native code.
8454   static {
8455     System.loadLibrary (\"guestfs_jni\");
8456   }
8457
8458   /**
8459    * The native guestfs_h pointer.
8460    */
8461   long g;
8462
8463   /**
8464    * Create a libguestfs handle.
8465    *
8466    * @throws LibGuestFSException
8467    */
8468   public GuestFS () throws LibGuestFSException
8469   {
8470     g = _create ();
8471   }
8472   private native long _create () throws LibGuestFSException;
8473
8474   /**
8475    * Close a libguestfs handle.
8476    *
8477    * You can also leave handles to be collected by the garbage
8478    * collector, but this method ensures that the resources used
8479    * by the handle are freed up immediately.  If you call any
8480    * other methods after closing the handle, you will get an
8481    * exception.
8482    *
8483    * @throws LibGuestFSException
8484    */
8485   public void close () throws LibGuestFSException
8486   {
8487     if (g != 0)
8488       _close (g);
8489     g = 0;
8490   }
8491   private native void _close (long g) throws LibGuestFSException;
8492
8493   public void finalize () throws LibGuestFSException
8494   {
8495     close ();
8496   }
8497
8498 ";
8499
8500   List.iter (
8501     fun (name, style, _, flags, _, shortdesc, longdesc) ->
8502       if not (List.mem NotInDocs flags); then (
8503         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8504         let doc =
8505           if List.mem ProtocolLimitWarning flags then
8506             doc ^ "\n\n" ^ protocol_limit_warning
8507           else doc in
8508         let doc =
8509           if List.mem DangerWillRobinson flags then
8510             doc ^ "\n\n" ^ danger_will_robinson
8511           else doc in
8512         let doc =
8513           match deprecation_notice flags with
8514           | None -> doc
8515           | Some txt -> doc ^ "\n\n" ^ txt in
8516         let doc = pod2text ~width:60 name doc in
8517         let doc = List.map (            (* RHBZ#501883 *)
8518           function
8519           | "" -> "<p>"
8520           | nonempty -> nonempty
8521         ) doc in
8522         let doc = String.concat "\n   * " doc in
8523
8524         pr "  /**\n";
8525         pr "   * %s\n" shortdesc;
8526         pr "   * <p>\n";
8527         pr "   * %s\n" doc;
8528         pr "   * @throws LibGuestFSException\n";
8529         pr "   */\n";
8530         pr "  ";
8531       );
8532       generate_java_prototype ~public:true ~semicolon:false name style;
8533       pr "\n";
8534       pr "  {\n";
8535       pr "    if (g == 0)\n";
8536       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
8537         name;
8538       pr "    ";
8539       if fst style <> RErr then pr "return ";
8540       pr "_%s " name;
8541       generate_java_call_args ~handle:"g" (snd style);
8542       pr ";\n";
8543       pr "  }\n";
8544       pr "  ";
8545       generate_java_prototype ~privat:true ~native:true name style;
8546       pr "\n";
8547       pr "\n";
8548   ) all_functions;
8549
8550   pr "}\n"
8551
8552 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8553 and generate_java_call_args ~handle args =
8554   pr "(%s" handle;
8555   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8556   pr ")"
8557
8558 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8559     ?(semicolon=true) name style =
8560   if privat then pr "private ";
8561   if public then pr "public ";
8562   if native then pr "native ";
8563
8564   (* return type *)
8565   (match fst style with
8566    | RErr -> pr "void ";
8567    | RInt _ -> pr "int ";
8568    | RInt64 _ -> pr "long ";
8569    | RBool _ -> pr "boolean ";
8570    | RConstString _ | RConstOptString _ | RString _
8571    | RBufferOut _ -> pr "String ";
8572    | RStringList _ -> pr "String[] ";
8573    | RStruct (_, typ) ->
8574        let name = java_name_of_struct typ in
8575        pr "%s " name;
8576    | RStructList (_, typ) ->
8577        let name = java_name_of_struct typ in
8578        pr "%s[] " name;
8579    | RHashtable _ -> pr "HashMap<String,String> ";
8580   );
8581
8582   if native then pr "_%s " name else pr "%s " name;
8583   pr "(";
8584   let needs_comma = ref false in
8585   if native then (
8586     pr "long g";
8587     needs_comma := true
8588   );
8589
8590   (* args *)
8591   List.iter (
8592     fun arg ->
8593       if !needs_comma then pr ", ";
8594       needs_comma := true;
8595
8596       match arg with
8597       | Pathname n
8598       | Device n | Dev_or_Path n
8599       | String n
8600       | OptString n
8601       | FileIn n
8602       | FileOut n ->
8603           pr "String %s" n
8604       | StringList n | DeviceList n ->
8605           pr "String[] %s" n
8606       | Bool n ->
8607           pr "boolean %s" n
8608       | Int n ->
8609           pr "int %s" n
8610   ) (snd style);
8611
8612   pr ")\n";
8613   pr "    throws LibGuestFSException";
8614   if semicolon then pr ";"
8615
8616 and generate_java_struct jtyp cols =
8617   generate_header CStyle LGPLv2;
8618
8619   pr "\
8620 package com.redhat.et.libguestfs;
8621
8622 /**
8623  * Libguestfs %s structure.
8624  *
8625  * @author rjones
8626  * @see GuestFS
8627  */
8628 public class %s {
8629 " jtyp jtyp;
8630
8631   List.iter (
8632     function
8633     | name, FString
8634     | name, FUUID
8635     | name, FBuffer -> pr "  public String %s;\n" name
8636     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
8637     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
8638     | name, FChar -> pr "  public char %s;\n" name
8639     | name, FOptPercent ->
8640         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
8641         pr "  public float %s;\n" name
8642   ) cols;
8643
8644   pr "}\n"
8645
8646 and generate_java_c () =
8647   generate_header CStyle LGPLv2;
8648
8649   pr "\
8650 #include <stdio.h>
8651 #include <stdlib.h>
8652 #include <string.h>
8653
8654 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8655 #include \"guestfs.h\"
8656
8657 /* Note that this function returns.  The exception is not thrown
8658  * until after the wrapper function returns.
8659  */
8660 static void
8661 throw_exception (JNIEnv *env, const char *msg)
8662 {
8663   jclass cl;
8664   cl = (*env)->FindClass (env,
8665                           \"com/redhat/et/libguestfs/LibGuestFSException\");
8666   (*env)->ThrowNew (env, cl, msg);
8667 }
8668
8669 JNIEXPORT jlong JNICALL
8670 Java_com_redhat_et_libguestfs_GuestFS__1create
8671   (JNIEnv *env, jobject obj)
8672 {
8673   guestfs_h *g;
8674
8675   g = guestfs_create ();
8676   if (g == NULL) {
8677     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8678     return 0;
8679   }
8680   guestfs_set_error_handler (g, NULL, NULL);
8681   return (jlong) (long) g;
8682 }
8683
8684 JNIEXPORT void JNICALL
8685 Java_com_redhat_et_libguestfs_GuestFS__1close
8686   (JNIEnv *env, jobject obj, jlong jg)
8687 {
8688   guestfs_h *g = (guestfs_h *) (long) jg;
8689   guestfs_close (g);
8690 }
8691
8692 ";
8693
8694   List.iter (
8695     fun (name, style, _, _, _, _, _) ->
8696       pr "JNIEXPORT ";
8697       (match fst style with
8698        | RErr -> pr "void ";
8699        | RInt _ -> pr "jint ";
8700        | RInt64 _ -> pr "jlong ";
8701        | RBool _ -> pr "jboolean ";
8702        | RConstString _ | RConstOptString _ | RString _
8703        | RBufferOut _ -> pr "jstring ";
8704        | RStruct _ | RHashtable _ ->
8705            pr "jobject ";
8706        | RStringList _ | RStructList _ ->
8707            pr "jobjectArray ";
8708       );
8709       pr "JNICALL\n";
8710       pr "Java_com_redhat_et_libguestfs_GuestFS_";
8711       pr "%s" (replace_str ("_" ^ name) "_" "_1");
8712       pr "\n";
8713       pr "  (JNIEnv *env, jobject obj, jlong jg";
8714       List.iter (
8715         function
8716         | Pathname n
8717         | Device n | Dev_or_Path n
8718         | String n
8719         | OptString n
8720         | FileIn n
8721         | FileOut n ->
8722             pr ", jstring j%s" n
8723         | StringList n | DeviceList n ->
8724             pr ", jobjectArray j%s" n
8725         | Bool n ->
8726             pr ", jboolean j%s" n
8727         | Int n ->
8728             pr ", jint j%s" n
8729       ) (snd style);
8730       pr ")\n";
8731       pr "{\n";
8732       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
8733       let error_code, no_ret =
8734         match fst style with
8735         | RErr -> pr "  int r;\n"; "-1", ""
8736         | RBool _
8737         | RInt _ -> pr "  int r;\n"; "-1", "0"
8738         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
8739         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8740         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8741         | RString _ ->
8742             pr "  jstring jr;\n";
8743             pr "  char *r;\n"; "NULL", "NULL"
8744         | RStringList _ ->
8745             pr "  jobjectArray jr;\n";
8746             pr "  int r_len;\n";
8747             pr "  jclass cl;\n";
8748             pr "  jstring jstr;\n";
8749             pr "  char **r;\n"; "NULL", "NULL"
8750         | RStruct (_, typ) ->
8751             pr "  jobject jr;\n";
8752             pr "  jclass cl;\n";
8753             pr "  jfieldID fl;\n";
8754             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8755         | RStructList (_, typ) ->
8756             pr "  jobjectArray jr;\n";
8757             pr "  jclass cl;\n";
8758             pr "  jfieldID fl;\n";
8759             pr "  jobject jfl;\n";
8760             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8761         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
8762         | RBufferOut _ ->
8763             pr "  jstring jr;\n";
8764             pr "  char *r;\n";
8765             pr "  size_t size;\n";
8766             "NULL", "NULL" in
8767       List.iter (
8768         function
8769         | Pathname n
8770         | Device n | Dev_or_Path n
8771         | String n
8772         | OptString n
8773         | FileIn n
8774         | FileOut n ->
8775             pr "  const char *%s;\n" n
8776         | StringList n | DeviceList n ->
8777             pr "  int %s_len;\n" n;
8778             pr "  const char **%s;\n" n
8779         | Bool n
8780         | Int n ->
8781             pr "  int %s;\n" n
8782       ) (snd style);
8783
8784       let needs_i =
8785         (match fst style with
8786          | RStringList _ | RStructList _ -> true
8787          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8788          | RConstOptString _
8789          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8790           List.exists (function
8791                        | StringList _ -> true
8792                        | DeviceList _ -> true
8793                        | _ -> false) (snd style) in
8794       if needs_i then
8795         pr "  int i;\n";
8796
8797       pr "\n";
8798
8799       (* Get the parameters. *)
8800       List.iter (
8801         function
8802         | Pathname n
8803         | Device n | Dev_or_Path n
8804         | String n
8805         | FileIn n
8806         | FileOut n ->
8807             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8808         | OptString n ->
8809             (* This is completely undocumented, but Java null becomes
8810              * a NULL parameter.
8811              *)
8812             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8813         | StringList n | DeviceList n ->
8814             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8815             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8816             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8817             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8818               n;
8819             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8820             pr "  }\n";
8821             pr "  %s[%s_len] = NULL;\n" n n;
8822         | Bool n
8823         | Int n ->
8824             pr "  %s = j%s;\n" n n
8825       ) (snd style);
8826
8827       (* Make the call. *)
8828       pr "  r = guestfs_%s " name;
8829       generate_c_call_args ~handle:"g" style;
8830       pr ";\n";
8831
8832       (* Release the parameters. *)
8833       List.iter (
8834         function
8835         | Pathname n
8836         | Device n | Dev_or_Path n
8837         | String n
8838         | FileIn n
8839         | FileOut n ->
8840             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8841         | OptString n ->
8842             pr "  if (j%s)\n" n;
8843             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8844         | StringList n | DeviceList n ->
8845             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8846             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8847               n;
8848             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8849             pr "  }\n";
8850             pr "  free (%s);\n" n
8851         | Bool n
8852         | Int n -> ()
8853       ) (snd style);
8854
8855       (* Check for errors. *)
8856       pr "  if (r == %s) {\n" error_code;
8857       pr "    throw_exception (env, guestfs_last_error (g));\n";
8858       pr "    return %s;\n" no_ret;
8859       pr "  }\n";
8860
8861       (* Return value. *)
8862       (match fst style with
8863        | RErr -> ()
8864        | RInt _ -> pr "  return (jint) r;\n"
8865        | RBool _ -> pr "  return (jboolean) r;\n"
8866        | RInt64 _ -> pr "  return (jlong) r;\n"
8867        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
8868        | RConstOptString _ ->
8869            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
8870        | RString _ ->
8871            pr "  jr = (*env)->NewStringUTF (env, r);\n";
8872            pr "  free (r);\n";
8873            pr "  return jr;\n"
8874        | RStringList _ ->
8875            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
8876            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
8877            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
8878            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
8879            pr "  for (i = 0; i < r_len; ++i) {\n";
8880            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
8881            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
8882            pr "    free (r[i]);\n";
8883            pr "  }\n";
8884            pr "  free (r);\n";
8885            pr "  return jr;\n"
8886        | RStruct (_, typ) ->
8887            let jtyp = java_name_of_struct typ in
8888            let cols = cols_of_struct typ in
8889            generate_java_struct_return typ jtyp cols
8890        | RStructList (_, typ) ->
8891            let jtyp = java_name_of_struct typ in
8892            let cols = cols_of_struct typ in
8893            generate_java_struct_list_return typ jtyp cols
8894        | RHashtable _ ->
8895            (* XXX *)
8896            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
8897            pr "  return NULL;\n"
8898        | RBufferOut _ ->
8899            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
8900            pr "  free (r);\n";
8901            pr "  return jr;\n"
8902       );
8903
8904       pr "}\n";
8905       pr "\n"
8906   ) all_functions
8907
8908 and generate_java_struct_return typ jtyp cols =
8909   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8910   pr "  jr = (*env)->AllocObject (env, cl);\n";
8911   List.iter (
8912     function
8913     | name, FString ->
8914         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8915         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
8916     | name, FUUID ->
8917         pr "  {\n";
8918         pr "    char s[33];\n";
8919         pr "    memcpy (s, r->%s, 32);\n" name;
8920         pr "    s[32] = 0;\n";
8921         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8922         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8923         pr "  }\n";
8924     | name, FBuffer ->
8925         pr "  {\n";
8926         pr "    int len = r->%s_len;\n" name;
8927         pr "    char s[len+1];\n";
8928         pr "    memcpy (s, r->%s, len);\n" name;
8929         pr "    s[len] = 0;\n";
8930         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8931         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8932         pr "  }\n";
8933     | name, (FBytes|FUInt64|FInt64) ->
8934         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8935         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8936     | name, (FUInt32|FInt32) ->
8937         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8938         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8939     | name, FOptPercent ->
8940         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8941         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
8942     | name, FChar ->
8943         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8944         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8945   ) cols;
8946   pr "  free (r);\n";
8947   pr "  return jr;\n"
8948
8949 and generate_java_struct_list_return typ jtyp cols =
8950   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8951   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
8952   pr "  for (i = 0; i < r->len; ++i) {\n";
8953   pr "    jfl = (*env)->AllocObject (env, cl);\n";
8954   List.iter (
8955     function
8956     | name, FString ->
8957         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8958         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
8959     | name, FUUID ->
8960         pr "    {\n";
8961         pr "      char s[33];\n";
8962         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
8963         pr "      s[32] = 0;\n";
8964         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8965         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8966         pr "    }\n";
8967     | name, FBuffer ->
8968         pr "    {\n";
8969         pr "      int len = r->val[i].%s_len;\n" name;
8970         pr "      char s[len+1];\n";
8971         pr "      memcpy (s, r->val[i].%s, len);\n" name;
8972         pr "      s[len] = 0;\n";
8973         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8974         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8975         pr "    }\n";
8976     | name, (FBytes|FUInt64|FInt64) ->
8977         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8978         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8979     | name, (FUInt32|FInt32) ->
8980         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8981         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8982     | name, FOptPercent ->
8983         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8984         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
8985     | name, FChar ->
8986         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8987         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8988   ) cols;
8989   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
8990   pr "  }\n";
8991   pr "  guestfs_free_%s_list (r);\n" typ;
8992   pr "  return jr;\n"
8993
8994 and generate_java_makefile_inc () =
8995   generate_header HashStyle GPLv2;
8996
8997   pr "java_built_sources = \\\n";
8998   List.iter (
8999     fun (typ, jtyp) ->
9000         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9001   ) java_structs;
9002   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9003
9004 and generate_haskell_hs () =
9005   generate_header HaskellStyle LGPLv2;
9006
9007   (* XXX We only know how to generate partial FFI for Haskell
9008    * at the moment.  Please help out!
9009    *)
9010   let can_generate style =
9011     match style with
9012     | RErr, _
9013     | RInt _, _
9014     | RInt64 _, _ -> true
9015     | RBool _, _
9016     | RConstString _, _
9017     | RConstOptString _, _
9018     | RString _, _
9019     | RStringList _, _
9020     | RStruct _, _
9021     | RStructList _, _
9022     | RHashtable _, _
9023     | RBufferOut _, _ -> false in
9024
9025   pr "\
9026 {-# INCLUDE <guestfs.h> #-}
9027 {-# LANGUAGE ForeignFunctionInterface #-}
9028
9029 module Guestfs (
9030   create";
9031
9032   (* List out the names of the actions we want to export. *)
9033   List.iter (
9034     fun (name, style, _, _, _, _, _) ->
9035       if can_generate style then pr ",\n  %s" name
9036   ) all_functions;
9037
9038   pr "
9039   ) where
9040 import Foreign
9041 import Foreign.C
9042 import Foreign.C.Types
9043 import IO
9044 import Control.Exception
9045 import Data.Typeable
9046
9047 data GuestfsS = GuestfsS            -- represents the opaque C struct
9048 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9049 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9050
9051 -- XXX define properly later XXX
9052 data PV = PV
9053 data VG = VG
9054 data LV = LV
9055 data IntBool = IntBool
9056 data Stat = Stat
9057 data StatVFS = StatVFS
9058 data Hashtable = Hashtable
9059
9060 foreign import ccall unsafe \"guestfs_create\" c_create
9061   :: IO GuestfsP
9062 foreign import ccall unsafe \"&guestfs_close\" c_close
9063   :: FunPtr (GuestfsP -> IO ())
9064 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9065   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9066
9067 create :: IO GuestfsH
9068 create = do
9069   p <- c_create
9070   c_set_error_handler p nullPtr nullPtr
9071   h <- newForeignPtr c_close p
9072   return h
9073
9074 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9075   :: GuestfsP -> IO CString
9076
9077 -- last_error :: GuestfsH -> IO (Maybe String)
9078 -- last_error h = do
9079 --   str <- withForeignPtr h (\\p -> c_last_error p)
9080 --   maybePeek peekCString str
9081
9082 last_error :: GuestfsH -> IO (String)
9083 last_error h = do
9084   str <- withForeignPtr h (\\p -> c_last_error p)
9085   if (str == nullPtr)
9086     then return \"no error\"
9087     else peekCString str
9088
9089 ";
9090
9091   (* Generate wrappers for each foreign function. *)
9092   List.iter (
9093     fun (name, style, _, _, _, _, _) ->
9094       if can_generate style then (
9095         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9096         pr "  :: ";
9097         generate_haskell_prototype ~handle:"GuestfsP" style;
9098         pr "\n";
9099         pr "\n";
9100         pr "%s :: " name;
9101         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9102         pr "\n";
9103         pr "%s %s = do\n" name
9104           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9105         pr "  r <- ";
9106         (* Convert pointer arguments using with* functions. *)
9107         List.iter (
9108           function
9109           | FileIn n
9110           | FileOut n
9111           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9112           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9113           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9114           | Bool _ | Int _ -> ()
9115         ) (snd style);
9116         (* Convert integer arguments. *)
9117         let args =
9118           List.map (
9119             function
9120             | Bool n -> sprintf "(fromBool %s)" n
9121             | Int n -> sprintf "(fromIntegral %s)" n
9122             | FileIn n | FileOut n
9123             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9124           ) (snd style) in
9125         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9126           (String.concat " " ("p" :: args));
9127         (match fst style with
9128          | RErr | RInt _ | RInt64 _ | RBool _ ->
9129              pr "  if (r == -1)\n";
9130              pr "    then do\n";
9131              pr "      err <- last_error h\n";
9132              pr "      fail err\n";
9133          | RConstString _ | RConstOptString _ | RString _
9134          | RStringList _ | RStruct _
9135          | RStructList _ | RHashtable _ | RBufferOut _ ->
9136              pr "  if (r == nullPtr)\n";
9137              pr "    then do\n";
9138              pr "      err <- last_error h\n";
9139              pr "      fail err\n";
9140         );
9141         (match fst style with
9142          | RErr ->
9143              pr "    else return ()\n"
9144          | RInt _ ->
9145              pr "    else return (fromIntegral r)\n"
9146          | RInt64 _ ->
9147              pr "    else return (fromIntegral r)\n"
9148          | RBool _ ->
9149              pr "    else return (toBool r)\n"
9150          | RConstString _
9151          | RConstOptString _
9152          | RString _
9153          | RStringList _
9154          | RStruct _
9155          | RStructList _
9156          | RHashtable _
9157          | RBufferOut _ ->
9158              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9159         );
9160         pr "\n";
9161       )
9162   ) all_functions
9163
9164 and generate_haskell_prototype ~handle ?(hs = false) style =
9165   pr "%s -> " handle;
9166   let string = if hs then "String" else "CString" in
9167   let int = if hs then "Int" else "CInt" in
9168   let bool = if hs then "Bool" else "CInt" in
9169   let int64 = if hs then "Integer" else "Int64" in
9170   List.iter (
9171     fun arg ->
9172       (match arg with
9173        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9174        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9175        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9176        | Bool _ -> pr "%s" bool
9177        | Int _ -> pr "%s" int
9178        | FileIn _ -> pr "%s" string
9179        | FileOut _ -> pr "%s" string
9180       );
9181       pr " -> ";
9182   ) (snd style);
9183   pr "IO (";
9184   (match fst style with
9185    | RErr -> if not hs then pr "CInt"
9186    | RInt _ -> pr "%s" int
9187    | RInt64 _ -> pr "%s" int64
9188    | RBool _ -> pr "%s" bool
9189    | RConstString _ -> pr "%s" string
9190    | RConstOptString _ -> pr "Maybe %s" string
9191    | RString _ -> pr "%s" string
9192    | RStringList _ -> pr "[%s]" string
9193    | RStruct (_, typ) ->
9194        let name = java_name_of_struct typ in
9195        pr "%s" name
9196    | RStructList (_, typ) ->
9197        let name = java_name_of_struct typ in
9198        pr "[%s]" name
9199    | RHashtable _ -> pr "Hashtable"
9200    | RBufferOut _ -> pr "%s" string
9201   );
9202   pr ")"
9203
9204 and generate_bindtests () =
9205   generate_header CStyle LGPLv2;
9206
9207   pr "\
9208 #include <stdio.h>
9209 #include <stdlib.h>
9210 #include <inttypes.h>
9211 #include <string.h>
9212
9213 #include \"guestfs.h\"
9214 #include \"guestfs-internal-actions.h\"
9215 #include \"guestfs_protocol.h\"
9216
9217 #define error guestfs_error
9218 #define safe_calloc guestfs_safe_calloc
9219 #define safe_malloc guestfs_safe_malloc
9220
9221 static void
9222 print_strings (char *const *argv)
9223 {
9224   int argc;
9225
9226   printf (\"[\");
9227   for (argc = 0; argv[argc] != NULL; ++argc) {
9228     if (argc > 0) printf (\", \");
9229     printf (\"\\\"%%s\\\"\", argv[argc]);
9230   }
9231   printf (\"]\\n\");
9232 }
9233
9234 /* The test0 function prints its parameters to stdout. */
9235 ";
9236
9237   let test0, tests =
9238     match test_functions with
9239     | [] -> assert false
9240     | test0 :: tests -> test0, tests in
9241
9242   let () =
9243     let (name, style, _, _, _, _, _) = test0 in
9244     generate_prototype ~extern:false ~semicolon:false ~newline:true
9245       ~handle:"g" ~prefix:"guestfs__" name style;
9246     pr "{\n";
9247     List.iter (
9248       function
9249       | Pathname n
9250       | Device n | Dev_or_Path n
9251       | String n
9252       | FileIn n
9253       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9254       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9255       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9256       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9257       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9258     ) (snd style);
9259     pr "  /* Java changes stdout line buffering so we need this: */\n";
9260     pr "  fflush (stdout);\n";
9261     pr "  return 0;\n";
9262     pr "}\n";
9263     pr "\n" in
9264
9265   List.iter (
9266     fun (name, style, _, _, _, _, _) ->
9267       if String.sub name (String.length name - 3) 3 <> "err" then (
9268         pr "/* Test normal return. */\n";
9269         generate_prototype ~extern:false ~semicolon:false ~newline:true
9270           ~handle:"g" ~prefix:"guestfs__" name style;
9271         pr "{\n";
9272         (match fst style with
9273          | RErr ->
9274              pr "  return 0;\n"
9275          | RInt _ ->
9276              pr "  int r;\n";
9277              pr "  sscanf (val, \"%%d\", &r);\n";
9278              pr "  return r;\n"
9279          | RInt64 _ ->
9280              pr "  int64_t r;\n";
9281              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9282              pr "  return r;\n"
9283          | RBool _ ->
9284              pr "  return strcmp (val, \"true\") == 0;\n"
9285          | RConstString _
9286          | RConstOptString _ ->
9287              (* Can't return the input string here.  Return a static
9288               * string so we ensure we get a segfault if the caller
9289               * tries to free it.
9290               *)
9291              pr "  return \"static string\";\n"
9292          | RString _ ->
9293              pr "  return strdup (val);\n"
9294          | RStringList _ ->
9295              pr "  char **strs;\n";
9296              pr "  int n, i;\n";
9297              pr "  sscanf (val, \"%%d\", &n);\n";
9298              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9299              pr "  for (i = 0; i < n; ++i) {\n";
9300              pr "    strs[i] = safe_malloc (g, 16);\n";
9301              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9302              pr "  }\n";
9303              pr "  strs[n] = NULL;\n";
9304              pr "  return strs;\n"
9305          | RStruct (_, typ) ->
9306              pr "  struct guestfs_%s *r;\n" typ;
9307              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9308              pr "  return r;\n"
9309          | RStructList (_, typ) ->
9310              pr "  struct guestfs_%s_list *r;\n" typ;
9311              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9312              pr "  sscanf (val, \"%%d\", &r->len);\n";
9313              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9314              pr "  return r;\n"
9315          | RHashtable _ ->
9316              pr "  char **strs;\n";
9317              pr "  int n, i;\n";
9318              pr "  sscanf (val, \"%%d\", &n);\n";
9319              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9320              pr "  for (i = 0; i < n; ++i) {\n";
9321              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9322              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9323              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9324              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9325              pr "  }\n";
9326              pr "  strs[n*2] = NULL;\n";
9327              pr "  return strs;\n"
9328          | RBufferOut _ ->
9329              pr "  return strdup (val);\n"
9330         );
9331         pr "}\n";
9332         pr "\n"
9333       ) else (
9334         pr "/* Test error return. */\n";
9335         generate_prototype ~extern:false ~semicolon:false ~newline:true
9336           ~handle:"g" ~prefix:"guestfs__" name style;
9337         pr "{\n";
9338         pr "  error (g, \"error\");\n";
9339         (match fst style with
9340          | RErr | RInt _ | RInt64 _ | RBool _ ->
9341              pr "  return -1;\n"
9342          | RConstString _ | RConstOptString _
9343          | RString _ | RStringList _ | RStruct _
9344          | RStructList _
9345          | RHashtable _
9346          | RBufferOut _ ->
9347              pr "  return NULL;\n"
9348         );
9349         pr "}\n";
9350         pr "\n"
9351       )
9352   ) tests
9353
9354 and generate_ocaml_bindtests () =
9355   generate_header OCamlStyle GPLv2;
9356
9357   pr "\
9358 let () =
9359   let g = Guestfs.create () in
9360 ";
9361
9362   let mkargs args =
9363     String.concat " " (
9364       List.map (
9365         function
9366         | CallString s -> "\"" ^ s ^ "\""
9367         | CallOptString None -> "None"
9368         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9369         | CallStringList xs ->
9370             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9371         | CallInt i when i >= 0 -> string_of_int i
9372         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9373         | CallBool b -> string_of_bool b
9374       ) args
9375     )
9376   in
9377
9378   generate_lang_bindtests (
9379     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9380   );
9381
9382   pr "print_endline \"EOF\"\n"
9383
9384 and generate_perl_bindtests () =
9385   pr "#!/usr/bin/perl -w\n";
9386   generate_header HashStyle GPLv2;
9387
9388   pr "\
9389 use strict;
9390
9391 use Sys::Guestfs;
9392
9393 my $g = Sys::Guestfs->new ();
9394 ";
9395
9396   let mkargs args =
9397     String.concat ", " (
9398       List.map (
9399         function
9400         | CallString s -> "\"" ^ s ^ "\""
9401         | CallOptString None -> "undef"
9402         | CallOptString (Some s) -> sprintf "\"%s\"" s
9403         | CallStringList xs ->
9404             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9405         | CallInt i -> string_of_int i
9406         | CallBool b -> if b then "1" else "0"
9407       ) args
9408     )
9409   in
9410
9411   generate_lang_bindtests (
9412     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9413   );
9414
9415   pr "print \"EOF\\n\"\n"
9416
9417 and generate_python_bindtests () =
9418   generate_header HashStyle GPLv2;
9419
9420   pr "\
9421 import guestfs
9422
9423 g = guestfs.GuestFS ()
9424 ";
9425
9426   let mkargs args =
9427     String.concat ", " (
9428       List.map (
9429         function
9430         | CallString s -> "\"" ^ s ^ "\""
9431         | CallOptString None -> "None"
9432         | CallOptString (Some s) -> sprintf "\"%s\"" s
9433         | CallStringList xs ->
9434             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9435         | CallInt i -> string_of_int i
9436         | CallBool b -> if b then "1" else "0"
9437       ) args
9438     )
9439   in
9440
9441   generate_lang_bindtests (
9442     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9443   );
9444
9445   pr "print \"EOF\"\n"
9446
9447 and generate_ruby_bindtests () =
9448   generate_header HashStyle GPLv2;
9449
9450   pr "\
9451 require 'guestfs'
9452
9453 g = Guestfs::create()
9454 ";
9455
9456   let mkargs args =
9457     String.concat ", " (
9458       List.map (
9459         function
9460         | CallString s -> "\"" ^ s ^ "\""
9461         | CallOptString None -> "nil"
9462         | CallOptString (Some s) -> sprintf "\"%s\"" s
9463         | CallStringList xs ->
9464             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9465         | CallInt i -> string_of_int i
9466         | CallBool b -> string_of_bool b
9467       ) args
9468     )
9469   in
9470
9471   generate_lang_bindtests (
9472     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9473   );
9474
9475   pr "print \"EOF\\n\"\n"
9476
9477 and generate_java_bindtests () =
9478   generate_header CStyle GPLv2;
9479
9480   pr "\
9481 import com.redhat.et.libguestfs.*;
9482
9483 public class Bindtests {
9484     public static void main (String[] argv)
9485     {
9486         try {
9487             GuestFS g = new GuestFS ();
9488 ";
9489
9490   let mkargs args =
9491     String.concat ", " (
9492       List.map (
9493         function
9494         | CallString s -> "\"" ^ s ^ "\""
9495         | CallOptString None -> "null"
9496         | CallOptString (Some s) -> sprintf "\"%s\"" s
9497         | CallStringList xs ->
9498             "new String[]{" ^
9499               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9500         | CallInt i -> string_of_int i
9501         | CallBool b -> string_of_bool b
9502       ) args
9503     )
9504   in
9505
9506   generate_lang_bindtests (
9507     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
9508   );
9509
9510   pr "
9511             System.out.println (\"EOF\");
9512         }
9513         catch (Exception exn) {
9514             System.err.println (exn);
9515             System.exit (1);
9516         }
9517     }
9518 }
9519 "
9520
9521 and generate_haskell_bindtests () =
9522   generate_header HaskellStyle GPLv2;
9523
9524   pr "\
9525 module Bindtests where
9526 import qualified Guestfs
9527
9528 main = do
9529   g <- Guestfs.create
9530 ";
9531
9532   let mkargs args =
9533     String.concat " " (
9534       List.map (
9535         function
9536         | CallString s -> "\"" ^ s ^ "\""
9537         | CallOptString None -> "Nothing"
9538         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9539         | CallStringList xs ->
9540             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9541         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9542         | CallInt i -> string_of_int i
9543         | CallBool true -> "True"
9544         | CallBool false -> "False"
9545       ) args
9546     )
9547   in
9548
9549   generate_lang_bindtests (
9550     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
9551   );
9552
9553   pr "  putStrLn \"EOF\"\n"
9554
9555 (* Language-independent bindings tests - we do it this way to
9556  * ensure there is parity in testing bindings across all languages.
9557  *)
9558 and generate_lang_bindtests call =
9559   call "test0" [CallString "abc"; CallOptString (Some "def");
9560                 CallStringList []; CallBool false;
9561                 CallInt 0; CallString "123"; CallString "456"];
9562   call "test0" [CallString "abc"; CallOptString None;
9563                 CallStringList []; CallBool false;
9564                 CallInt 0; CallString "123"; CallString "456"];
9565   call "test0" [CallString ""; CallOptString (Some "def");
9566                 CallStringList []; CallBool false;
9567                 CallInt 0; CallString "123"; CallString "456"];
9568   call "test0" [CallString ""; CallOptString (Some "");
9569                 CallStringList []; CallBool false;
9570                 CallInt 0; CallString "123"; CallString "456"];
9571   call "test0" [CallString "abc"; CallOptString (Some "def");
9572                 CallStringList ["1"]; CallBool false;
9573                 CallInt 0; CallString "123"; CallString "456"];
9574   call "test0" [CallString "abc"; CallOptString (Some "def");
9575                 CallStringList ["1"; "2"]; CallBool false;
9576                 CallInt 0; CallString "123"; CallString "456"];
9577   call "test0" [CallString "abc"; CallOptString (Some "def");
9578                 CallStringList ["1"]; CallBool true;
9579                 CallInt 0; CallString "123"; CallString "456"];
9580   call "test0" [CallString "abc"; CallOptString (Some "def");
9581                 CallStringList ["1"]; CallBool false;
9582                 CallInt (-1); CallString "123"; CallString "456"];
9583   call "test0" [CallString "abc"; CallOptString (Some "def");
9584                 CallStringList ["1"]; CallBool false;
9585                 CallInt (-2); CallString "123"; CallString "456"];
9586   call "test0" [CallString "abc"; CallOptString (Some "def");
9587                 CallStringList ["1"]; CallBool false;
9588                 CallInt 1; CallString "123"; CallString "456"];
9589   call "test0" [CallString "abc"; CallOptString (Some "def");
9590                 CallStringList ["1"]; CallBool false;
9591                 CallInt 2; CallString "123"; CallString "456"];
9592   call "test0" [CallString "abc"; CallOptString (Some "def");
9593                 CallStringList ["1"]; CallBool false;
9594                 CallInt 4095; CallString "123"; CallString "456"];
9595   call "test0" [CallString "abc"; CallOptString (Some "def");
9596                 CallStringList ["1"]; CallBool false;
9597                 CallInt 0; CallString ""; CallString ""]
9598
9599 (* XXX Add here tests of the return and error functions. *)
9600
9601 (* This is used to generate the src/MAX_PROC_NR file which
9602  * contains the maximum procedure number, a surrogate for the
9603  * ABI version number.  See src/Makefile.am for the details.
9604  *)
9605 and generate_max_proc_nr () =
9606   let proc_nrs = List.map (
9607     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9608   ) daemon_functions in
9609
9610   let max_proc_nr = List.fold_left max 0 proc_nrs in
9611
9612   pr "%d\n" max_proc_nr
9613
9614 let output_to filename =
9615   let filename_new = filename ^ ".new" in
9616   chan := open_out filename_new;
9617   let close () =
9618     close_out !chan;
9619     chan := stdout;
9620
9621     (* Is the new file different from the current file? *)
9622     if Sys.file_exists filename && files_equal filename filename_new then
9623       Unix.unlink filename_new          (* same, so skip it *)
9624     else (
9625       (* different, overwrite old one *)
9626       (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9627       Unix.rename filename_new filename;
9628       Unix.chmod filename 0o444;
9629       printf "written %s\n%!" filename;
9630     )
9631   in
9632   close
9633
9634 (* Main program. *)
9635 let () =
9636   check_functions ();
9637
9638   if not (Sys.file_exists "HACKING") then (
9639     eprintf "\
9640 You are probably running this from the wrong directory.
9641 Run it from the top source directory using the command
9642   src/generator.ml
9643 ";
9644     exit 1
9645   );
9646
9647   let close = output_to "src/guestfs_protocol.x" in
9648   generate_xdr ();
9649   close ();
9650
9651   let close = output_to "src/guestfs-structs.h" in
9652   generate_structs_h ();
9653   close ();
9654
9655   let close = output_to "src/guestfs-actions.h" in
9656   generate_actions_h ();
9657   close ();
9658
9659   let close = output_to "src/guestfs-internal-actions.h" in
9660   generate_internal_actions_h ();
9661   close ();
9662
9663   let close = output_to "src/guestfs-actions.c" in
9664   generate_client_actions ();
9665   close ();
9666
9667   let close = output_to "daemon/actions.h" in
9668   generate_daemon_actions_h ();
9669   close ();
9670
9671   let close = output_to "daemon/stubs.c" in
9672   generate_daemon_actions ();
9673   close ();
9674
9675   let close = output_to "daemon/names.c" in
9676   generate_daemon_names ();
9677   close ();
9678
9679   let close = output_to "capitests/tests.c" in
9680   generate_tests ();
9681   close ();
9682
9683   let close = output_to "src/guestfs-bindtests.c" in
9684   generate_bindtests ();
9685   close ();
9686
9687   let close = output_to "fish/cmds.c" in
9688   generate_fish_cmds ();
9689   close ();
9690
9691   let close = output_to "fish/completion.c" in
9692   generate_fish_completion ();
9693   close ();
9694
9695   let close = output_to "guestfs-structs.pod" in
9696   generate_structs_pod ();
9697   close ();
9698
9699   let close = output_to "guestfs-actions.pod" in
9700   generate_actions_pod ();
9701   close ();
9702
9703   let close = output_to "guestfish-actions.pod" in
9704   generate_fish_actions_pod ();
9705   close ();
9706
9707   let close = output_to "ocaml/guestfs.mli" in
9708   generate_ocaml_mli ();
9709   close ();
9710
9711   let close = output_to "ocaml/guestfs.ml" in
9712   generate_ocaml_ml ();
9713   close ();
9714
9715   let close = output_to "ocaml/guestfs_c_actions.c" in
9716   generate_ocaml_c ();
9717   close ();
9718
9719   let close = output_to "ocaml/bindtests.ml" in
9720   generate_ocaml_bindtests ();
9721   close ();
9722
9723   let close = output_to "perl/Guestfs.xs" in
9724   generate_perl_xs ();
9725   close ();
9726
9727   let close = output_to "perl/lib/Sys/Guestfs.pm" in
9728   generate_perl_pm ();
9729   close ();
9730
9731   let close = output_to "perl/bindtests.pl" in
9732   generate_perl_bindtests ();
9733   close ();
9734
9735   let close = output_to "python/guestfs-py.c" in
9736   generate_python_c ();
9737   close ();
9738
9739   let close = output_to "python/guestfs.py" in
9740   generate_python_py ();
9741   close ();
9742
9743   let close = output_to "python/bindtests.py" in
9744   generate_python_bindtests ();
9745   close ();
9746
9747   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9748   generate_ruby_c ();
9749   close ();
9750
9751   let close = output_to "ruby/bindtests.rb" in
9752   generate_ruby_bindtests ();
9753   close ();
9754
9755   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9756   generate_java_java ();
9757   close ();
9758
9759   List.iter (
9760     fun (typ, jtyp) ->
9761       let cols = cols_of_struct typ in
9762       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9763       let close = output_to filename in
9764       generate_java_struct jtyp cols;
9765       close ();
9766   ) java_structs;
9767
9768   let close = output_to "java/Makefile.inc" in
9769   generate_java_makefile_inc ();
9770   close ();
9771
9772   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9773   generate_java_c ();
9774   close ();
9775
9776   let close = output_to "java/Bindtests.java" in
9777   generate_java_bindtests ();
9778   close ();
9779
9780   let close = output_to "haskell/Guestfs.hs" in
9781   generate_haskell_hs ();
9782   close ();
9783
9784   let close = output_to "haskell/Bindtests.hs" in
9785   generate_haskell_bindtests ();
9786   close ();
9787
9788   let close = output_to "src/MAX_PROC_NR" in
9789   generate_max_proc_nr ();
9790   close ();
9791
9792   (* Always generate this file last, and unconditionally.  It's used
9793    * by the Makefile to know when we must re-run the generator.
9794    *)
9795   let chan = open_out "src/stamp-generator" in
9796   fprintf chan "1\n";
9797   close_out chan